<commit_before>Module.register('MMM-pages', {

  // We require the older style of function declaration for compatibility
  // reasons.

  /**
   * By default, we have don't pseudo-paginate any modules. We also exclude
   * the page indicator by default, in case people actually want to use the
   * sister module. We also don't rotate out modules by default.
   */
  defaults: {
    modules: [],
    excludes: ['MMM-page-indicator'],
    animationTime: 1000,
    rotationTime: 0,
    rotationDelay: 10000
  },

  /**
   * Apply any styles, if we have any.
   */
  getStyles: function() {
    return ['pages.css'];
  },

  /**
   * Modulo that also works with negative numbers.
   * @param {number} x The dividend
   * @param {number} n The divisor
   */
  mod: function(x, n) {
    return ((x % n) + n) % n;
  },

  /**
   * Pseudo-constructor for our module. Makes sure that values aren't negative,
   * and sets the default current page to 0.
   */
  start: function() {
    this.curPage = 0;

    // Disable rotation if an invalid input is given
    this.config.rotationTime = Math.max(this.config.rotationTime, 0);
    this.config.rotationDelay = Math.max(this.config.rotationDelay, 0);
  },

  /**
   * Handles incoming notifications. Responds to the following:
   *   'PAGE_CHANGED' - Set the page to the specified payload page.
   *   'PAGE_INCREMENT' - Move to the next page.
   *   'PAGE_DECREMENT' - Move to the previous page.
   *   'DOM_OBJECTS_CREATED' - Starts the module.
   *   'REQUEST_CURRENT_PAGE' - Requests the current page number
   * @param {string} notification the notification ID
   * @param {number} payload the page to change to
   */
  notificationReceived: function(notification, payload) {
    const isValidPayload = typeof payload === 'number';

    Log.log(`[Pages]:${payload} is a number? ${isValidPayload}`);
    Log.log(`[Pages]:${this.curPage + (isValidPayload) ? payload : 1}`);
    switch (notification) {
      case 'PAGE_CHANGED':
        Log.log(`${this.name} received a notification`
          + `to change to page ${payload} of type ${typeof payload}`);
        if (typeof payload === 'number') {
          this.curPage = payload;
        } else {
          Log.error('Was asked to change to an invalid number!');
          Log.error(`Payload=${payload}, type=${typeof payload},
            maxPageIndex=${this.config.modules.length - 1}`);
        }
        this.updatePages(true);
        break;
      case 'PAGE_INCREMENT':
        Log.log(`${this.name} received a notification to increment pages!`);
        this.curPage = this.mod(
          this.curPage + ((isValidPayload) ? payload : 1),
          this.config.modules.length
        );
        this.updatePages(true);
        break;
      case 'PAGE_DECREMENT':
        Log.log(`${this.name} received a notification to decrement pages!`);
        this.curPage = this.mod(
          this.curPage - ((isValidPayload) ? payload : 1),
          this.config.modules.length
        );
        this.updatePages(true);
        break;
      case 'DOM_OBJECTS_CREATED':
        Log.log(`${this.name} received that all objects are created;`
          + 'will now hide things!');
        this.updatePages(true);
        this.sendNotification('MAX_PAGES_CHANGED', this.config.modules.length);
        break;
      case 'QUERY_PAGE_NUMBER':
        this.sendNotification('PAGE_NUMBER_IS', this.curPage);
        break;
      default:
    }
  },

  // TODO: Add slide-left/right animation
  /**
   * Handles hiding the current page's elements and showing the next page's
   * elements.
   * @param {boolean} manuallyCalled whether or not to add in an extended delay.
   */
  updatePages: function(manuallyCalled) {
    if (this.config.modules.length !== 0) {
      // We need to use self because upstream uses an older electron and thus
      // older version of node
      const self = this;

      Log.log(`updatePages was ${manuallyCalled ? '' : 'not'} manually called`);

      // Hides the current page's elements.
      MM.getModules()
        .exceptWithClass(this.config.excludes)
        .exceptWithClass(this.config.modules[this.curPage])
        .enumerate((module) => {
          module.hide(
            self.config.animationTime / 2,
            { lockString: self.identifier }
          );
        });

      // Shows the next page's elements
      setTimeout(() => MM.getModules()
        .withClass(self.config.modules[self.curPage])
        .enumerate(module => module.show(
          self.config.animationTime / 2,
          { lockString: self.identifier },
        )), this.config.animationTime / 2);

      if (manuallyCalled && this.config.rotationTime > 0) {
        Log.log('Manually updated page! setting delay before resuming timer!');

        clearInterval(this.timer);

        setTimeout(() => {
          self.timer = setInterval(() => {
            // Incrementing page
            self.curPage = self.mod(
              self.curPage + 1,
              self.config.modules.length
            );
            self.sendNotification('PAGE_INCREMENT');
            self.updatePages(false);
          }, self.config.rotationTime, false);
        }, this.config.rotationDelay);
      }
    } else { Log.error("Pages aren't properly defined!"); }
  },
});
<commit_msg>added more documentation<commit_after>Module.register('MMM-pages', {

  // We require the older style of function declaration for compatibility
  // reasons.

  /**
   * By default, we have don't pseudo-paginate any modules. We also exclude
   * the page indicator by default, in case people actually want to use the
   * sister module. We also don't rotate out modules by default.
   */
  defaults: {
    modules: [],
    excludes: ['MMM-page-indicator'],
    animationTime: 1000,
    rotationTime: 0,
    rotationDelay: 10000
  },

  /**
   * Apply any styles, if we have any.
   */
  getStyles: function() {
    return ['pages.css'];
  },

  /**
   * Modulo that also works with negative numbers.
   * @param {number} x The dividend
   * @param {number} n The divisor
   */
  mod: function(x, n) {
    return ((x % n) + n) % n;
  },

  /**
   * Pseudo-constructor for our module. Makes sure that values aren't negative,
   * and sets the default current page to 0.
   */
  start: function() {
    this.curPage = 0;

    // Disable rotation if an invalid input is given
    this.config.rotationTime = Math.max(this.config.rotationTime, 0);
    this.config.rotationDelay = Math.max(this.config.rotationDelay, 0);
  },

  /**
   * Handles incoming notifications. Responds to the following:
   *   'PAGE_CHANGED' - Set the page to the specified payload page.
   *   'PAGE_INCREMENT' - Move to the next page.
   *   'PAGE_DECREMENT' - Move to the previous page.
   *   'DOM_OBJECTS_CREATED' - Starts the module.
   *   'REQUEST_CURRENT_PAGE' - Requests the current page number
   * @param {string} notification the notification ID
   * @param {number} payload the page to change to
   */
  notificationReceived: function(notification, payload) {
    const isValidPayload = typeof payload === 'number';

    Log.log(`[Pages]:${payload} is a number? ${isValidPayload}`);
    Log.log(`[Pages]:${this.curPage + (isValidPayload) ? payload : 1}`);
    switch (notification) {
      case 'PAGE_CHANGED':
        Log.log(`${this.name} received a notification`
          + `to change to page ${payload} of type ${typeof payload}`);
        if (typeof payload === 'number') {
          this.curPage = payload;
        } else {
          Log.error('Was asked to change to an invalid number!');
          Log.error(`Payload=${payload}, type=${typeof payload},
            maxPageIndex=${this.config.modules.length - 1}`);
        }
        this.updatePages(true);
        break;
      case 'PAGE_INCREMENT':
        Log.log(`${this.name} received a notification to increment pages!`);
        this.curPage = this.mod(
          this.curPage + ((isValidPayload) ? payload : 1),
          this.config.modules.length
        );
        this.updatePages(true);
        break;
      case 'PAGE_DECREMENT':
        Log.log(`${this.name} received a notification to decrement pages!`);
        this.curPage = this.mod(
          this.curPage - ((isValidPayload) ? payload : 1),
          this.config.modules.length
        );
        this.updatePages(true);
        break;
      case 'DOM_OBJECTS_CREATED':
        Log.log(`${this.name} received that all objects are created;`
          + 'will now hide things!');
        this.updatePages(true);
        this.sendNotification('MAX_PAGES_CHANGED', this.config.modules.length);
        break;
      case 'QUERY_PAGE_NUMBER':
        this.sendNotification('PAGE_NUMBER_IS', this.curPage);
        break;
      default:
    }
  },

  // TODO: Add slide-left/right animation
  /**
   * Handles hiding the current page's elements and showing the next page's
   * elements.
   * @param {boolean} manuallyCalled whether or not to add in an extended delay.
   */
  updatePages: function(manuallyCalled) {
    // Update iff there's at least one page.
    if (this.config.modules.length !== 0) {
      // We need to use self because upstream uses an older electron and thus
      // older version of node
      const self = this;

      Log.log(`updatePages was ${manuallyCalled ? '' : 'not'} manually called`);

      // Hides the current page's elements; using half the animation time we
      // were allowed to switch between modules.
      MM.getModules()
        .exceptWithClass(this.config.excludes)
        .exceptWithClass(this.config.modules[this.curPage])
        .enumerate((module) => {
          module.hide(
            self.config.animationTime / 2,
            { lockString: self.identifier }
          );
        });

      // Shows the next page's elements; after half the animation time, start
      // the animations for showing the next page's modules.
      setTimeout(() => MM.getModules()
        .withClass(self.config.modules[self.curPage])
        .enumerate(module => module.show(
          self.config.animationTime / 2,
          { lockString: self.identifier },
        )), this.config.animationTime / 2);

      if (manuallyCalled && this.config.rotationTime > 0) {
        Log.log('Manually updated page! setting delay before resuming timer!');

        clearInterval(this.timer);

        setTimeout(() => {
          self.timer = setInterval(() => {
            // Incrementing page
            self.curPage = self.mod(
              self.curPage + 1,
              self.config.modules.length
            );
            self.sendNotification('PAGE_INCREMENT');
            self.updatePages(false);
          }, self.config.rotationTime);
        }, this.config.rotationDelay);
      }
    } else { Log.error("Pages aren't properly defined!"); }
  },
});
<|endoftext|>


