<commit_before>/* eslint eqeqeq: "off" */
import User from '../models/users';
import Api from '../services/api';
import ShareAnalyse from '../models/share-analyse';
import getCacheKey from './helper/cacheKey';
import {
  combineReposCommits
} from './helper/github';
import { is, sortBy } from '../utils/helper';

/* ================== private func ==================== */

const _getUser = async (ctx) => {
  const { login } = ctx.params;
  const user = await Api.getUser(login);
  if (!user) {
    return ctx.redirect('/404');
  }
  return user;
};

const _getRepositories = async (login, token) => {
  const repositories = await Api.getUserRepositories(login, token);
  const pinned = await User.findPinnedRepos(login);
  const checkPinned = repository =>
    pinned.some(item => item === repository.name);
  const pinnedRepos = pinned.length
    ? repositories.filter(repository => checkPinned(repository) || repository.fork)
    : repositories;

  pinnedRepos.sort(sortBy.star);
  return pinnedRepos;
};

const _getContributed = async (login, token) => {
  const repos = await Api.getUserContributed(login, token);
  repos.sort(sortBy.star);
  return repos;
};

const _getCommits = async (login, token) => {
  const commits = await Api.getUserCommits(login, token);
  const formatCommits = combineReposCommits(commits);
  commits.sort(sortBy.x('totalCommits', parseInt));

  return {
    commits,
    formatCommits,
  };
};

/* ================== router handler ================== */

const toggleShare = async (ctx) => {
  const { githubLogin } = ctx.session;
  const { enable } = ctx.request.body;
  await ShareAnalyse.changeShareStatus({
    enable,
    url: `github/${githubLogin}`
  });
  const message = Boolean(enable) == true
    ? 'messages.share.toggleOpen'
    : 'messages.share.toggleClose'
  ctx.body = {
    success: true,
    message: ctx.__(message)
  };
};

const fetchRepositories = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserRepositories(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch repos success'
  };
};

const fetchCommits = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserCommits(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch commits success'
  };
};

const fetchOrganizations = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserOrganizations(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch orgs success'
  };
};

const getAllRepositories = async (ctx, next) => {
  const { githubLogin, githubToken } = ctx.session;
  const repos = await Api.getUserRepositories(githubLogin, githubToken);
  const result = repos.filter(repository => !repository.fork)
    .map((repository) => {
      const {
        name,
        language,
        stargazers_count
      } = repository;
      return {
        name,
        language,
        stargazers_count,
      };
    });

  ctx.body = {
    result,
    success: true,
  };

  await next();
};

const getUserContributed = async (ctx, next) => {
  const repositories =
    await _getContributed(ctx.params.login, ctx.session.githubToken);
  ctx.body = {
    success: true,
    result: {
      repositories,
    }
  };
  await next();
};

const getUserRepositories = async (ctx, next) => {
  const repositories =
    await _getRepositories(ctx.params.login, ctx.session.githubToken);
  ctx.body = {
    success: true,
    result: {
      repositories,
    }
  };
  await next();
};

const getUserCommits = async (ctx, next) => {
  const {
    commits,
    formatCommits
  } = await _getCommits(ctx.params.login, ctx.session.githubToken);

  if (!commits.length) {
    ctx.query.shouldCache = false;
  }

  ctx.body = {
    success: true,
    result: {
      commits,
      formatCommits
    }
  };
  await next();
};

const getUserOrganizations = async (ctx, next) => {
  const { login } = ctx.params;
  const { githubToken } = ctx.session;
  const organizations =
    await Api.getUserOrganizations(login, githubToken);

  ctx.body = {
    success: true,
    result: { organizations }
  };
  await next();
};

const getUser = async (ctx, next) => {
  const { login } = ctx.params;
  const user = await _getUser(ctx);
  const shareAnalyse =
    await ShareAnalyse.findOne({ login, url: `github/${login}` });

  const result = Object.assign({}, user);
  result.openShare = shareAnalyse.enable;
  result.shareUrl = `github/${login}?locale=${ctx.session.locale}`;
  ctx.body = {
    success: true,
    result
  };
  await next();
};

const githubPage = async (ctx) => {
  const { login } = ctx.params;
  const { isMobile } = ctx.state;
  const { githubLogin } = ctx.session;
  const title = ctx.__('sharePage.github', user.name || user.login);

  if (isMobile) {
    const locale = ctx.__('language.id');
    await ctx.render('user/mobile/github', {
      title,
      locale,
      user: {
        login,
        isAdmin: login === githubLogin,
      },
      shareText: ctx.__('messages.share.mobileText'),
    });
  } else {
    await ctx.render('github/share', {
      title,
      user: {
        login,
        isAdmin: login === githubLogin
      },
      shareText: ctx.__('messages.share.text')
    });
  }
};

const getShareRecords = async (ctx) => {
  const { githubLogin } = ctx.session;
  const url = `github/${githubLogin}`;
  const shareAnalyse =
    await ShareAnalyse.findOne({ login: githubLogin, url });
  const {
    enable,
    pageViews,
    viewDevices,
    viewSources,
  } = shareAnalyse;
  ctx.body = {
    success: true,
    result: {
      pageViews,
      viewDevices,
      viewSources,
      openShare: enable,
      url: `${url}?locale=${ctx.session.locale}`,
    }
  };
};

const getUpdateTime = async (ctx) => {
  const { githubLogin } = ctx.session;
  const result = await Api.getUpdateTime(githubLogin);
  ctx.body = {
    result,
    success: true,
  };
};

const refreshRepositories = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  await Api.refreshUser(githubLogin, githubToken);
  const result = await Api.refreshRepositories(githubLogin, githubToken);
  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  await Api.refreshContributed(githubLogin, githubToken);

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-repositories', {
      session: ['githubLogin']
    }),
    cacheKey('user-contributed', {
      session: ['githubLogin']
    }),
    cacheKey('allRepositories', {
      session: ['githubLogin']
    }),
    cacheKey('user-github', {
      session: ['githubLogin']
    }),
    cacheKey('user-hotmap', {
      session: ['githubLogin', 'locale']
    }),
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateRepos'),
  };

  await next();
};

const refreshCommits = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  const result = await Api.refreshCommits(githubLogin, githubToken);

  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-commits', {
      session: ['githubLogin']
    })
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateCommits'),
  };

  await next();
};

const refreshOrganizations = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  const result = await Api.refreshOrganizations(githubLogin, githubToken);

  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-organizations', {
      session: ['githubLogin']
    })
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateOrgs'),
  };

  await next();
};

const getZen = async (ctx) => {
  const { githubToken } = ctx.session;
  const val = await Api.getZen(githubToken);
  const result = is.object(val) ? '' : val;
  ctx.body = {
    result,
    success: true,
  };
};

const getOctocat = async (ctx) => {
  const result = await Api.getOctocat();
  ctx.body = {
    result,
    success: true,
  };
};

const getUserHotmap = async (ctx, next) => {
  const { login } = ctx.params;
  const { locale } = ctx.session;
  const result = await Api.getHotmap(login, locale);
  ctx.body = {
    result,
    success: true,
  };
  await next();
};

export default {
  githubPage,
  fetchRepositories,
  fetchCommits,
  fetchOrganizations,
  getAllRepositories,
  // github info
  getUser,
  getUserRepositories,
  getUserContributed,
  getUserCommits,
  getUserOrganizations,
  toggleShare,
  getShareRecords,
  getUserHotmap,
  /* ===== refresh & update ====== */
  getUpdateTime,
  refreshRepositories,
  refreshOrganizations,
  refreshCommits,
  /* ========== */
  getZen,
  getOctocat,
};
<commit_msg>WHAT: A small fix<commit_after>/* eslint eqeqeq: "off" */
import User from '../models/users';
import Api from '../services/api';
import ShareAnalyse from '../models/share-analyse';
import getCacheKey from './helper/cacheKey';
import {
  combineReposCommits
} from './helper/github';
import { is, sortBy } from '../utils/helper';

/* ================== private func ==================== */

const _getUser = async (ctx) => {
  const { login } = ctx.params;
  const user = await Api.getUser(login);
  if (!user) {
    return ctx.redirect('/404');
  }
  return user;
};

const _getRepositories = async (login, token) => {
  const repositories = await Api.getUserRepositories(login, token);
  const pinned = await User.findPinnedRepos(login);
  const checkPinned = repository =>
    pinned.some(item => item === repository.name);
  const pinnedRepos = pinned.length
    ? repositories.filter(repository => checkPinned(repository) || repository.fork)
    : repositories;

  pinnedRepos.sort(sortBy.star);
  return pinnedRepos;
};

const _getContributed = async (login, token) => {
  const repos = await Api.getUserContributed(login, token);
  repos.sort(sortBy.star);
  return repos;
};

const _getCommits = async (login, token) => {
  const commits = await Api.getUserCommits(login, token);
  const formatCommits = combineReposCommits(commits);
  commits.sort(sortBy.x('totalCommits', parseInt));

  return {
    commits,
    formatCommits,
  };
};

/* ================== router handler ================== */

const toggleShare = async (ctx) => {
  const { githubLogin } = ctx.session;
  const { enable } = ctx.request.body;
  await ShareAnalyse.changeShareStatus({
    enable,
    url: `github/${githubLogin}`
  });
  const message = Boolean(enable) == true
    ? 'messages.share.toggleOpen'
    : 'messages.share.toggleClose'
  ctx.body = {
    success: true,
    message: ctx.__(message)
  };
};

const fetchRepositories = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserRepositories(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch repos success'
  };
};

const fetchCommits = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserCommits(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch commits success'
  };
};

const fetchOrganizations = async (ctx) => {
  const { githubLogin, githubToken } = ctx.session;
  await Api.getUserOrganizations(githubLogin, githubToken);
  ctx.body = {
    success: true,
    result: 'fetch orgs success'
  };
};

const getAllRepositories = async (ctx, next) => {
  const { githubLogin, githubToken } = ctx.session;
  const repos = await Api.getUserRepositories(githubLogin, githubToken);
  const result = repos.filter(repository => !repository.fork)
    .map((repository) => {
      const {
        name,
        language,
        stargazers_count
      } = repository;
      return {
        name,
        language,
        stargazers_count,
      };
    });

  ctx.body = {
    result,
    success: true,
  };

  await next();
};

const getUserContributed = async (ctx, next) => {
  const repositories =
    await _getContributed(ctx.params.login, ctx.session.githubToken);
  ctx.body = {
    success: true,
    result: {
      repositories,
    }
  };
  await next();
};

const getUserRepositories = async (ctx, next) => {
  const repositories =
    await _getRepositories(ctx.params.login, ctx.session.githubToken);
  ctx.body = {
    success: true,
    result: {
      repositories,
    }
  };
  await next();
};

const getUserCommits = async (ctx, next) => {
  const {
    commits,
    formatCommits
  } = await _getCommits(ctx.params.login, ctx.session.githubToken);

  if (!commits.length) {
    ctx.query.shouldCache = false;
  }

  ctx.body = {
    success: true,
    result: {
      commits,
      formatCommits
    }
  };
  await next();
};

const getUserOrganizations = async (ctx, next) => {
  const { login } = ctx.params;
  const { githubToken } = ctx.session;
  const organizations =
    await Api.getUserOrganizations(login, githubToken);

  ctx.body = {
    success: true,
    result: { organizations }
  };
  await next();
};

