<commit_before>import * as types from '../constants/actionTypes';
import axios from 'axios';
import {displayNotification} from './notificationActions';

export function beginDeleteRoom() {
  return {
    type: types.DELETE_ROOM
  };
}

export function deleteRoomSuccess(roomId) {
  return {
    type: types.DELETE_ROOM_SUCCESS,
    roomId
  };
}

export function deleteRoomError(error) {
  return {
    type: types.DELETE_ROOM_ERROR,
    error
  };
}

export function beginLoadAllRooms() {
  return {
    type: types.LOAD_ALL_ROOMS
  };
}

export function loadAllRoomsSuccess(rooms) {
  return {
    type: types.LOAD_ALL_ROOMS_SUCCESS,
    rooms
  };
}

export function loadAllRoomsError(error) {
  return {
    type: types.LOAD_ALL_ROOMS_ERROR,
    error
  };
}

export function loadRoomSuccess(room) {
  return {
    type: types.LOAD_ROOM_SUCCESS,
    room
  };
}

export function loadRoomError(error) {
  return {
    type: types.LOAD_ROOM_ERROR,
    error
  };
}

export function beginLoadRoom() {
  return {
    type: types.LOAD_ROOM
  };
}

export function beginAddRoom() {
  return {
    type: types.ADD_ROOM
  };
}

export function addRoomSuccess(room) {
  return {
    type: types.ADD_ROOM_SUCCESS,
    room
  };
}

export function addRoomError(error) {
  return {
    type: types.ADD_ROOM_ERROR,
    error
  };
}

export function beginModifyRoom() {
  return {
    type: types.MODIFY_ROOM
  };
}

export function modifyRoomSuccess(room) {
  return {
    type: types.MODIFY_ROOM_SUCCESS,
    room
  };
}

export function modifyRoomError(error) {
  return {
    type: types.MODIFY_ROOM_ERROR,
    error
  };
}

export function beginUploadImage() {
  return {
    type: types.UPLOAD_IMAGE
  };
}

export function uploadImageSuccess() {
  return {
    type: types.UPLOAD_IMAGE_SUCCESS
  };
}

export function uploadImageError(error) {
  return {
    type: types.UPLOAD_IMAGE_ERROR,
    error
  };
}

export function deleteRoom(roomId) {
  return (dispatch, getState) => {
    dispatch(beginDeleteRoom());
    const token = getState().user.token;
    return axios.delete('/room/' + roomId + '?token=' + token)
      .then(response => {
        if (response.status === 200) {
          dispatch(deleteRoomSuccess(roomId));
          dispatch(displayNotification('success', '操作成功', '删除房间成功'));
        }
        else {
          dispatch(displayNotification('error', '错误', toString(response.data.error)));
        }
      })
      .catch(error => dispatch(displayNotification('error', '错误', toString(error.response.data.error || error))));
  };
}

export function loadAllRooms() {
  return (dispatch, getState) => {
    dispatch(beginLoadAllRooms());
    const token = getState().user.token;
    return axios.get('/room', {
      params:{
        token,
        offset: 0,
        limit: 20
      }
    })
      .then(response => {
        if (response.status === 200) {
          dispatch(loadAllRoomsSuccess(response.data.rooms));
        }
        else {
          dispatch(displayNotification('error', '错误', response.data.error));
        }
      })
      .catch(error => dispatch(displayNotification('error', '错误', toString(error.response.data.error || error))));
  };
}

export function loadInterviewerRoom() {
  return (dispatch, getState) => {
    const token = getState().user.token;
    // get roomId by token
    return axios.get('/interviewer' + '?token=' + token)
      .then(res => {
        if (res.status === 200) {
          // get room info by roomId
          const roomId = res.data.roomId;
          return axios.get('/room/' + roomId + '?token=' + token);
        }
        else if (res.status === 400) {
          throw '获取房间信息失败';
        }
        else {
          throw res.data;
        }
      })
      .then(res => {
        if (res.status === 200) {
          dispatch(loadRoomSuccess(res.data));
        }
        else if (res.status === 403) {
          throw '用户无访问权限';
        }
        else if (res.status === 404) {
          throw '房间不存在';
        }
        else {
          throw res.data;
        }
      })
      .catch(err => {
        dispatch(displayNotification('error', '错误', toString(err.response.data.error || err)));
      });
  };
}

export function modifyRoom(data) {
  return (dispatch, getState) => {
    dispatch(beginModifyRoom());
    const room_id = data.room_id;
    const room = data.newRoom;
    const image = new FormData();
    image.append('logo', data.logo);
    const token = getState().user.token;
    return axios.put('/room/' + room_id +'?token=' + token, room)
      .then(response => {
        if(response.status === 200) {
          dispatch(modifyRoomSuccess(response.data.room));
          dispatch(beginUploadImage());
          debugger;
          console.log(image);
          return axios.put('/room/' + room_id + '/logo' + '?token=' + token, image);
        }
        else {
          throw (response.data);
        }
      })
      .then(response => {
        if(response.status === 200) {
          dispatch(uploadImageSuccess());
        }
        else {
          throw (response.data);
        }
      })
      .catch(error => {
        dispatch(displayNotification('error', '错误', error.message));
      });
  };
}

export function addRoom(data) {
  return (dispatch, getState) => {
    dispatch(beginAddRoom());
    const room = data.newRoom;
    const image = new FormData();
    image.append('logo', data.logo);
    const token = getState().user.token;
    return axios.post('/room' + '?token=' + token, room)
      .then(response => {
        if(response.status === 200) {
          dispatch(addRoomSuccess(response.data.room));
          const roomNum = getState().roomsStates.rooms.length;
          const room_id = getState().roomsStates.rooms[roomNum - 1].id;
          dispatch(beginUploadImage());
          return axios.put('/room/' + room_id + '/logo' + '?token=' + token, image);
        }
        else {
          throw (response.data);
        }
      })
      .then(response => {
        if(response.status === 200) {
          dispatch(uploadImageSuccess());
        }
        else {
          throw (response.data);
        }
      })
      .catch(error => {
        dispatch(displayNotification('error', '错误', toString(error)));
      });
  };
}
<commit_msg>Fix display error issue<commit_after>import * as types from '../constants/actionTypes';
import axios from 'axios';
import {displayNotification} from './notificationActions';

export function beginDeleteRoom() {
  return {
    type: types.DELETE_ROOM
  };
}

export function deleteRoomSuccess(roomId) {
  return {
    type: types.DELETE_ROOM_SUCCESS,
    roomId
  };
}

export function deleteRoomError(error) {
  return {
    type: types.DELETE_ROOM_ERROR,
    error
  };
}

export function beginLoadAllRooms() {
  return {
    type: types.LOAD_ALL_ROOMS
  };
}

export function loadAllRoomsSuccess(rooms) {
  return {
    type: types.LOAD_ALL_ROOMS_SUCCESS,
    rooms
  };
}

export function loadAllRoomsError(error) {
  return {
    type: types.LOAD_ALL_ROOMS_ERROR,
    error
  };
}

export function loadRoomSuccess(room) {
  return {
    type: types.LOAD_ROOM_SUCCESS,
    room
  };
}

export function loadRoomError(error) {
  return {
    type: types.LOAD_ROOM_ERROR,
    error
  };
}

export function beginLoadRoom() {
  return {
    type: types.LOAD_ROOM
  };
}

export function beginAddRoom() {
  return {
    type: types.ADD_ROOM
  };
}

export function addRoomSuccess(room) {
  return {
    type: types.ADD_ROOM_SUCCESS,
    room
  };
}

export function addRoomError(error) {
  return {
    type: types.ADD_ROOM_ERROR,
    error
  };
}

export function beginModifyRoom() {
  return {
    type: types.MODIFY_ROOM
  };
}

export function modifyRoomSuccess(room) {
  return {
    type: types.MODIFY_ROOM_SUCCESS,
    room
  };
}

export function modifyRoomError(error) {
  return {
    type: types.MODIFY_ROOM_ERROR,
    error
  };
}

export function beginUploadImage() {
  return {
    type: types.UPLOAD_IMAGE
  };
}

export function uploadImageSuccess() {
  return {
    type: types.UPLOAD_IMAGE_SUCCESS
  };
}

export function uploadImageError(error) {
  return {
    type: types.UPLOAD_IMAGE_ERROR,
    error
  };
}

export function deleteRoom(roomId) {
  return (dispatch, getState) => {
    dispatch(beginDeleteRoom());
    const token = getState().user.token;
    return axios.delete('/room/' + roomId + '?token=' + token)
      .then(response => {
        if (response.status === 200) {
          dispatch(deleteRoomSuccess(roomId));
          dispatch(displayNotification('success', '操作成功', '删除房间成功'));
        }
        else {
          dispatch(displayNotification('error', '错误', toString(response.data.error)));
        }
      })
      .catch(error => dispatch(displayNotification('error', '错误', toString(error.response.data.error || error))));
  };
}

export function loadAllRooms() {
  return (dispatch, getState) => {
    dispatch(beginLoadAllRooms());
    const token = getState().user.token;
    return axios.get('/room', {
      params:{
        token,
        offset: 0,
        limit: 20
      }
    })
      .then(response => {
        if (response.status === 200) {
          dispatch(loadAllRoomsSuccess(response.data.rooms));
        }
        else {
          dispatch(displayNotification('error', '错误', response.data.error));
        }
      })
      .catch(error => dispatch(displayNotification('error', '错误', error.message)));
  };
}

export function loadInterviewerRoom() {
  return (dispatch, getState) => {
    const token = getState().user.token;
    // get roomId by token
    return axios.get('/interviewer' + '?token=' + token)
      .then(res => {
        if (res.status === 200) {
          // get room info by roomId
          const roomId = res.data.roomId;
          return axios.get('/room/' + roomId + '?token=' + token);
        }
        else if (res.status === 400) {
          throw '获取房间信息失败';
        }
        else {
          throw res.data;
        }
      })
      .then(res => {
        if (res.status === 200) {
          dispatch(loadRoomSuccess(res.data));
        }
        else if (res.status === 403) {
          throw '用户无访问权限';
        }
        else if (res.status === 404) {
          throw '房间不存在';
        }
        else {
          throw res.data;
        }
      })
      .catch(err => {
        dispatch(displayNotification('error', '错误', err.message));
      });
  };
}

export function modifyRoom(data) {
  return (dispatch, getState) => {
    dispatch(beginModifyRoom());
    const room_id = data.room_id;
    const room = data.newRoom;
    const image = new FormData();
    image.append('logo', data.logo);
    const token = getState().user.token;
    return axios.put('/room/' + room_id +'?token=' + token, room)
      .then(response => {
        if(response.status === 200) {
          dispatch(modifyRoomSuccess(response.data.room));
          dispatch(beginUploadImage());
          debugger;
          console.log(image);
          return axios.put('/room/' + room_id + '/logo' + '?token=' + token, image);
        }
        else {
          throw (response.data);
        }
      })
      .then(response => {
        if(response.status === 200) {
          dispatch(uploadImageSuccess());
        }
        else {
          throw (response.data);
        }
      })
      .catch(error => {
        dispatch(displayNotification('error', '错误', error.message));
      });
  };
}