<commit_before>app.views.PostViewerNewComment = app.views.Base.extend({

  templateName: "post-viewer/new-comment",

  events : {
    "click button" : "createComment",
    "focus textarea" : "scrollToBottom"
  },

  scrollableArea : "#post-reactions",

  postRenderTemplate : function() {
    this.$("textarea").placeholder();
    this.$("textarea").autoResize({'extraSpace' : 0});
  },

  createComment: function(evt) {
    if(evt){ evt.preventDefault(); }

    var self = this;

    this.toggleFormState()
    this.model.comments.create({
      "text" : this.$("textarea").val()
    }, {success : _.bind(self.clearAndReactivateForm, self)});

  },

  clearAndReactivateForm : function() {
    this.model.trigger("interacted")
    this.toggleFormState()
    this.$("textarea").val("")
    this.$("textarea").css('height', '18px')

    /* scroll to bottom without animation */
    $(this.scrollableArea).scrollTop($(this.scrollableArea).prop("scrollHeight"))

    this.$("textarea").focus()
  },

  toggleFormState : function() {
    this.$("form").children().toggleClass('disabled')
  },

  scrollToBottom : function() {
    $(this.scrollableArea).animate({ scrollTop: $(this.scrollableArea).prop("scrollHeight") }, 1000);
  }

})
<commit_msg>fix bug with interaction pane scrolling<commit_after>app.views.PostViewerNewComment = app.views.Base.extend({

  templateName: "post-viewer/new-comment",

  events : {
    "click button" : "createComment",
    "focus textarea" : "scrollToBottom"
  },

  scrollableArea : "#post-reactions",

  postRenderTemplate : function() {
    this.$("textarea").placeholder();
    this.$("textarea").autoResize({'extraSpace' : 0});
  },

  createComment: function(evt) {
    if(evt){ evt.preventDefault(); }

    var self = this;

    this.toggleFormState()
    this.model.comments.create({
      "text" : this.$("textarea").val()
    }, {success : _.bind(self.clearAndReactivateForm, self)});

  },

  clearAndReactivateForm : function() {
    this.model.trigger("interacted")
    this.toggleFormState()
    this.$("textarea").val("")
      .css('height', '18px')
      .focus()
  },

  toggleFormState : function() {
    this.$("form").children().toggleClass('disabled')
  },

  scrollToBottom : function() {
    $(this.scrollableArea).scrollTop($(this.scrollableArea).prop("scrollHeight"))
  }

})
<|endoftext|>


<commit_before>#!/usr/bin/env node
/* eslint-disable no-console */

const fs = require('fs-extra');
const path = require('path');
const program = require('commander');
const chalk = require('chalk');

const before = require('./_before');

const {
    keyConfigQuiet,
    filenameBuilding
} = require('../defaults/before-build');

const __ = require('../utils/translate');
const sleep = require('../utils/sleep');
const setEnvFromCommand = require('../utils/set-env-from-command');
const getAppType = require('../utils/get-app-type');
const validateConfig = require('../libs/validate-config');
const validateConfigDist = require('../libs/validate-config-dist');
const spinner = require('../utils/spinner');
const initNodeEnv = require('../utils/init-node-env');
// const emptyTempConfigDir = require('../libs/empty-temp-config-dir')
const getDirTemp = require('../libs/get-dir-tmp');

const kootWebpackBuild = require('koot-webpack/build');

program
    .version(require('../package').version, '-v, --version')
    .usage('[options]')
    .option('-c, --client', 'Set STAGE to CLIENT')
    .option('-s, --server', 'Set STAGE to SERVER')
    .option('--stage <stage>', 'Set STAGE')
    .option('--env <env>', 'Set ENV')
    .option('--dest <destination-path>', 'Set destination directory')
    .option('--config <config-file-path>', 'Set config file pathname')
    .option('--type <project-type>', 'Set project type')
    .option('--koot-dev', 'Koot dev env')
    .option('--koot-test', 'Koot test mode')
    .option('--koot-development', 'Koot development mode')
    .parse(process.argv);

/** 判断是否是通过 koot-start 命令启动
 * @returns {Boolean}
 */
const isFromCommandStart = () =>
    process.env.KOOT_COMMAND_START &&
    JSON.parse(process.env.KOOT_COMMAND_START);

/** Building result */
let result;

/**
 * 执行打包
 */
const run = async () => {
    const {
        client,
        server,
        stage: _stage,
        env = 'prod',
        config,
        type,
        dest,
        kootDev = false,
        kootTest = false,
        kootDevelopment = false
    } = program;

    initNodeEnv();
    // console.log(program)

    /** @type {Boolean} 是否为通过 koot-start 命令启动 */
    const fromCommandStart = isFromCommandStart();
    const fromOtherCommand = kootDev || fromCommandStart;
    if (!fromOtherCommand)
        // 清空 log
        process.stdout.write('\x1B[2J\x1B[0f');

    setEnvFromCommand(
        {
            config,
            type
        },
        fromOtherCommand
    );

    process.env.KOOT_TEST_MODE = JSON.stringify(kootTest);
    process.env.KOOT_DEVELOPMENT_MODE = JSON.stringify(kootDevelopment);

    const stage = (() => {
        if (_stage) return _stage;
        if (client) return 'client';
        if (server) return 'server';
        return false;
    })();

    // 在所有操作执行之前定义环境变量
    process.env.WEBPACK_BUILD_STAGE = stage || 'client';
    process.env.WEBPACK_BUILD_ENV = env;

    // 清理临时目录
    await before(program);

    // 生成配置
    const kootConfig = await validateConfig();
    await getAppType();
    if (dest) kootConfig.dist = validateConfigDist(dest);

    // 如果通过 koot-start 命令启动...
    if (fromCommandStart) {
        // 安静模式: 非报错 log 不打出
        kootConfig[keyConfigQuiet] = true;
    }

    // Building process =======================================================

    // 如果提供了 stage，仅针对该 stage 执行打包
    // SPA: 强制仅打包 client
    if (process.env.WEBPACK_BUILD_TYPE === 'spa' || stage) {
        // if (stage === 'server' && !hasServer) {
        //     console.log(chalk.redBright('× '))
        // }
        result = await kootWebpackBuild(kootConfig);
        await after(kootConfig);
        if (!fromCommandStart) console.log(' ');
        return;
    }

    // 如过没有提供 stage，自动相继打包 client 和 server
    result = await kootWebpackBuild({ ...kootConfig });
    await sleep(100);

    if (!fromCommandStart) console.log('\n' + ''.padEnd(60, '=') + '\n');
    process.env.WEBPACK_BUILD_STAGE = 'server';
    result = await kootWebpackBuild({ ...kootConfig });
    await sleep(100);

    if (!fromCommandStart) console.log('\n' + ''.padEnd(60, '=') + '\n');
    if (!fromCommandStart)
        console.log(
            chalk.green('√ ') +
                chalk.yellowBright('[koot/build] ') +
                __('build.complete', {
                    time: new Date().toLocaleString()
                })
        );

    await after(kootConfig);
    if (!fromCommandStart) console.log(' ');

    // 结束
};

const after = async (config = {}) => {
    const ENV = process.env.WEBPACK_BUILD_ENV;

    const { dist } = config;

    if (ENV === 'prod') {
        // 清理临时目录
        await fs.remove(getDirTemp());
        // 移除临时配置文件
        // emptyTempConfigDir()
    }

    // 移除标记文件
    const fileBuilding = path.resolve(dist, filenameBuilding);

    if (fs.existsSync(fileBuilding)) await fs.remove(fileBuilding);
};