const getUser = async (ctx, next) => {
  const { login } = ctx.params;
  const user = await _getUser(ctx);
  const shareAnalyse =
    await ShareAnalyse.findOne({ login, url: `github/${login}` });

  const result = Object.assign({}, user);
  result.openShare = shareAnalyse.enable;
  result.shareUrl = `github/${login}?locale=${ctx.session.locale}`;
  ctx.body = {
    success: true,
    result
  };
  await next();
};

const githubPage = async (ctx) => {
  const { login } = ctx.params;
  const { isMobile } = ctx.state;
  const { githubLogin } = ctx.session;
  const title = ctx.__('sharePage.github', login);

  if (isMobile) {
    const locale = ctx.__('language.id');
    await ctx.render('user/mobile/github', {
      title,
      locale,
      user: {
        login,
        isAdmin: login === githubLogin,
      },
      shareText: ctx.__('messages.share.mobileText'),
    });
  } else {
    await ctx.render('github/share', {
      title,
      user: {
        login,
        isAdmin: login === githubLogin
      },
      shareText: ctx.__('messages.share.text')
    });
  }
};

const getShareRecords = async (ctx) => {
  const { githubLogin } = ctx.session;
  const url = `github/${githubLogin}`;
  const shareAnalyse =
    await ShareAnalyse.findOne({ login: githubLogin, url });
  const {
    enable,
    pageViews,
    viewDevices,
    viewSources,
  } = shareAnalyse;
  ctx.body = {
    success: true,
    result: {
      pageViews,
      viewDevices,
      viewSources,
      openShare: enable,
      url: `${url}?locale=${ctx.session.locale}`,
    }
  };
};

const getUpdateTime = async (ctx) => {
  const { githubLogin } = ctx.session;
  const result = await Api.getUpdateTime(githubLogin);
  ctx.body = {
    result,
    success: true,
  };
};

const refreshRepositories = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  await Api.refreshUser(githubLogin, githubToken);
  const result = await Api.refreshRepositories(githubLogin, githubToken);
  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  await Api.refreshContributed(githubLogin, githubToken);

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-repositories', {
      session: ['githubLogin']
    }),
    cacheKey('user-contributed', {
      session: ['githubLogin']
    }),
    cacheKey('allRepositories', {
      session: ['githubLogin']
    }),
    cacheKey('user-github', {
      session: ['githubLogin']
    }),
    cacheKey('user-hotmap', {
      session: ['githubLogin', 'locale']
    }),
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateRepos'),
  };

  await next();
};

const refreshCommits = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  const result = await Api.refreshCommits(githubLogin, githubToken);

  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-commits', {
      session: ['githubLogin']
    })
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateCommits'),
  };

  await next();
};

const refreshOrganizations = async (ctx, next) => {
  const { githubToken, githubLogin } = ctx.session;
  const result = await Api.refreshOrganizations(githubLogin, githubToken);

  if (result.success === false) {
    const error = result.error || ctx.__('messages.error.frequent').replace(/%s/, result.result);
    ctx.body = {
      error,
      result: null,
      success: true,
    };
    return;
  }

  // set cache keys to remove
  const cacheKey = getCacheKey(ctx);
  ctx.query.deleteKeys = [
    cacheKey('user-organizations', {
      session: ['githubLogin']
    })
  ];

  ctx.body = {
    result,
    success: true,
    message: ctx.__('messages.success.updateOrgs'),
  };

  await next();
};

const getZen = async (ctx) => {
  const { githubToken } = ctx.session;
  const val = await Api.getZen(githubToken);
  const result = is.object(val) ? '' : val;
  ctx.body = {
    result,
    success: true,
  };
};

const getOctocat = async (ctx) => {
  const result = await Api.getOctocat();
  ctx.body = {
    result,
    success: true,
  };
};

const getUserHotmap = async (ctx, next) => {
  const { login } = ctx.params;
  const { locale } = ctx.session;
  const result = await Api.getHotmap(login, locale);
  ctx.body = {
    result,
    success: true,
  };
  await next();
};

export default {
  githubPage,
  fetchRepositories,
  fetchCommits,
  fetchOrganizations,
  getAllRepositories,
  // github info
  getUser,
  getUserRepositories,
  getUserContributed,
  getUserCommits,
  getUserOrganizations,
  toggleShare,
  getShareRecords,
  getUserHotmap,
  /* ===== refresh & update ====== */
  getUpdateTime,
  refreshRepositories,
  refreshOrganizations,
  refreshCommits,
  /* ========== */
  getZen,
  getOctocat,
};
<|endoftext|>


<commit_before>'use strict';
/**
 * Copyright (c) 2016, WikiWeb
*/
const mongoose = require('mongoose');
const Entity = mongoose.model('Entity');
const Edge = require('../models/edge');
const utils = require('../../lib/utils');
const User = mongoose.model('User');
const _ = require('lodash');
const pageSearch = require('../../lib/pageSearch');
const slackNewHeart = utils.slackNewHeart;

/**
 * loadApi
 */
exports.load = function (req, res, next, id){
  Entity.load(id, function (err, entity) {
    if (!entity || (err && err.message === 'Cast to ObjectId failed')) return  res.status(404).send(utils.errsForApi('Page not found'));
    if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );
    req.entity = entity;
    Edge.getNearByNodeEdges(entity._id, function (errNear, nearByEdges) {
      if (errNear) return  res.status(500).send( utils.errsForApi(errNear.errors || errNear) );
      req.nearByEdges = nearByEdges;

      Edge.getNode(entity._id, function (errNodeEdge, edges){
        if (errNodeEdge) return res.status(500).send( utils.errsForApi(errNodeEdge.errors || errNodeEdge) );
        req.edges = edges;
        next();
      });
    });
  });
};

/**
* Entities API for Reverse Chronological Hearts
 */
exports.getHeartsController = function (req, res) {
  var SortQ = '-hearts.createdAt'
  Entity.find(
    {},
    '_id title description hearts createdAt canonicalLink queryLink faviconCDN isConnected image imageCDN')
    .populate('hearts.user', 'name username profile_image_large profile_image')
    .sort(SortQ)
    .limit(30)
    .skip(0)
    .exec(function (err, entities){
      return res.send(entities);
  });
}

/**
* Entity API for Nodes
 */
exports.getEntityController = function (req, res) {
  const entity = req.entity;
  const uId = req.user? req.user.id: null;

  const edges = _.chain(req.edges)
    .groupBy('_idNode')
    .map(function (edgesGrouped ){
        const edgeSorted = _.sortBy(edgesGrouped,'createdAt');
        return {
          _idNode: edgeSorted[0]._idNode,
          _idLink: edgeSorted[0]._idLink,
          createdAt: edgeSorted[0].createdAt,
          edges:edgeSorted
        };
    }).value();
  const nearByEdges = req.nearByEdges;
  const entityIds = _.map(req.edges, '_idNode');
  const userIds = _.map(req.edges, '_idUser');
  const entityIdsRelated = _.chain(nearByEdges)
    .map('nodes')
    .flatten()
    .map('_id')
    .value();
  const userIdsRelated = _.chain(nearByEdges)
    .map('edges')
    .flatten()
    .map('properties.userId')
    .reject(_.isUndefined)
    .value();

  if (!entity) {
    res.status(404).send(utils.errsForApi('Node not found!!'));
  } else {
    const object = entity.toJSON();

    Edge.getNodeCount(entityIds.concat(entity.id).concat(entityIdsRelated), function (err, entityCount){
      if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );

      Entity.find(
        { _id: { $in:  entityIds.concat(entityIdsRelated) } },
        '_id title description createdAt canonicalLink queryLink faviconCDN isConnected image imageCDN')
      .exec(function (err, entities){

        User.find(
          { _id: { $in: userIds.concat(userIdsRelated) } },
          'name username profile_image'
        )
        .exec(function (err, users){
          object.entityCount =  entityCount[entity.id] ? entityCount[entity.id].length : 0;
          object.nearByEdges = nearByEdges.map(function (near){
            const nodes = near.nodes.map(function (node){
              const _id = node._id;
              return  {
                node: _.find(entities, { id: _id }),
                entityCount: entityCount[_id] ? entityCount[_id].length : 0
              };
            });

            const edges = near.edges.map(function (edge){
              const userId = edge.properties.userId;
              if (userId !== undefined){
                edge.properties.userId = _.find(users, { id: userId });
              }
              return edge;
            });
            return {
              nodes,
              edges
            };
          });

          object.superEdges = edges.map(function (edge){
            return {
              entity: _.find(entities, { id: edge._idNode }),
              entityCount: entityCount[edge._idNode].length,
              createdAt: edge.createdAt,
              edges: edge.edges.map(function (e){
                return {
                  user:_.find(users, { id: e._idUser }),
                  createdAt: e.createdAt,
                  _id: e._idLink,
                  tags: e.tags ? e.tags : [],
                  description: e.description ? e.description : ''
                };
              })
            };
          });
          const heartValue = object.hearts.find(function (heart){
            return uId === String(heart.user)
          });
          object.heart = {
            count: object.hearts.length,
            value: heartValue !== undefined
          }
          res.send(object);
        });
      });// Entity.find
    });// Edge.getNodeCount
  }
};

/**
* Entity API for Hearts POST
 */
exports.postHeartController = function (req, res) {
  const value = req.body.value;
  const user = req.user
  const uId = user.id;
  var text;
  const entity = req.entity;

  if (value === true){
    const existingHeart = entity.hearts.find(function (heart){
      return uId === String(heart.user)
    });
    if (existingHeart === undefined ) {
      entity.hearts.push({
        user:uId
      });
    }
    text = 'Awesome! You recommend this article.';
  } else if (value === false) {
    entity.hearts = entity.hearts.filter(function (heart){
      return uId !== String(heart.user);
    });
    text = 'Awesome! You removed your recommendation.';
  } else {
    return res.status(500).send({
      success: false,
      text:'Please include true/false value for your recommendation.'
    })
  }
  const count = entity.hearts.length;
  entity.save(function (err){
    if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );
    if (value === true){slackNewHeart(user.username, entity.canonicalLink, entity.title);}
    return res.send({
      success: true,
      value,
      count,
      messages: [{
        type: 'success',
        text: text
      }]
    });
  });

};

/**
 * Search API for Node and Scrape Page
 */
exports.getSearchController = function (req, res) {
  const q = req.query.q;
  if (!q) return res.status(422).send(utils.errsForApi('Please Enter a URL.'));

  pageSearch(q, function (err, url, resultDB){
      if (err &&
         (err.status === 404 )) { // Did we get a 404 from the search. We tell the search
        res.send({
           node : {},
           isURL: true,
           parseSuccess: false,
           messages: [{
             type: 'Warning',
             text: 'This URL does not return a valid page'
           }]
        });
      } else if (err) {
        res.send({
          isURL: true,
          node : {},
          parseSuccess: false,
          messages: [{
            type: 'warning',
            text: 'Invalid URL'
          }]
        });
      } else {
        // Here is where we push all links to our child scrapper.
        const pageDB = resultDB;
        addToScrapperQ(_.map(resultDB.links, function (link){
          const linkDB = link;
          return {
            href: link.href,
            fromId: resultDB.id,
            linkDB,
            pageDB,
          };
        }));
        const payload = {
           node : resultDB.toObject(),
           isURL: true,
           parseSuccess: true,
           messages:[{
             type: 'success',
             text: 'This site exists'
           }]
        };
        res.send(payload);
      }
  });
};