export function addRoom(data) {
  return (dispatch, getState) => {
    dispatch(beginAddRoom());
    const room = data.newRoom;
    const image = new FormData();
    image.append('logo', data.logo);
    const token = getState().user.token;
    return axios.post('/room' + '?token=' + token, room)
      .then(response => {
        if(response.status === 200) {
          dispatch(addRoomSuccess(response.data.room));
          const roomNum = getState().roomsStates.rooms.length;
          const room_id = getState().roomsStates.rooms[roomNum - 1].id;
          dispatch(beginUploadImage());
          return axios.put('/room/' + room_id + '/logo' + '?token=' + token, image);
        }
        else {
          throw (response.data);
        }
      })
      .then(response => {
        if(response.status === 200) {
          dispatch(uploadImageSuccess());
        }
        else {
          throw (response.data);
        }
      })
      .catch(error => {
        dispatch(displayNotification('error', '错误', error.message));
      });
  };
}
<|endoftext|>


<commit_before>'use strict'

const request = require('request');
const Q = require('q');
const companySearch = require('../services/company-api-gh');
const postSearch = require('../services/post-api-gh');
const utilities = require('../brain/utilities');

/**
 * Processes generic request
 *
 * @param genericRequest
 * @returns {genericResponse}
 */
function processRequest(genericRequest) {
  var genericResponse = {
    context: commonRequest.context
  };
  var userInput = commonRequest.userInput;

  // todo: do pre-response here
  utilities.preResponse(commonRequest.context);

  if (!userInput) {
    return Q.when(commonResponse);
  }

// this is where things get hairy ...
  var company = {};

  return Q.when(companySearch.findAllByText(userInput))
  .then(function (companySearchResults) {

    // ----------------
    // Pick out Company of interest from search results
    // (separate out this as function for testing - MAYBE?
    var exactMatch = companySearchResults.filter(function(eachCompany) {
      return eachCompany.name.toLowerCase() === userInput.toLowerCase();
    });
    if (!companySearchResults.length) {
      console.log("Nothing found in initial Company search");
      genericResponse.data = {};
      // returning an empty object as Posts for the next step in chain
      return Q.when({});
    }
    else if (exactMatch && exactMatch.length) {
      company = exactMatch[0];
      console.log("Found an exact match from Companies search");
    }
    else {
      company = companySearchResults[0];
      console.log("Going with first result from Companies search");
    };
    // ----------------

    // ----------------
    // attach Other Companies to Company object
    // (separate out this as function for testing)
    // ??? should this be here in the chain ???
    var companyNames = companySearchResults.map(function(eachCompany) {
      return eachCompany.name;
    })
    company.otherCompanies = companyNames.filter(function(name){
      return name.toLowerCase() !== userInput.toLowerCase();
    });
    // ----------------

    // TROUBLE STARTING HERE - Async trickiness ...
    console.log("Check-in BEFORE querying Posts of Company");
    return postSearch.findPostsofCompany(company)
  })
  .then(function (posts) {
    console.log("Check-in AFTER querying Posts of Company, within Promise chain.");
    company.posts = posts;
    genericResponse.data = company;
    console.log("About to return a Generic Response from action handler: " +JSON.stringify(genericResponse).substring(0,200));
    return genericResponse;
  });
}

// function attachPostsToCompany(company) {
//   return Q.when(postSearch.findPostsofCompany(company))
//     .then(function (posts) {
//       company.posts = posts;
//       return company;
//     })
// }

module.exports = {
  processRequest: processRequest
};
<commit_msg>debug<commit_after>'use strict'

const request = require('request');
const Q = require('q');
const companySearch = require('../services/company-api-gh');
const postSearch = require('../services/post-api-gh');
const utilities = require('../brain/utilities');

/**
 * Processes generic request
 *
 * @param genericRequest
 * @returns {genericResponse}
 */
function processRequest(genericRequest) {
  var genericResponse = {
    context: commonRequest.context
  };
  var userInput = genericRequest.userInput;

  // todo: do pre-response here
  utilities.preResponse(genericRequest.context);

  if (!userInput) {
    return Q.when(genericResponse);
  }

// this is where things get hairy ...
  var company = {};

  return Q.when(companySearch.findAllByText(userInput))
  .then(function (companySearchResults) {

    // ----------------
    // Pick out Company of interest from search results
    // (separate out this as function for testing - MAYBE?
    var exactMatch = companySearchResults.filter(function(eachCompany) {
      return eachCompany.name.toLowerCase() === userInput.toLowerCase();
    });
    if (!companySearchResults.length) {
      console.log("Nothing found in initial Company search");
      genericResponse.data = {};
      // returning an empty object as Posts for the next step in chain
      return Q.when({});
    }
    else if (exactMatch && exactMatch.length) {
      company = exactMatch[0];
      console.log("Found an exact match from Companies search");
    }
    else {
      company = companySearchResults[0];
      console.log("Going with first result from Companies search");
    };
    // ----------------

    // ----------------
    // attach Other Companies to Company object
    // (separate out this as function for testing)
    // ??? should this be here in the chain ???
    var companyNames = companySearchResults.map(function(eachCompany) {
      return eachCompany.name;
    })
    company.otherCompanies = companyNames.filter(function(name){
      return name.toLowerCase() !== userInput.toLowerCase();
    });
    // ----------------

    // TROUBLE STARTING HERE - Async trickiness ...
    console.log("Check-in BEFORE querying Posts of Company");
    return postSearch.findPostsofCompany(company)
  })
  .then(function (posts) {
    console.log("Check-in AFTER querying Posts of Company, within Promise chain.");
    company.posts = posts;
    genericResponse.data = company;
    console.log("About to return a Generic Response from action handler: " +JSON.stringify(genericResponse).substring(0,200));
    return genericResponse;
  });
}

// function attachPostsToCompany(company) {
//   return Q.when(postSearch.findPostsofCompany(company))
//     .then(function (posts) {
//       company.posts = posts;
//       return company;
//     })
// }

module.exports = {
  processRequest: processRequest
};
<|endoftext|>


<commit_before>const cache = {};
const prefixesFind = ['Webkit','Moz','O','ms', ''];
const prefixesReplace = ['-webkit-','-moz-','-o-','-ms-', ''];
const numPrefixes = prefixesFind.length;
let testElement;

/*
    Test style property for prefixed version

    @param [string]: Style property
    @return [string]: Cached property name
*/
const testPrefix = (key) => {
    testElement = testElement || document.createElement('div');

    if (cache[key] === false) {
        return false;
    } else {
        cache[key] = false;
    }

    for (var i = 0; i < numPrefixes; i++) {
        var prefix = prefixesFind[i],
            prefixed = (prefix === '') ? key : prefix + key.charAt(0).toUpperCase() + key.slice(1); //

        if (prefixed in testElement.style) {
            cache[key] = prefixesReplace[i] + key;
        }
    }

    return cache[key];
};

export default (key) => cache[key] || testPrefix(key);<commit_msg>cleanup<commit_after>const cache = {};
const prefixesFind = ['Webkit','Moz','O','ms', ''];
const prefixesReplace = ['-webkit-','-moz-','-o-','-ms-', ''];
const numPrefixes = prefixesFind.length;
let testElement;

/*
    Test style property for prefixed version

    @param [string]: Style property
    @return [string]: Cached property name
*/
const testPrefix = (key) => {
    testElement = testElement || document.createElement('div');

    if (cache[key] === false) {
        return false;
    } else {
        cache[key] = false;
    }

    for (var i = 0; i < numPrefixes; i++) {
        var prefix = prefixesFind[i],
            prefixed = (prefix === '') ? key : prefix + key.charAt(0).toUpperCase() + key.slice(1);

        if (prefixed in testElement.style) {
            cache[key] = prefixesReplace[i] + key;
        }
    }

    return cache[key];
};

export default (key) => cache[key] || testPrefix(key);<|endoftext|>


<commit_before>var express = require('express'),
    Path = require('path'),
    socketio = require('socket.io'),
    HTTP = require('http');

var BaseAdapter = require('../../base_adapter'),
    logger = require('../../utils/logger')('DebugAdapter'),
    SocketModel = require('./socket'),
    UrlChecker = require('./url_checker');

var DebugAdapter = function(bot) {
    BaseAdapter.call(this, bot);
    this.express = express()
        .use(express.static(Path.join(__dirname, 'public')))
        .get('/', (req, res) => {
            res.sendfile(__dirname + '/views/channel/index.html');
        });
    this.http = HTTP.Server(this.express);
    this.io = new socketio(this.http);
    this.users = [];
    this.channelName = '__debug_channel';
    this.urlChecker = new UrlChecker();
}

DebugAdapter.prototype = {
    setup: function() {
        return new Promise((resolve, reject) => {
            this.io.on('connection', (socket) => {
                this.users.push(new SocketModel(this, socket));
            });
            this.bot.mentionMarks = ['@giskard', 'giskard', 'bot'];
            this.bot.name = 'giskard';

            this.db.Channel.fromSlackData({
                id: this.channelName,
                name: 'debug',
                is_archived: false,
                is_member: true
            }).then((c) => {
                this.channelModel = c;
                resolve();
            }).catch(reject);
        });
    },
    run: function() {
        this.http.listen(2728, () => {
            logger.warning('DebugAdapter HTTP interface is ready on port 2728');
        });
    },
    dmForUser: function(u) {
        return this.channelName;
    },
    channelIdForChannel: function(c) {
        return c.id ? c.id : c;
    },
    getMentionTagForUser: function(user) {
        return '@' + user.username;
    },
    removeMessage: function(messageId, channel) {
        this.io.emit('delete_message', {
            ts: messageId
        });
        return Promise.resolve();
    },
    messageShouldBeUsedInContext: function(envelope) {
        return true;
    },
    sendTypingState: function(envelope) {
        this.io.emit('bot_is_typing');
    },
    addReaction: function(envelope, reaction) {
        this.io.emit('add_reaction_to', {
            id: envelope.message.ts,
            reaction: reaction
        });
        return Promise.resolve();
    },
    contextlessSend: function(target, string) {
        var what,
            channel = null;
        if (target.indexOf && target.indexOf('__debug_user') === 0) {
            what = 'user';
        } else {
            what = 'channel';
            channel = target.name;
        }
        var ts = Date.now();
        this.io.emit('bot_said', {
            to: what,
            message: string,
            target: target,
            channel: channel,
            ts: ts
        });
        this.checkForMetadata(string, ts);
        return Promise.resolve({ ts: ts });
    },
    send: function(envelope, string) {
        var ts = Date.now();
        this.io.emit('bot_said', {
            to: 'channel',
            message: string,
            ts: ts
        });
        logger.debug({
            to: 'channel',
            message: string
        });
        this.checkForMetadata(string, ts);
        return Promise.resolve({ ts: ts });
    },
    reply: function(envelope, string) {
        var breaksLine = string.trim()[0] === '>' ? '\n' : ' ';
        string = '@' + envelope.user.username + ':' + breaksLine + string;
        return this.send(envelope, string);
    },
    checkForMetadata: function(text, ts) {
        var proms = [];
        (text + '').replace(/(https?:\/\/[^\s]+)/g, (u) => {
            proms.push(this.urlChecker.checkUrl(u, ts));
            return '';
        });
        Promise.race(proms)
            .then((meta) => {
                this.io.emit('extra_metadata', meta);
            });
    },
    searchChannel: function(nameOrId) {
        var c = new this.db.Channel({
            name: nameOrId,
            id: nameOrId,
        });
        c.save = function() { };
        return Promise.resolve(c);
    }
};