run().catch(err => {
    if (!isFromCommandStart())
        spinner(chalk.yellowBright('[koot/build] ')).fail();

    if (Array.isArray(result.errors) && result.errors.length) {
        result.errors.forEach(e => console.error(e));
    } else {
        console.error(err);
    }

    process.exit();
});
<commit_msg>more reliable error logging for build<commit_after>#!/usr/bin/env node
/* eslint-disable no-console */

const fs = require('fs-extra');
const path = require('path');
const program = require('commander');
const chalk = require('chalk');

const before = require('./_before');

const {
    keyConfigQuiet,
    filenameBuilding
} = require('../defaults/before-build');

const __ = require('../utils/translate');
const sleep = require('../utils/sleep');
const setEnvFromCommand = require('../utils/set-env-from-command');
const getAppType = require('../utils/get-app-type');
const validateConfig = require('../libs/validate-config');
const validateConfigDist = require('../libs/validate-config-dist');
const spinner = require('../utils/spinner');
const initNodeEnv = require('../utils/init-node-env');
// const emptyTempConfigDir = require('../libs/empty-temp-config-dir')
const getDirTemp = require('../libs/get-dir-tmp');

const kootWebpackBuild = require('koot-webpack/build');

program
    .version(require('../package').version, '-v, --version')
    .usage('[options]')
    .option('-c, --client', 'Set STAGE to CLIENT')
    .option('-s, --server', 'Set STAGE to SERVER')
    .option('--stage <stage>', 'Set STAGE')
    .option('--env <env>', 'Set ENV')
    .option('--dest <destination-path>', 'Set destination directory')
    .option('--config <config-file-path>', 'Set config file pathname')
    .option('--type <project-type>', 'Set project type')
    .option('--koot-dev', 'Koot dev env')
    .option('--koot-test', 'Koot test mode')
    .option('--koot-development', 'Koot development mode')
    .parse(process.argv);

/** 判断是否是通过 koot-start 命令启动
 * @returns {Boolean}
 */
const isFromCommandStart = () =>
    process.env.KOOT_COMMAND_START &&
    JSON.parse(process.env.KOOT_COMMAND_START);

/** Building result */
let result;

/**
 * 执行打包
 */
const run = async () => {
    const {
        client,
        server,
        stage: _stage,
        env = 'prod',
        config,
        type,
        dest,
        kootDev = false,
        kootTest = false,
        kootDevelopment = false
    } = program;

    initNodeEnv();
    // console.log(program)

    /** @type {Boolean} 是否为通过 koot-start 命令启动 */
    const fromCommandStart = isFromCommandStart();
    const fromOtherCommand = kootDev || fromCommandStart;
    if (!fromOtherCommand)
        // 清空 log
        process.stdout.write('\x1B[2J\x1B[0f');

    setEnvFromCommand(
        {
            config,
            type
        },
        fromOtherCommand
    );

    process.env.KOOT_TEST_MODE = JSON.stringify(kootTest);
    process.env.KOOT_DEVELOPMENT_MODE = JSON.stringify(kootDevelopment);

    const stage = (() => {
        if (_stage) return _stage;
        if (client) return 'client';
        if (server) return 'server';
        return false;
    })();

    // 在所有操作执行之前定义环境变量
    process.env.WEBPACK_BUILD_STAGE = stage || 'client';
    process.env.WEBPACK_BUILD_ENV = env;

    // 清理临时目录
    await before(program);

    // 生成配置
    const kootConfig = await validateConfig();
    await getAppType();
    if (dest) kootConfig.dist = validateConfigDist(dest);

    // 如果通过 koot-start 命令启动...
    if (fromCommandStart) {
        // 安静模式: 非报错 log 不打出
        kootConfig[keyConfigQuiet] = true;
    }

    // Building process =======================================================

    // 如果提供了 stage，仅针对该 stage 执行打包
    // SPA: 强制仅打包 client
    if (process.env.WEBPACK_BUILD_TYPE === 'spa' || stage) {
        // if (stage === 'server' && !hasServer) {
        //     console.log(chalk.redBright('× '))
        // }
        result = await kootWebpackBuild(kootConfig);
        await after(kootConfig);
        if (!fromCommandStart) console.log(' ');
        return;
    }

    // 如过没有提供 stage，自动相继打包 client 和 server
    result = await kootWebpackBuild({ ...kootConfig });
    await sleep(100);

    if (!fromCommandStart) console.log('\n' + ''.padEnd(60, '=') + '\n');
    process.env.WEBPACK_BUILD_STAGE = 'server';
    result = await kootWebpackBuild({ ...kootConfig });
    await sleep(100);

    if (!fromCommandStart) console.log('\n' + ''.padEnd(60, '=') + '\n');
    if (!fromCommandStart)
        console.log(
            chalk.green('√ ') +
                chalk.yellowBright('[koot/build] ') +
                __('build.complete', {
                    time: new Date().toLocaleString()
                })
        );

    await after(kootConfig);
    if (!fromCommandStart) console.log(' ');

    // 结束
};

const after = async (config = {}) => {
    const ENV = process.env.WEBPACK_BUILD_ENV;

    const { dist } = config;

    if (ENV === 'prod') {
        // 清理临时目录
        await fs.remove(getDirTemp());
        // 移除临时配置文件
        // emptyTempConfigDir()
    }

    // 移除标记文件
    const fileBuilding = path.resolve(dist, filenameBuilding);

    if (fs.existsSync(fileBuilding)) await fs.remove(fileBuilding);
};

run().catch(err => {
    if (!isFromCommandStart())
        spinner(chalk.yellowBright('[koot/build] ')).fail();

    if (result && Array.isArray(result.errors) && result.errors.length) {
        result.errors.forEach(e => console.error(e));
    } else {
        console.error(err);
    }

    process.exit();
});
<|endoftext|>


<commit_before>const ghGot = require('gh-got');
const got = require('got');
const semver = require('semver');
const stable = require('semver-stable');

const token = process.env.RENOVATE_TOKEN;
const repoName = process.argv[2];
const userName = repoName.split('/')[0];
const packageFile = process.argv[3] || 'package.json';

let masterSHA;
let masterPackageJson;

ghGot(`repos/${repoName}/git/refs/head`, {token: token}).then(res => {
  // First, get the SHA for master branch
  res.body.forEach(function(branch) {
    // Loop through all branches because master may not be the first
    if (branch.ref === 'refs/heads/master') {
      // This is the SHA we will create new branches from
      masterSHA = branch.object.sha;
    }
  });
  // Now, retrieve the master package.json
  ghGot(`repos/${repoName}/contents/${packageFile}`, {token: token}).then(res => {
    masterPackageJson = JSON.parse(new Buffer(res.body.content, 'base64').toString());
    // Iterate through dependencies and then devDependencies
    return iterateDependencies('dependencies')
      .then(() => iterateDependencies('devDependencies'));
  }).catch(err => {
    console.log('Error reading master package.json');
  });
});

function iterateDependencies(depType) {
  const deps = masterPackageJson[depType];
  if (!deps) {
    return;
  }
  return Object.keys(deps).reduce((total, depName) => {
    return total.then(() => {
      const currentVersion = deps[depName].replace(/[^\d.]/g, '');

      if (!semver.valid(currentVersion)) {
        console.log('Invalid current version');
        return;
      }

      // supports scoped packages, e.g. @user/package
      return got(`https://registry.npmjs.org/${depName.replace('/', '%2F')}`, { json: true })
        .then(res => {
          let allUpgrades = {};
          Object.keys(res.body['versions']).forEach(function(version) {
            if (stable.is(currentVersion) && !stable.is(version)) {
              return;
            }
            if (semver.gt(version, currentVersion)) {
              var thisMajor = semver.major(version);
              if (!allUpgrades[thisMajor] || semver.gt(version, allUpgrades[thisMajor])) {
                allUpgrades[thisMajor] = version;
              }
            }
          });

          let upgradePromises = [];

          Object.keys(allUpgrades).forEach(function(upgrade) {
            const nextVersion = allUpgrades[upgrade];
            upgradePromises.push(updateDependency(depType, depName, currentVersion, nextVersion));
          });

          return Promise.all(upgradePromises);
        });
    });
  }, Promise.resolve());
}

function updateDependency(depType, depName, currentVersion, nextVersion) {
  const nextVersionMajor = semver.major(nextVersion);
  const branchName = `upgrade/${depName}-${nextVersionMajor}.x`;
  let prName = '';
  if (nextVersionMajor > semver.major(currentVersion)) {
    prName = `Upgrade dependency ${depName} to version ${nextVersionMajor}.x`;
    // Check if PR was already closed previously
    ghGot(`repos/${repoName}/pulls?state=closed&head=${userName}:${branchName}`, { token: token })
      .then(res => {
        if (res.body.length > 0) {
          console.log(`Dependency ${depName} upgrade to ${nextVersionMajor}.x PR already existed, so skipping`);
        } else {
          writeUpdates(depType, depName, branchName, prName, nextVersion);
        }
      });
  } else {
    prName = `Upgrade dependency ${depName} to version ${nextVersion}`;
    writeUpdates(depType, depName, branchName, prName, nextVersion);
  }
}