function scraperRecursive (){
  running = true;

  const link = Q.pop();
  if (link === undefined || !link.href){// no link stop attempt for page search
    if (Q.length === 0) { // Q was empty we can not continue;
      running = false;
    } else {
      scraperRecursive();
    }
    return false; // Do not run the page search
  }
  console.log(link, 'link')
  pageSearch(link.href, function (err, url, resultDB){
    if (!err && resultDB){
      const fromId = link.fromId;
      const toId = resultDB.id;
      const linkDB = link.linkDB;
      const pageDB = link.pageDB

      Edge.getEdgesForPath(
        fromId,
        toId,
        function (err, resultExisting){
          if (resultExisting && resultExisting.length === 0){
            Edge.createSiteEdge(
              fromId,
              toId,
              function (err, edges){
                //console.log(edges, 'edge')/ @TODO Add edge id to links
                //linkDB.linkToID = edge[0].properties.Relationship.id;
                linkDB.pageTo = toId !== null ? toId : '';
                pageDB.save(function(err, result){
                  if (err) console.log(err, 'pageDB save');
                });
                if (err) console.log(err, 'scraperRecursive getEdgesForPath');
            });
          }

        });

    } else {
      // No Opp
    }

    if (Q.length === 0){
      running = false; // Stop the recursive call and set running to false
    } else {
      scraperRecursive();
    }
  });

}

function addToScrapperQ (hrefs){
  Q = Q.concat(_.uniq(hrefs));

  if (running === false){
    scraperRecursive();
  }
}

let Q = [];
let running = false;
<commit_msg>Killing log.<commit_after>'use strict';
/**
 * Copyright (c) 2016, WikiWeb
*/
const mongoose = require('mongoose');
const Entity = mongoose.model('Entity');
const Edge = require('../models/edge');
const utils = require('../../lib/utils');
const User = mongoose.model('User');
const _ = require('lodash');
const pageSearch = require('../../lib/pageSearch');
const slackNewHeart = utils.slackNewHeart;

/**
 * loadApi
 */
exports.load = function (req, res, next, id){
  Entity.load(id, function (err, entity) {
    if (!entity || (err && err.message === 'Cast to ObjectId failed')) return  res.status(404).send(utils.errsForApi('Page not found'));
    if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );
    req.entity = entity;
    Edge.getNearByNodeEdges(entity._id, function (errNear, nearByEdges) {
      if (errNear) return  res.status(500).send( utils.errsForApi(errNear.errors || errNear) );
      req.nearByEdges = nearByEdges;

      Edge.getNode(entity._id, function (errNodeEdge, edges){
        if (errNodeEdge) return res.status(500).send( utils.errsForApi(errNodeEdge.errors || errNodeEdge) );
        req.edges = edges;
        next();
      });
    });
  });
};

/**
* Entities API for Reverse Chronological Hearts
 */
exports.getHeartsController = function (req, res) {
  var SortQ = '-hearts.createdAt'
  Entity.find(
    {},
    '_id title description hearts createdAt canonicalLink queryLink faviconCDN isConnected image imageCDN')
    .populate('hearts.user', 'name username profile_image_large profile_image')
    .sort(SortQ)
    .limit(30)
    .skip(0)
    .exec(function (err, entities){
      return res.send(entities);
  });
}

/**
* Entity API for Nodes
 */
exports.getEntityController = function (req, res) {
  const entity = req.entity;
  const uId = req.user? req.user.id: null;

  const edges = _.chain(req.edges)
    .groupBy('_idNode')
    .map(function (edgesGrouped ){
        const edgeSorted = _.sortBy(edgesGrouped,'createdAt');
        return {
          _idNode: edgeSorted[0]._idNode,
          _idLink: edgeSorted[0]._idLink,
          createdAt: edgeSorted[0].createdAt,
          edges:edgeSorted
        };
    }).value();
  const nearByEdges = req.nearByEdges;
  const entityIds = _.map(req.edges, '_idNode');
  const userIds = _.map(req.edges, '_idUser');
  const entityIdsRelated = _.chain(nearByEdges)
    .map('nodes')
    .flatten()
    .map('_id')
    .value();
  const userIdsRelated = _.chain(nearByEdges)
    .map('edges')
    .flatten()
    .map('properties.userId')
    .reject(_.isUndefined)
    .value();

  if (!entity) {
    res.status(404).send(utils.errsForApi('Node not found!!'));
  } else {
    const object = entity.toJSON();

    Edge.getNodeCount(entityIds.concat(entity.id).concat(entityIdsRelated), function (err, entityCount){
      if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );

      Entity.find(
        { _id: { $in:  entityIds.concat(entityIdsRelated) } },
        '_id title description createdAt canonicalLink queryLink faviconCDN isConnected image imageCDN')
      .exec(function (err, entities){

        User.find(
          { _id: { $in: userIds.concat(userIdsRelated) } },
          'name username profile_image'
        )
        .exec(function (err, users){
          object.entityCount =  entityCount[entity.id] ? entityCount[entity.id].length : 0;
          object.nearByEdges = nearByEdges.map(function (near){
            const nodes = near.nodes.map(function (node){
              const _id = node._id;
              return  {
                node: _.find(entities, { id: _id }),
                entityCount: entityCount[_id] ? entityCount[_id].length : 0
              };
            });

            const edges = near.edges.map(function (edge){
              const userId = edge.properties.userId;
              if (userId !== undefined){
                edge.properties.userId = _.find(users, { id: userId });
              }
              return edge;
            });
            return {
              nodes,
              edges
            };
          });

          object.superEdges = edges.map(function (edge){
            return {
              entity: _.find(entities, { id: edge._idNode }),
              entityCount: entityCount[edge._idNode].length,
              createdAt: edge.createdAt,
              edges: edge.edges.map(function (e){
                return {
                  user:_.find(users, { id: e._idUser }),
                  createdAt: e.createdAt,
                  _id: e._idLink,
                  tags: e.tags ? e.tags : [],
                  description: e.description ? e.description : ''
                };
              })
            };
          });
          const heartValue = object.hearts.find(function (heart){
            return uId === String(heart.user)
          });
          object.heart = {
            count: object.hearts.length,
            value: heartValue !== undefined
          }
          res.send(object);
        });
      });// Entity.find
    });// Edge.getNodeCount
  }
};

/**
* Entity API for Hearts POST
 */
exports.postHeartController = function (req, res) {
  const value = req.body.value;
  const user = req.user
  const uId = user.id;
  var text;
  const entity = req.entity;

  if (value === true){
    const existingHeart = entity.hearts.find(function (heart){
      return uId === String(heart.user)
    });
    if (existingHeart === undefined ) {
      entity.hearts.push({
        user:uId
      });
    }
    text = 'Awesome! You recommend this article.';
  } else if (value === false) {
    entity.hearts = entity.hearts.filter(function (heart){
      return uId !== String(heart.user);
    });
    text = 'Awesome! You removed your recommendation.';
  } else {
    return res.status(500).send({
      success: false,
      text:'Please include true/false value for your recommendation.'
    })
  }
  const count = entity.hearts.length;
  entity.save(function (err){
    if (err) return  res.status(500).send( utils.errsForApi(err.errors || err) );
    if (value === true){slackNewHeart(user.username, entity.canonicalLink, entity.title);}
    return res.send({
      success: true,
      value,
      count,
      messages: [{
        type: 'success',
        text: text
      }]
    });
  });

};

/**
 * Search API for Node and Scrape Page
 */
exports.getSearchController = function (req, res) {
  const q = req.query.q;
  if (!q) return res.status(422).send(utils.errsForApi('Please Enter a URL.'));

  pageSearch(q, function (err, url, resultDB){
      if (err &&
         (err.status === 404 )) { // Did we get a 404 from the search. We tell the search
        res.send({
           node : {},
           isURL: true,
           parseSuccess: false,
           messages: [{
             type: 'Warning',
             text: 'This URL does not return a valid page'
           }]
        });
      } else if (err) {
        res.send({
          isURL: true,
          node : {},
          parseSuccess: false,
          messages: [{
            type: 'warning',
            text: 'Invalid URL'
          }]
        });
      } else {
        // Here is where we push all links to our child scrapper.
        const pageDB = resultDB;
        addToScrapperQ(_.map(resultDB.links, function (link){
          const linkDB = link;
          return {
            href: link.href,
            fromId: resultDB.id,
            linkDB,
            pageDB,
          };
        }));
        const payload = {
           node : resultDB.toObject(),
           isURL: true,
           parseSuccess: true,
           messages:[{
             type: 'success',
             text: 'This site exists'
           }]
        };
        res.send(payload);
      }
  });
};

function scraperRecursive (){
  running = true;

  const link = Q.pop();
  if (link === undefined || !link.href){// no link stop attempt for page search
    if (Q.length === 0) { // Q was empty we can not continue;
      running = false;
    } else {
      scraperRecursive();
    }
    return false; // Do not run the page search
  }

  pageSearch(link.href, function (err, url, resultDB){
    if (!err && resultDB){
      const fromId = link.fromId;
      const toId = resultDB.id;
      const linkDB = link.linkDB;
      const pageDB = link.pageDB

      Edge.getEdgesForPath(
        fromId,
        toId,
        function (err, resultExisting){
          if (resultExisting && resultExisting.length === 0){
            Edge.createSiteEdge(
              fromId,
              toId,
              function (err, edges){
                //console.log(edges, 'edge')/ @TODO Add edge id to links
                //linkDB.linkToID = edge[0].properties.Relationship.id;
                linkDB.pageTo = toId !== null ? toId : '';
                pageDB.save(function(err, result){
                  if (err) console.log(err, 'pageDB save');
                });
                if (err) console.log(err, 'scraperRecursive getEdgesForPath');
            });
          }

        });

    } else {
      // No Opp
    }

    if (Q.length === 0){
      running = false; // Stop the recursive call and set running to false
    } else {
      scraperRecursive();
    }
  });

}

function addToScrapperQ (hrefs){
  Q = Q.concat(_.uniq(hrefs));

  if (running === false){
    scraperRecursive();
  }
}

let Q = [];
let running = false;
<|endoftext|>


<commit_before>'use strict';

import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import {SharedCache} from '../lib/SharedCache';
import {AbstractDriver} from '../lib/Driver/AbstractDriver';
import {ContainerAware} from '../node_modules/deep-kernel/lib.compiled/ContainerAware';
import {CloudFrontDriverMock} from './Mocks/CloudFrontDriverMock';

chai.use(sinonChai);