BaseAdapter.setup(DebugAdapter);
module.exports = DebugAdapter;
<commit_msg>Remove spurious log<commit_after>var express = require('express'),
    Path = require('path'),
    socketio = require('socket.io'),
    HTTP = require('http');

var BaseAdapter = require('../../base_adapter'),
    logger = require('../../utils/logger')('DebugAdapter'),
    SocketModel = require('./socket'),
    UrlChecker = require('./url_checker');

var DebugAdapter = function(bot) {
    BaseAdapter.call(this, bot);
    this.express = express()
        .use(express.static(Path.join(__dirname, 'public')))
        .get('/', (req, res) => {
            res.sendfile(__dirname + '/views/channel/index.html');
        });
    this.http = HTTP.Server(this.express);
    this.io = new socketio(this.http);
    this.users = [];
    this.channelName = '__debug_channel';
    this.urlChecker = new UrlChecker();
}

DebugAdapter.prototype = {
    setup: function() {
        return new Promise((resolve, reject) => {
            this.io.on('connection', (socket) => {
                this.users.push(new SocketModel(this, socket));
            });
            this.bot.mentionMarks = ['@giskard', 'giskard', 'bot'];
            this.bot.name = 'giskard';

            this.db.Channel.fromSlackData({
                id: this.channelName,
                name: 'debug',
                is_archived: false,
                is_member: true
            }).then((c) => {
                this.channelModel = c;
                resolve();
            }).catch(reject);
        });
    },
    run: function() {
        this.http.listen(2728, () => {
            logger.warning('DebugAdapter HTTP interface is ready on port 2728');
        });
    },
    dmForUser: function(u) {
        return this.channelName;
    },
    channelIdForChannel: function(c) {
        return c.id ? c.id : c;
    },
    getMentionTagForUser: function(user) {
        return '@' + user.username;
    },
    removeMessage: function(messageId, channel) {
        this.io.emit('delete_message', {
            ts: messageId
        });
        return Promise.resolve();
    },
    messageShouldBeUsedInContext: function(envelope) {
        return true;
    },
    sendTypingState: function(envelope) {
        this.io.emit('bot_is_typing');
    },
    addReaction: function(envelope, reaction) {
        this.io.emit('add_reaction_to', {
            id: envelope.message.ts,
            reaction: reaction
        });
        return Promise.resolve();
    },
    contextlessSend: function(target, string) {
        var what,
            channel = null;
        if (target.indexOf && target.indexOf('__debug_user') === 0) {
            what = 'user';
        } else {
            what = 'channel';
            channel = target.name;
        }
        var ts = Date.now();
        this.io.emit('bot_said', {
            to: what,
            message: string,
            target: target,
            channel: channel,
            ts: ts
        });
        this.checkForMetadata(string, ts);
        return Promise.resolve({ ts: ts });
    },
    send: function(envelope, string) {
        var ts = Date.now();
        this.io.emit('bot_said', {
            to: 'channel',
            message: string,
            ts: ts
        });
        this.checkForMetadata(string, ts);
        return Promise.resolve({ ts: ts });
    },
    reply: function(envelope, string) {
        var breaksLine = string.trim()[0] === '>' ? '\n' : ' ';
        string = '@' + envelope.user.username + ':' + breaksLine + string;
        return this.send(envelope, string);
    },
    checkForMetadata: function(text, ts) {
        var proms = [];
        (text + '').replace(/(https?:\/\/[^\s]+)/g, (u) => {
            proms.push(this.urlChecker.checkUrl(u, ts));
            return '';
        });
        Promise.race(proms)
            .then((meta) => {
                this.io.emit('extra_metadata', meta);
            });
    },
    searchChannel: function(nameOrId) {
        var c = new this.db.Channel({
            name: nameOrId,
            id: nameOrId,
        });
        c.save = function() { };
        return Promise.resolve(c);
    }
};

BaseAdapter.setup(DebugAdapter);
module.exports = DebugAdapter;
<|endoftext|>


<commit_before>openerp.web_default_home = function (openerp) {
    var QWeb = openerp.web.qweb;
    QWeb.add_template('/web_default_home/static/src/xml/web_default_home.xml');

    openerp.web_default_home = {
        applications: [
            [
                {
                    module: 'crm', name: 'CRM',
                    help: "Acquire leads, follow opportunities, manage prospects and phone calls, \u2026"
                }, {
                    module: 'sale', name: 'Sales',
                    help: "Do quotations, follow sales orders, invoice and control deliveries"
                }, {
                    module: 'account_voucher', name: 'Invoicing',
                    help: "Send invoice, track payments and reminders"
                }, {
                    module: 'project', name: 'Projects',
                    help: "Manage projects, track tasks, invoice task works, follow issues, \u2026"
                }
            ], [
                {
                    module: 'purchase', name: 'Purchase',
                    help: "Do purchase orders, control invoices and reception, follow your suppliers, \u2026"
                }, {
                    module: 'stock', name: 'Warehouse',
                    help: "Track your stocks, schedule product moves, manage incoming and outgoing shipments, \u2026"
                }, {
                    module: 'hr', name: 'Human Resources',
                    help: "Manage employees and their contracts, follow laves, recruit people, \u2026"
                }, {
                    module: 'point_of_sale', name: 'Point of Sales',
                    help: "Manage shop sales, use touch-screen POS"
                }
            ], [
                {
                    module: 'profile_tools', name: 'Extra Tools',
                    help: "Track ideas, manage lunch, create surveys, share data"
                }, {
                    module: 'mrp', name: 'Manufacturing',
                    help: "Manage your manufacturing, control your supply chain, personalize master data, \u2026"
                }, {
                    module: 'marketing', name: 'Marketing',
                    help: "Manage campaigns, follow activities, automate emails, \u2026"
                }, {
                    module: 'knowledge', name: 'Knowledge',
                    help: "Track your documents, browse your files, \u2026"
                }
            ]
        ]
    };

    openerp.web.WebClient.include({
        default_home: function () {
            var self = this,
                // resig class can't handle _super in async contexts, by the
                // time async callback comes back, _super has already been
                // reset to a baseline value of this.prototype (or something
                // like that)
                old_home = this._super;
            var Installer = new openerp.web.DataSet(
                    this, 'base.setup.installer');
            Installer.call('already_installed', [], function (installed_modules) {
                if (!_(installed_modules).isEmpty()) {
                    return old_home.call(self);
                }
                self.action_manager.do_action({
                    type: 'ir.actions.client',
                    tag: 'home.default'
                })
            }, function (err, event) {
                event.preventDefault();
                return old_home.call(self);
            });
        }
    });

    openerp.web.client_actions.add(
        'home.default', 'openerp.web_default_home.DefaultHome');
    openerp.web_default_home.DefaultHome = openerp.web.View.extend({
        template: 'StaticHome',
        start: function () {
            var r = this._super(), self = this;
            this.$element.delegate('.oe-static-home-tile-text button', 'click', function () {
                self.install_module($(this).val());
            });
            return r;
        },
        render: function () {
            return this._super({
                url: window.location.protocol + '//' + window.location.host + window.location.pathname,
                session: this.session,
                rows: openerp.web_default_home.applications
            })
        },
        install_module: function (module_name) {
            var Modules = new openerp.web.DataSetSearch(
                this, 'ir.module.module', null, [['name', '=', module_name], ['state', '=', 'uninstalled']]);
            var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade');

            $.blockUI({message:''});
            Modules.read_slice(['id'], {}, function (records) {
                if (!(records.length === 1)) { return; }
                Modules.call('state_update',
                    [_.pluck(records, 'id'), 'to install', ['uninstalled']],
                    function () {
                        Upgrade.call('upgrade_module', [[]], function () {
                            $.unblockUI();
                            // TODO: less brutal reloading
                            window.location.reload(true);
                        });
                    }
                )
            });
        }
    });
};
<commit_msg>[FIX] installing a module should trigger the launch of any pending configuration wizard<commit_after>openerp.web_default_home = function (openerp) {
    var QWeb = openerp.web.qweb;
    QWeb.add_template('/web_default_home/static/src/xml/web_default_home.xml');

    openerp.web_default_home = {
        applications: [
            [
                {
                    module: 'crm', name: 'CRM',
                    help: "Acquire leads, follow opportunities, manage prospects and phone calls, \u2026"
                }, {
                    module: 'sale', name: 'Sales',
                    help: "Do quotations, follow sales orders, invoice and control deliveries"
                }, {
                    module: 'account_voucher', name: 'Invoicing',
                    help: "Send invoice, track payments and reminders"
                }, {
                    module: 'project', name: 'Projects',
                    help: "Manage projects, track tasks, invoice task works, follow issues, \u2026"
                }
            ], [
                {
                    module: 'purchase', name: 'Purchase',
                    help: "Do purchase orders, control invoices and reception, follow your suppliers, \u2026"
                }, {
                    module: 'stock', name: 'Warehouse',
                    help: "Track your stocks, schedule product moves, manage incoming and outgoing shipments, \u2026"
                }, {
                    module: 'hr', name: 'Human Resources',
                    help: "Manage employees and their contracts, follow laves, recruit people, \u2026"
                }, {
                    module: 'point_of_sale', name: 'Point of Sales',
                    help: "Manage shop sales, use touch-screen POS"
                }
            ], [
                {
                    module: 'profile_tools', name: 'Extra Tools',
                    help: "Track ideas, manage lunch, create surveys, share data"
                }, {
                    module: 'mrp', name: 'Manufacturing',
                    help: "Manage your manufacturing, control your supply chain, personalize master data, \u2026"
                }, {
                    module: 'marketing', name: 'Marketing',
                    help: "Manage campaigns, follow activities, automate emails, \u2026"
                }, {
                    module: 'knowledge', name: 'Knowledge',
                    help: "Track your documents, browse your files, \u2026"
                }
            ]
        ]
    };

    openerp.web.WebClient.include({
        default_home: function () {
            var self = this,
                // resig class can't handle _super in async contexts, by the
                // time async callback comes back, _super has already been
                // reset to a baseline value of this.prototype (or something
                // like that)
                old_home = this._super;
            var Installer = new openerp.web.DataSet(
                    this, 'base.setup.installer');
            Installer.call('already_installed', [], function (installed_modules) {
                if (!_(installed_modules).isEmpty()) {
                    return old_home.call(self);
                }
                self.action_manager.do_action({
                    type: 'ir.actions.client',
                    tag: 'home.default'
                })
            }, function (err, event) {
                event.preventDefault();
                return old_home.call(self);
            });
        }
    });

    openerp.web.client_actions.add(
        'home.default', 'openerp.web_default_home.DefaultHome');
    openerp.web_default_home.DefaultHome = openerp.web.View.extend({
        template: 'StaticHome',
        start: function () {
            var r = this._super(), self = this;
            this.$element.delegate('.oe-static-home-tile-text button', 'click', function () {
                self.install_module($(this).val());
            });
            return r;
        },
        render: function () {
            return this._super({
                url: window.location.protocol + '//' + window.location.host + window.location.pathname,
                session: this.session,
                rows: openerp.web_default_home.applications
            })
        },
        install_module: function (module_name) {
            var self = this;
            var Modules = new openerp.web.DataSetSearch(
                this, 'ir.module.module', null,
                [['name', '=', module_name], ['state', '=', 'uninstalled']]);
            var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade');

            $.blockUI({message:''});
            Modules.read_slice(['id'], {}, function (records) {
                if (!(records.length === 1)) { return; }
                Modules.call('state_update',
                    [_.pluck(records, 'id'), 'to install', ['uninstalled']],
                    function () {
                        Upgrade.call('upgrade_module', [[]], function () {
                            self.run_configuration_wizards();
                        });
                    }
                )
            });
        },
        run_configuration_wizards: function () {
            var self = this;
            new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) {
                $.unblockUI();
                self.do_action(action, function () {
                    // TODO: less brutal reloading
                    window.location.reload(true);
                });
            });
        }
    });
};
<|endoftext|>