function writeUpdates(depType, depName, branchName, prName, nextVersion) {
  const commitMessage = `Upgrade dependency ${depName} to version ${nextVersion}`;
  // Try to create branch
  const body = {
    ref: `refs/heads/${branchName}`,
    sha: masterSHA
  };
  ghGot.post(`repos/${repoName}/git/refs`, {
    token: token,
    body: body
  }).catch(error => {
    if (error.response.body.message !== 'Reference already exists') {
      console.log('Error creating branch' + branchName);
      console.log(error.response.body);
    }
  }).then(res => {
    ghGot(`repos/${repoName}/contents/${packageFile}?ref=${branchName}`, { token: token })
    .then(res => {
      const oldFileSHA = res.body.sha;
      let branchPackageJson = JSON.parse(new Buffer(res.body.content, 'base64').toString());
      if (branchPackageJson[depType][depName] !== nextVersion) {
        // Branch is new, or needs version updated
        console.log(`Dependency ${depName} needs upgrading to ${nextVersion}`);
        branchPackageJson[depType][depName] = nextVersion;
        branchPackageString = JSON.stringify(branchPackageJson, null, 2) + '\n';

        ghGot.put(`repos/${repoName}/contents/${packageFile}`, {
          token: token,
          body: {
            branch: branchName,
            sha: oldFileSHA,
            message: commitMessage,
            content: new Buffer(branchPackageString).toString('base64')
          }
        }).then(res => {
          return createOrUpdatePullRequest(branchName, prName);
        });
      }
    });
  })
  .catch(error => {
    console.log('Promise catch');
  });
}

function createOrUpdatePullRequest(branchName, title) {
  return ghGot.post(`repos/${repoName}/pulls`, {
    token: token,
    body: {
      title: title,
      head: branchName,
      base: 'master',
      body: ''
    }
  }).then(res => {
    console.log('Created Pull Request: ' + title);
  }).catch(error => {
    if (error.response.body.errors[0].message.indexOf('A pull request already exists') === 0) {
      // Pull Request already exists
      // Now we need to find the Pull Request number
      return ghGot(`repos/${repoName}/pulls?base=master&head=${userName}:${branchName}`, {
        token: token,
      }).then(res => {
        // TODO iterate through list and confirm branch
        if (res.body.length !== 1) {
          console.error('Could not find matching PR');
          return;
        }
        const existingPrNo = res.body[0].number;
        return ghGot.patch(`repos/${repoName}/pulls/${existingPrNo}`, {
          token: token,
          body: {
            title: title
          }
        }).then(res => {
          console.log('Updated Pull Request: ' + title);
        });
      });
    } else {
      console.log('Error creating Pull Request:');
      console.log(error.response.body);
      Promise.reject();
    }
  });
}
<commit_msg>Add description to Pull Request<commit_after>const ghGot = require('gh-got');
const got = require('got');
const semver = require('semver');
const stable = require('semver-stable');

const token = process.env.RENOVATE_TOKEN;
const repoName = process.argv[2];
const userName = repoName.split('/')[0];
const packageFile = process.argv[3] || 'package.json';

let masterSHA;
let masterPackageJson;

ghGot(`repos/${repoName}/git/refs/head`, {token: token}).then(res => {
  // First, get the SHA for master branch
  res.body.forEach(function(branch) {
    // Loop through all branches because master may not be the first
    if (branch.ref === 'refs/heads/master') {
      // This is the SHA we will create new branches from
      masterSHA = branch.object.sha;
    }
  });
  // Now, retrieve the master package.json
  ghGot(`repos/${repoName}/contents/${packageFile}`, {token: token}).then(res => {
    masterPackageJson = JSON.parse(new Buffer(res.body.content, 'base64').toString());
    // Iterate through dependencies and then devDependencies
    return iterateDependencies('dependencies')
      .then(() => iterateDependencies('devDependencies'));
  }).catch(err => {
    console.log('Error reading master package.json');
  });
});

function iterateDependencies(depType) {
  const deps = masterPackageJson[depType];
  if (!deps) {
    return;
  }
  return Object.keys(deps).reduce((total, depName) => {
    return total.then(() => {
      const currentVersion = deps[depName].replace(/[^\d.]/g, '');

      if (!semver.valid(currentVersion)) {
        console.log('Invalid current version');
        return;
      }

      // supports scoped packages, e.g. @user/package
      return got(`https://registry.npmjs.org/${depName.replace('/', '%2F')}`, { json: true })
        .then(res => {
          let allUpgrades = {};
          Object.keys(res.body['versions']).forEach(function(version) {
            if (stable.is(currentVersion) && !stable.is(version)) {
              return;
            }
            if (semver.gt(version, currentVersion)) {
              var thisMajor = semver.major(version);
              if (!allUpgrades[thisMajor] || semver.gt(version, allUpgrades[thisMajor])) {
                allUpgrades[thisMajor] = version;
              }
            }
          });

          let upgradePromises = [];

          Object.keys(allUpgrades).forEach(function(upgrade) {
            const nextVersion = allUpgrades[upgrade];
            upgradePromises.push(updateDependency(depType, depName, currentVersion, nextVersion));
          });

          return Promise.all(upgradePromises);
        });
    });
  }, Promise.resolve());
}

function updateDependency(depType, depName, currentVersion, nextVersion) {
  const nextVersionMajor = semver.major(nextVersion);
  const branchName = `upgrade/${depName}-${nextVersionMajor}.x`;
  let prName = '';
  if (nextVersionMajor > semver.major(currentVersion)) {
    prName = `Upgrade dependency ${depName} to version ${nextVersionMajor}.x`;
    // Check if PR was already closed previously
    ghGot(`repos/${repoName}/pulls?state=closed&head=${userName}:${branchName}`, { token: token })
      .then(res => {
        if (res.body.length > 0) {
          console.log(`Dependency ${depName} upgrade to ${nextVersionMajor}.x PR already existed, so skipping`);
        } else {
          writeUpdates(depType, depName, branchName, prName, currentVersion, nextVersion);
        }
      });
  } else {
    prName = `Upgrade dependency ${depName} to version ${nextVersion}`;
    writeUpdates(depType, depName, branchName, prName, currentVersion, nextVersion);
  }
}

function writeUpdates(depType, depName, branchName, prName, currentVersion, nextVersion) {
  const commitMessage = `Upgrade dependency ${depName} to version ${nextVersion}`;
  const prBody = `This Pull Request updates dependency ${depName} from version ${currentVersion} to ${nextVersion}.`;
  // Try to create branch
  const body = {
    ref: `refs/heads/${branchName}`,
    sha: masterSHA
  };
  ghGot.post(`repos/${repoName}/git/refs`, {
    token: token,
    body: body
  }).catch(error => {
    if (error.response.body.message !== 'Reference already exists') {
      console.log('Error creating branch' + branchName);
      console.log(error.response.body);
    }
  }).then(res => {
    ghGot(`repos/${repoName}/contents/${packageFile}?ref=${branchName}`, { token: token })
    .then(res => {
      const oldFileSHA = res.body.sha;
      let branchPackageJson = JSON.parse(new Buffer(res.body.content, 'base64').toString());
      if (branchPackageJson[depType][depName] !== nextVersion) {
        // Branch is new, or needs version updated
        console.log(`Dependency ${depName} needs upgrading to ${nextVersion}`);
        branchPackageJson[depType][depName] = nextVersion;
        branchPackageString = JSON.stringify(branchPackageJson, null, 2) + '\n';

        ghGot.put(`repos/${repoName}/contents/${packageFile}`, {
          token: token,
          body: {
            branch: branchName,
            sha: oldFileSHA,
            message: commitMessage,
            content: new Buffer(branchPackageString).toString('base64')
          }
        }).then(res => {
          return createOrUpdatePullRequest(branchName, prName, prBody);
        });
      }
    });
  })
  .catch(error => {
    console.log('Promise catch');
  });
}

function createOrUpdatePullRequest(branchName, title, body) {
  return ghGot.post(`repos/${repoName}/pulls`, {
    token: token,
    body: {
      title: title,
      head: branchName,
      base: 'master',
      body: body,
    }
  }).then(res => {
    console.log('Created Pull Request: ' + title);
  }).catch(error => {
    if (error.response.body.errors[0].message.indexOf('A pull request already exists') === 0) {
      // Pull Request already exists
      // Now we need to find the Pull Request number
      return ghGot(`repos/${repoName}/pulls?base=master&head=${userName}:${branchName}`, {
        token: token,
      }).then(res => {
        // TODO iterate through list and confirm branch
        if (res.body.length !== 1) {
          console.error('Could not find matching PR');
          return;
        }
        const existingPrNo = res.body[0].number;
        return ghGot.patch(`repos/${repoName}/pulls/${existingPrNo}`, {
          token: token,
          body: {
            title: title,
            body: body,
          }
        }).then(res => {
          console.log('Updated Pull Request: ' + title);
        });
      });
    } else {
      console.log('Error creating Pull Request:');
      console.log(error.response.body);
      Promise.reject();
    }
  });
}
<|endoftext|>