suite('SharedCache', () => {
  let containerAware = new ContainerAware();
  let cloudFrontDriver = null;
  let data = {dataKey: 'Data here'};
  let sharedCache = null;
  let arn = 'arn:aws:lambda:us-west-2:9283468276298:function:test_backend';
  let request = {
    isLambda: true,
    payload: {id1: 'blabla', id3: 'uhuhu', arr: [3, 6, 9], o2: {hey: 's', hey5: 'm'}},
    action: {
      source: {
        original: arn,
      },
    },
    send: (callback = () => { }) => {
      callback({code: 200});
      return this;
    }
  };

  test('Class SharedCache exists in SharedCache', () => {
    chai.expect(SharedCache).to.be.an('function');
  });

  test('Check constructor', () => {
    cloudFrontDriver = new CloudFrontDriverMock(containerAware);
    cloudFrontDriver.fixBabelTranspile();
    sharedCache = new SharedCache(cloudFrontDriver);

    chai.expect(sharedCache, 'is an instance of SharedCache').to.be.an.instanceOf(SharedCache);

    chai.expect(
      sharedCache._driver, 'is an instance of AbstractDriver'
    ).to.be.an.instanceOf(AbstractDriver);
  });

  test('Test SharedCache buildKeyFromRequest() === buildKeyFromLambdaRuntime()', () => {
    let requestCacheKey = sharedCache.buildKeyFromRequest(request);

    let runtimeCacheKey = sharedCache.buildKeyFromLambdaRuntime({
      context: {
        has: () => true,
        getOption: () => arn,
      },
      request: {
        data: {id1: 'blabla', o2: {hey5: 'm', hey: 's'}, id3: 'uhuhu', arr: [3, 9, 6]},
      },
    });

    chai.expect(requestCacheKey).to.equal(runtimeCacheKey);
  });

  test('Class _createSuccessfulResponse returns valid object', () => {
    let expectedResult = {
      data: data,
      statusCode: 200,
      isError: false,
      error: null,
    };

    chai.expect(sharedCache._createSuccessfulResponse(data)).to.eql(expectedResult);
  });

  //@todo - add additional checks
  test('Check assure() if key exists', () => {
    let spyCallback = sinon.spy();
    let key = 'testKey';
    let value = 'testValue';
    let ttl = 0;

    sharedCache._driver.setMode(CloudFrontDriverMock.DATA_MODE);

    let actualResult = sharedCache.assure(key, value, ttl, spyCallback);

    chai.expect(actualResult).to.equal(undefined);
    //chai.expect(spyCallback).to.have.been.calledWithExactly(null, true);
  });

  //@todo - need to clarify with Alex c
  //test('Check assure() if key doesn"t exist', () => {
  //  let spyCallback = sinon.spy();
  //  let key = 'testKey';
  //  let value = 'testValue';
  //  let ttl = 0;
  //
  //  cloudFrontDriver.setMode(CloudFrontDriverMock.NO_RESULT_MODE);
  //
  //  let actualResult = sharedCache.assure(key, value, ttl, spyCallback);
  //
  //  chai.expect(actualResult).to.equal(undefined);
  //  //chai.expect(spyCallback).to.have.been.calledWithExactly(null, true);
  //});

  test('Check request() if key exists', () => {
    let spyCallback = sinon.spy();

    sharedCache._driver.setMode(CloudFrontDriverMock.DATA_MODE);

    let actualResult = sharedCache.request(request, spyCallback);

    chai.expect(actualResult).to.equal(undefined);
    chai.expect(spyCallback).to.have.been.calledWithExactly({code: 200});
  });

});
<commit_msg>Remove commented code<commit_after>'use strict';

import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import {SharedCache} from '../lib/SharedCache';
import {AbstractDriver} from '../lib/Driver/AbstractDriver';
import {ContainerAware} from '../node_modules/deep-kernel/lib.compiled/ContainerAware';
import {CloudFrontDriverMock} from './Mocks/CloudFrontDriverMock';

chai.use(sinonChai);

suite('SharedCache', () => {
  let containerAware = new ContainerAware();
  let cloudFrontDriver = null;
  let data = {dataKey: 'Data here'};
  let sharedCache = null;
  let arn = 'arn:aws:lambda:us-west-2:9283468276298:function:test_backend';
  let request = {
    isLambda: true,
    payload: {id1: 'blabla', id3: 'uhuhu', arr: [3, 6, 9], o2: {hey: 's', hey5: 'm'}},
    action: {
      source: {
        original: arn,
      },
    },
    send: (callback = () => { }) => {
      callback({code: 200});
      return this;
    }
  };

  test('Class SharedCache exists in SharedCache', () => {
    chai.expect(SharedCache).to.be.an('function');
  });

  test('Check constructor', () => {
    cloudFrontDriver = new CloudFrontDriverMock(containerAware);
    cloudFrontDriver.fixBabelTranspile();
    sharedCache = new SharedCache(cloudFrontDriver);

    chai.expect(sharedCache, 'is an instance of SharedCache').to.be.an.instanceOf(SharedCache);

    chai.expect(
      sharedCache._driver, 'is an instance of AbstractDriver'
    ).to.be.an.instanceOf(AbstractDriver);
  });

  test('Test SharedCache buildKeyFromRequest() === buildKeyFromLambdaRuntime()', () => {
    let requestCacheKey = sharedCache.buildKeyFromRequest(request);

    let runtimeCacheKey = sharedCache.buildKeyFromLambdaRuntime({
      context: {
        has: () => true,
        getOption: () => arn,
      },
      request: {
        data: {id1: 'blabla', o2: {hey5: 'm', hey: 's'}, id3: 'uhuhu', arr: [3, 9, 6]},
      },
    });

    chai.expect(requestCacheKey).to.equal(runtimeCacheKey);
  });

  test('Class _createSuccessfulResponse returns valid object', () => {
    let expectedResult = {
      data: data,
      statusCode: 200,
      isError: false,
      error: null,
    };

    chai.expect(sharedCache._createSuccessfulResponse(data)).to.eql(expectedResult);
  });

  //@todo - add additional checks
  test('Check assure() if key exists', () => {
    let spyCallback = sinon.spy();
    let key = 'testKey';
    let value = 'testValue';
    let ttl = 0;

    sharedCache._driver.setMode(CloudFrontDriverMock.DATA_MODE);

    let actualResult = sharedCache.assure(key, value, ttl, spyCallback);

    chai.expect(actualResult).to.equal(undefined);
  });

  test('Check request() if key exists', () => {
    let spyCallback = sinon.spy();

    sharedCache._driver.setMode(CloudFrontDriverMock.DATA_MODE);

    let actualResult = sharedCache.request(request, spyCallback);

    chai.expect(actualResult).to.equal(undefined);
    chai.expect(spyCallback).to.have.been.calledWithExactly({code: 200});
  });

});
<|endoftext|>


<commit_before>import EventEmitter from 'events';
import {pull} from 'lodash/array';
import {contains} from 'lodash/collection';
import {addNode, addEdge, pruneFromNode, removeEdge, removeNode} from './graph';

/*
Events
------

start
complete

added [node]
removed [node]
error [err, node]

tracing [node]
traced [node]

*/

/*
 we need a notion of 'jobs', to enable async
 invalidation and resolution.

 `pending` should be a list of objects where
 each object takes the form:
 {
 file: '...',
 isValid: true
 }

 if a file is ever invalidated while a job is pending,
 the `isValid` property should be set to false, so that
 when that job completes, it will discard its results
 */

/*
 Handle file change while tracing:
 given predecessors [a, b, ...] -> c

 if c changes during dep resolution:
 when c's dep resolution has completed:
 if c's job is still active:
 update graph
 else:
 discard results
 */

/*
 Handle file change:
 given predecessors [a, b, ...] -> c

 when c changes:
 deps = []
 for predecessor of c:
 deps += getDeps(predecessor)
 rebuildGraph(deps)
 */

/*
 When pruning, we'll need a notion of entry points,
 so that we can safely prune the tree without
 removing required nodes.

 Also need to take into consideration that `trace`
 may be called by iteration functions which provide
 index values of an object. Should make sure that
 defining an entry point is an explicit process
 */

export function createGraph({getDependencies}) {
  const nodes = Object.create(null);
  const permanentNodes = [];
  const events = new EventEmitter;
  const pendingJobs = [];

  return {
    nodes,
    permanentNodes,
    pendingJobs,
    events,
    traceNode(node) {
      const job = {
        node,
        isActive: true
      };

      pendingJobs.push(job);

      process.nextTick(startTracingNode);

      function removeJob() {
        pull(pendingJobs, job);
      }

      function startTracingNode() {
        // Allow jobs to be cancelled synchronously
        if (!job.isActive) {
          return removeJob();
        }

        getDependencies(file, (err, dependencies) => {
          if (err) {
            return events.emit('error', err, file);
          }

          // Allow jobs to be cancelled asynchronously
          if (!job.isActive) {
            return removeJob();
          }

          const nodesAdded = [];

          if (!nodes[node]) {
            addNode(nodes, node);
            nodesAdded.push(node);
          }

          dependencies.forEach(depNode => {
            if (!nodes[depNode]) {
              addNode(nodes, depNode);
              nodesAdded.push(depNode);
            }
            addEdge(nodes, node, depNode);
          });

          nodesAdded.forEach(() => events.emit('added', node));
        });
      }
    },
    setNodeAsPermanent(node) {
      if (!contains(permanentNodes, node)) {
        permanentNodes.push(node);
      }
    },
    isGraphComplete() {
      return pendingJobs.length === 0;
    },
    invalidateNode(node) {
      const prunedNodes = pruneFromNode(nodes, node, permanentNodes);

      prunedNodes.forEach(node => {
        pendingJobs
          .filter(job => job.node === node)
          .forEach(job => job.isActive = false);

        events.emit('removed', node);
      });
    }
  };
}
<commit_msg>Node tracing cleanup<commit_after>import EventEmitter from 'events';
import {pull} from 'lodash/array';
import {contains} from 'lodash/collection';
import {addNode, addEdge, pruneFromNode, removeEdge, removeNode} from './graph';

/*
Events
------

start
complete

added [node]
removed [node]
error [err, node]

tracing [node]
traced [node]

*/

/*
 we need a notion of 'jobs', to enable async
 invalidation and resolution.

 `pending` should be a list of objects where
 each object takes the form:
 {
 file: '...',
 isValid: true
 }

 if a file is ever invalidated while a job is pending,
 the `isValid` property should be set to false, so that
 when that job completes, it will discard its results
 */

/*
 Handle file change while tracing:
 given predecessors [a, b, ...] -> c

 if c changes during dep resolution:
 when c's dep resolution has completed:
 if c's job is still active:
 update graph
 else:
 discard results
 */

/*
 Handle file change:
 given predecessors [a, b, ...] -> c

 when c changes:
 deps = []
 for predecessor of c:
 deps += getDeps(predecessor)
 rebuildGraph(deps)
 */

/*
 When pruning, we'll need a notion of entry points,
 so that we can safely prune the tree without
 removing required nodes.

 Also need to take into consideration that `trace`
 may be called by iteration functions which provide
 index values of an object. Should make sure that
 defining an entry point is an explicit process
 */

export function createGraph({getDependencies}) {
  const nodes = Object.create(null);
  const permanentNodes = [];
  const events = new EventEmitter;
  const pendingJobs = [];

  return {
    nodes,
    permanentNodes,
    pendingJobs,
    events,
    traceNode(node) {
      const job = {
        node,
        isActive: true
      };

      pendingJobs.push(job);

      process.nextTick(startTracingNode);

      function removeJob() {
        pull(pendingJobs, job);
      }

      function startTracingNode() {
        // Allow jobs to be cancelled synchronously
        if (!job.isActive) {
          return removeJob();
        }

        getDependencies(file, (err, dependencies) => {
          removeJob();

          if (err) {
            return events.emit('error', err, file);
          }

          // Allow jobs to be cancelled asynchronously
          if (!job.isActive) {
            return;
          }

          const nodesAdded = [];

          if (!nodes[node]) {
            addNode(nodes, node);
            nodesAdded.push(node);
          }

          dependencies.forEach(depNode => {
            if (!nodes[depNode]) {
              addNode(nodes, depNode);
              nodesAdded.push(depNode);
            }

            addEdge(nodes, node, depNode);
          });

          nodesAdded.forEach(() => events.emit('added', node));
        });
      }
    },
    setNodeAsPermanent(node) {
      if (!contains(permanentNodes, node)) {
        permanentNodes.push(node);
      }
    },
    isGraphComplete() {
      return pendingJobs.length === 0;
    },
    invalidateNode(node) {
      const prunedNodes = pruneFromNode(nodes, node, permanentNodes);

      prunedNodes.forEach(node => {
        pendingJobs
          .filter(job => job.node === node)
          .forEach(job => job.isActive = false);

        events.emit('removed', node);
      });
    }
  };
}
<|endoftext|>