<commit_before>// Base :: Sass :: Lint
'use strict';

var gulp = require('gulp');
var gutil = require('gulp-util');
var lint = require('gulp-scss-lint');

var exec = require('child_process').exec;
var parse = function(data) {
  return data.toString().replace(/\n\s*\n/g,'');
};

var commandOptions = {
  env: process.env,
  cwd: process.cwd(),
  maxBuffer: 300 * 1024,
};

var lintProcess = function() {
  gutil.log(gutil.colors.yellow('Testing your .scss files…'));
  return new Promise(function(resolve, reject) {
    exec('bundle exec scss-lint', commandOptions, function(error, report) {
      if (report) {
        return reject(report);
      }
      // Check for important error codes
      if(error && error.code !== 1 && error.code !== 2 && error.code !== 65) {
        return reject(report);
      }
      return resolve(report);
    });
  });
};

gulp.task('lint', function(callback) {
  return lintProcess()
    .then(function(report) {
      var message = gutil.colors.green('Passed! Your .scss looks spectacular');
      gutil.log(message, '😄');
    })
    .catch(function(report) {
      var message = gutil.colors.red('Failed: There were errors in your .scss');
      gutil.log(message, '😱');
      console.log(parse(report));
      process.exit(1);
    });
});
<commit_msg>Adjusted failed lint message<commit_after>// Base :: Sass :: Lint
'use strict';

var gulp = require('gulp');
var gutil = require('gulp-util');
var lint = require('gulp-scss-lint');

var exec = require('child_process').exec;
var parse = function(data) {
  return data.toString().replace(/\n\s*\n/g,'');
};

var commandOptions = {
  env: process.env,
  cwd: process.cwd(),
  maxBuffer: 300 * 1024,
};

var lintProcess = function() {
  gutil.log(gutil.colors.yellow('Testing your .scss files…'));
  return new Promise(function(resolve, reject) {
    exec('bundle exec scss-lint', commandOptions, function(error, report) {
      if (report) {
        return reject(report);
      }
      // Check for important error codes
      if(error && error.code !== 1 && error.code !== 2 && error.code !== 65) {
        return reject(report);
      }
      return resolve(report);
    });
  });
};

gulp.task('lint', function(callback) {
  return lintProcess()
    .then(function(report) {
      var message = gutil.colors.green('Passed! Your .scss looks spectacular');
      gutil.log(message, '😄');
    })
    .catch(function(report) {
      var message = gutil.colors.red('Failed! There were errors in your .scss');
      gutil.log(message, '😱');
      console.log(parse(report));
      process.exit(1);
    });
});
<|endoftext|>


<commit_before>/*

ZVM - the ifvms.js Z-Machine (versions 3-5, 8)
==============================================

Copyright (c) 2017 The ifvms.js team
MIT licenced
https://github.com/curiousdannii/ifvms.js

*/

/*

This file is the public API of ZVM, which is based on the API of Quixe:
https://github.com/erkyrath/quixe/wiki/Quixe-Without-GlkOte#quixes-api

ZVM willfully ignores the standard in these ways:
	Non-buffered output is not supported
	Saving tables is not supported (yet?)
	No interpreter number or version is set

Any other non-standard behaviour should be considered a bug

*/

'use strict';

var utils = require( './common/utils.js' ),
file = require( './common/file.js' ),

default_options = {
	stack_len: 100 * 1000,
	undo_len: 1000 * 1000,
},

api = {

	init: function()
	{
		// Create this here so that it won't be cleared on restart
		this.jit = {};

		// The Quixe API expects the start function to be named init
		this.init = this.start;
	},

	prepare: function( storydata, options )
	{
		// If we are not given a glk option then we cannot continue
		if ( !options.Glk )
		{
			throw new Error( 'A reference to Glk is required' );
		}
		this.Glk = options.Glk;
		this.data = storydata;
		this.options = utils.extend( {}, default_options, options );
	},

	start: function()
	{
		var Glk = this.Glk,
		data;
		try
		{
			// Identify the format and version number of the data file we were given
			data = file.identify( this.data );
			delete this.data;
			if ( !data || data.format !== 'ZCOD' )
			{
				throw new Error( 'This is not a Z-Code file' );
			}
			if ( [ 3, 4, 5, 8 ].indexOf( data.version ) < 0 )
			{
				throw new Error( 'Unsupported Z-Machine version: ' + data.version );
			}

			// Load the storyfile we are given into our MemoryView (an enhanced DataView)
			this.m = utils.MemoryView( data.data );

			// Make a seperate MemoryView for the ram, and store the original ram
			this.staticmem = this.m.getUint16( 0x0E );
			this.ram = utils.MemoryView( this.m.buffer, 0, this.staticmem );
			this.origram = this.m.getUint8Array( 0, this.staticmem );

			// Cache the game signature
			let signature = ''
			let i = 0
			while ( i < 0x1E )
			{
				signature += ( this.origram[i] < 0x10 ? '0' : '' ) + this.origram[i++].toString( 16 )
			}
			this.signature = signature

			// Handle loading and clearing autosaves
			let autorestored
			const Dialog = this.options.Dialog
			if ( Dialog )
			{
				if ( this.options.clear_vm_autosave )
				{
					Dialog.autosave_write( signature, null )
				}
				else if ( this.options.do_vm_autosave )
				{
					try
					{
						const snapshot = Dialog.autosave_read( signature )
						if ( snapshot )
						{
							this.do_autorestore( snapshot )
							autorestored = 1
						}
					}
					catch (ex)
					{
						this.log( 'Autorestore failed, deleting it' )
						Dialog.autosave_write( signature, null )
					}
				}
			}

			// Initiate the engine, run, and wait for our first Glk event
			if ( !autorestored )
			{
				this.restart();
				this.run();
			}
			if ( !this.quit )
			{
				this.glk_event = new Glk.RefStruct();
				if ( !this.glk_blocking_call )
				{
					Glk.glk_select( this.glk_event );
				}
				else
				{
					this.glk_event.push_field( this.glk_blocking_call );
				}
			}
			Glk.update()
		}
		catch ( e )
		{
			if ( e instanceof Error )
			{
				e.message = 'ZVM start: ' + e.message;
			}
			Glk.fatal_error( e );
			throw e;
		}
	},

	resume: function( resumearg )
	{
		var Glk = this.Glk,
		glk_event = this.glk_event,
		event_type,
		run;

		try
		{
			event_type = glk_event.get_field( 0 );

			// Process the event
			if ( event_type === 2 )
			{
				this.handle_char_input( glk_event.get_field( 2 ) );
				run = 1;
			}
			if ( event_type === 3 )
			{
				this.handle_line_input( glk_event.get_field( 2 ), glk_event.get_field( 3 ) );
				run = 1;
			}

			// Arrange events
			if ( event_type === 5 )
			{
				this.update_screen_size()
			}

			// glk_fileref_create_by_prompt handler
			if ( event_type === 'fileref_create_by_prompt' )
			{
				run = this.handle_create_fileref( resumearg );
			}

			this.glk_blocking_call = null;
			if ( run )
			{
				this.run();
			}

			// Wait for another event
			if ( !this.quit )
			{
				this.glk_event = new Glk.RefStruct();
				if ( !this.glk_blocking_call )
				{
					Glk.glk_select( this.glk_event );
				}
				else
				{
					this.glk_event.push_field( this.glk_blocking_call );
				}
			}
			Glk.update()
		}
		catch ( e )
		{
			if ( e instanceof Error )
			{
				e.message = 'ZVM: ' + e.message;
			}
			Glk.fatal_error( e );
			throw e;
		}
	},

	get_signature: function()
	{
		return this.signature
	},

	// Run
	run: function()
	{
		var pc,
		result;

		// Stop when ordered to
		this.stop = 0;
		while ( !this.stop )
		{
			pc = this.pc;
			if ( !this.jit[pc] )
			{
				this.compile();
			}
			result = this.jit[pc]( this );

			// Return from a VM func if the JIT function returned a result
			if ( !isNaN( result ) )
			{
				this.ret( result );
			}
		}
	},

	// Compile a JIT routine
	compile: function()
	{
		var context = this.disassemble();

		// Compile the routine with new Function()
		this.jit[context.pc] = new Function( 'e', '' + context );

		if ( context.pc < this.staticmem )
		{
			this.log( 'Caching a JIT function in dynamic memory: ' + context.pc );
		}
	},

},

VM = utils.Class.subClass( utils.extend(
	api,
	require( './zvm/runtime.js' ),
	require( './zvm/text.js' ),
	require( './zvm/io.js' ),
	require( './zvm/disassembler.js' )
) );

module.exports = VM;
<commit_msg>Don't rethrow caught errors<commit_after>/*

ZVM - the ifvms.js Z-Machine (versions 3-5, 8)
==============================================

Copyright (c) 2017 The ifvms.js team
MIT licenced
https://github.com/curiousdannii/ifvms.js

*/

/*

This file is the public API of ZVM, which is based on the API of Quixe:
https://github.com/erkyrath/quixe/wiki/Quixe-Without-GlkOte#quixes-api

ZVM willfully ignores the standard in these ways:
	Non-buffered output is not supported
	Saving tables is not supported (yet?)
	No interpreter number or version is set

Any other non-standard behaviour should be considered a bug

*/

'use strict';

var utils = require( './common/utils.js' ),
file = require( './common/file.js' ),

default_options = {
	stack_len: 100 * 1000,
	undo_len: 1000 * 1000,
},