<commit_before>var cadence = require('cadence')
var typer = require('media-typer')
var errorify = require('./errorify')
var Signal = require('signal')
var coalesce = require('extant')
var logger = require('prolific.logger').createLogger('vizsla')
var stream = require('stream')

function Transport () {
}

Transport.prototype.descend = cadence(function (async, descent) {
    var request = descent.request()
    var sent = {
        url: request.url,
        options: request.options,
        body: request.payload,
        when: Date.now(),
        duration: null
    }
    var timeout = null, status = 'requesting', errors = 0, $response = null, caught = false
    var signal = new Signal, wait = null
    var client = request.http.request(request.options)
    async([function () {
        async(function () {
            var xxx = new Signal
            function responded (response) {
                xxx.unlatch(null, response)
            }
            function errored (error) {
                xxx.unlatch(error)
            }
            client.addListener('error', errored)
            client.addListener('response', responded)
            xxx.wait(function () {
                client.removeListener('error', errored)
                client.removeListener('response', responded)
            })
            xxx.wait(async())
            descent.cancel.wait(function () {
                client.abort()
                signal.unlatch('ECONNABORTED', 'aborted')
            })
            if (request.timeout != null) {
                timeout = setTimeout(function () {
                    timeout = null
                    client.abort()
                    signal.unlatch('ETIMEDOUT', 'timedout')
                }, request.timeout)
            }
            wait = signal.wait(function (code, newStatus) {
                // The abort is going to close the socket. If we are waiting on
                // a response there is going to be an error. Otherwise, there is
                // going to be an `"aborted"` message on the response.
                client.once('error', function () { caught = true })
                descent.input.unpipe()
                descent.input.resume()
                xxx.unlatch(code)
                status = newStatus
            })
            // TODO Make this terminate correctly and pipe up a stream
            // correctly.
            if ('payload' in request) {
                client.end(request.payload)
            } else {
                descent.input.pipe(client)
            }
        }, function (response) {
            signal.cancel(wait)
            status = 'responded'
            $response = response
            client.once('error', function (error) {
                signal.notify(error, 'errored')
            })
            signal.wait(function (code, newStatus) {
            //    status = newStatus
                $response.unpipe()
                $response.resume()
                if (typeof code == 'string') {
                    var error = new Error('vizsla#cancel')
                    error.code = code
                    body.emit('error', error)
                } else {
                    body.emit('error', code)
                }
            })
            $response.once('end', function () {
                $response.unpipe()
                $response.resume()
                response.trailers = $response.trailers
            })
            $response.once('aborted', function () {
                signal.notify('ECONNABORTED', 'aborted')
            })
            var statusCodeClass = Math.floor($response.statusCode / 100)
            response = {
                okay: statusCodeClass == 2,
                statusCode: $response.statusCode,
                statusCodeClass: statusCodeClass,
                statusMessage: $response.statusMessage,
                headers: JSON.parse(JSON.stringify($response.headers)),
                rawHeaders: JSON.parse(JSON.stringify(response.rawHeaders)),
                trailers: null,
                type: typer.parse(coalesce(response.headers['content-type'], 'application/octet-stream'))
            }
            var body = new stream.PassThrough
            $response.pipe(body)
            return [ body, response ]
        })
    }, function (error) {
        signal.cancel(wait)
        var statusCode = typeof error == 'string' ? 504 : 503
        var code = typeof error == 'string' ? error : coalesce(error.code, 'EIO')
        return errorify(statusCode, { 'x-vizsla-errno': code })
    }], function (body, response) {
        // TODO Come back and test this when you've created a Prolific Test library.
        client.on('error', function (error) {
            switch (status) {
            case 'timedout':
            case 'aborted':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            case 'requesting':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            case 'responded':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            }
        })
        if (timeout) {
            clearTimeout(timeout)
        }
        return [ body, response ]
    })
})

module.exports = Transport
<commit_msg>Notes on truncation.<commit_after>var cadence = require('cadence')
var typer = require('media-typer')
var errorify = require('./errorify')
var Signal = require('signal')
var coalesce = require('extant')
var logger = require('prolific.logger').createLogger('vizsla')
var stream = require('stream')

function Transport () {
}

Transport.prototype.descend = cadence(function (async, descent) {
    var request = descent.request()
    var sent = {
        url: request.url,
        options: request.options,
        body: request.payload,
        when: Date.now(),
        duration: null
    }
    var timeout = null, status = 'requesting', errors = 0, $response = null, caught = false
    var signal = new Signal, wait = null
    var client = request.http.request(request.options)
    async([function () {
        async(function () {
            var xxx = new Signal
            function responded (response) {
                xxx.unlatch(null, response)
            }
            function errored (error) {
                xxx.unlatch(error)
            }
            client.addListener('error', errored)
            client.addListener('response', responded)
            xxx.wait(function () {
                client.removeListener('error', errored)
                client.removeListener('response', responded)
            })
            xxx.wait(async())
            descent.cancel.wait(function () {
                client.abort()
                signal.unlatch('ECONNABORTED', 'aborted')
            })
            if (request.timeout != null) {
                timeout = setTimeout(function () {
                    timeout = null
                    client.abort()
                    signal.unlatch('ETIMEDOUT', 'timedout')
                }, request.timeout)
            }
            wait = signal.wait(function (code, newStatus) {
                // The abort is going to close the socket. If we are waiting on
                // a response there is going to be an error. Otherwise, there is
                // going to be an `"aborted"` message on the response.
                client.once('error', function () { caught = true })
                descent.input.unpipe()
                descent.input.resume()
                xxx.unlatch(code)
                status = newStatus
            })
            // TODO Make this terminate correctly and pipe up a stream
            // correctly.
            if ('payload' in request) {
                client.end(request.payload)
            } else {
                descent.input.pipe(client)
            }
        }, function (response) {
            signal.cancel(wait)
            status = 'responded'
            $response = response
            client.once('error', function (error) {
                signal.notify(error, 'errored')
            })
            // TODO Likely that the only proper response once the first response
            // is done is to truncate. It is my believe that streams are bound
            // to truncate sooner or later and that all applications should have
            // a strategy for when they do truncate. Rather than raise an error
            // here, simply terminate the stream. Whatever is handling the
            // stream then handles it as if it where a truncation. If it is
            // important that it was as a result of a cancel then maybe cancel
            // your read explicitly before you cancel the http request.
            signal.wait(function (code, newStatus) {
            //    status = newStatus
                $response.unpipe()
                $response.resume()
                if (typeof code == 'string') {
                    var error = new Error('vizsla#cancel')
                    error.code = code
                    body.emit('error', error)
                } else {
                    body.emit('error', code)
                }
            })
            $response.once('end', function () {
                $response.unpipe()
                $response.resume()
                response.trailers = $response.trailers
            })
            $response.once('aborted', function () {
                signal.notify('ECONNABORTED', 'aborted')
            })
            var statusCodeClass = Math.floor($response.statusCode / 100)
            response = {
                okay: statusCodeClass == 2,
                statusCode: $response.statusCode,
                statusCodeClass: statusCodeClass,
                statusMessage: $response.statusMessage,
                headers: JSON.parse(JSON.stringify($response.headers)),
                rawHeaders: JSON.parse(JSON.stringify(response.rawHeaders)),
                trailers: null,
                type: typer.parse(coalesce(response.headers['content-type'], 'application/octet-stream'))
            }
            var body = new stream.PassThrough
            $response.pipe(body)
            return [ body, response ]
        })
    }, function (error) {
        signal.cancel(wait)
        var statusCode = typeof error == 'string' ? 504 : 503
        var code = typeof error == 'string' ? error : coalesce(error.code, 'EIO')
        return errorify(statusCode, { 'x-vizsla-errno': code })
    }], function (body, response) {
        // TODO Come back and test this when you've created a Prolific Test library.
        client.on('error', function (error) {
            switch (status) {
            case 'timedout':
            case 'aborted':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            case 'requesting':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            case 'responded':
                logger.error(status, { errors: ++errors, stack: error.stack, $options: request.options })
                break
            }
        })
        if (timeout) {
            clearTimeout(timeout)
        }
        return [ body, response ]
    })
})

module.exports = Transport
<|endoftext|>