<commit_before>import SkypeService from '../services/skype';

export function initialize(application) {
    application.register('service:skype', SkypeService, { initialize: true, singleton: true });
}

export default {
  name: 'skype',
  initialize
};
<commit_msg>Add App global object for sanity<commit_after>import SkypeService from '../services/skype';

export function initialize(application) {
    application.register('service:skype', SkypeService, { initialize: true, singleton: true });
    window.App = application;
}

export default {
  name: 'skype',
  initialize
};
<|endoftext|>


<commit_before>angular.module('makeithappen').controller('LocalController', ['$scope', function($scope) {

    $scope.schema = {
        "type": "object",
        "properties": {
            "id": "user.json",
            "name": {
                "type": "string"
            },
            "age": {
                "type": "integer"
            },
            "height": {
                "type": "number"
            },
            "vegetarian": {
                "type": "boolean"
            },
            "birthDate": {
                "type": "string",
                "format": "date-time"
            },
            "nationality": {
                "type": "string",
                "enum": ["DE", "IT", "JP", "US", "RU", "Other"]
            }
        }
    };
    $scope.uiSchema = {
        "type": "HorizontalLayout",
        "elements": [
            {
                "type": "Control",
                "label": "Name",
                "scope": {
                    "$ref": "#/properties/name"
                }
            },
            {
                "type": "Control",
                "label": "Age",
                "scope": {
                    "$ref": "#/properties/age"
                }
            },
            {
                "type": "Control",
                "label": "Height",
                "scope": {
                    "$ref": "#/properties/height"
                }
            },
            {
                "type": "Control",
                "label": "Vegetarian",
                "scope": {
                    "$ref": "#/properties/vegetarian"
                }
            },
            {
                "type": "Control",
                "label": "Nationality",
                "scope": {
                    "$ref": "#/properties/nationality"
                }
            },
            {
                "type": "Control",
                "label": "Birthday",
                "scope": {
                    "$ref": "#/properties/birthDate"
                }
            }
        ]
    };

    $scope.usersSchema = {
        "type": "array",
        "items": $scope.schema
    };
    $scope.usersUiSchema = {
        "type": "Control",
        "scope": {
            "$ref": "#"
        },
        "columns": [
            {
                "label": "Name",
                "scope": {
                    "$ref": "#/items/properties/name"
                }
            },
            {
                "label": "Age",
                "scope": {
                    "$ref": "#/items/properties/age"
                }
            }
        ]
    };

    $scope.data = {
        name: 'John Doe',
        age: 36,
        height: 1.76,
        vegetarian: false,
        birthDate: "02.06.1985",
        nationality: "US"
    };
    $scope.users = [
        $scope.data,
        {
            name: 'Todd',
            age: 33
        },
        {
            name: 'Jimmy',
            age: 34
        },
        {
            name: 'Max',
            age: 35
        },
        {
            name: 'Jonas',
            age: 34
        },
        {
            name: 'Edgar',
            age: 30
        },
        {
            name: 'Eugen',
            age: 28
        },
        {
            name: 'Johannes',
            age: 26
        },
        {
            name: 'Alex',
            age: 25
        },
        {
            name: 'Stefan',
            age: 27
        },
        {
            name: 'Eva',
            age: 30
        }
    ];

    $scope.formattedData = function() {
        return JSON.stringify($scope.data, null, 4);
    };
}]);<commit_msg>Modified schema to test Auto-complete<commit_after>angular.module('makeithappen').controller('LocalController', ['$scope', function($scope) {

    $scope.schema = {
        "type": "object",
        "properties": {
            "id": "user.json",
            "name": {
                "type": "string"
            },
            "age": {
                "type": "integer"
            },
            "height": {
                "type": "number"
            },
            "vegetarian": {
                "type": "boolean"
            },
            "birthDate": {
                "type": "string",
                "format": "date-time"
            },
            "nationality": {
                "type": "string",
                "enum": ["DE", "IT", "JP", "US", "RU", "Other"]
            },
            "occupation": {
                "type": "string"
            },
        }
    };
    $scope.uiSchema = {
        "type": "HorizontalLayout",
        "elements": [
            {
                "type": "Control",
                "label": "Name",
                "scope": {
                    "$ref": "#/properties/name"
                }
            },
            {
                "type": "Control",
                "label": "Age",
                "scope": {
                    "$ref": "#/properties/age"
                }
            },
            {
                "type": "Control",
                "label": "Height",
                "scope": {
                    "$ref": "#/properties/height"
                }
            },
            {
                "type": "Control",
                "label": "Vegetarian",
                "scope": {
                    "$ref": "#/properties/vegetarian"
                }
            },
            {
                "type": "Control",
                "label": "Nationality",
                "scope": {
                    "$ref": "#/properties/nationality"
                }
            },
            {
                "type": "Control",
                "label": "Occupation",
                "scope": {
                    "$ref": "#/properties/occupation"
                },
                "suggestion": ["Accountant", "Engineer", "Freelancer", "Journalism", "Physician", "Student", "Teacher", "Other"]
            },
            {
                "type": "Control",
                "label": "Birthday",
                "scope": {
                    "$ref": "#/properties/birthDate"
                }
            }
        ]
    };

    $scope.usersSchema = {
        "type": "array",
        "items": $scope.schema
    };
    $scope.usersUiSchema = {
        "type": "Control",
        "scope": {
            "$ref": "#"
        },
        "columns": [
            {
                "label": "Name",
                "scope": {
                    "$ref": "#/items/properties/name"
                }
            },
            {
                "label": "Age",
                "scope": {
                    "$ref": "#/items/properties/age"
                }
            }
        ]
    };

    $scope.data = {
        name: 'John Doe',
        age: 36,
        height: 1.76,
        vegetarian: false,
        birthDate: "02.06.1985",
        nationality: "US"
    };
    $scope.users = [
        $scope.data,
        {
            name: 'Todd',
            age: 33
        },
        {
            name: 'Jimmy',
            age: 34
        },
        {
            name: 'Max',
            age: 35
        },
        {
            name: 'Jonas',
            age: 34
        },
        {
            name: 'Edgar',
            age: 30
        },
        {
            name: 'Eugen',
            age: 28
        },
        {
            name: 'Johannes',
            age: 26
        },
        {
            name: 'Alex',
            age: 25
        },
        {
            name: 'Stefan',
            age: 27
        },
        {
            name: 'Eva',
            age: 30
        }
    ];

    $scope.formattedData = function() {
        return JSON.stringify($scope.data, null, 4);
    };
}]);<|endoftext|>


<commit_before>/**
 * Created with JetBrains WebStorm.
 * User: gtarcea
 * Date: 1/12/13
 * Time: 1:11 PM
 * To change this template use File | Settings | File Templates.
 */

var Filter = angular.module('Filter', []);

Filter.filter('startFrom', function() {
    return function(input, start) {
        start = +start; //parse to int
        return input.slice(start);
    }
});

Filter.filter('matchDates', function() {
    return function( search_results, start_end_dates ) {
        if (! search_results) { return;}
        if (! start_end_dates) { return;}
        var arrayToReturn = [];
        var utc_start_date =  Date.parse(start_end_dates[0])/1000;
        var utc_end_date =  Date.parse(start_end_dates[1])/1000;
            for (var i=0; i< search_results.length; i++){
            if ( (search_results[i].key[1] == start_end_dates[2]) && (search_results[i].key[0] > utc_start_date) && (search_results[i].key[0] < utc_end_date)) {
                arrayToReturn.push(search_results[i]);
            }
        }

        return arrayToReturn;

    };
});

Filter.filter('private', function(){
   return function(list){
       if (! list) { return;}
       var return_array = [];
       for (var i=0; i< list.length; i++){
           if (list[i].value.access == "private"){
               return_array.push(list[i]);
           }
       }
       return return_array;
   };

});

Filter.filter('public', function(){
    return function(list){
        //console.log('entered filetr');
        var return_array = [];
        for (var i=0; i< list.length; i++){
            if (list[i].value.access == "public"){
                return_array.push(list[i]);
            }
        }
        return return_array;
    };

});

Filter.filter('data_by_user', function(){
    return function(list, user){
        var return_array = [];
        for(var i=0; i< list.length;i++){
            if (list[i].key[0] == user[0]){
                return_array.push(list[i]);
            }
        }
        return return_array;

    }
});

//This is not used because in full text search index is getting complicated
// because we have to apply filter in service to get paginated results
Filter.filter('elastic_search_filter_data', function(){
    return function(list){
        var return_array = [];
        for(var i=0; i< list.length;i++){

            if (list[i]._source.type == "data"){
                return_array.push(list[i]);
            }
        }
        return return_array;

    }
});

Filter.filter('truncate', function(){
    return function (text, length, end) {
        if (isNaN(length))
            length = 10;

        if (end === undefined)
            end = ".....";

        if (text.length <= length || text.length - end.length <= length) {
            return text;
        }
        else {
            return String(text).substring(0, length-end.length) + end;
        }

    };
});

Filter.filter('toDateString', function() {
    return function(input) {
        if (input) {
            var t = input.epoch_time;
            return new Date(t * 1000).toDateString();
        }
    }
});

Filter.filter('page', function() {
    return function(input, currentPage, pageSize) {
        var page_size = pageSize ? pageSize : 10;
        var to_page_size = page_size;
        var to = currentPage == 0 ? 1 : currentPage;
        if (currentPage != 0) {
           to_page_size++;
        }
        return input ? input.slice(currentPage * page_size, to * to_page_size) : [];
    }
});

<commit_msg>ISSUE#5 Page display calculations in the filter were incorrect. Also simplified the code when I corrected the issue.<commit_after>/**
 * Created with JetBrains WebStorm.
 * User: gtarcea
 * Date: 1/12/13
 * Time: 1:11 PM
 * To change this template use File | Settings | File Templates.
 */

var Filter = angular.module('Filter', []);

Filter.filter('startFrom', function() {
    return function(input, start) {
        start = +start; //parse to int
        return input.slice(start);
    }
});

Filter.filter('matchDates', function() {
    return function( search_results, start_end_dates ) {
        if (! search_results) { return;}
        if (! start_end_dates) { return;}
        var arrayToReturn = [];
        var utc_start_date =  Date.parse(start_end_dates[0])/1000;
        var utc_end_date =  Date.parse(start_end_dates[1])/1000;
            for (var i=0; i< search_results.length; i++){
            if ( (search_results[i].key[1] == start_end_dates[2]) && (search_results[i].key[0] > utc_start_date) && (search_results[i].key[0] < utc_end_date)) {
                arrayToReturn.push(search_results[i]);
            }
        }

        return arrayToReturn;

    };
});

Filter.filter('private', function(){
   return function(list){
       if (! list) { return;}
       var return_array = [];
       for (var i=0; i< list.length; i++){
           if (list[i].value.access == "private"){
               return_array.push(list[i]);
           }
       }
       return return_array;
   };

});