api = {

	init: function()
	{
		// Create this here so that it won't be cleared on restart
		this.jit = {};

		// The Quixe API expects the start function to be named init
		this.init = this.start;
	},

	prepare: function( storydata, options )
	{
		// If we are not given a glk option then we cannot continue
		if ( !options.Glk )
		{
			throw new Error( 'A reference to Glk is required' );
		}
		this.Glk = options.Glk;
		this.data = storydata;
		this.options = utils.extend( {}, default_options, options );
	},

	start: function()
	{
		var Glk = this.Glk,
		data;
		try
		{
			// Identify the format and version number of the data file we were given
			data = file.identify( this.data );
			delete this.data;
			if ( !data || data.format !== 'ZCOD' )
			{
				throw new Error( 'This is not a Z-Code file' );
			}
			if ( [ 3, 4, 5, 8 ].indexOf( data.version ) < 0 )
			{
				throw new Error( 'Unsupported Z-Machine version: ' + data.version );
			}

			// Load the storyfile we are given into our MemoryView (an enhanced DataView)
			this.m = utils.MemoryView( data.data );

			// Make a seperate MemoryView for the ram, and store the original ram
			this.staticmem = this.m.getUint16( 0x0E );
			this.ram = utils.MemoryView( this.m.buffer, 0, this.staticmem );
			this.origram = this.m.getUint8Array( 0, this.staticmem );

			// Cache the game signature
			let signature = ''
			let i = 0
			while ( i < 0x1E )
			{
				signature += ( this.origram[i] < 0x10 ? '0' : '' ) + this.origram[i++].toString( 16 )
			}
			this.signature = signature

			// Handle loading and clearing autosaves
			let autorestored
			const Dialog = this.options.Dialog
			if ( Dialog )
			{
				if ( this.options.clear_vm_autosave )
				{
					Dialog.autosave_write( signature, null )
				}
				else if ( this.options.do_vm_autosave )
				{
					try
					{
						const snapshot = Dialog.autosave_read( signature )
						if ( snapshot )
						{
							this.do_autorestore( snapshot )
							autorestored = 1
						}
					}
					catch (ex)
					{
						this.log( 'Autorestore failed, deleting it' )
						Dialog.autosave_write( signature, null )
					}
				}
			}

			// Initiate the engine, run, and wait for our first Glk event
			if ( !autorestored )
			{
				this.restart();
				this.run();
			}
			if ( !this.quit )
			{
				this.glk_event = new Glk.RefStruct();
				if ( !this.glk_blocking_call )
				{
					Glk.glk_select( this.glk_event );
				}
				else
				{
					this.glk_event.push_field( this.glk_blocking_call );
				}
			}
			Glk.update()
		}
		catch ( e )
		{
			Glk.fatal_error( e );
			console.log( e );
		}
	},

	resume: function( resumearg )
	{
		var Glk = this.Glk,
		glk_event = this.glk_event,
		event_type,
		run;

		try
		{
			event_type = glk_event.get_field( 0 );

			// Process the event
			if ( event_type === 2 )
			{
				this.handle_char_input( glk_event.get_field( 2 ) );
				run = 1;
			}
			if ( event_type === 3 )
			{
				this.handle_line_input( glk_event.get_field( 2 ), glk_event.get_field( 3 ) );
				run = 1;
			}

			// Arrange events
			if ( event_type === 5 )
			{
				this.update_screen_size()
			}

			// glk_fileref_create_by_prompt handler
			if ( event_type === 'fileref_create_by_prompt' )
			{
				run = this.handle_create_fileref( resumearg );
			}

			this.glk_blocking_call = null;
			if ( run )
			{
				this.run();
			}

			// Wait for another event
			if ( !this.quit )
			{
				this.glk_event = new Glk.RefStruct();
				if ( !this.glk_blocking_call )
				{
					Glk.glk_select( this.glk_event );
				}
				else
				{
					this.glk_event.push_field( this.glk_blocking_call );
				}
			}
			Glk.update()
		}
		catch ( e )
		{
			Glk.fatal_error( e );
			console.log( e );
		}
	},

	get_signature: function()
	{
		return this.signature
	},

	// Run
	run: function()
	{
		var pc,
		result;

		// Stop when ordered to
		this.stop = 0;
		while ( !this.stop )
		{
			pc = this.pc;
			if ( !this.jit[pc] )
			{
				this.compile();
			}
			result = this.jit[pc]( this );

			// Return from a VM func if the JIT function returned a result
			if ( !isNaN( result ) )
			{
				this.ret( result );
			}
		}
	},

	// Compile a JIT routine
	compile: function()
	{
		var context = this.disassemble();

		// Compile the routine with new Function()
		this.jit[context.pc] = new Function( 'e', '' + context );

		if ( context.pc < this.staticmem )
		{
			this.log( 'Caching a JIT function in dynamic memory: ' + context.pc );
		}
	},

},

VM = utils.Class.subClass( utils.extend(
	api,
	require( './zvm/runtime.js' ),
	require( './zvm/text.js' ),
	require( './zvm/io.js' ),
	require( './zvm/disassembler.js' )
) );

module.exports = VM;
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	{env, argv} = process,
	{src} = require('config');

const
	fs = require('fs'),
	path = require('path'),
	minimist = require('minimist');

/**
 * Process arguments
 */
const args = exports.args = minimist(argv.slice(2));
args.env && (env.NODE_ENV = args.env);

/**
 * Output pattern
 */
exports.output = r('[hash]_[name]');

/**
 * File hash length
 */
exports.hashLength = 15;

/**
 * Project version
 * (for longterm caching)
 */
exports.version = '';

if (isProd) {
	if (Number(env.BUMP_VERSION)) {
		if (env.VERSION) {
			exports.version = env.VERSION;

		} else {
			const
				src = include('package.json'),
				pack = require(src),
				v = pack.version.split('.');

			pack.version = [v[0], v[1], Number(v[2]) + 1].join('.');
			env.VERSION = exports.version = `${pack.version.replace(/\./g, '')}_`;
			fs.writeFileSync(src, `${JSON.stringify(pack, null, 2)}\n`);
		}
	}

	if (!args.fast) {
		args.fast = true;
		argv.push('--fast');
	}
}

/**
 * Build cache folder
 */
exports.buildCache = path.join(src.cwd(), 'app-cache');

/**
 * Path to assets.json
 */
exports.assetsJSON = r(`${version}assets.json`);

/* eslint-disable no-unused-vars */

/**
 * Returns WebPack output path string from the specified with hash parameters
 * (for longterm cache)
 *
 * @param {string} output - source string
 * @param {boolean=} [chunk] - if true, then the specified output is a chunk
 */
exports.hash = function (output, chunk) {
	const l = exports.hashLength;
	return output.replace(/\[hash]_/g, isProd ? chunk ? `[chunkhash:${l}]_` : `[hash:${l}]_` : '');
};

/* eslint-enable no-unused-vars */

function r(file) {
	return `./${path.relative(src.cwd(), path.join(src.clientOutput(), file)).replace(/\\/g, '/')}`;
}
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	{env, argv} = process,
	{src} = require('config');

const
	fs = require('fs'),
	path = require('path'),
	minimist = require('minimist');

/**
 * Process arguments
 */
const args = exports.args = minimist(argv.slice(2));
args.env && (env.NODE_ENV = args.env);

/**
 * Output pattern
 */
exports.output = r('[hash]_[name]');

/**
 * File hash length
 */
exports.hashLength = 15;

/**
 * Project version
 * (for longterm caching)
 */
exports.version = '';

if (isProd) {
	if (Number(env.BUMP_VERSION)) {
		if (env.VERSION) {
			exports.version = env.VERSION;

		} else {
			const
				src = include('package.json'),
				pack = require(src),
				v = pack.version.split('.');

			pack.version = [v[0], v[1], Number(v[2]) + 1].join('.');
			env.VERSION = exports.version = `${pack.version.replace(/\./g, '')}_`;
			fs.writeFileSync(src, `${JSON.stringify(pack, null, 2)}\n`);
		}
	}

	if (!args.fast) {
		args.fast = true;
		argv.push('--fast');
	}
}

/**
 * Build cache folder
 */
exports.buildCache = path.join(src.cwd(), 'app-cache');

/**
 * Path to assets.json
 */
exports.assetsJSON = r(`${exports.version}assets.json`);

/* eslint-disable no-unused-vars */

/**
 * Returns WebPack output path string from the specified with hash parameters
 * (for longterm cache)
 *
 * @param {string} output - source string
 * @param {boolean=} [chunk] - if true, then the specified output is a chunk
 */
exports.hash = function (output, chunk) {
	const l = exports.hashLength;
	return output.replace(/\[hash]_/g, isProd ? chunk ? `[chunkhash:${l}]_` : `[hash:${l}]_` : '');
};

/* eslint-enable no-unused-vars */

function r(file) {
	return `./${path.relative(src.cwd(), path.join(src.clientOutput(), file)).replace(/\\/g, '/')}`;
}
<|endoftext|>


<commit_before>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactSwipeable = require('react-swipeable');

var _reactSwipeable2 = _interopRequireDefault(_reactSwipeable);