<commit_before>$(document).ready(function(){

    	 $.tzPOST("getUserinfo",null,function(data){
    		    var r=eval( "(" + data + ")" );
    		    var arr=[];
    		    if(r.userinfo){
    		    	arr=['
'];
    		    	for(var i=0;i < r.userinfo.length;i++){
    		    		var info='
'+r.userinfo[i].fullName+'
';
    		    		arr.push(info);
    		    		}
    		    	arr.push('');
    		    }

    		    $("ul#patientlist_ul").replaceWith(arr.join(''));

	});
    	 $("#patientinfo1").live('click',function(){
    		 $("#basicinfo_email").replaceWith('');
    	 });
});

$.tzPOST = function(action,data,callback){
	$.post('http://localhost:8080/Health_managment/Action?action='+action,data,callback,'text');
}

$.tzGET = function(action,data,callback){
	$.get('php/ajax.php?action='+action,data,callback,'text');
}
<commit_msg>show userinfo and appointmentinfo<commit_after>$(document).ready(function(){

    	 $.tzPOST("getUserinfo",null,function(data){
    		    var r=eval( "(" + data + ")" );
    		    var arr=[];
    		    if(r.userinfo){
    		    	arr=['
'];
    		    	for(var i=0;i < r.userinfo.length;i++){
    		    		var info='
'+r.userinfo[i].fullName+'
';
    		    		arr.push(info);
    		    		}
    		    	arr.push('
');
    		    }
    		    $("ul#patientlist_ul").replaceWith(arr.join(''));

	});
    	 $("[href='#patientinfo']").live('click',function(){
    		 var num=$(this).attr("name");
    		 $.tzPOST("getUserinfo",null,function(data){
    	     var r=eval( "(" + data + ")" );
    	     $("#patientinfo_title").replaceWith('
'+r.userinfo[num].fullName+'
');
    		 $("#basicinfo_email").replaceWith(''+r.userinfo[num].emailaddress+'');
    		 $("#basicinfo_birthday").replaceWith(''+r.userinfo[num].birthDate+'');
    		 $("#basicinfo_gender").replaceWith(''+r.userinfo[num].gender+'');
    		 $("#basicinfo_marital").replaceWith(''+r.userinfo[num].married+'');
    		 $("div#allergies").replaceWith('
'+r.userinfo[num].allergies+'
');
    		 });
    		 $.tzPOST("getRecordinfo",null,function(data){
    			var r=eval( "(" + data + ")" );
     		    var arr=[];
     		   if(r.recordinfo){
   		    	arr=['
'];
   		    	for(var i=0;i < r.recordinfo.length;i++){
   		    		var info='
'+r.recordinfo[i].date+'
';
   		    		arr.push(info);
   		    		}
   		    	arr.push('
');
   		    }
   		    $("ul#patientinfo_records_ul").replaceWith(arr.join(''));
        		 });
    	 });

    	 $("[href='#record']").live('click',function(){
    		 var num=$(this).attr("name");
    		 $.tzPOST("getRecordinfo",null,function(data){
    	     var r=eval( "(" + data + ")" );
    	     $("#record_doctor").replaceWith('
'+r.recordinfo[num].doctor+'
');
    	     $("#record_symptom").replaceWith('
'+r.recordinfo[num].symptom+'
');
    	     $("#record_diagnosis").replaceWith('
'+r.recordinfo[num].diagnosis+'
');
    	     $("#record_treatment").replaceWith('
'+r.recordinfo[num].treatment+'
');
    	    // $("#record_remark").replaceWith('
'+r.recordinfo[num].remark+'
');

    		 });
    	 });

    	 $("[href='#appointments']").live('click',function(){
    		 $.tzPOST("getAppointmentinfo",null,function(data){
    	     var r=eval( "(" + data + ")" );
     		    var arr=[];
     		   if(r.appointmentinfo){
   		    	arr=['
'];
   		    	for(var i=0;i < r.appointmentinfo.length;i++){
   		    		var info='
'+r.appointmentinfo[i].endtime+'
';
   		    		arr.push(info);
   		    		}
   		    	arr.push('
');
   		    }
   		    $("ul#appointments_ul").replaceWith(arr.join(''));
        		 });
    	 });

    	 $("[href='#appointment']").live('click',function(){
    		 var num=$(this).attr("name");
    		 $.tzPOST("getAppointmentinfo",null,function(data){
    	     var r=eval( "(" + data + ")" );
    	     $("#appointment_doctor_name").val("'"+r.appointmentinfo[num].doctor+"'");
    	     $("#appointment_start").val("'"+r.appointmentinfo[num].begintime+"'");
    	     $("#appointment_end").val("'"+r.appointmentinfo[num].endtime+"'");
    		 });
    	 });
});

$.tzPOST = function(action,data,callback){
	$.post('http://localhost:8080/Health_managment/Action?action='+action,data,callback,'text');
}

$.tzGET = function(action,data,callback){
	$.get('php/ajax.php?action='+action,data,callback,'text');
}
<|endoftext|>


<commit_before>'use strict';

var SERVER_PORT = 9000;

// # Globbing

module.exports = function (grunt) {
  // show elapsed time at the end
  require('time-grunt')(grunt);
  // load all grunt tasks
  require('load-grunt-tasks')(grunt);

  // configurable paths
  var yeomanConfig = {
    app: 'app',
    dist: 'dist',
    originalScriptTag: '<script src="scripts/main.js"></script>',
    tmpScriptTag: '<script src="scripts/.build.js"></script>'
  };

  grunt.initConfig({
    yeoman: yeomanConfig,
    pkg: grunt.file.readJSON('bower.json'),
    banner: '/* <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n',

    clean: {
      dev: ['.sass-cache', '.tmp', '<%= yeoman.app %>/.css'],
      dist: ['.sass-cache', '.tmp', '<%= yeoman.app %>/.css',
             '<%= yeoman.dist %>/scripts', '<%= yeoman.dist %>/styles', '<%= yeoman.dist %>/vendor'],
      tmpBuild: ['<%= yeoman.app %>/scripts/.build.js']
    },

    compass: {
      compile: {
        options: {
          cssDir: '<%= yeoman.app %>/.css',
          sassDir: '<%= yeoman.app %>/styles',
          javascriptsDir: '<%= yeoman.app %>/scripts',
          imagesDir: '<%= yeoman.app %>/images',
          noLineComments: true,
          relativeAssets: true,
          raw: 'preferred_syntax = :scss\n'
        }
      }
    },

    handlebars: {
      compile: {
        options: {
          namespace: 'JST',
          amd: true
        },
        files: {
          '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.hbs']
        }
      }
    },

    bower: {
      all: {
        rjsConfig: '<%= yeoman.app %>/scripts/main.js',
        options: {
          exclude: ['jquery', 'modernizr', 'requirejs']
        }
      }
    },

    requirejs: {
      dist: {
        options: {
          baseUrl: '<%= yeoman.app %>/scripts',
          mainConfigFile: "<%= yeoman.app %>/scripts/main.js",
          name: 'main',
          optimize: 'none',
          out: "<%= yeoman.app %>/scripts/.build.js",

          paths: {
            'templates': '.tmp/scripts/templates'
          },

          almond: false,
          preserveLicenseComments: false
        }
      }
    },

    watch: {
      options: {
        spawn: false
      },
      css: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.scss'],
        tasks: ['compass']
      },
      handlebars: {
        files: [
          '<%= yeoman.app %>/scripts/templates/*.hbs'
        ],
        tasks: ['handlebars']
      }
    },

    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>'
      }
    },

    cssmin: {
      options: {
        banner: '<%= banner %>'
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,svg}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>',
          src: '*.html',
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    rev: {
      dist: {
        files: {
          src: [
            '<%= yeoman.dist %>/scripts/{,*/}*.js',
            '<%= yeoman.dist %>/styles/{,*/}*.css',
            '<%= yeoman.dist %>/vendor/{,*/}*.js',
          ]
        }
      }
    },

    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      options: {
        dirs: ['<%= yeoman.dist %>']
      }
    },

    copy: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>',
          src: [
            '*.{ico,png}',
            'audio/{,*/}*.*'
          ],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    connect: {
      options: {
        protocol: 'https',
        port: grunt.option('port') || SERVER_PORT,
        open: true,
        // change this to '0.0.0.0' to access the server from outside
        hostname: '192.168.1.106'
      },
      dev: {
        options: {
          base: [
            '.tmp',
            '<%= yeoman.app %>'
          ]
        }
      },
      dist: {
        options: {
          protocol: 'https',
          base: '<%= yeoman.dist %>'
        }
      }
    },

    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= yeoman.app %>/scripts/{,*/}*.js',
        '!<%= yeoman.app %>/vendor/*'
      ]
    }
  });

  grunt.registerTask('createDefaultTemplate', function () {
    grunt.file.write('.tmp/scripts/templates.js', 'this.JST = this.JST || {};');
  });

  grunt.registerTask('createTmpScriptTag', function (rollBack) {
    var path = yeomanConfig.app + '/index.html';
    var indexFile = grunt.file.read(path);
    if (typeof rollBack === 'undefined') {
      grunt.file.write(path, indexFile.replace(yeomanConfig.originalScriptTag, yeomanConfig.tmpScriptTag));
    } else {
      grunt.file.write(path, indexFile.replace(yeomanConfig.tmpScriptTag, yeomanConfig.originalScriptTag));
      grunt.task.run(['clean:tmpBuild']);
    }
  });

  grunt.registerTask('server', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve' + (target ? ':' + target : '')]);
  });

  grunt.registerTask('serve', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:dev',
      'compass',
      'createDefaultTemplate',
      'handlebars',
      'connect:dev',
      'watch'
    ]);
  });

  grunt.registerTask('build', [
    'jshint',
    'clean:dist',
    'compass',
    'createDefaultTemplate',
    'handlebars',
    'requirejs',
    'createTmpScriptTag',
    'useminPrepare',
    'concat',
    'cssmin',
    'uglify',
    'newer:imagemin',
    'htmlmin',
    'rev',
    'usemin',
    'newer:copy',
    'createTmpScriptTag:rollBack'
  ]);

  grunt.registerTask('default', ['build']);

};<commit_msg>localhost for grunt config<commit_after>'use strict';

var SERVER_PORT = 9000;

// # Globbing

module.exports = function (grunt) {
  // show elapsed time at the end
  require('time-grunt')(grunt);
  // load all grunt tasks
  require('load-grunt-tasks')(grunt);

  // configurable paths
  var yeomanConfig = {
    app: 'app',
    dist: 'dist',
    originalScriptTag: '<script src="scripts/main.js"></script>',
    tmpScriptTag: '<script src="scripts/.build.js"></script>'
  };

  grunt.initConfig({
    yeoman: yeomanConfig,
    pkg: grunt.file.readJSON('bower.json'),
    banner: '/* <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> */\n',

    clean: {
      dev: ['.sass-cache', '.tmp', '<%= yeoman.app %>/.css'],
      dist: ['.sass-cache', '.tmp', '<%= yeoman.app %>/.css',
             '<%= yeoman.dist %>/scripts', '<%= yeoman.dist %>/styles', '<%= yeoman.dist %>/vendor'],
      tmpBuild: ['<%= yeoman.app %>/scripts/.build.js']
    },

    compass: {
      compile: {
        options: {
          cssDir: '<%= yeoman.app %>/.css',
          sassDir: '<%= yeoman.app %>/styles',
          javascriptsDir: '<%= yeoman.app %>/scripts',
          imagesDir: '<%= yeoman.app %>/images',
          noLineComments: true,
          relativeAssets: true,
          raw: 'preferred_syntax = :scss\n'
        }
      }
    },

    handlebars: {
      compile: {
        options: {
          namespace: 'JST',
          amd: true
        },
        files: {
          '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.hbs']
        }
      }
    },

    bower: {
      all: {
        rjsConfig: '<%= yeoman.app %>/scripts/main.js',
        options: {
          exclude: ['jquery', 'modernizr', 'requirejs']
        }
      }
    },

    requirejs: {
      dist: {
        options: {
          baseUrl: '<%= yeoman.app %>/scripts',
          mainConfigFile: "<%= yeoman.app %>/scripts/main.js",
          name: 'main',
          optimize: 'none',
          out: "<%= yeoman.app %>/scripts/.build.js",

          paths: {
            'templates': '.tmp/scripts/templates'
          },

          almond: false,
          preserveLicenseComments: false
        }
      }
    },

    watch: {
      options: {
        spawn: false
      },
      css: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.scss'],
        tasks: ['compass']
      },
      handlebars: {
        files: [
          '<%= yeoman.app %>/scripts/templates/*.hbs'
        ],
        tasks: ['handlebars']
      }
    },

    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>'
      }
    },

    cssmin: {
      options: {
        banner: '<%= banner %>'
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      }
    },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,svg}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>',
          src: '*.html',
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    rev: {
      dist: {
        files: {
          src: [
            '<%= yeoman.dist %>/scripts/{,*/}*.js',
            '<%= yeoman.dist %>/styles/{,*/}*.css',
            '<%= yeoman.dist %>/vendor/{,*/}*.js',
          ]
        }
      }
    },

    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      options: {
        dirs: ['<%= yeoman.dist %>']
      }
    },

    copy: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>',
          src: [
            '*.{ico,png}',
            'audio/{,*/}*.*'
          ],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    connect: {
      options: {
        protocol: 'https',
        port: grunt.option('port') || SERVER_PORT,
        open: true,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
      },
      dev: {
        options: {
          base: [
            '.tmp',
            '<%= yeoman.app %>'
          ]
        }
      },
      dist: {
        options: {
          protocol: 'https',
          base: '<%= yeoman.dist %>'
        }
      }
    },

    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: [
        'Gruntfile.js',
        '<%= yeoman.app %>/scripts/{,*/}*.js',
        '!<%= yeoman.app %>/vendor/*'
      ]
    }
  });

  grunt.registerTask('createDefaultTemplate', function () {
    grunt.file.write('.tmp/scripts/templates.js', 'this.JST = this.JST || {};');
  });

  grunt.registerTask('createTmpScriptTag', function (rollBack) {
    var path = yeomanConfig.app + '/index.html';
    var indexFile = grunt.file.read(path);
    if (typeof rollBack === 'undefined') {
      grunt.file.write(path, indexFile.replace(yeomanConfig.originalScriptTag, yeomanConfig.tmpScriptTag));
    } else {
      grunt.file.write(path, indexFile.replace(yeomanConfig.tmpScriptTag, yeomanConfig.originalScriptTag));
      grunt.task.run(['clean:tmpBuild']);
    }
  });

  grunt.registerTask('server', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve' + (target ? ':' + target : '')]);
  });

  grunt.registerTask('serve', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:dev',
      'compass',
      'createDefaultTemplate',
      'handlebars',
      'connect:dev',
      'watch'
    ]);
  });

  grunt.registerTask('build', [
    'jshint',
    'clean:dist',
    'compass',
    'createDefaultTemplate',
    'handlebars',
    'requirejs',
    'createTmpScriptTag',
    'useminPrepare',
    'concat',
    'cssmin',
    'uglify',
    'newer:imagemin',
    'htmlmin',
    'rev',
    'usemin',
    'newer:copy',
    'createTmpScriptTag:rollBack'
  ]);

  grunt.registerTask('default', ['build']);

};<|endoftext|>