Filter.filter('public', function(){
    return function(list){
        //console.log('entered filetr');
        var return_array = [];
        for (var i=0; i< list.length; i++){
            if (list[i].value.access == "public"){
                return_array.push(list[i]);
            }
        }
        return return_array;
    };

});

Filter.filter('data_by_user', function(){
    return function(list, user){
        var return_array = [];
        for(var i=0; i< list.length;i++){
            if (list[i].key[0] == user[0]){
                return_array.push(list[i]);
            }
        }
        return return_array;

    }
});

//This is not used because in full text search index is getting complicated
// because we have to apply filter in service to get paginated results
Filter.filter('elastic_search_filter_data', function(){
    return function(list){
        var return_array = [];
        for(var i=0; i< list.length;i++){

            if (list[i]._source.type == "data"){
                return_array.push(list[i]);
            }
        }
        return return_array;

    }
});

Filter.filter('truncate', function(){
    return function (text, length, end) {
        if (isNaN(length))
            length = 10;

        if (end === undefined)
            end = ".....";

        if (text.length <= length || text.length - end.length <= length) {
            return text;
        }
        else {
            return String(text).substring(0, length-end.length) + end;
        }

    };
});

Filter.filter('toDateString', function() {
    return function(input) {
        if (input) {
            var t = input.epoch_time;
            return new Date(t * 1000).toDateString();
        }
    }
});

Filter.filter('page', function() {
    return function(input, currentPage, pageSize) {
        var from = currentPage * pageSize;
        var to = from + pageSize;
        return input ? input.slice(from, to) : [];
    }
});

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */
define(
[
  'rye',
  'Q',
  'page',
  'puzzle-widget',
  'slide-menu-widget',
  'game-info-widget',
  'leaderboard-mini-widget',
  'game-level-select-widget',
  'dust-render',
  'i18n!../../nls/strings',
  'api'
],
function (
  $,
  Q,
  Page,
  PuzzleWidget,
  SlideMenuWidget,
  GameInfoWidget,
  LeaderboardMiniWidget,
  GameLevelSelectWidget,
  render,
  translations,
  api
) {
  'use strict';

  var parentElt = null;
  var game = api.game;
  var leaderboard = api.leaderboard;
  var soundBoard = api.soundBoard;

  return Page({
    templateName: 'game',

    init: function (elt) {
      var dfd = Q.defer();
      var self = this;

      soundBoard.load('shuffle');

      parentElt = $(elt);
      render(this.templateName, {translations: translations}).then(function (html) {
        parentElt.append(html);

        // create HTML from template
        self.elt = parentElt.find('[data-page=game]');

        // add widgets to the basic HTML which update themselves
        // in response to changes in models
        var puzzleWidgetElt = self.elt.find('[data-widget=puzzle]');
        self.puzzleWidget = PuzzleWidget(puzzleWidgetElt, game);

        // setup slide menus; NB the markup of the menus doesn't change,
        // just the markup of text elements inside the menus; so we use
        // separate small widgets to handle those
        var leftMenuElt = self.elt.find('.slide-menu[data-menu-side=left]');
        var rightMenuElt = self.elt.find('.slide-menu[data-menu-side=right]');

        self.leftMenu = SlideMenuWidget(leftMenuElt, rightMenuElt);
        self.rightMenu = SlideMenuWidget(rightMenuElt, leftMenuElt);

        // expanding a menu pauses the game (as soon as the slide out
        // starts);
        // collapsing a menu starts the game again (as soon as the slide in
        // finishes)
        self.leftMenu.on('in', function () {
          game.start();
          self.puzzleWidget.start();
        });

        self.leftMenu.on('animating-out', function () {
          game.pause();
          self.puzzleWidget.pause();
        });

        self.rightMenu.on('in', function () {
          game.start();
          self.puzzleWidget.start();
        });

        self.rightMenu.on('animating-out', function () {
          game.pause();
          self.puzzleWidget.pause();
        });

        // game info panel, left-hand menu
        var gameInfoElt = self.leftMenu.elt.find('[data-widget=game-info]');
        var showPhotoCredit = true;
        self.gameInfo = GameInfoWidget(gameInfoElt, game, showPhotoCredit);
        self.gameInfo.update();

        // mini leaderboard, left-hand menu
        var leaderboardElt = self.leftMenu.elt
                             .find('[data-widget=leaderboard-mini]');
        var scoresToDisplay = 3;

        self.leaderboardMini = LeaderboardMiniWidget(
          leaderboardElt,
          game,
          leaderboard,
          scoresToDisplay
        );
        self.leaderboardMini.update();

        // level select, right-hand menu
        var levelWidgetSelector = '[data-widget=game-level-select]';
        var levelSelectElt = self.rightMenu.elt.find(levelWidgetSelector);
        self.levelSelect = GameLevelSelectWidget(levelSelectElt, game);
        self.levelSelect.update();

        self.levelSelect.on('select', function (newDifficultyLevel) {
          soundBoard.play('shuffle');
          game.setDifficulty(newDifficultyLevel);
          game.reset();
        });

        // handler for the "Play again" button, which slides the menu
        // back in and resets the game
        self.playAgainBtn = self.rightMenu.elt.find('[data-menu-action=reset]');
        self.playAgainBtn.on('click', function () {
          soundBoard.play('shuffle');
          self.rightMenu.slide();
          game.reset();
        });

        // enable buttons on menus
        self.enableNavButtons();

        // hook data-bound widgets up so that if data changes, they
        // update themselves in the background
        self.gameInfo.watch(game);
        self.leaderboardMini.watch(leaderboard);
        self.leaderboardMini.watch(game);
        self.puzzleWidget.watch(game, ['reset']);

        // if the game ends, transfer to the "finished" page
        game.on('completed', function () {
          game.pause();
          self.loadPageAndNavigate('finish');
        });

        // done
        setTimeout(function () {
          dfd.resolve(self);
        }, 0);
      });

      return dfd.promise;
    },

    // note that this page is static with dynamic areas, so each
    // widget is redrawn only if the data it is bound to has changed;
    // this happens in the background automatically
    show: function (params) {
      soundBoard.play('shuffle');

      // get parameters for the game
      var difficulty = params.difficulty;
      var photo = game.getPhotoById(params.photoId);

      var difficultyChanged = (difficulty &&
                               difficulty !== game.get('difficulty'));
      var photoChanged = (photo && photo !== game.get('photo'));

      if (difficultyChanged) {
        game.set('difficulty', difficulty);
      }

      if (photoChanged) {
        game.set('photo', photo);
      }

      // show the page element
      this.elt.removeClass('page-inactive').addClass('page-active');

      // reset the game every time the page is shown
      game.reset();
    },

    hide: function () {
      if (this.elt) {
        this.elt.removeClass('page-active').addClass('page-inactive');
        this.rightMenu.close();
        this.leftMenu.close();
      }
    }
  });
});
<commit_msg>Update highlight in right-hand menu when difficulty changes<commit_after>/*
 * Copyright (c) 2013, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */
define(
[
  'rye',
  'Q',
  'page',
  'puzzle-widget',
  'slide-menu-widget',
  'game-info-widget',
  'leaderboard-mini-widget',
  'game-level-select-widget',
  'dust-render',
  'i18n!../../nls/strings',
  'api'
],
function (
  $,
  Q,
  Page,
  PuzzleWidget,
  SlideMenuWidget,
  GameInfoWidget,
  LeaderboardMiniWidget,
  GameLevelSelectWidget,
  render,
  translations,
  api
) {
  'use strict';

  var parentElt = null;
  var game = api.game;
  var leaderboard = api.leaderboard;
  var soundBoard = api.soundBoard;

  return Page({
    templateName: 'game',

    init: function (elt) {
      var dfd = Q.defer();
      var self = this;

      soundBoard.load('shuffle');

      parentElt = $(elt);
      render(this.templateName, {translations: translations}).then(function (html) {
        parentElt.append(html);

        // create HTML from template
        self.elt = parentElt.find('[data-page=game]');

        // add widgets to the basic HTML which update themselves
        // in response to changes in models
        var puzzleWidgetElt = self.elt.find('[data-widget=puzzle]');
        self.puzzleWidget = PuzzleWidget(puzzleWidgetElt, game);

        // setup slide menus; NB the markup of the menus doesn't change,
        // just the markup of text elements inside the menus; so we use
        // separate small widgets to handle those
        var leftMenuElt = self.elt.find('.slide-menu[data-menu-side=left]');
        var rightMenuElt = self.elt.find('.slide-menu[data-menu-side=right]');

        self.leftMenu = SlideMenuWidget(leftMenuElt, rightMenuElt);
        self.rightMenu = SlideMenuWidget(rightMenuElt, leftMenuElt);

        // expanding a menu pauses the game (as soon as the slide out
        // starts);
        // collapsing a menu starts the game again (as soon as the slide in
        // finishes)
        self.leftMenu.on('in', function () {
          game.start();
          self.puzzleWidget.start();
        });

        self.leftMenu.on('animating-out', function () {
          game.pause();
          self.puzzleWidget.pause();
        });

        self.rightMenu.on('in', function () {
          game.start();
          self.puzzleWidget.start();
        });

        self.rightMenu.on('animating-out', function () {
          game.pause();
          self.puzzleWidget.pause();
        });

        // game info panel, left-hand menu
        var gameInfoElt = self.leftMenu.elt.find('[data-widget=game-info]');
        var showPhotoCredit = true;
        self.gameInfo = GameInfoWidget(gameInfoElt, game, showPhotoCredit);
        self.gameInfo.update();

        // mini leaderboard, left-hand menu
        var leaderboardElt = self.leftMenu.elt
                             .find('[data-widget=leaderboard-mini]');
        var scoresToDisplay = 3;

        self.leaderboardMini = LeaderboardMiniWidget(
          leaderboardElt,
          game,
          leaderboard,
          scoresToDisplay
        );
        self.leaderboardMini.update();

        // level select, right-hand menu
        var levelWidgetSelector = '[data-widget=game-level-select]';
        var levelSelectElt = self.rightMenu.elt.find(levelWidgetSelector);
        self.levelSelect = GameLevelSelectWidget(levelSelectElt, game);
        self.levelSelect.watch(game, ['update:difficulty']);
        self.levelSelect.update();

        self.levelSelect.on('select', function (newDifficultyLevel) {
          soundBoard.play('shuffle');
          game.setDifficulty(newDifficultyLevel);
          game.reset();
        });

        // handler for the "Play again" button, which slides the menu
        // back in and resets the game
        self.playAgainBtn = self.rightMenu.elt.find('[data-menu-action=reset]');
        self.playAgainBtn.on('click', function () {
          soundBoard.play('shuffle');
          self.rightMenu.slide();
          game.reset();
        });

        // enable buttons on menus
        self.enableNavButtons();

        // hook data-bound widgets up so that if data changes, they
        // update themselves in the background
        self.gameInfo.watch(game);
        self.leaderboardMini.watch(leaderboard);
        self.leaderboardMini.watch(game);
        self.puzzleWidget.watch(game, ['reset']);

        // if the game ends, transfer to the "finished" page
        game.on('completed', function () {
          game.pause();
          self.loadPageAndNavigate('finish');
        });

        // done
        setTimeout(function () {
          dfd.resolve(self);
        }, 0);
      });

      return dfd.promise;
    },

    // note that this page is static with dynamic areas, so each
    // widget is redrawn only if the data it is bound to has changed;
    // this happens in the background automatically
    show: function (params) {
      soundBoard.play('shuffle');

      // get parameters for the game
      var difficulty = params.difficulty;
      var photo = game.getPhotoById(params.photoId);

      var difficultyChanged = (difficulty &&
                               difficulty !== game.get('difficulty'));
      var photoChanged = (photo && photo !== game.get('photo'));

      if (difficultyChanged) {
        game.set('difficulty', difficulty);
      }

      if (photoChanged) {
        game.set('photo', photo);
      }

      // show the page element
      this.elt.removeClass('page-inactive').addClass('page-active');

      // reset the game every time the page is shown
      game.reset();
    },

    hide: function () {
      if (this.elt) {
        this.elt.removeClass('page-active').addClass('page-inactive');
        this.rightMenu.close();
        this.leftMenu.close();
      }
    }
  });
});
<|endoftext|>