var ImageGallery = _react2['default'].createClass({

  displayName: 'ImageGallery',

  propTypes: {
    items: _react2['default'].PropTypes.array.isRequired,
    showThumbnails: _react2['default'].PropTypes.bool,
    showBullets: _react2['default'].PropTypes.bool,
    autoPlay: _react2['default'].PropTypes.bool,
    lazyLoad: _react2['default'].PropTypes.bool,
    slideInterval: _react2['default'].PropTypes.number,
    onSlide: _react2['default'].PropTypes.func
  },

  getDefaultProps: function getDefaultProps() {
    return {
      lazyLoad: true,
      showThumbnails: true,
      showBullets: false,
      autoPlay: false,
      slideInterval: 4000
    };
  },

  getInitialState: function getInitialState() {
    return {
      currentIndex: 0,
      thumbnailsTranslateX: 0,
      containerWidth: 0
    };
  },

  componentDidUpdate: function componentDidUpdate(prevProps, prevState) {
    if (prevState.containerWidth !== this.state.containerWidth || prevProps.showThumbnails !== this.props.showThumbnails) {

      // adjust thumbnail container when window width is adjusted
      // when the container resizes, thumbnailsTranslateX
      // should always be negative (moving right),
      // if container fits all thumbnails its set to 0

      this._setThumbnailsTranslateX(-this._getScrollX(this.state.currentIndex > 0 ? 1 : 0) * this.state.currentIndex);
    }

    if (prevState.currentIndex !== this.state.currentIndex) {

      // call back function if provided
      if (this.props.onSlide) {
        this.props.onSlide(this.state.currentIndex);
      }

      // calculates thumbnail container position
      if (this.state.currentIndex === 0) {
        this._setThumbnailsTranslateX(0);
      } else {
        var indexDifference = Math.abs(prevState.currentIndex - this.state.currentIndex);
        var _scrollX = this._getScrollX(indexDifference);
        if (_scrollX > 0) {
          if (prevState.currentIndex < this.state.currentIndex) {
            this._setThumbnailsTranslateX(this.state.thumbnailsTranslateX - _scrollX);
          } else if (prevState.currentIndex > this.state.currentIndex) {
            this._setThumbnailsTranslateX(this.state.thumbnailsTranslateX + _scrollX);
          }
        }
      }
    }
  },

  componentDidMount: function componentDidMount() {
    this._handleResize();
    if (this.props.autoPlay) {
      this.play();
    }
    if (window.addEventListener) {
      window.addEventListener('resize', this._handleResize);
    } else if (window.attachEvent) {
      window.attachEvent('onresize', this._handleResize);
    }
  },

  componentWillUnmount: function componentWillUnmount() {
    if (window.removeEventListener) {
      window.removeEventListener('resize', this._handleResize);
    } else if (window.detachEvent) {
      window.detachEvent('onresize', this._handleResize);
    }

    if (this._intervalId) {
      window.clearInterval(this._intervalId);
      this._intervalId = null;
    }
  },

  slideToIndex: function slideToIndex(index, event) {
    var slideCount = this.props.items.length - 1;

    if (index < 0) {
      this.setState({ currentIndex: slideCount });
    } else if (index > slideCount) {
      this.setState({ currentIndex: 0 });
    } else {
      this.setState({ currentIndex: index });
    }
    if (event) {
      if (this._intervalId) {
        // user event, reset interval
        this.pause();
        this.play();
      }
      event.preventDefault();
    }
  },

  play: function play() {
    var _this = this;

    if (this._intervalId) {
      return;
    }
    this._intervalId = window.setInterval((function () {
      if (!_this.state.hovering) {
        _this.slideToIndex(_this.state.currentIndex + 1);
      }
    }).bind(this), this.props.slideInterval);
  },

  pause: function pause() {
    if (this._intervalId) {
      window.clearInterval(this._intervalId);
      this._intervalId = null;
    }
  },

  _setThumbnailsTranslateX: function _setThumbnailsTranslateX(x) {
    this.setState({ thumbnailsTranslateX: x });
  },

  _handleResize: function _handleResize() {
    this.setState({ containerWidth: this.refs.imageGallery.offsetWidth });
  },

  _getScrollX: function _getScrollX(indexDifference) {
    if (this.refs.thumbnails) {
      var thumbNode = this.refs.thumbnails;
      if (thumbNode.scrollWidth <= this.state.containerWidth) {
        return 0;
      }
      var totalThumbnails = thumbNode.children.length;

      // total scroll-x required to see the last thumbnail
      var totalScrollX = thumbNode.scrollWidth - this.state.containerWidth;

      // scroll-x required per index change
      var perIndexScrollX = totalScrollX / (totalThumbnails - 1);

      return indexDifference * perIndexScrollX;
    }
  },

  _handleMouseOver: function _handleMouseOver() {
    this.setState({ hovering: true });
  },

  _handleMouseLeave: function _handleMouseLeave() {
    this.setState({ hovering: false });
  },

  _getAlignment: function _getAlignment(index) {
    var currentIndex = this.state.currentIndex;
    var alignment = '';
    switch (index) {
      case currentIndex - 1:
        alignment = 'left';
        break;
      case currentIndex:
        alignment = 'center';
        break;
      case currentIndex + 1:
        alignment = 'right';
        break;
    }

    if (this.props.items.length >= 3) {
      if (index === 0 && currentIndex === this.props.items.length - 1) {
        // set first slide as right slide if were sliding right from last slide
        alignment = 'right';
      } else if (index === this.props.items.length - 1 && currentIndex === 0) {
        // set last slide as left slide if were sliding left from first slide
        alignment = 'left';
      }
    }

    return alignment;
  },

  renderSlides: function renderSlides(slides) {
    return this.props.items.length >= 2 ? [_react2['default'].createElement('a', { key: 'leftNav',
      className: 'image-gallery-left-nav',
      onTouchStart: this.swipePrev,
      onClick: this.swipePrev }), _react2['default'].createElement('a', {
      key: 'rightNav',
      className: 'image-gallery-right-nav',
      onTouchStart: this.swipeNext,
      onClick: this.swipeNext }), _react2['default'].createElement(
      _reactSwipeable2['default'],
      {
        key: 'swipeable',
        onSwipedLeft: this.swipeNext,
        onSwipedRight: this.swipePrev },
      _react2['default'].createElement(
        'div',
        { className: 'image-gallery-slides' },
        slides
      )
    )] : _react2['default'].createElement(
      'div',
      { className: 'image-gallery-slides' },
      slides
    );
  },

  render: function render() {
    var _this2 = this;

    var currentIndex = this.state.currentIndex;
    var thumbnailStyle = {
      MozTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      WebkitTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      OTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      msTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      transform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)'
    };

    var slides = [];
    var thumbnails = [];
    var bullets = [];

    this.props.items.map(function (item, index) {
      var alignment = _this2._getAlignment(index);
      if (_this2.props.lazyLoad) {
        if (alignment) {
          slides.push(_react2['default'].createElement(
            'div',
            {
              key: index,
              className: 'image-gallery-slide ' + alignment },
            _react2['default'].createElement('img', { src: item.original })
          ));
        }
      } else {
        slides.push(_react2['default'].createElement(
          'div',
          {
            key: index,
            className: 'image-gallery-slide ' + alignment },
          _react2['default'].createElement('img', { src: item.original })
        ));
      }

      if (_this2.props.showThumbnails) {
        thumbnails.push(_react2['default'].createElement(
          'a',
          {
            key: index,
            className: 'image-gallery-thumbnail ' + (currentIndex === index ? 'active' : ''),

            onTouchStart: _this2.slideToIndex.bind(_this2, index),
            onClick: _this2.slideToIndex.bind(_this2, index) },
          _react2['default'].createElement('img', { src: item.thumbnail })
        ));
      }

      if (_this2.props.showBullets) {
        bullets.push(_react2['default'].createElement('li', {
          key: index,
          className: 'image-gallery-bullet ' + (currentIndex === index ? 'active' : ''),

          onTouchStart: _this2.slideToIndex.bind(_this2, index),
          onClick: _this2.slideToIndex.bind(_this2, index) }));
      }
    });

    this.swipePrev = this.slideToIndex.bind(this, currentIndex - 1);
    this.swipeNext = this.slideToIndex.bind(this, currentIndex + 1);

    return _react2['default'].createElement(
      'section',
      { ref: 'imageGallery', className: 'image-gallery' },
      _react2['default'].createElement(
        'div',
        {
          onMouseOver: this._handleMouseOver,
          onMouseLeave: this._handleMouseLeave,
          className: 'image-gallery-content' },
        this.renderSlides(slides),
        this.props.showBullets && _react2['default'].createElement(
          'div',
          { className: 'image-gallery-bullets' },
          _react2['default'].createElement(
            'ul',
            { className: 'image-gallery-bullets-container' },
            bullets
          )
        )
      ),
      this.props.showThumbnails && _react2['default'].createElement(
        'div',
        { className: 'image-gallery-thumbnails' },
        _react2['default'].createElement(
          'div',
          {
            ref: 'thumbnails',
            className: 'image-gallery-thumbnails-container',
            style: thumbnailStyle },
          thumbnails
        )
      )
    );
  }

});

exports['default'] = ImageGallery;
module.exports = exports['default'];<commit_msg>update build<commit_after>'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactSwipeable = require('react-swipeable');

var _reactSwipeable2 = _interopRequireDefault(_reactSwipeable);