<commit_before>"use strict";
/**
 * @module   FM.playlist.PlaylistCtrl
 * @author   SOON_
 * @requires FM.api.TracksResource
 * @requires FM.api.UsersResource
 * @requires FFM.api.PlayerQueueResource
 * @requires ngRoute
 */
angular.module("FM.playlist.PlaylistCtrl", [
    "FM.api.TracksResource",
    "FM.api.UsersResource",
    "FM.api.PlayerQueueResource",
    "FM.api.PaginationInterceptor",
    "FM.player.removeLeadingZeros",
    "ngRoute",
    "config"
])
/**
 * @method config
 * @param  {Provider} $routeProvider
 */
.config([
    "$routeProvider",
    function ($routeProvider) {

        $routeProvider
            .when("/", {
                templateUrl: "partials/playlist.html",
                controller: "PlaylistCtrl",
                resolve: {
                    playlistData: ["PlayerQueueResource", "$route", function (PlayerQueueResource, $route){
                        return PlayerQueueResource.query($route.current.params).$promise;
                    }],
                    playlistMeta: ["PlayerQueueResource", function (PlayerQueueResource){
                        return PlayerQueueResource.meta().$promise;
                    }],
                }
            });

    }
])
/**
 * @constructor
 * @class PlaylistCtrl
 * @param {Object}  $scope
 * @param {Service} $q
 * @param {Factory} TracksResource
 * @param {Factory} UsersResource
 * @param {Factory} PlayerQueueResource
 * @param {Array}   playlistData
 * @param {Object}  playlistMeta
 */