<commit_before>const webpack = require('webpack')

const { log, warn, fatal, success } = require('../helpers/logger')
const { spawn } = require('../helpers/spawn')
const appPaths = require('../app-paths')
const nodePackager = require('../helpers/node-packager')
const getPackageJson = require('../helpers/get-package-json')
const getPackage = require('../helpers/get-package')

class ElectronRunner {
  constructor () {
    this.pid = 0
    this.mainWatcher = null
    this.preloadWatcher = null
  }

  init () {}

  async run (quasarConfFile, argv) {
    const url = quasarConfFile.quasarConf.build.APP_URL

    if (this.pid) {
      if (this.url !== url) {
        await this.stop()
      }
      else {
        return
      }
    }

    this.url = url

    const mainCompiler = webpack(quasarConfFile.webpackConf.main)
    const preloadCompiler = webpack(quasarConfFile.webpackConf.preload)

    let mainReady = false
    let preloadReady = false

    const resolveMain = new Promise(resolve => {
      this.mainWatcher = mainCompiler.watch({}, async (err, stats) => {
        if (err) {
          console.log(err)
          return
        }

        if (stats.hasErrors()) {
          return
        }

        mainReady = true

        if (preloadReady === true) {
          await this.__stopElectron()
          this.__startElectron(argv._)
        }

        resolve()
      })
    })

    const resolvePreload = new Promise(resolve => {
      this.preloadWatcher = preloadCompiler.watch({}, async (err, stats) => {
        if (err) {
          console.log(err)
          return
        }

        if (stats.hasErrors()) {
          return
        }

        preloadReady = true

        if (mainReady === true) {
          await this.__stopElectron()
          this.__startElectron(argv._)
        }

        resolve()
      })
    })

    return Promise.all([ resolveMain, resolvePreload ])
  }

  build (quasarConfFile) {
    const cfg = quasarConfFile.quasarConf

    return new Promise(resolve => {
      spawn(
        nodePackager,
        [ 'install', '--production' ].concat(cfg.electron.unPackagedInstallParams),
        { cwd: cfg.build.distDir },
        code => {
          if (code) {
            fatal(`${nodePackager} failed installing dependencies`, 'FAIL')
          }
          resolve()
        }
      )
    }).then(() => {
      return new Promise(async resolve => {
        if (typeof cfg.electron.beforePackaging === 'function') {
          log('Running beforePackaging()')
          log()

          const result = cfg.electron.beforePackaging({
            appPaths,
            unpackagedDir: cfg.build.distDir
          })

          if (result && result.then) {
            await result
          }

          log()
          log('[SUCCESS] Done running beforePackaging()')
        }
        resolve()
      })
    }).then(() => {
      const bundlerName = cfg.electron.bundler
      const bundlerConfig = cfg.electron[bundlerName]
      const bundler = require('./bundler').getBundler(bundlerName)
      const pkgName = `electron-${bundlerName}`

      return new Promise((resolve, reject) => {
        log(`Bundling app with electron-${bundlerName}...`)
        log()

        const bundlePromise = bundlerName === 'packager'
          ? bundler({
            ...bundlerConfig,
            electronVersion: getPackageJson('electron').version
          })
          : bundler.build(bundlerConfig)

        bundlePromise
          .then(() => {
            log()
            success(`${pkgName} built the app`, 'SUCCESS')
            log()
            resolve()
          })
          .catch(err => {
            log()
            warn(`${pkgName} could not build`, 'FAIL')
            log()
            console.error(err + '\n')
            reject()
          })
      })
    })
  }

  stop () {
    return new Promise(resolve => {
      let counter = 0
      const maxCounter = (this.mainWatcher ? 1 : 0) + (this.preloadWatcher ? 1 : 0)

      const finalize = () => {
        counter++
        if (maxCounter <= counter) {
          this.__stopElectron().then(resolve)
        }
      }

      if (this.mainWatcher) {
        this.mainWatcher.close(finalize)
        this.mainWatcher = null
      }

      if (this.preloadWatcher) {
        this.preloadWatcher.close(finalize)
        this.preloadWatcher = null
      }

      if (maxCounter === 0) {
        finalize()
      }
    })
  }

  __startElectron (extraParams) {
    this.pid = spawn(
      getPackage('electron'),
      [
        '--inspect=5858',
        appPaths.resolve.app('.quasar/electron/electron-main.js')
      ].concat(extraParams),
      { cwd: appPaths.appDir },
      code => {
        if (this.killPromise) {
          this.killPromise()
          this.killPromise = null
        }
        else if (code) {
          warn()
          fatal(`Electron process ended with error code: ${code}`)
        }
        else { // else it wasn't killed by us
          warn()
          fatal('Electron process was killed. Exiting...')
        }
      }
    )
  }

  __stopElectron () {
    const pid = this.pid

    if (!pid) {
      return Promise.resolve()
    }

    log('Shutting down Electron process...')
    this.pid = 0
    return new Promise(resolve => {
      this.killPromise = resolve
      process.kill(pid)
    })
  }
}

module.exports = new ElectronRunner()
<commit_msg>fix(app): Ensure not running the electron process multiple times simultaneously #12235<commit_after>const webpack = require('webpack')
const debounce = require('lodash.debounce')

const { log, warn, fatal, success } = require('../helpers/logger')
const { spawn } = require('../helpers/spawn')
const appPaths = require('../app-paths')
const nodePackager = require('../helpers/node-packager')
const getPackageJson = require('../helpers/get-package-json')
const getPackage = require('../helpers/get-package')

class ElectronRunner {
  constructor () {
    this.pid = 0
    this.mainWatcher = null
    this.preloadWatcher = null

    this.__restartElectron = debounce(params => {
      this.__stopElectron()
      this.__startElectron(params)
    }, 1000)
  }

  init () {}

  async run (quasarConfFile, argv) {
    const url = quasarConfFile.quasarConf.build.APP_URL

    if (this.url === url) {
      return
    }

    if (this.pid) {
      this.stop()
    }

    this.url = url

    const mainCompiler = webpack(quasarConfFile.webpackConf.main)
    const preloadCompiler = webpack(quasarConfFile.webpackConf.preload)

    let mainReady = false
    let preloadReady = false

    const resolveMain = new Promise(resolve => {
      this.mainWatcher = mainCompiler.watch({}, async (err, stats) => {
        if (err) {
          console.log(err)
          return
        }

        if (stats.hasErrors()) {
          return
        }

        mainReady = true

        if (preloadReady === true) {
          this.__restartElectron(argv._)
        }

        resolve()
      })
    })

    const resolvePreload = new Promise(resolve => {
      this.preloadWatcher = preloadCompiler.watch({}, async (err, stats) => {
        if (err) {
          console.log(err)
          return
        }

        if (stats.hasErrors()) {
          return
        }

        preloadReady = true

        if (mainReady === true) {
          this.__restartElectron(argv._)
        }

        resolve()
      })
    })

    return Promise.all([ resolveMain, resolvePreload ])
  }

  build (quasarConfFile) {
    const cfg = quasarConfFile.quasarConf

    return new Promise(resolve => {
      spawn(
        nodePackager,
        [ 'install', '--production' ].concat(cfg.electron.unPackagedInstallParams),
        { cwd: cfg.build.distDir },
        code => {
          if (code) {
            fatal(`${nodePackager} failed installing dependencies`, 'FAIL')
          }
          resolve()
        }
      )
    }).then(() => {
      return new Promise(async resolve => {
        if (typeof cfg.electron.beforePackaging === 'function') {
          log('Running beforePackaging()')
          log()

          const result = cfg.electron.beforePackaging({
            appPaths,
            unpackagedDir: cfg.build.distDir
          })

          if (result && result.then) {
            await result
          }

          log()
          log('[SUCCESS] Done running beforePackaging()')
        }
        resolve()
      })
    }).then(() => {
      const bundlerName = cfg.electron.bundler
      const bundlerConfig = cfg.electron[bundlerName]
      const bundler = require('./bundler').getBundler(bundlerName)
      const pkgName = `electron-${bundlerName}`

      return new Promise((resolve, reject) => {
        log(`Bundling app with electron-${bundlerName}...`)
        log()

        const bundlePromise = bundlerName === 'packager'
          ? bundler({
            ...bundlerConfig,
            electronVersion: getPackageJson('electron').version
          })
          : bundler.build(bundlerConfig)

        bundlePromise
          .then(() => {
            log()
            success(`${pkgName} built the app`, 'SUCCESS')
            log()
            resolve()
          })
          .catch(err => {
            log()
            warn(`${pkgName} could not build`, 'FAIL')
            log()
            console.error(err + '\n')
            reject()
          })
      })
    })
  }

  stop () {
    this.__restartElectron.cancel()

    this.__stopElectron()

    ;[ this.mainWatcher, this.preloadWatcher]
      .forEach(w => {
        if (w) {
          w.close()
        }
      })

    this.mainWatcher = null
    this.preloadWatcher = null
  }

  __stopElectron () {
    if (!this.pid) { return }

    log('Shutting down Electron process...')
    process.kill(this.pid)

    this.pid = 0
    this.__justKilledIt = true
  }

  __startElectron (extraParams) {
    this.pid = spawn(
      getPackage('electron'),
      [
        '--inspect=5858',
        appPaths.resolve.app('.quasar/electron/electron-main.js')
      ].concat(extraParams),
      { cwd: appPaths.appDir },
      code => {
        if (this.__justKilledIt === true) {
          this.__justKilledIt = false
          return
        }
        else if (code) {
          warn()
          fatal(`Electron process ended with error code: ${code}`)
        }
        else { // else it wasn't killed by us
          warn()
          fatal('Electron process was killed. Exiting...')
        }
      }
    )
  }
}

module.exports = new ElectronRunner()
<|endoftext|>


<commit_before>/**
 * @fileoverview
 * This file contains a lookup table of css properties, the value of the
 * property contains the initial value ( default value is defined in the browser.css )
 * used by Opera if ther is no CSS defined
 * by the author. This is used in the CSS inspector
 * @see stylesheets
 */