var ImageGallery = _react2['default'].createClass({

  displayName: 'ImageGallery',

  propTypes: {
    items: _react2['default'].PropTypes.array.isRequired,
    showThumbnails: _react2['default'].PropTypes.bool,
    showBullets: _react2['default'].PropTypes.bool,
    autoPlay: _react2['default'].PropTypes.bool,
    lazyLoad: _react2['default'].PropTypes.bool,
    slideInterval: _react2['default'].PropTypes.number,
    onSlide: _react2['default'].PropTypes.func
  },

  getDefaultProps: function getDefaultProps() {
    return {
      lazyLoad: true,
      showThumbnails: true,
      showBullets: false,
      autoPlay: false,
      slideInterval: 4000
    };
  },

  getInitialState: function getInitialState() {
    return {
      currentIndex: 0,
      thumbnailsTranslateX: 0,
      containerWidth: 0
    };
  },

  componentDidUpdate: function componentDidUpdate(prevProps, prevState) {
    if (prevState.containerWidth !== this.state.containerWidth || prevProps.showThumbnails !== this.props.showThumbnails) {

      // adjust thumbnail container when window width is adjusted
      // when the container resizes, thumbnailsTranslateX
      // should always be negative (moving right),
      // if container fits all thumbnails its set to 0

      this._setThumbnailsTranslateX(-this._getScrollX(this.state.currentIndex > 0 ? 1 : 0) * this.state.currentIndex);
    }

    if (prevState.currentIndex !== this.state.currentIndex) {

      // call back function if provided
      if (this.props.onSlide) {
        this.props.onSlide(this.state.currentIndex);
      }

      // calculates thumbnail container position
      if (this.state.currentIndex === 0) {
        this._setThumbnailsTranslateX(0);
      } else {
        var indexDifference = Math.abs(prevState.currentIndex - this.state.currentIndex);
        var _scrollX = this._getScrollX(indexDifference);
        if (_scrollX > 0) {
          if (prevState.currentIndex < this.state.currentIndex) {
            this._setThumbnailsTranslateX(this.state.thumbnailsTranslateX - _scrollX);
          } else if (prevState.currentIndex > this.state.currentIndex) {
            this._setThumbnailsTranslateX(this.state.thumbnailsTranslateX + _scrollX);
          }
        }
      }
    }
  },

  componentDidMount: function componentDidMount() {
    this._handleResize();
    if (this.props.autoPlay) {
      this.play();
    }
    if (window.addEventListener) {
      window.addEventListener('resize', this._handleResize);
    } else if (window.attachEvent) {
      window.attachEvent('onresize', this._handleResize);
    }
  },

  componentWillUnmount: function componentWillUnmount() {
    if (window.removeEventListener) {
      window.removeEventListener('resize', this._handleResize);
    } else if (window.detachEvent) {
      window.detachEvent('onresize', this._handleResize);
    }

    if (this._intervalId) {
      window.clearInterval(this._intervalId);
      this._intervalId = null;
    }
  },

  slideToIndex: function slideToIndex(index, event) {
    var slideCount = this.props.items.length - 1;

    if (index < 0) {
      this.setState({ currentIndex: slideCount });
    } else if (index > slideCount) {
      this.setState({ currentIndex: 0 });
    } else {
      this.setState({ currentIndex: index });
    }
    if (event) {
      if (this._intervalId) {
        // user event, reset interval
        this.pause();
        this.play();
      }
      event.preventDefault();
    }
  },

  play: function play() {
    var _this = this;

    if (this._intervalId) {
      return;
    }
    this._intervalId = window.setInterval((function () {
      if (!_this.state.hovering) {
        _this.slideToIndex(_this.state.currentIndex + 1);
      }
    }).bind(this), this.props.slideInterval);
  },

  pause: function pause() {
    if (this._intervalId) {
      window.clearInterval(this._intervalId);
      this._intervalId = null;
    }
  },

  _setThumbnailsTranslateX: function _setThumbnailsTranslateX(x) {
    this.setState({ thumbnailsTranslateX: x });
  },

  _handleResize: function _handleResize() {
    this.setState({ containerWidth: this.refs.imageGallery.offsetWidth });
  },

  _getScrollX: function _getScrollX(indexDifference) {
    if (this.refs.thumbnails) {
      var thumbNode = this.refs.thumbnails;
      if (thumbNode.scrollWidth <= this.state.containerWidth) {
        return 0;
      }
      var totalThumbnails = thumbNode.children.length;

      // total scroll-x required to see the last thumbnail
      var totalScrollX = thumbNode.scrollWidth - this.state.containerWidth;

      // scroll-x required per index change
      var perIndexScrollX = totalScrollX / (totalThumbnails - 1);

      return indexDifference * perIndexScrollX;
    }
  },

  _handleMouseOver: function _handleMouseOver() {
    this.setState({ hovering: true });
  },

  _handleMouseLeave: function _handleMouseLeave() {
    this.setState({ hovering: false });
  },

  _getAlignment: function _getAlignment(index) {
    var currentIndex = this.state.currentIndex;
    var alignment = '';
    switch (index) {
      case currentIndex - 1:
        alignment = 'left';
        break;
      case currentIndex:
        alignment = 'center';
        break;
      case currentIndex + 1:
        alignment = 'right';
        break;
    }

    if (this.props.items.length >= 3) {
      if (index === 0 && currentIndex === this.props.items.length - 1) {
        // set first slide as right slide if were sliding right from last slide
        alignment = 'right';
      } else if (index === this.props.items.length - 1 && currentIndex === 0) {
        // set last slide as left slide if were sliding left from first slide
        alignment = 'left';
      }
    }

    return alignment;
  },

  render: function render() {
    var _this2 = this;

    var currentIndex = this.state.currentIndex;
    var thumbnailStyle = {
      MozTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      WebkitTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      OTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      msTransform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)',
      transform: 'translate3d(' + this.state.thumbnailsTranslateX + 'px, 0, 0)'
    };

    var slides = [];
    var thumbnails = [];
    var bullets = [];

    this.props.items.map(function (item, index) {
      var alignment = _this2._getAlignment(index);
      if (_this2.props.lazyLoad) {
        if (alignment) {
          slides.push(_react2['default'].createElement(
            'div',
            {
              key: index,
              className: 'image-gallery-slide ' + alignment },
            _react2['default'].createElement('img', { src: item.original })
          ));
        }
      } else {
        slides.push(_react2['default'].createElement(
          'div',
          {
            key: index,
            className: 'image-gallery-slide ' + alignment },
          _react2['default'].createElement('img', { src: item.original })
        ));
      }

      if (_this2.props.showThumbnails) {
        thumbnails.push(_react2['default'].createElement(
          'a',
          {
            key: index,
            className: 'image-gallery-thumbnail ' + (currentIndex === index ? 'active' : ''),

            onTouchStart: _this2.slideToIndex.bind(_this2, index),
            onClick: _this2.slideToIndex.bind(_this2, index) },
          _react2['default'].createElement('img', { src: item.thumbnail })
        ));
      }

      if (_this2.props.showBullets) {
        bullets.push(_react2['default'].createElement('li', {
          key: index,
          className: 'image-gallery-bullet ' + (currentIndex === index ? 'active' : ''),

          onTouchStart: _this2.slideToIndex.bind(_this2, index),
          onClick: _this2.slideToIndex.bind(_this2, index) }));
      }
    });

    var swipePrev = this.slideToIndex.bind(this, currentIndex - 1);
    var swipeNext = this.slideToIndex.bind(this, currentIndex + 1);

    return _react2['default'].createElement(
      'section',
      { ref: 'imageGallery', className: 'image-gallery' },
      _react2['default'].createElement(
        'div',
        {
          onMouseOver: this._handleMouseOver,
          onMouseLeave: this._handleMouseLeave,
          className: 'image-gallery-content' },
        this.props.items.length >= 2 ? [_react2['default'].createElement('a', { key: 'leftNav',
          className: 'image-gallery-left-nav',
          onTouchStart: swipePrev,
          onClick: swipePrev }), _react2['default'].createElement('a', {
          key: 'rightNav',
          className: 'image-gallery-right-nav',
          onTouchStart: swipeNext,
          onClick: swipeNext }), _react2['default'].createElement(
          _reactSwipeable2['default'],
          {
            key: 'swipeable',
            onSwipedLeft: swipeNext,
            onSwipedRight: swipePrev },
          _react2['default'].createElement(
            'div',
            { className: 'image-gallery-slides' },
            slides
          )
        )] : _react2['default'].createElement(
          'div',
          { className: 'image-gallery-slides' },
          slides
        ),
        this.props.showBullets && _react2['default'].createElement(
          'div',
          { className: 'image-gallery-bullets' },
          _react2['default'].createElement(
            'ul',
            { className: 'image-gallery-bullets-container' },
            bullets
          )
        )
      ),
      this.props.showThumbnails && _react2['default'].createElement(
        'div',
        { className: 'image-gallery-thumbnails' },
        _react2['default'].createElement(
          'div',
          {
            ref: 'thumbnails',
            className: 'image-gallery-thumbnails-container',
            style: thumbnailStyle },
          thumbnails
        )
      )
    );
  }

});

exports['default'] = ImageGallery;
module.exports = exports['default'];
<|endoftext|>