.controller("PlaylistCtrl", [
    "$scope",
    "$q",
    "TracksResource",
    "UsersResource",
    "PlayerQueueResource",
    "playlistData",
    "playlistMeta",
    "env",
    function ($scope, $q, TracksResource, UsersResource, PlayerQueueResource, playlistData, playlistMeta, env) {

        /**
         * @property playlist
         * @type {Array}
         */
        $scope.playlist = playlistData.items;

        /**
         * @property meta
         * @type {Object}
         */
        $scope.meta = playlistMeta;

        /**
         * Paging properties
         * @property {Object} page
         */
        $scope.page = {
            loading: false,
            pages: 1,
            total: playlistData.meta.totalPages
        };

        /**
         * Update `playlist` with queue data from the API
         * @method refreshPlaylist
         */
        $scope.refreshPlaylist = function refreshPlaylist(){
            PlayerQueueResource.query().$promise
                .then(function (response){
                    $scope.playlist = response.items;
                    $scope.page.total = response.meta.totalPages;
                    $scope.page.pages = 1;
                });

            PlayerQueueResource.meta().$promise
                .then(function (response){
                    $scope.meta = response;
                });
        };

        /**
         * Load more tracks from playlist
         * @method loadMore
         */
        $scope.loadMore = function loadMore() {

            $scope.page.loading = true;
            $scope.page.pages++;

            PlayerQueueResource.query({ page: $scope.page.pages }).$promise
                .then(function (response){
                    $scope.playlist = $scope.playlist.concat(response.items);

                    $scope.page.loading = false;
                    $scope.page.total = response.meta.totalPages ? response.meta.totalPages : 1;
                });
        };

        /**
         * On play event, set playback state variables
         * refresh playlist if song URI doesn't match the playlist
         * @method onPlay
         */
        $scope.onPlay = function onPlay() {
            $scope.refreshPlaylist();
        };

        /**
         * On end event, remove track from playlist
         * refresh playlist if song URI doesn't match the playlist
         * @method onEnd
         */
        $scope.onEnd = function onEnd(event, data) {
            if (($scope.playlist[0].track.uri === data.uri) && ($scope.page.pages === $scope.page.total)) { // jshint ignore:line
                $scope.meta.total--;
                $scope.meta.play_time = $scope.meta.play_time - $scope.playlist[0].track.duration; // jshint ignore:line
                $scope.playlist.splice(0, 1);
            } else {
                $scope.refreshPlaylist();
            }
        };

        /**
         * On add event, get track data and push to playlist
         * @method onAdd
         */
        $scope.onAdd = function onAdd(event, data) {

            $q.all([
                TracksResource.get({ id: data.uri }).$promise,
                UsersResource.get({ id: data.user }).$promise
            ]).then(function (response){
                var item = {
                    track: response[0],
                    user: response[1]
                };
                if ($scope.page.pages === $scope.page.total) {
                    $scope.playlist.push(item);
                } else if ( ($scope.meta.total + 1) > (env.SEARCH_LIMIT * $scope.page.total) ) {
                    $scope.page.total++;
                }
                $scope.meta.total++;
                $scope.meta.play_time = $scope.meta.play_time + response[0].duration; //jshint ignore:line
            });
        };

        /**
         * On delete event, remove track from playlist
         * refresh playlist if song URI doesn't match the playlist
         * @method onDeleted
         */
        $scope.onDeleted = function onDeleted(event, data) {
            angular.forEach($scope.playlist, function (track, $index){
                if (track.uuid === data.uuid){
                    $scope.meta.total--;
                    $scope.meta.play_time = $scope.meta.play_time - $scope.playlist[$index].track.duration; // jshint ignore:line
                    $scope.playlist.splice($index, 1);
                }
            });
        };

        $scope.$on("fm:player:play", $scope.onPlay);
        $scope.$on("fm:player:end", $scope.onEnd);
        $scope.$on("fm:player:add", $scope.onAdd);
        $scope.$on("fm:player:deleted", $scope.onDeleted);

    }

]);
<commit_msg>fix pagination data<commit_after>"use strict";
/**
 * @module   FM.playlist.PlaylistCtrl
 * @author   SOON_
 * @requires FM.api.TracksResource
 * @requires FM.api.UsersResource
 * @requires FFM.api.PlayerQueueResource
 * @requires ngRoute
 */
angular.module("FM.playlist.PlaylistCtrl", [
    "FM.api.TracksResource",
    "FM.api.UsersResource",
    "FM.api.PlayerQueueResource",
    "FM.api.PaginationInterceptor",
    "FM.player.removeLeadingZeros",
    "ngRoute",
    "config"
])
/**
 * @method config
 * @param  {Provider} $routeProvider
 */
.config([
    "$routeProvider",
    function ($routeProvider) {

        $routeProvider
            .when("/", {
                templateUrl: "partials/playlist.html",
                controller: "PlaylistCtrl",
                resolve: {
                    playlistData: ["PlayerQueueResource", "$route", function (PlayerQueueResource, $route){
                        return PlayerQueueResource.query($route.current.params).$promise;
                    }],
                    playlistMeta: ["PlayerQueueResource", function (PlayerQueueResource){
                        return PlayerQueueResource.meta().$promise;
                    }],
                }
            });

    }
])
/**
 * @constructor
 * @class PlaylistCtrl
 * @param {Object}  $scope
 * @param {Service} $q
 * @param {Factory} TracksResource
 * @param {Factory} UsersResource
 * @param {Factory} PlayerQueueResource
 * @param {Array}   playlistData
 * @param {Object}  playlistMeta
 */
.controller("PlaylistCtrl", [
    "$scope",
    "$q",
    "TracksResource",
    "UsersResource",
    "PlayerQueueResource",
    "playlistData",
    "playlistMeta",
    "env",
    function ($scope, $q, TracksResource, UsersResource, PlayerQueueResource, playlistData, playlistMeta, env) {

        /**
         * @property playlist
         * @type {Array}
         */
        $scope.playlist = playlistData.items;

        /**
         * @property meta
         * @type {Object}
         */
        $scope.meta = playlistMeta;

        /**
         * Paging properties
         * @property {Object} page
         */
        $scope.page = {
            loading: false,
            pages: 1,
            total: playlistData.meta.totalPages || 1
        };

        /**
         * Update `playlist` with queue data from the API
         * @method refreshPlaylist
         */
        $scope.refreshPlaylist = function refreshPlaylist(){
            PlayerQueueResource.query().$promise
                .then(function (response){
                    $scope.playlist = response.items;
                    $scope.page.total = response.meta.totalPages;
                    $scope.page.pages = 1;
                });

            PlayerQueueResource.meta().$promise
                .then(function (response){
                    $scope.meta = response;
                });
        };

        /**
         * Load more tracks from playlist
         * @method loadMore
         */
        $scope.loadMore = function loadMore() {

            $scope.page.loading = true;
            $scope.page.pages++;

            PlayerQueueResource.query({ page: $scope.page.pages }).$promise
                .then(function (response){
                    $scope.playlist = $scope.playlist.concat(response.items);

                    $scope.page.loading = false;
                    $scope.page.total = response.meta.totalPages ? response.meta.totalPages : 1;
                });
        };

        /**
         * On play event, set playback state variables
         * refresh playlist if song URI doesn't match the playlist
         * @method onPlay
         */
        $scope.onPlay = function onPlay() {
            $scope.refreshPlaylist();
        };

        /**
         * On end event, remove track from playlist
         * refresh playlist if song URI doesn't match the playlist
         * @method onEnd
         */
        $scope.onEnd = function onEnd(event, data) {
            if (($scope.playlist[0].track.uri === data.uri) && ($scope.page.pages === $scope.page.total)) { // jshint ignore:line
                $scope.meta.total--;
                $scope.meta.play_time = $scope.meta.play_time - $scope.playlist[0].track.duration; // jshint ignore:line
                $scope.playlist.splice(0, 1);
            } else {
                $scope.refreshPlaylist();
            }
        };

        /**
         * On add event, get track data and push to playlist
         * @method onAdd
         */
        $scope.onAdd = function onAdd(event, data) {

            $q.all([
                TracksResource.get({ id: data.uri }).$promise,
                UsersResource.get({ id: data.user }).$promise
            ]).then(function (response){
                var item = {
                    track: response[0],
                    user: response[1]
                };
                if ($scope.page.pages === $scope.page.total) {
                    $scope.playlist.push(item);
                } else if ( ($scope.meta.total + 1) > (env.SEARCH_LIMIT * $scope.page.total) ) {
                    $scope.page.total++;
                }
                $scope.meta.total++;
                $scope.meta.play_time = $scope.meta.play_time + response[0].duration; //jshint ignore:line
            });
        };

        /**
         * On delete event, remove track from playlist
         * refresh playlist if song URI doesn't match the playlist
         * @method onDeleted
         */
        $scope.onDeleted = function onDeleted(event, data) {
            angular.forEach($scope.playlist, function (track, $index){
                if (track.uuid === data.uuid){
                    $scope.meta.total--;
                    $scope.meta.play_time = $scope.meta.play_time - $scope.playlist[$index].track.duration; // jshint ignore:line
                    $scope.playlist.splice($index, 1);
                }
            });
        };

        $scope.$on("fm:player:play", $scope.onPlay);
        $scope.$on("fm:player:end", $scope.onEnd);
        $scope.$on("fm:player:add", $scope.onAdd);
        $scope.$on("fm:player:deleted", $scope.onDeleted);

    }

]);
<|endoftext|>