css_initial_values =
{
"-apple-dashboard-region": "",
"-o-background-size": "",
"-o-link": "",
"-o-link-source": "",
"-o-table-baseline": "",
"-o-text-overflow": "",
"-wap-accesskey": "",
"-wap-input-format": "",
"-wap-input-required": "",
"-wap-marquee-dir": "",
"-wap-marquee-loop": "",
"-wap-marquee-speed": "",
"-wap-marquee-style": "",
"-xv-interpret-as": "",
"-xv-phonemes": "",
"-xv-voice-balance": "",
"-xv-voice-duration": "",
"-xv-voice-pitch": "",
"-xv-voice-pitch-range": "",
"-xv-voice-rate": "",
"-xv-voice-stress": "",
"-xv-voice-volume": "",
"alignment-baseline": "",
"audio-level": "",
"background": "transparent none repeat scroll 0px 0px",
"background-attachment": "scroll",
"background-color": "transparent",
"background-image": "none",
"background-position": "0px 0px",
"background-repeat": "repeat",
"baseline-shift": "",
"border": "0px #000000",
"border-bottom": "0px #000000",
"border-bottom-color": "#000000",
"border-bottom-style": "none",
"border-bottom-width": "0px",
"border-collapse": "separate",
"border-color": "#000000",
"border-left": "0px #000000",
"border-left-color": "#000000",
"border-left-style": "none",
"border-left-width": "0px",
"border-right": "0px #000000",
"border-right-color": "#000000",
"border-right-style": "none",
"border-right-width": "0px",
"border-spacing": "0px",
"border-style": "none",
"border-top": "0px #000000",
"border-top-color": "#000000",
"border-top-style": "none",
"border-top-width": "0px",
"border-width": "0px",
"bottom": "auto",
"box-sizing": "",
"caption-side": "top",
"cell-spacing": "",
"clear": "none",
"clip": "rect(0px, 0px, 0px, 0px)",
"clip-path": "",
"clip-rule": "",
"color": "#000000",
"color-interpolation": "",
"color-interpolation-filters": "",
"color-profile": "",
"color-rendering": "",
"column-span": "",
"content": "none",
"counter-increment": "none",
"counter-reset": "none",
"cue": "",
"cue-after": "",
"cue-before": "",
"cursor": "default",
"direction": "ltr",
"display": "inline",
"display-align": "",
"dominant-baseline": "",
"empty-cells": "show",
"enable-background": "",
"fill": "#000000",
"fill-opacity": "",
"fill-rule": "",
"filter": "",
"float": "none",
"flood-color": "",
"flood-opacity": "",
"font": "shorthand",
"font-family": "Times New Roman",
"font-size": "16px",
"font-size-adjust": "none",
"font-stretch": "normal",
"font-style": "normal",
"font-variant": "normal",
"font-weight": "400",
"glyph-orientation-horizontal": "",
"glyph-orientation-vertical": "",
"height": "auto",
"image-rendering": "",
"kerning": "",
"left": "auto",
"letter-spacing": "0px",
"lighting-color": "",
"line-height": "normal",
"line-increment": "",
"list-style": "disc outside none",
"list-style-image": "none",
"list-style-position": "outside",
"list-style-type": "disc",
"margin": "0px",
"margin-bottom": "0px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "0px",
"mark": "",
"mark-after": "",
"mark-before": "",
"marker": "",
"marker-end": "",
"marker-mid": "",
"marker-offset": "",
"marker-start": "",
"marks": "none",
"mask": "none",
"max-height": "-1px",
"max-width": "-1px",
"min-height": "0px",
"min-width": "0px",
"nav-down": "",
"nav-index": "",
"nav-left": "",
"nav-right": "",
"nav-up": "",
"opacity": "1",
"orphans": "2",
"outline": "3px",
"outline-color": "invert",
"outline-offset": "",
"outline-style": "none",
"outline-width": "3px",
"overflow": "visible",
"overflow-x": "visible",
"overflow-y": "visible",
"padding": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"page": "auto",
"page-break-after": "auto",
"page-break-before": "auto",
"page-break-inside": "auto",
"pause": "",
"pause-after": "",
"pause-before": "",
"pointer-events": "",
"position": "static",
"quotes": "none",
"rest": "",
"rest-after": "",
"rest-before": "",
"right": "auto",
"row-span": "",
"scrollbar-3dlight-color": "",
"scrollbar-arrow-color": "",
"scrollbar-base-color": "",
"scrollbar-darkshadow-color": "",
"scrollbar-face-color": "",
"scrollbar-highlight-color": "",
"scrollbar-shadow-color": "",
"scrollbar-track-color": "",
"shape-rendering": "",
"size": "portrait",
"solid-color": "",
"solid-opacity": "",
"speak": "",
"stop-color": "",
"stop-opacity": "",
"stroke": "",
"stroke-dasharray": "",
"stroke-dashoffset": "",
"stroke-linecap": "",
"stroke-linejoin": "",
"stroke-miterlimit": "",
"stroke-opacity": "",
"stroke-width": "",
"table-layout": "auto",
"text-align": "left",
"text-anchor": "",
"text-decoration": "none",
"text-indent": "0px",
"text-rendering": "",
"text-shadow": "",
"text-transform": "none",
"top": "auto",
"unicode-bidi": "normal",
"vector-effect": "",
"vertical-align": "baseline",
"viewport-fill": "",
"viewport-fill-opacity": "",
"visibility": "visible",
"voice-family": "",
"white-space": "normal",
"widows": "2",
"width": "auto",
"word-spacing": "0px",
"writing-mode": "",
"z-index": "auto"
}<commit_msg>Other part of fix for DFL-1040. Updated list of CSS initial values.<commit_after>/**
 * @fileoverview
 * This file contains a lookup table of css properties, the value of the
 * property contains the initial value ( default value is defined in the browser.css )
 * used by Opera if ther is no CSS defined
 * by the author. This is used in the CSS inspector
 * @see stylesheets
 */

css_initial_values =
{
"-apple-dashboard-region": "",
"-o-link": "",
"-o-link-source": "",
"-o-table-baseline": "",
"-o-text-overflow": "",
"-o-transform": "none",
"-o-transform-origin": "50% 50%",
"-o-transition": "",
"-o-transition-delay": "0",
"-o-transition-duration": "0",
"-o-transition-property": "all",
"-o-transition-timing-function": "ease",
"-wap-accesskey": "",
"-wap-input-format": "",
"-wap-input-required": "",
"-wap-marquee-dir": "",
"-wap-marquee-loop": "",
"-wap-marquee-speed": "",
"-wap-marquee-style": "",
"-xv-interpret-as": "",
"-xv-phonemes": "",
"-xv-voice-balance": "",
"-xv-voice-duration": "",
"-xv-voice-pitch": "",
"-xv-voice-pitch-range": "",
"-xv-voice-rate": "",
"-xv-voice-stress": "",
"-xv-voice-volume": "",
"alignment-baseline": "",
"audio-level": "",
"background": "transparent none repeat scroll 0px 0px",
"background-attachment": "scroll",
"background-clip": "border-box",
"background-color": "transparent",
"background-image": "none",
"background-origin": "padding",
"background-position": "0px 0px",
"background-repeat": "repeat",
"background-size": "none",
"baseline-shift": "",
"border": "0px #000000",
"border-bottom": "0px #000000",
"border-bottom-color": "#000000",
"border-bottom-style": "none",
"border-bottom-width": "0px",
"border-collapse": "separate",
"border-color": "#000000",
"border-left": "0px #000000",
"border-left-color": "#000000",
"border-left-style": "none",
"border-left-width": "0px",
"border-right": "0px #000000",
"border-right-color": "#000000",
"border-right-style": "none",
"border-right-width": "0px",
"border-spacing": "0px",
"border-style": "none",
"border-top": "0px #000000",
"border-top-color": "#000000",
"border-top-style": "none",
"border-top-width": "0px",
"border-width": "0px",
"bottom": "auto",
"box-sizing": "content-box",
"box-shadow": "",
"caption-side": "top",
"cell-spacing": "",
"clear": "none",
"clip": "rect(0px, 0px, 0px, 0px)",
"clip-path": "",
"clip-rule": "",
"color": "#000000",
"color-interpolation": "",
"color-interpolation-filters": "",
"color-profile": "",
"color-rendering": "",
"column-span": "",
"content": "none",
"counter-increment": "none",
"counter-reset": "none",
"cue": "",
"cue-after": "",
"cue-before": "",
"cursor": "auto",
"direction": "ltr",
"display": "inline",
"display-align": "",
"dominant-baseline": "",
"empty-cells": "show",
"enable-background": "",
"fill": "#000000",
"fill-opacity": "",
"fill-rule": "",
"filter": "",
"float": "none",
"flood-color": "",
"flood-opacity": "",
"font": "shorthand",
"font-family": "",
"font-size": "16px",
"font-size-adjust": "none",
"font-stretch": "normal",
"font-style": "normal",
"font-variant": "normal",
"font-weight": "400",
"glyph-orientation-horizontal": "",
"glyph-orientation-vertical": "",
"height": "auto",
"image-rendering": "",
"kerning": "",
"left": "auto",
"letter-spacing": "0px",
"lighting-color": "",
"line-height": "normal",
"line-increment": "",
"list-style": "disc outside none",
"list-style-image": "none",
"list-style-position": "outside",
"list-style-type": "disc",
"margin": "0px",
"margin-bottom": "0px",
"margin-left": "0px",
"margin-right": "0px",
"margin-top": "0px",
"mark": "",
"mark-after": "",
"mark-before": "",
"marker": "",
"marker-end": "",
"marker-mid": "",
"marker-offset": "",
"marker-start": "",
"marks": "none",
"mask": "none",
"max-height": "-1px",
"max-width": "-1px",
"min-height": "0px",
"min-width": "0px",
"nav-down": "",
"nav-index": "",
"nav-left": "",
"nav-right": "",
"nav-up": "",
"opacity": "1",
"orphans": "2",
"outline": "3px",
"outline-color": "invert",
"outline-offset": "",
"outline-style": "none",
"outline-width": "3px",
"overflow": "visible",
"overflow-x": "visible",
"overflow-y": "visible",
"padding": "0px",
"padding-bottom": "0px",
"padding-left": "0px",
"padding-right": "0px",
"padding-top": "0px",
"page": "auto",
"page-break-after": "auto",
"page-break-before": "auto",
"page-break-inside": "auto",
"pause": "",
"pause-after": "",
"pause-before": "",
"pointer-events": "",
"position": "static",
"quotes": "none",
"rest": "",
"rest-after": "",
"rest-before": "",
"right": "auto",
"row-span": "",
"scrollbar-3dlight-color": "",
"scrollbar-arrow-color": "",
"scrollbar-base-color": "",
"scrollbar-darkshadow-color": "",
"scrollbar-face-color": "",
"scrollbar-highlight-color": "",
"scrollbar-shadow-color": "",
"scrollbar-track-color": "",
"shape-rendering": "",
"size": "portrait",
"solid-color": "",
"solid-opacity": "",
"speak": "",
"stop-color": "",
"stop-opacity": "",
"stroke": "",
"stroke-dasharray": "",
"stroke-dashoffset": "",
"stroke-linecap": "",
"stroke-linejoin": "",
"stroke-miterlimit": "",
"stroke-opacity": "",
"stroke-width": "",
"table-layout": "auto",
"text-align": "left",
"text-anchor": "",
"text-decoration": "none",
"text-indent": "0px",
"text-rendering": "",
"text-shadow": "",
"text-transform": "none",
"top": "auto",
"unicode-bidi": "normal",
"vector-effect": "",
"vertical-align": "baseline",
"viewport-fill": "",
"viewport-fill-opacity": "",
"visibility": "visible",
"voice-family": "",
"white-space": "normal",
"widows": "2",
"width": "auto",
"word-spacing": "0px",
"word-wrap": "normal",
"writing-mode": "",
"z-index": "auto"
}
<|endoftext|>