<commit_before>
/*
Copyright 2016 Resin.io

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
var LocalStorage, settings;

if (typeof localStorage !== 'undefined') {
  module.exports = localStorage;
} else {
  settings = require('resin-settings-client');
  LocalStorage = require('node-localstorage').LocalStorage;
  module.exports = new LocalStorage(settings.get('dataDirectory'), Infinity);
}
<commit_msg>Rebuild CoffeeScript<commit_after>
/*
Copyright 2016 Resin.io

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
var LocalStorage, settings;

if (typeof localStorage !== "undefined" && localStorage !== null) {
  module.exports = localStorage;
} else {
  settings = require('resin-settings-client');
  LocalStorage = require('node-localstorage').LocalStorage;
  module.exports = new LocalStorage(settings.get('dataDirectory'), Infinity);
}
<|endoftext|>


<commit_before>import webpack from 'webpack'
import cssnano from 'cssnano'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import config from '../../config'
import _debug from 'debug'

const paths = config.utils_paths
const debug = _debug('app:webpack:_base')
debug('Create configuration.')

const CSS_LOADER = !config.compiler_css_modules
  ? 'css-loader?sourceMap'
  : [
    'css-loader?modules',
    'sourceMap',
    'importLoaders=1',
    'localIdentName=[name]__[local]___[hash:base64:5]'
  ].join('&')

const webpackConfig = {
  name: 'client',
  target: 'web',
  entry: {
    app: [
      paths.base(config.dir_client) + '/app.js'
    ],
    vendor: config.compiler_vendor
  },
  output: {
    filename: `[name].[${config.compiler_hash_type}].js`,
    path: paths.base(config.dir_dist),
    publicPath: config.compiler_public_path
  },
  plugins: [
    new webpack.DefinePlugin(config.globals),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new HtmlWebpackPlugin({
      template: paths.client('index.html'),
      hash: false,
      filename: 'index.html',
      inject: 'body',
      minify: {
        collapseWhitespace: true
      }
    })
  ],
  resolve: {
    root: paths.base(config.dir_client),
    extensions: ['', '.js', '.jsx']
  },
  module: {
    preLoaders: [
      {
        test: /\.js$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ],
    loaders: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          cacheDirectory: true,
          plugins: ['transform-runtime', 'add-module-exports'],
          presets: ['es2015', 'react', 'stage-0'],
          env: {
            development: {
              plugins: [
                ['react-transform', {
                  // omit HMR plugin by default and _only_ load in hot mode
                  transforms: [{
                    transform: 'react-transform-catch-errors',
                    imports: ['react', 'redbox-react']
                  }]
                }]
              ]
            }
          }
        }
      },
      {
        test: /\.scss$/,
        loaders: [
          'style-loader',
          CSS_LOADER,
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.css$/,
        loaders: [
          'style-loader',
          CSS_LOADER
        ]
      },
      /* eslint-disable */
      { test: /\.woff(\?.*)?$/,  loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff" },
      { test: /\.woff2(\?.*)?$/, loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff2" },
      { test: /\.ttf(\?.*)?$/,   loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/octet-stream" },
      { test: /\.eot(\?.*)?$/,   loader: "file-loader?prefix=fonts/&name=[path][name].[ext]" },
      { test: /\.svg(\?.*)?$/,   loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=image/svg+xml" },
      { test: /\.(png|jpg)$/,    loader: 'url-loader?limit=8192' }
      /* eslint-enable */
    ]
  },
  sassLoader: {
    includePaths: paths.client('styles')
  },
  postcss: [
    cssnano({
      sourcemap: true,
      autoprefixer: {
        add: true,
        remove: true,
        browsers: ['last 2 versions']
      },
      discardComments: {
        removeAll: true
      }
    })
  ],
  eslint: {
    configFile: `${paths.base()}/.eslintrc`
  }
}

// NOTE: this is a temporary workaround. I don't know how to get Karma
// to include the vendor bundle that webpack creates, so to get around that
// we remove the bundle splitting when webpack is used with Karma.
const commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin({
  names: ['vendor']
})
commonChunkPlugin.__KARMA_IGNORE__ = true

webpackConfig.plugins.push(commonChunkPlugin)

export default webpackConfig
<commit_msg>fix(webpack): run .css files through postcss-loader<commit_after>import webpack from 'webpack'
import cssnano from 'cssnano'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import config from '../../config'
import _debug from 'debug'

const paths = config.utils_paths
const debug = _debug('app:webpack:_base')
debug('Create configuration.')

const CSS_LOADER = !config.compiler_css_modules
  ? 'css-loader?sourceMap'
  : [
    'css-loader?modules',
    'sourceMap',
    'importLoaders=1',
    'localIdentName=[name]__[local]___[hash:base64:5]'
  ].join('&')

const webpackConfig = {
  name: 'client',
  target: 'web',
  entry: {
    app: [
      paths.base(config.dir_client) + '/app.js'
    ],
    vendor: config.compiler_vendor
  },
  output: {
    filename: `[name].[${config.compiler_hash_type}].js`,
    path: paths.base(config.dir_dist),
    publicPath: config.compiler_public_path
  },
  plugins: [
    new webpack.DefinePlugin(config.globals),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.DedupePlugin(),
    new HtmlWebpackPlugin({
      template: paths.client('index.html'),
      hash: false,
      filename: 'index.html',
      inject: 'body',
      minify: {
        collapseWhitespace: true
      }
    })
  ],
  resolve: {
    root: paths.base(config.dir_client),
    extensions: ['', '.js', '.jsx']
  },
  module: {
    preLoaders: [
      {
        test: /\.js$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ],
    loaders: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          cacheDirectory: true,
          plugins: ['transform-runtime', 'add-module-exports'],
          presets: ['es2015', 'react', 'stage-0'],
          env: {
            development: {
              plugins: [
                ['react-transform', {
                  // omit HMR plugin by default and _only_ load in hot mode
                  transforms: [{
                    transform: 'react-transform-catch-errors',
                    imports: ['react', 'redbox-react']
                  }]
                }]
              ]
            }
          }
        }
      },
      {
        test: /\.scss$/,
        loaders: [
          'style-loader',
          CSS_LOADER,
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.css$/,
        loaders: [
          'style-loader',
          CSS_LOADER,
          'postcss-loader'
        ]
      },
      /* eslint-disable */
      { test: /\.woff(\?.*)?$/,  loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff" },
      { test: /\.woff2(\?.*)?$/, loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff2" },
      { test: /\.ttf(\?.*)?$/,   loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/octet-stream" },
      { test: /\.eot(\?.*)?$/,   loader: "file-loader?prefix=fonts/&name=[path][name].[ext]" },
      { test: /\.svg(\?.*)?$/,   loader: "url-loader?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=image/svg+xml" },
      { test: /\.(png|jpg)$/,    loader: 'url-loader?limit=8192' }
      /* eslint-enable */
    ]
  },
  sassLoader: {
    includePaths: paths.client('styles')
  },
  postcss: [
    cssnano({
      sourcemap: true,
      autoprefixer: {
        add: true,
        remove: true,
        browsers: ['last 2 versions']
      },
      discardComments: {
        removeAll: true
      }
    })
  ],
  eslint: {
    configFile: `${paths.base()}/.eslintrc`
  }
}

// NOTE: this is a temporary workaround. I don't know how to get Karma
// to include the vendor bundle that webpack creates, so to get around that
// we remove the bundle splitting when webpack is used with Karma.
const commonChunkPlugin = new webpack.optimize.CommonsChunkPlugin({
  names: ['vendor']
})
commonChunkPlugin.__KARMA_IGNORE__ = true

webpackConfig.plugins.push(commonChunkPlugin)

export default webpackConfig
<|endoftext|>


<commit_before>// @ts-nocheck

// Send onetime emails to inactive old unpaid EU users
// Assumes prod env variables to run

// TODO: test with keep me updated prompt

// TODO: test on limited batch of users first

// TODO: delete inactive users 1 month after one-time email sent

require('coffee-script');
require('coffee-script/register');
global._ = require('lodash');
_.str = require('underscore.string');
const database = require('../server/commons/database');
const User = require('../server/models/User');
const co = require('co');
const utils = require('../app/core/utils');
const sendwithus = require('../server/sendwithus');

database.connect();

const oneTimeEmailType = 'delete inactive unpaid EU user';
const batchSize = 500; // 10K yields sendwithus 503 service unavailable
const batchSleepMS = 3000;
const newestDate = new Date();
newestDate.setUTCMonth(newestDate.getUTCMonth() - 23);
// const euCountries = utils.countries.filter((c) => c.inEU).map((c) => c.country);
const upperEUCountries = ['Austria', 'Belgium', 'Bulgaria', 'Broatia', 'Cyprus', 'Czech Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Germany', 'Greece', 'Hungary', 'Ireland', 'Italy', 'Latvia', 'Lithuania', 'Luxembourg', 'Malta', 'Netherlands', 'Poland', 'Portugal', 'Romania', 'Slovakia', 'Slovenia', 'Spain', 'Sweden', 'United-kingdom']

let errors = 0;
function sendOptInEmail(user) {
  return new Promise((resolve, reject) => {
    // Testing
    // setTimeout(() => {
    //   console.log('hi', user.get('emailLower'), user.get('country'));
    //   resolve();
    // }, 1000)
    // return;

    let opt_in_link = `https://codecombat.com/user/${user.id}/opt-in/${user.verificationCode((new Date()).getTime())}?no_delete_inactive_eu=true`;
    if (!user.isTeacher()) opt_in_link += "&prompt_keep_me_updated=true";

    const context = {
      email_id: sendwithus.templates.delete_inactive_eu_users,
      recipient: {
        address: user.get('emailLower'),
        name: user.broadName()
      },
      email_data: {
        opt_in_link: opt_in_link
      }
    }
    sendwithus.api.send(context, (err, result) => {
      if (err) {
        console.log(`${new Date().toISOString()} ${errors} Error sending email to ${user.get('emailLower')}`);
        ++errors;
        if (!/Request failed with 400/.test(err.message) && !/getaddrinfo ENOTFOUND api.sendwithus.com/.test(err.message))
          return reject(err);
        if (errors > batchSize / 20)
          return reject(err);
      }
      user.update({$push: {"emails.oneTimes": {type: oneTimeEmailType, email: user.get('emailLower'), sent: new Date()}}}, (err, numAffected) => {
        if (err) {
          console.log(`${new Date().toISOString()} Error updating emails.oneTimes for ${user.get('emailLower')}`);
          return reject(err);
        }
        resolve();
      });
    });
  });
}

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

co(function*() {
  const query = {$and: [
    // Do NOT send one time email again
    {$or: [{'emails.oneTimes': {$exists: false}}, {$and: [{'emails.oneTimes': {$exists: true}}, {$where : `!this.emails.oneTimes.find(function(o){return o.type === '${oneTimeEmailType}'})`}]}]},
    // Inactive
    {$or: [
        {$and: [
            {'activity.login.last': {$exists: true}}, {'activity.login.last': {$lt: newestDate}}
        ]},
        {$and: [
            {'activity.login.last': {$exists: false}}, {dateCreated: {$lt: newestDate}}
        ]}
    ]},
    // In EU
    {$or: [
      {country: {$in: upperEUCountries}},
      {'geo.countryName': {$in: upperEUCountries}},
      {$and: [{country: {$exists: false}}, {'geo.countryName': {$exists: false}}]},
    ]},
    // Unpaid
    {'stripe.subscriptionID': {$exists: false}},
    {'stripe.sponsorID': {$exists: false}},
    {anonymous: false}
  ]};
  const select = {emailLower: 1, country: 1, email: 1}; // email required for verification code generation

  while (true) {
    const users = yield User.find(query, select).limit(batchSize);
    if (users.length < 1) break;

    console.log(`${new Date().toISOString()} processing ${users.length} users..`);
    const tasks = [];
    for (const user of users) {
      // console.log(user.get('emailLower'));
      tasks.push(sendOptInEmail(user));
    }
    yield tasks;

    errors = 0;
    console.log(`${new Date().toISOString()} sleeping for ${batchSleepMS / 1000} seconds..`);
    yield sleep(batchSleepMS);

    // TODO: remove for full run
    //break;
  }
})
.then(() => {
  console.log('Done')
  process.exit()
})
.catch((e) => {
  console.log("Error: ")
  console.log(e)
  process.exit()
})
<commit_msg>Adjust inactive user script error handling<commit_after>// @ts-nocheck

// Send onetime emails to inactive old unpaid EU users
// Assumes prod env variables to run

// TODO: test with keep me updated prompt

// TODO: test on limited batch of users first

// TODO: delete inactive users 1 month after one-time email sent

require('coffee-script');
require('coffee-script/register');
global._ = require('lodash');
_.str = require('underscore.string');
const database = require('../server/commons/database');
const User = require('../server/models/User');
const co = require('co');
const utils = require('../app/core/utils');
const sendwithus = require('../server/sendwithus');

database.connect();

const oneTimeEmailType = 'delete inactive unpaid EU user';
const batchSize = 1000; // 10K yields sendwithus 503 service unavailable
const batchSleepMS = 1000;
const newestDate = new Date();
newestDate.setUTCMonth(newestDate.getUTCMonth() - 23);
// const euCountries = utils.countries.filter((c) => c.inEU).map((c) => c.country);
const upperEUCountries = ['Austria', 'Belgium', 'Bulgaria', 'Broatia', 'Cyprus', 'Czech Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Germany', 'Greece', 'Hungary', 'Ireland', 'Italy', 'Latvia', 'Lithuania', 'Luxembourg', 'Malta', 'Netherlands', 'Poland', 'Portugal', 'Romania', 'Slovakia', 'Slovenia', 'Spain', 'Sweden', 'United-kingdom']

let errors = 0;
function sendOptInEmail(user) {
  return new Promise((resolve, reject) => {
    // Testing
    // setTimeout(() => {
    //   console.log('hi', user.get('emailLower'), user.get('country'));
    //   resolve();
    // }, 1000)
    // return;

    let opt_in_link = `https://codecombat.com/user/${user.id}/opt-in/${user.verificationCode((new Date()).getTime())}?no_delete_inactive_eu=true`;
    if (!user.isTeacher()) opt_in_link += "&prompt_keep_me_updated=true";

    const context = {
      email_id: sendwithus.templates.delete_inactive_eu_users,
      recipient: {
        address: user.get('emailLower'),
        name: user.broadName()
      },
      email_data: {
        opt_in_link: opt_in_link
      }
    }
    sendwithus.api.send(context, (err, result) => {
      if (err) {
        console.log(`${new Date().toISOString()} ${errors} Error sending email to ${user.get('emailLower')}`);
        ++errors;
        if (!/Request failed with/.test(err.message) && !/getaddrinfo ENOTFOUND api.sendwithus.com/.test(err.message))
          return reject(err);
        if (errors > batchSize / 10)
          return reject(err);
      }
      user.update({$push: {"emails.oneTimes": {type: oneTimeEmailType, email: user.get('emailLower'), sent: new Date()}}}, (err, numAffected) => {
        if (err) {
          console.log(`${new Date().toISOString()} Error updating emails.oneTimes for ${user.get('emailLower')}`);
          return reject(err);
        }
        resolve();
      });
    });
  });
}

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

co(function*() {
  const query = {$and: [
    // Do NOT send one time email again
    {$or: [{'emails.oneTimes': {$exists: false}}, {$and: [{'emails.oneTimes': {$exists: true}}, {$where : `!this.emails.oneTimes.find(function(o){return o.type === '${oneTimeEmailType}'})`}]}]},
    // Inactive
    {$or: [
        {$and: [
            {'activity.login.last': {$exists: true}}, {'activity.login.last': {$lt: newestDate}}
        ]},
        {$and: [
            {'activity.login.last': {$exists: false}}, {dateCreated: {$lt: newestDate}}
        ]}
    ]},
    // In EU
    {$or: [
      {country: {$in: upperEUCountries}},
      {'geo.countryName': {$in: upperEUCountries}},
      {$and: [{country: {$exists: false}}, {'geo.countryName': {$exists: false}}]},
    ]},
    // Unpaid
    {'stripe.subscriptionID': {$exists: false}},
    {'stripe.sponsorID': {$exists: false}},
    {anonymous: false}
  ]};
  const select = {emailLower: 1, country: 1, email: 1}; // email required for verification code generation

  while (true) {
    const users = yield User.find(query, select).limit(batchSize);
    if (users.length < 1) break;

    console.log(`${new Date().toISOString()} processing ${users.length} users..`);
    const tasks = [];
    for (const user of users) {
      // console.log(user.get('emailLower'));
      tasks.push(sendOptInEmail(user));
    }
    yield tasks;

    errors = 0;
    console.log(`${new Date().toISOString()} sleeping for ${batchSleepMS / 1000} seconds..`);
    yield sleep(batchSleepMS);

    // TODO: remove for full run
    //break;
  }
})
.then(() => {
  console.log('Done')
  process.exit()
})
.catch((e) => {
  console.log("Error: ")
  console.log(e)
  process.exit()
})
<|endoftext|>