<commit_before>const fs = require('fs');
const mongojs = require('mongojs');
const Discordie = require('discordie');
const handlebars = require('handlebars');
const screenshot = require('screenshot-stream');
const winston = require('winston');

/** A Discord bot, which encourages players to join voice channels. */
class Kirito {
  constructor() {
    // Prepare discord api
    this.discordApi = new Discordie({autoReconnect: true});
    this.discordApi.connect({ token: process.env.AUTH_TOKEN });

    // Prepare database
    this.db = mongojs(process.env.DATABASE, ['users']);

    // Prepare application state
    this.connectedUsers = [];
    this.subscribeToEvents();
  }

  /**
   * Registers callback functions to certain events which are triggered
   * through the DiscordApi.
   */
  subscribeToEvents() {
    // Bind this into callback functions
    this.prepareBot = this.prepareBot.bind(this);
    this.joinServer = this.joinServer.bind(this);
    this.userConnected = this.userConnected.bind(this);
    this.userDisconnected = this.userDisconnected.bind(this);
    this.handleChatCommand = this.handleChatCommand.bind(this);

    // Subscribe to events
    this.discordApi.Dispatcher.on(Discordie.Events.GATEWAY_READY, this.prepareBot);
    this.discordApi.Dispatcher.on(Discordie.Events.GUILD_CREATE, this.joinServer);
    this.discordApi.Dispatcher.on(Discordie.Events.VOICE_CHANNEL_JOIN, this.userConnected);
    this.discordApi.Dispatcher.on(Discordie.Events.VOICE_CHANNEL_LEAVE, this.userDisconnected);
    this.discordApi.Dispatcher.on(Discordie.Events.MESSAGE_CREATE, this.handleChatCommand);
  }

  /**
   * Initializes the bot using the Discord API.
   */
  prepareBot() {
    this.discordApi.User.setGame('together with Asuna');
    this.addCurrentlyConnectedUsers();
  }

  /**
   * Adds all currently connected users to the list of connected users.
   */
  addCurrentlyConnectedUsers() {
    this.discordApi.Guilds.forEach((server) => {
      server.voiceChannels.forEach((channel) => {
        channel.members.forEach((user) => {
          this.addConnectedUser(user, server);
        });
      });
    });
  }

  /**
   * Prints an introduction message.
   * @param {Event} e - Discord API event.
   */
  joinServer(e) {
    e.guild.generalChannel.sendTyping();
    const introduction = [
      'Hi!',
      'I am Kirito, your personal voice chat coach. From now on, every time you join',
      'a voice channel on this Server you will receive experience and therefore level.',
      'Additionally, you can ask me things through so called commands. Currently,',
      'I know two commands. Command number one is `ping`, which obviously starts a',
      'table tennis match, and command number two is called `profile` where I will',
      'print an image of your current player profile.',
      '',
      'Enjoy your time in voice channels :).'
    ];
    e.guild.generalChannel.sendMessage(introduction);
  }

  /**
   * Handles users connecting to voice channels.
   * @param {Event} e - Discord API event.
   */
  userConnected(e) {
    this.addConnectedUser(e.user, e.channel.guild);
  }

  /**
   * Adds a user to the list of users in voice channels (connected users).
   * @param {Object} user - Discord API user object.
   * @param {Object} server - Discord API guild object.
   */
  addConnectedUser(user, server) {
    const rewardInterval = 60000;
    const experiencePerMinute = 1;
    const connectedUser = {};
    connectedUser.experienceTimer = setInterval(() => { this.addExperience(user, server, experiencePerMinute); }, rewardInterval);
    this.connectedUsers[user.id] = connectedUser;
    winston.log("info", 'User ' + user.username + ' connected to server ' + server.name + '.');
  }

  /**
   * Handles users disconnecting from voice channels.
   * @param {Event} e - Discord API event.
   */
  userDisconnected(e) {
    this.removeConnectedUser(e.user);
  }

  /**
   * Removes a user from the list of users in voice channels (connected users).
   * @param {Object} user - Discord API user object.
   */
  removeConnectedUser(user) {
    if (!this.connectedUsers[user.id]) {
      winston.log("warn", 'User ' + user.username + ' not found in list of online users.');
      return;
    }
    clearInterval(this.connectedUsers[user.id].experienceTimer);
    delete this.connectedUsers[user.id];
    winston.log("info", 'User ' + user.username + ' disconnected.');
  }

  /**
   * Adds experience to the user account.
   * @param {Object} user - Discord API user object.
   * @param {Object} server - Discord API guild object.
   * @param {Number} experience - Amount of experience to add.
   */
  addExperience(user, server, experience) {
    this.db.users.update({id: user.id}, { $setOnInsert: user, $inc: { experience } }, {upsert: true});
    this.db.users.update({id: user.id, 'servers.id': server.id}, {$inc: {'servers.$.experience': experience}} );
    this.db.users.update({id: user.id, 'servers.id': {$ne: server.id}}, { $push: {'servers': {id: server.id, experience}} }, (err, res) => {
      winston.log("info", 'Added ' + experience + ' experience to user ' + user.username + '.');
      winston.log("info", user.username + ' has now a total experience of ' + res.experience + '.');
    });
  }

  /**
   * Handles received chat messages and checks for chat commands.
   * @param {Event} e - Discord API event.
   */
  handleChatCommand(e) {
    switch (e.message.content) {
      case 'ping':
        e.message.channel.sendTyping();
        e.message.channel.sendMessage('pong');
        break;

      case 'profile':
        this.getProfile(e.message.author, (profile) => {
          e.message.channel.sendTyping();
          e.message.channel.uploadFile(profile, 'profile.png');
        });
        break;
      case 'toplist':
        this.getToplist((toplist) => {
          e.message.channel.sendTyping();
          e.message.channel.uploadFile(toplist, 'toplist.png');
        });
        break;
    }
  }

  /**
   * Gathers necessary user data and prepares the image stream to print
   * a users profile.
   * @param {Object} user - Discord API user object.
   * @param {Callback} callback - Called when image stream is ready.
   */
  getProfile(user, callback) {
    const newUser = JSON.parse(JSON.stringify(user));
    newUser.experience = 0;
    winston.log("info", 'Printing profile for user ' + user.username + '.');
    this.db.users.findAndModify({query: {id: user.id}, update: { $setOnInsert: newUser }, upsert: true, new: true}, (err, result) => {
      const profileInformation = {
        username: user.username,
        level: this.calculateLevel(result.experience),
        levelProgress: this.calculateLevelProgress(result.experience),
        avatar: this.getAvatarUrl(user),
        servers: this.getAdditionalServerData(result.servers)
      };
      winston.log("info", 'username:' + user.username);
      winston.log("info", 'level:' + this.calculateLevel(result.experience));
      winston.log("info", 'experience:' + result.experience);
      winston.log("info", 'levelProgress:' + this.calculateLevelProgress(result.experience));
      winston.log("info", 'servers:' + this.getAdditionalServerData(result.servers));
      const templateFilename = 'interface/templates/profile.html';
      const stream = this.getImageStream(templateFilename, profileInformation);

      /**
       * Is called when the profile creation finished and the image stream
       * is ready.
       * @callback callback
       * @param {String} stream - Image stream containing the user profile.
       */
      callback(stream);
    });
  }

  getToplist(callback) {
    //get 10 users ordered by experience
    this.db.users.find().sort({experience: -1}).limit(10, (err, result) => {
      const toplist = {
        toplist: []
      };
      result.forEach((user) => {
        toplist.toplist.push({
          username: user.username,
          avatar: this.getAvatarUrl(user),
          experience: user.experience
        })
      })
      const templateFilename = 'interface/templates/toplist.html';
      const stream = this.getImageStream(templateFilename, toplist);

      /**
         * Is called when the profile creation finished and the image stream
         * is ready.
         * @callback callback
         * @param {String} stream - Image stream containing the user profile.
         */
        callback(stream);
    });
  }

  /**
   * Calculates the level given a total amount of experience.
   * @param {Number} experience - Amount of experience.
   * @return {Number} Level corresponding to experience.
   */
  calculateLevel(experience) {
    return Math.floor(Math.sqrt(experience / 3 + 36) - 5);
  }

  /**
   * Calculates the progress of the current level given a total amount
   * of experience.
   * @param {Number} experience - Amount of experience.
   * @return {Number} Level progress in percent (0 - 100).
   */
  calculateLevelProgress(experience) {
    const userLevel = this.calculateLevel(experience);
    const currentLevelMinExperience = this.minLevelExperience(userLevel);
    const nextLevelMinExperience = this.minLevelExperience(userLevel + 1);
    const currentLevelExperience = nextLevelMinExperience - currentLevelMinExperience;
    const userLevelExperience = experience - currentLevelMinExperience;
    return userLevelExperience * 100 / currentLevelExperience;
  }

  /**
   * If the user has an avatar, the avatar is returned, otherwise an URL to
   * a default avatar is returned.
   * @param {Object} user - Discord API user object.
   * @return {String} Avatar URL.
   */
  getAvatarUrl(user) {
    let avatarUrl = '';
    if (user.avatar) {
      avatarUrl = 'https://cdn.discordapp.com/avatars/' + user.id + '/' + user.avatar + '.png';
    } else {
      const defaultAvatarIndex = Number(user.id) % 100;
      avatarUrl = './images/superheroes/heroes-and-villains-' + defaultAvatarIndex + '.png';
    }
    return avatarUrl;
  }

  /**
   * If the server has an icon, the icon is returned, otherwise an URL to
   * a default icon is returned.
   * @param {Object} server - Discord API server object.
   * @return {String} Icon URL.
   */
  getIconUrl(server) {
    let iconUrl = '';
    if (server.icon) {
      iconUrl = 'https://cdn.discordapp.com/icons/' + server.id + '/' + server.icon + '.png';
    } else {
      const defaultIconIndex = Number(server.id) % 100;
      iconUrl = './images/superheroes/heroes-and-villains-' + defaultIconIndex + '.png';
    }
    return iconUrl;
  }

  /**
   * Calculates the minimal amount of experience needed for a given level.
   * @param {Number} level - The level, which the experience is calculated for.
   * @return {Number} Amount of Experience needed for the level.
   */
  minLevelExperience(level) {
    return (3 * level * (level + 10) - 33);
  }

  /**
   * Fetches additional information for a given list of Discord servers
   * through the Discord API.
   * @param {Array} servers - List of objects containing Discord server ids.
   * @return {Array} List of Discord servers.
   */
  getAdditionalServerData(servers) {
    let serverList = [];
    if (!servers) {
      return [];
    }

    servers.map((currentServer) => {
      const server = this.discordApi.Guilds.get(currentServer.id);
      const databaseServer = JSON.parse(JSON.stringify(server));
      databaseServer.iconURL = this.getIconUrl(server);
      databaseServer.experience = currentServer.experience;
      serverList.push(databaseServer);
    });

    serverList.sort((a, b) => {b.experience - a.experience;});
    return serverList;
  }

  /**
   * Creates a HTML profile file containing user information based on
   * a profile template.
   * @param {String} templateFilename - Path of the template Handlebars file.
   * @param {Object} templateInformation - Information to fill the Handlebars teamplate with.
   * @return {String} Image stream.
   */
  getImageStream(templateFilename, templateInformation) {
    const randomFilename = Math.random().toString(36).substring(17);
    const outputFilname = 'interface/' + randomFilename + '.html';
    const templateFile = fs.readFileSync(templateFilename).toString();
    const template = handlebars.compile(templateFile);
    const html = template(templateInformation);
    fs.writeFileSync(outputFilname, html);
    return screenshot(outputFilname, '500x1000', {crop: true, selector: '.main'});
  }
}

const kiritoInstance = new Kirito();
<commit_msg>Corrected random filename generation<commit_after>const fs = require('fs');
const mongojs = require('mongojs');
const Discordie = require('discordie');
const handlebars = require('handlebars');
const screenshot = require('screenshot-stream');
const winston = require('winston');

/** A Discord bot, which encourages players to join voice channels. */
class Kirito {
  constructor() {
    // Prepare discord api
    this.discordApi = new Discordie({autoReconnect: true});
    this.discordApi.connect({ token: process.env.AUTH_TOKEN });

    // Prepare database
    this.db = mongojs(process.env.DATABASE, ['users']);

    // Prepare application state
    this.connectedUsers = [];
    this.subscribeToEvents();
  }

  /**
   * Registers callback functions to certain events which are triggered
   * through the DiscordApi.
   */
  subscribeToEvents() {
    // Bind this into callback functions
    this.prepareBot = this.prepareBot.bind(this);
    this.joinServer = this.joinServer.bind(this);
    this.userConnected = this.userConnected.bind(this);
    this.userDisconnected = this.userDisconnected.bind(this);
    this.handleChatCommand = this.handleChatCommand.bind(this);

    // Subscribe to events
    this.discordApi.Dispatcher.on(Discordie.Events.GATEWAY_READY, this.prepareBot);
    this.discordApi.Dispatcher.on(Discordie.Events.GUILD_CREATE, this.joinServer);
    this.discordApi.Dispatcher.on(Discordie.Events.VOICE_CHANNEL_JOIN, this.userConnected);
    this.discordApi.Dispatcher.on(Discordie.Events.VOICE_CHANNEL_LEAVE, this.userDisconnected);
    this.discordApi.Dispatcher.on(Discordie.Events.MESSAGE_CREATE, this.handleChatCommand);
  }

  /**
   * Initializes the bot using the Discord API.
   */
  prepareBot() {
    this.discordApi.User.setGame('together with Asuna');
    this.addCurrentlyConnectedUsers();
  }

  /**
   * Adds all currently connected users to the list of connected users.
   */
  addCurrentlyConnectedUsers() {
    this.discordApi.Guilds.forEach((server) => {
      server.voiceChannels.forEach((channel) => {
        channel.members.forEach((user) => {
          this.addConnectedUser(user, server);
        });
      });
    });
  }

  /**
   * Prints an introduction message.
   * @param {Event} e - Discord API event.
   */
  joinServer(e) {
    e.guild.generalChannel.sendTyping();
    const introduction = [
      'Hi!',
      'I am Kirito, your personal voice chat coach. From now on, every time you join',
      'a voice channel on this Server you will receive experience and therefore level.',
      'Additionally, you can ask me things through so called commands. Currently,',
      'I know two commands. Command number one is `ping`, which obviously starts a',
      'table tennis match, and command number two is called `profile` where I will',
      'print an image of your current player profile.',
      '',
      'Enjoy your time in voice channels :).'
    ];
    e.guild.generalChannel.sendMessage(introduction);
  }

  /**
   * Handles users connecting to voice channels.
   * @param {Event} e - Discord API event.
   */
  userConnected(e) {
    this.addConnectedUser(e.user, e.channel.guild);
  }

  /**
   * Adds a user to the list of users in voice channels (connected users).
   * @param {Object} user - Discord API user object.
   * @param {Object} server - Discord API guild object.
   */
  addConnectedUser(user, server) {
    const rewardInterval = 60000;
    const experiencePerMinute = 1;
    const connectedUser = {};
    connectedUser.experienceTimer = setInterval(() => { this.addExperience(user, server, experiencePerMinute); }, rewardInterval);
    this.connectedUsers[user.id] = connectedUser;
    winston.log("info", 'User ' + user.username + ' connected to server ' + server.name + '.');
  }

  /**
   * Handles users disconnecting from voice channels.
   * @param {Event} e - Discord API event.
   */
  userDisconnected(e) {
    this.removeConnectedUser(e.user);
  }

  /**
   * Removes a user from the list of users in voice channels (connected users).
   * @param {Object} user - Discord API user object.
   */
  removeConnectedUser(user) {
    if (!this.connectedUsers[user.id]) {
      winston.log("warn", 'User ' + user.username + ' not found in list of online users.');
      return;
    }
    clearInterval(this.connectedUsers[user.id].experienceTimer);
    delete this.connectedUsers[user.id];
    winston.log("info", 'User ' + user.username + ' disconnected.');
  }

  /**
   * Adds experience to the user account.
   * @param {Object} user - Discord API user object.
   * @param {Object} server - Discord API guild object.
   * @param {Number} experience - Amount of experience to add.
   */
  addExperience(user, server, experience) {
    this.db.users.update({id: user.id}, { $setOnInsert: user, $inc: { experience } }, {upsert: true});
    this.db.users.update({id: user.id, 'servers.id': server.id}, {$inc: {'servers.$.experience': experience}} );
    this.db.users.update({id: user.id, 'servers.id': {$ne: server.id}}, { $push: {'servers': {id: server.id, experience}} }, (err, res) => {
      winston.log("info", 'Added ' + experience + ' experience to user ' + user.username + '.');
      winston.log("info", user.username + ' has now a total experience of ' + res.experience + '.');
    });
  }

  /**
   * Handles received chat messages and checks for chat commands.
   * @param {Event} e - Discord API event.
   */
  handleChatCommand(e) {
    switch (e.message.content) {
      case 'ping':
        e.message.channel.sendTyping();
        e.message.channel.sendMessage('pong');
        break;

      case 'profile':
        this.getProfile(e.message.author, (profile) => {
          e.message.channel.sendTyping();
          e.message.channel.uploadFile(profile, 'profile.png');
        });
        break;
      case 'toplist':
        this.getToplist((toplist) => {
          e.message.channel.sendTyping();
          e.message.channel.uploadFile(toplist, 'toplist.png');
        });
        break;
    }
  }

  /**
   * Gathers necessary user data and prepares the image stream to print
   * a users profile.
   * @param {Object} user - Discord API user object.
   * @param {Callback} callback - Called when image stream is ready.
   */
  getProfile(user, callback) {
    const newUser = JSON.parse(JSON.stringify(user));
    newUser.experience = 0;
    winston.log("info", 'Printing profile for user ' + user.username + '.');
    this.db.users.findAndModify({query: {id: user.id}, update: { $setOnInsert: newUser }, upsert: true, new: true}, (err, result) => {
      const profileInformation = {
        username: user.username,
        level: this.calculateLevel(result.experience),
        levelProgress: this.calculateLevelProgress(result.experience),
        avatar: this.getAvatarUrl(user),
        servers: this.getAdditionalServerData(result.servers)
      };
      winston.log("info", 'username:' + user.username);
      winston.log("info", 'level:' + this.calculateLevel(result.experience));
      winston.log("info", 'experience:' + result.experience);
      winston.log("info", 'levelProgress:' + this.calculateLevelProgress(result.experience));
      winston.log("info", 'servers:' + this.getAdditionalServerData(result.servers));
      const templateFilename = 'interface/templates/profile.html';
      const stream = this.getImageStream(templateFilename, profileInformation);

      /**
       * Is called when the profile creation finished and the image stream
       * is ready.
       * @callback callback
       * @param {String} stream - Image stream containing the user profile.
       */
      callback(stream);
    });
  }

  getToplist(callback) {
    //get 10 users ordered by experience
    this.db.users.find().sort({experience: -1}).limit(10, (err, result) => {
      const toplist = {
        toplist: []
      };
      result.forEach((user) => {
        toplist.toplist.push({
          username: user.username,
          avatar: this.getAvatarUrl(user),
          experience: user.experience
        })
      })
      const templateFilename = 'interface/templates/toplist.html';
      const stream = this.getImageStream(templateFilename, toplist);

      /**
         * Is called when the profile creation finished and the image stream
         * is ready.
         * @callback callback
         * @param {String} stream - Image stream containing the user profile.
         */
        callback(stream);
    });
  }

  /**
   * Calculates the level given a total amount of experience.
   * @param {Number} experience - Amount of experience.
   * @return {Number} Level corresponding to experience.
   */
  calculateLevel(experience) {
    return Math.floor(Math.sqrt(experience / 3 + 36) - 5);
  }

  /**
   * Calculates the progress of the current level given a total amount
   * of experience.
   * @param {Number} experience - Amount of experience.
   * @return {Number} Level progress in percent (0 - 100).
   */
  calculateLevelProgress(experience) {
    const userLevel = this.calculateLevel(experience);
    const currentLevelMinExperience = this.minLevelExperience(userLevel);
    const nextLevelMinExperience = this.minLevelExperience(userLevel + 1);
    const currentLevelExperience = nextLevelMinExperience - currentLevelMinExperience;
    const userLevelExperience = experience - currentLevelMinExperience;
    return userLevelExperience * 100 / currentLevelExperience;
  }

  /**
   * If the user has an avatar, the avatar is returned, otherwise an URL to
   * a default avatar is returned.
   * @param {Object} user - Discord API user object.
   * @return {String} Avatar URL.
   */
  getAvatarUrl(user) {
    let avatarUrl = '';
    if (user.avatar) {
      avatarUrl = 'https://cdn.discordapp.com/avatars/' + user.id + '/' + user.avatar + '.png';
    } else {
      const defaultAvatarIndex = Number(user.id) % 100;
      avatarUrl = './images/superheroes/heroes-and-villains-' + defaultAvatarIndex + '.png';
    }
    return avatarUrl;
  }

  /**
   * If the server has an icon, the icon is returned, otherwise an URL to
   * a default icon is returned.
   * @param {Object} server - Discord API server object.
   * @return {String} Icon URL.
   */
  getIconUrl(server) {
    let iconUrl = '';
    if (server.icon) {
      iconUrl = 'https://cdn.discordapp.com/icons/' + server.id + '/' + server.icon + '.png';
    } else {
      const defaultIconIndex = Number(server.id) % 100;
      iconUrl = './images/superheroes/heroes-and-villains-' + defaultIconIndex + '.png';
    }
    return iconUrl;
  }

  /**
   * Calculates the minimal amount of experience needed for a given level.
   * @param {Number} level - The level, which the experience is calculated for.
   * @return {Number} Amount of Experience needed for the level.
   */
  minLevelExperience(level) {
    return (3 * level * (level + 10) - 33);
  }

  /**
   * Fetches additional information for a given list of Discord servers
   * through the Discord API.
   * @param {Array} servers - List of objects containing Discord server ids.
   * @return {Array} List of Discord servers.
   */
  getAdditionalServerData(servers) {
    let serverList = [];
    if (!servers) {
      return [];
    }

    servers.map((currentServer) => {
      const server = this.discordApi.Guilds.get(currentServer.id);
      const databaseServer = JSON.parse(JSON.stringify(server));
      databaseServer.iconURL = this.getIconUrl(server);
      databaseServer.experience = currentServer.experience;
      serverList.push(databaseServer);
    });

    serverList.sort((a, b) => {b.experience - a.experience;});
    return serverList;
  }

  /**
   * Creates a HTML profile file containing user information based on
   * a profile template.
   * @param {String} templateFilename - Path of the template Handlebars file.
   * @param {Object} templateInformation - Information to fill the Handlebars teamplate with.
   * @return {String} Image stream.
   */
  getImageStream(templateFilename, templateInformation) {
    const randomFilename = Math.random().toString(36).substring(7);
    const outputFilname = 'interface/' + randomFilename + '.html';
    const templateFile = fs.readFileSync(templateFilename).toString();
    const template = handlebars.compile(templateFile);
    const html = template(templateInformation);
    fs.writeFileSync(outputFilname, html);
    return screenshot(outputFilname, '500x1000', {crop: true, selector: '.main'});
  }
}

const kiritoInstance = new Kirito();
<|endoftext|>


<commit_before>/*
 acrobat-js - http://github.com/fabianonunes/acrobat-js
 Copyright (c) 2011, Fabiano Nunes
 Released under the BSD License.
*/

var Utils = {

	stick : function(func) {
		return function() {
			return func.apply(event.target, Array.prototype.slice.call(arguments));
		}
	},

	stickAll : function(obj) {
		for (var b in obj) Utils.isFunction(obj[b]) && (obj[b] = Utils.stick(obj[b]))
	},

	isFunction : function(obj) {
		return Object.prototype.toString.call(obj) == '[object Function]';
	}

};

var AcrobatJs = {

	paths : {
		1 : '/r/APLICATIVOS/Certidoes/status_1.pdf',
		6 : '/r/APLICATIVOS/Certidoes/status_6.pdf'
	},

	insertDoc : app.trustedFunction(function(path){
		app.beginPriv();
		this.insertPages({
			nPage: this.numPages-1,
			cPath: path
		});
		this.pageNum = this.numPages-1;
		app.endPriv();
	}),

	addCert : function(status){

		console.println(AcrobatJs.paths[status]);

		AcrobatJs.insertDoc(AcrobatJs.paths[status]);

		var f = this.getField('numproc_' + status)
			, mask = /[1-9]\d{0,6}-\d{2}\.\d{4}\.\d\.\d{2}\.\d{4}/;

		f.value = mask.exec(this.documentFileName) || 'Digite o n\u00famero do processo';

	},

	sortBookmarks : function(root) {

		var returnTo = this.pageNum
			, chd = root.children
			, names = {}
			, key, bm;

		if(!chd) { return; }

		for(key = 0; bm = chd[key++];){
			bm.execute();
			bm.pageNum = this.pageNum;
			bm.order = key;
			names[bm.pageNum] = {};
			bm.children && AcrobatJs.sortBookmarks(bm);
		}

		chd.sort(function(a, b){
			return a.pageNum - b.pageNum || a.order - b.order;
		});

		for(key = 0; bm = chd[key++];){
			if(names[bm.pageNum][bm.name] && !bm.children){
				bm.remove();
				continue;
			}
			root.insertChild(bm, chd.length);
			names[bm.pageNum][bm.name] = !0;
		}

		this.pageNum = returnTo;

	}

};

Utils.stickAll(AcrobatJs);

var cEnable = "event.rc = (event.target != null);"
	, cExec = "AcrobatJs.sortBookmarks(this.bookmarkRoot);"
	, cLabel = "Ordenar &Marcadores";

app.addMenuItem({
	cName: "sortBookmarks",
	cUser: cLabel,
	cParent: "Tools",
	cEnable: cEnable,
	cExec: cExec
});

app.addToolButton({
	cName: "sortBkmButton",
	cLabel: cLabel,
	cEnable: cEnable,
	cExec: cExec,
	nPos: -1
});

app.addMenuItem({
	cName: "addCert6",
	cUser: "Certid\u00e3o - Status &6",
	cParent: "Tools",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(6);"
});

app.addMenuItem({
	cName: "addCert1",
	cUser: "Certid\u00e3o - Status &1",
	cParent: "Tools",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(1);"
});

<commit_msg>Add cert1 n cert6 toolbar buttons<commit_after>/*
 acrobat-js - http://github.com/fabianonunes/acrobat-js
 Copyright (c) 2011, Fabiano Nunes
 Released under the BSD License.
*/

var Utils = {

	stick : function(func) {
		return function() {
			return func.apply(event.target, Array.prototype.slice.call(arguments));
		}
	},

	stickAll : function(obj) {
		for (var b in obj) Utils.isFunction(obj[b]) && (obj[b] = Utils.stick(obj[b]))
	},

	isFunction : function(obj) {
		return Object.prototype.toString.call(obj) == '[object Function]';
	}

};

var AcrobatJs = {

	paths : {
		1 : '/r/APLICATIVOS/Certidoes/status_1.pdf',
		6 : '/r/APLICATIVOS/Certidoes/status_6.pdf'
	},

	insertDoc : app.trustedFunction(function(path){
		app.beginPriv();
		this.insertPages({
			nPage: this.numPages-1,
			cPath: path
		});
		this.pageNum = this.numPages-1;
		app.endPriv();
	}),

	addCert : function(status){

		console.println(AcrobatJs.paths[status]);

		AcrobatJs.insertDoc(AcrobatJs.paths[status]);

		var f = this.getField('numproc_' + status)
			, mask = /[1-9]\d{0,6}-\d{2}\.\d{4}\.\d\.\d{2}\.\d{4}/;

		f.value = mask.exec(this.documentFileName) || 'Digite o n\u00famero do processo';

	},

	sortBookmarks : function(root) {

		var returnTo = this.pageNum
			, chd = root.children
			, names = {}
			, key, bm;

		if(!chd) { return; }

		for(key = 0; bm = chd[key++];){
			bm.execute();
			bm.pageNum = this.pageNum;
			bm.order = key;
			names[bm.pageNum] = {};
			bm.children && AcrobatJs.sortBookmarks(bm);
		}

		chd.sort(function(a, b){
			return a.pageNum - b.pageNum || a.order - b.order;
		});

		for(key = 0; bm = chd[key++];){
			if(names[bm.pageNum][bm.name] && !bm.children){
				bm.remove();
				continue;
			}
			root.insertChild(bm, chd.length);
			names[bm.pageNum][bm.name] = !0;
		}

		this.pageNum = returnTo;

	}

};

Utils.stickAll(AcrobatJs);

var cEnable = "event.rc = (event.target != null);"
	, cExec = "AcrobatJs.sortBookmarks(this.bookmarkRoot);"
	, cLabel = "Ordenar &Marcadores";

app.addMenuItem({
	cName: "sortBookmarks",
	cUser: cLabel,
	cParent: "Tools",
	cEnable: cEnable,
	cExec: cExec
});

app.addToolButton({
	cName: "sortBkmButton",
	cLabel: cLabel,
	cEnable: cEnable,
	cExec: cExec,
	nPos: -1
});

app.addMenuItem({
	cName: "addCert6",
	cUser: "Certid\u00e3o - Status &6",
	cParent: "Tools",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(6);"
});

app.addToolButton({
	cName: "addCert6Button",
	cLabel: "Certid\u00e3o - Status 6",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(6);",
	nPos: -1
});

app.addMenuItem({
	cName: "addCert1",
	cUser: "Certid\u00e3o - Status &1",
	cParent: "Tools",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(1);"
});

app.addToolButton({
	cName: "addCert1Button",
	cLabel: "Certid\u00e3o - Status 1",
	cEnable: cEnable,
	cExec: "AcrobatJs.addCert(1);",
	nPos: -1

});

<|endoftext|>


<commit_before>const {Plugin} = require("../edit")
const {Transform} = require("../transform")
const {Subscription} = require("subscription")

const {rebaseSteps} = require("./rebase")
exports.rebaseSteps = rebaseSteps

// !! This module implements an API into which a communication channel
// for collaborative editing can be hooked. See [this
// guide](guide/collab.html) for more details and an example.

function randomID() { return Math.floor(Math.random() * 0xFFFFFFFF) }

// ;; This class accumulates changes that have to be sent to the
// central authority in the collaborating group, signals an event when
// it has something to send, and makes it possible to integrate
// changes made by peers into our local document. It is created and
// attached to the editor when the [plugin](#collabEditing) is enabled,
// and can be accessed with
// [`collabEditing.get`](#Plugin.get).
class Collab {
  constructor(pm, options) {
    this.pm = pm
    this.clientID = randomID()

    // :: number
    // The version number of the last update received from the central
    // authority. Starts at 0 or the value of the `version` property
    // in the option object, for the editor's value when the option
    // was enabled.
    this.version = options.version
    this.versionDoc = pm.doc
    if (pm.history) pm.history.preserveItems++

    this.unconfirmedSteps = []
    this.unconfirmedMaps = []

    // :: Subscription<()>
    // Fired when there are new steps to send to the central
    // authority. Consumers should respond by calling
    // `sendableSteps` and pushing those to the authority.
    this.mustSend = new Subscription

    // :: Subscription<(transform: Transform, selectionBeforeTransform: Selection)>
    // Signals that a transformation has been aplied to the editor.
    // Passes the `Transform` and the selection before the transform
    // as arguments to the handler.
    this.receivedTransform = new Subscription

    pm.on.transform.add(this.onTransform = transform => {
      for (let i = 0; i < transform.steps.length; i++) {
        this.unconfirmedSteps.push(transform.steps[i])
        this.unconfirmedMaps.push(transform.maps[i])
      }
      this.mustSend.dispatch()
    })
    pm.on.beforeSetDoc.add(this.onSetDoc = () => {
      throw new RangeError("setDoc is not supported on a collaborative editor")
    })
  }

  detach() {
    this.pm.on.transform.remove(this.onTransform)
    this.pm.on.beforeSetDoc.remove(this.onSetDoc)
    if (this.pm.history) this.pm.history.preserveItems++
  }

  // :: () → bool
  // Reports whether the editor has any unsent steps.
  hasSendableSteps() {
    return this.unconfirmedSteps.length > 0
  }

  // :: () → {version: number, steps: [Step]}
  // Provides the data describing the editor's unconfirmed steps. The
  // version and array of steps are the things you'd send to the
  // central authority. The whole return value must be passed to
  // [`confirmSteps`](#Collab.confirmSteps) when the steps go through.
  sendableSteps() {
    return {
      version: this.version,
      steps: this.unconfirmedSteps.slice(),
      clientID: this.clientID
    }
  }

  // :: ([Step], [number]) → [PosMap]
  // Pushes a set of steps (received from the central authority) into
  // the editor. Will recognize its own changes, and confirm
  // unconfirmed steps as appropriate. Remaining unconfirmed steps
  // will be rebased over remote steps.
  //
  // Returns the [position maps](#PosMap) produced by applying the
  // steps.
  receive(steps, clientIDs) {
    // Find out which prefix of the steps originated with us
    let ours = 0
    while (ours < clientIDs.length && clientIDs[ours] == this.clientID) ++ours

    this.version += steps.length
    if (ours == clientIDs.length && ours == this.unconfirmedSteps.length) {
      // If all steps originated with us, and we didn't make any new
      // steps in the meantime, we simply forward the confirmed state
      // to the current state.
      this.versionDoc = this.pm.doc
      this.unconfirmedSteps.length = this.unconfirmedMaps.length = 0
      return []
    }

    let transform = new Transform(this.versionDoc)
    steps.forEach(step => transform.step(step))
    this.versionDoc = transform.doc

    // Move the remaining unconfirmed steps across the new steps
    let newMaps = transform.maps.slice(ours)
    let rebased = rebaseSteps(transform.doc, newMaps,
                              this.unconfirmedSteps.slice(ours), this.unconfirmedMaps.slice(ours))
    this.unconfirmedSteps = rebased.transform.steps.slice()
    this.unconfirmedMaps = rebased.transform.maps.slice()

    let selectionBefore = this.pm.selection
    this.pm.updateDoc(rebased.doc, rebased.mapping)
    if (this.pm.history) this.pm.history.rebased(newMaps, rebased.transform, rebased.positions)
    this.receivedTransform.dispatch(transform, selectionBefore)
    return transform.maps
  }
}

// :: Plugin
//
// Enables the collaborative editing framework for the editor.
//
// You can pass a `version` option, which determines the starting
// version number of the collaborative editing, and defaults to 0.
const collabEditing = new Plugin(Collab, {
  version: 0
})
exports.collabEditing = collabEditing
<commit_msg>Give transforms a mapping, not an array of maps<commit_after>const {Plugin} = require("../edit")
const {Transform} = require("../transform")
const {Subscription} = require("subscription")

const {rebaseSteps} = require("./rebase")
exports.rebaseSteps = rebaseSteps

// !! This module implements an API into which a communication channel
// for collaborative editing can be hooked. See [this
// guide](guide/collab.html) for more details and an example.

function randomID() { return Math.floor(Math.random() * 0xFFFFFFFF) }

// ;; This class accumulates changes that have to be sent to the
// central authority in the collaborating group, signals an event when
// it has something to send, and makes it possible to integrate
// changes made by peers into our local document. It is created and
// attached to the editor when the [plugin](#collabEditing) is enabled,
// and can be accessed with
// [`collabEditing.get`](#Plugin.get).
class Collab {
  constructor(pm, options) {
    this.pm = pm
    this.clientID = randomID()

    // :: number
    // The version number of the last update received from the central
    // authority. Starts at 0 or the value of the `version` property
    // in the option object, for the editor's value when the option
    // was enabled.
    this.version = options.version
    this.versionDoc = pm.doc
    if (pm.history) pm.history.preserveItems++

    this.unconfirmedSteps = []
    this.unconfirmedMaps = []

    // :: Subscription<()>
    // Fired when there are new steps to send to the central
    // authority. Consumers should respond by calling
    // `sendableSteps` and pushing those to the authority.
    this.mustSend = new Subscription

    // :: Subscription<(transform: Transform, selectionBeforeTransform: Selection)>
    // Signals that a transformation has been aplied to the editor.
    // Passes the `Transform` and the selection before the transform
    // as arguments to the handler.
    this.receivedTransform = new Subscription

    pm.on.transform.add(this.onTransform = transform => {
      for (let i = 0; i < transform.steps.length; i++) {
        this.unconfirmedSteps.push(transform.steps[i])
        this.unconfirmedMaps.push(transform.mapping.maps[i])
      }
      this.mustSend.dispatch()
    })
    pm.on.beforeSetDoc.add(this.onSetDoc = () => {
      throw new RangeError("setDoc is not supported on a collaborative editor")
    })
  }

  detach() {
    this.pm.on.transform.remove(this.onTransform)
    this.pm.on.beforeSetDoc.remove(this.onSetDoc)
    if (this.pm.history) this.pm.history.preserveItems++
  }

  // :: () → bool
  // Reports whether the editor has any unsent steps.
  hasSendableSteps() {
    return this.unconfirmedSteps.length > 0
  }

  // :: () → {version: number, steps: [Step]}
  // Provides the data describing the editor's unconfirmed steps. The
  // version and array of steps are the things you'd send to the
  // central authority. The whole return value must be passed to
  // [`confirmSteps`](#Collab.confirmSteps) when the steps go through.
  sendableSteps() {
    return {
      version: this.version,
      steps: this.unconfirmedSteps.slice(),
      clientID: this.clientID
    }
  }

  // :: ([Step], [number]) → [PosMap]
  // Pushes a set of steps (received from the central authority) into
  // the editor. Will recognize its own changes, and confirm
  // unconfirmed steps as appropriate. Remaining unconfirmed steps
  // will be rebased over remote steps.
  //
  // Returns the [position maps](#PosMap) produced by applying the
  // steps.
  receive(steps, clientIDs) {
    // Find out which prefix of the steps originated with us
    let ours = 0
    while (ours < clientIDs.length && clientIDs[ours] == this.clientID) ++ours

    this.version += steps.length
    if (ours == clientIDs.length && ours == this.unconfirmedSteps.length) {
      // If all steps originated with us, and we didn't make any new
      // steps in the meantime, we simply forward the confirmed state
      // to the current state.
      this.versionDoc = this.pm.doc
      this.unconfirmedSteps.length = this.unconfirmedMaps.length = 0
      return []
    }

    let transform = new Transform(this.versionDoc)
    steps.forEach(step => transform.step(step))
    this.versionDoc = transform.doc

    // Move the remaining unconfirmed steps across the new steps
    let newMaps = transform.mapping.maps.slice(ours)
    let rebased = rebaseSteps(transform.doc, newMaps,
                              this.unconfirmedSteps.slice(ours), this.unconfirmedMaps.slice(ours))
    this.unconfirmedSteps = rebased.transform.steps.slice()
    this.unconfirmedMaps = rebased.transform.mapping.maps.slice()

    let selectionBefore = this.pm.selection
    this.pm.updateDoc(rebased.doc, rebased.mapping)
    if (this.pm.history) this.pm.history.rebased(newMaps, rebased.transform, rebased.positions)
    this.receivedTransform.dispatch(transform, selectionBefore)
    return transform.mapping
  }
}

// :: Plugin
//
// Enables the collaborative editing framework for the editor.
//
// You can pass a `version` option, which determines the starting
// version number of the collaborative editing, and defaults to 0.
const collabEditing = new Plugin(Collab, {
  version: 0
})
exports.collabEditing = collabEditing
<|endoftext|>


<commit_before>// Simple persistence driver that saves data to plain text files

'use strict';

var aFrom             = require('es5-ext/array/from')
  , group             = require('es5-ext/array/#/group')
  , assign            = require('es5-ext/object/assign')
  , forEach           = require('es5-ext/object/for-each')
  , setPrototypeOf    = require('es5-ext/object/set-prototype-of')
  , toArray           = require('es5-ext/object/to-array')
  , ensureObject      = require('es5-ext/object/valid-object')
  , ensureString      = require('es5-ext/object/validate-stringifiable-value')
  , d                 = require('d')
  , lazy              = require('d/lazy')
  , memoizeMethods    = require('memoizee/methods')
  , Set               = require('es6-set')
  , deferred          = require('deferred')
  , resolve           = require('path').resolve
  , mkdir             = require('fs2/mkdir')
  , readFile          = require('fs2/read-file')
  , readdir           = require('fs2/readdir')
  , writeFile         = require('fs2/write-file')
  , serialize         = require('dbjs/_setup/serialize/value')
  , PersistenceDriver = require('./abstract')

  , push = Array.prototype.push, keys = Object.keys
  , isId = RegExp.prototype.test.bind(/^[a-z0-9][a-z0-9A-Z]*$/)
  , byStamp = function (a, b) { return a.stamp - b.stamp; }
  , create = Object.create, parse = JSON.parse, stringify = JSON.stringify;

var TextFileDriver = module.exports = function (dbjs, data) {
	if (!(this instanceof TextFileDriver)) return new TextFileDriver(dbjs, data);
	ensureObject(data);
	this.dirPath = resolve(ensureString(data.path));
	PersistenceDriver.call(this, dbjs, data);
	this.dbDir = mkdir(this.dirPath, { intermediate: true }).aside(null, function (err) {
		this.isClosed = true;
		this.emitError(err);
	}.bind(this));
};
setPrototypeOf(TextFileDriver, PersistenceDriver);

TextFileDriver.prototype = Object.create(PersistenceDriver.prototype, assign({
	constructor: d(TextFileDriver),
	_getCustom: d(function (key) { return this._custom(function (data) { return data[key]; }); }),
	_loadValue: d(function (id) {
		var objId = id.split('/', 1)[0];
		return this._getObjectFile(objId)(function (map) {
			if (!map.regular[id]) return null;
			return this._importValue(id, map.regular[id].value, map.stamp);
		}.bind(this));
	}),
	_loadObject: d(function (id) {
		return this._getObjectFile(id)(function (map) {
			var result = [];
			forEach(map.regular, function (data, id) {
				var event = this._importValue(id, data.value, data.stamp);
				if (event) result.push(event);
			}, this, byStamp);
			return result;
		}.bind(this));
	}),
	_loadAll: d(function () {
		return this.dbDir()(function () {
			return this._allObjectsIds(function (data) {
				var result = [];
				return deferred.map(aFrom(data), function (id) {
					return this._loadObject(id).aside(function (events) { push.apply(result, events); });
				}, this)(result);
			}.bind(this));
		}.bind(this));
	}),
	_storeCustom: d(function (key, value) {
		return this._custom(function (data) {
			if (value === undefined) {
				if (!data.hasOwnProperty(key)) return;
				delete data[key];
			} else {
				if (data[key] === value) return;
				data[key] = value;
			}
			return writeFile(resolve(this.dirPath, '_custom'), stringify(data));
		});
	}),
	_storeEvent: d(function (event) {
		var id = event.object.master.__id__;
		return this._getObjectFile(id)(function (map) {
			map.regular[event.object.__valueId__] = {
				stamp: event.stamp,
				value: serialize(event.value)
			};
			return this._writeObjectFile(map, id);
		}.bind(this));
	}),
	_storeEvents: d(function (events) {
		var data = group.call(events, function (event) { return event.object.master.__id__; });
		return deferred.map(keys(data), function (id) {
			var events = data[id];
			return this._getObjectFile(id)(function (map) {
				events.forEach(function (event) {
					map.regular[event.object.__valueId__] = {
						stamp: event.stamp,
						value: serialize(event.value)
					};
				});
				return this._writeObjectFile(map, id);
			}.bind(this));
		}, this);
	}),
	_close: d(function () {
		// Nothing to do
	}),
	_getComputed: d(function (id) {
		return this._getObjectFile(id.split('/', 1)[0])(function (map) {
			return map.computed[id] || null;
		});
	}),
	_storeComputed: d(function (id, value, stamp) {
		return this._getObjectFile(id.split('/', 1)[0])(function (map) {
			var old = map.computed[id];
			if (old) {
				old.stamp = stamp;
				old.value = value;
			} else {
				map.computed[id] = {
					value: value,
					stamp: stamp
				};
			}
			return this._writeObjectFile(map, id);
		});
	}),
	_writeObjectFile: d(function (map, id) {
		this._allObjectsIds.aside(function (set) { set.add(id); });
		return writeFile(resolve(this.dirPath, id), toArray(map.regular, function (data, id) {
			return id + '\n' + data.stamp + '\n' + data.value;
		}, this, byStamp).concat(toArray(map.computed, function (data, id) {
			return '=' + id + '\n' + data.stamp + '\n' + data.value;
		}, this, byStamp)).join('\n\n'));
	})
}, lazy({
	_allObjectsIds: d(function () {
		return readdir(this.dirPath, { type: { file: true } })(function (data) {
			return new Set(data.filter(isId));
		});
	}),
	_custom: d(function () {
		return this.dbDir()(function () {
			return readFile(resolve(this.dirPath, '_custom'))(function (str) {
				try {
					return parse(String(str));
				} catch (e) { return {}; }
			}, function (err) {
				if (err.code !== 'ENOENT') throw err;
				return {};
			})({});
		});
	})
}), memoizeMethods({
	_getObjectFile: d(function (id) {
		return this.dbDir()(function () {
			var map = { regular: create(null), computed: create(null) };
			return readFile(resolve(this.dirPath, id))(function (data) {
				try {
					String(data).split('\n\n').forEach(function (data) {
						data = data.split('\n');
						if (data[0][0] === '=') {
							map.computed[data[0].slice(1)] = {
								stamp: Number(data[1]),
								value: data[2]
							};
						} else {
							map.regular[data[0]] = {
								stamp: Number(data[1]),
								value: data[2]
							};
						}
					});
				} catch (ignore) {}
				return map;
			}, function (err) {
				if (err.code !== 'ENOENT') throw err;
				return map;
			});
		}.bind(this));
	}, { primitive: true })
})));
<commit_msg>_getAllComputed for TextFile driver<commit_after>// Simple persistence driver that saves data to plain text files

'use strict';

var aFrom             = require('es5-ext/array/from')
  , group             = require('es5-ext/array/#/group')
  , assign            = require('es5-ext/object/assign')
  , forEach           = require('es5-ext/object/for-each')
  , setPrototypeOf    = require('es5-ext/object/set-prototype-of')
  , toArray           = require('es5-ext/object/to-array')
  , ensureObject      = require('es5-ext/object/valid-object')
  , ensureString      = require('es5-ext/object/validate-stringifiable-value')
  , d                 = require('d')
  , lazy              = require('d/lazy')
  , memoizeMethods    = require('memoizee/methods')
  , Set               = require('es6-set')
  , deferred          = require('deferred')
  , resolve           = require('path').resolve
  , mkdir             = require('fs2/mkdir')
  , readFile          = require('fs2/read-file')
  , readdir           = require('fs2/readdir')
  , writeFile         = require('fs2/write-file')
  , serialize         = require('dbjs/_setup/serialize/value')
  , PersistenceDriver = require('./abstract')

  , push = Array.prototype.push, keys = Object.keys
  , isId = RegExp.prototype.test.bind(/^[a-z0-9][a-z0-9A-Z]*$/)
  , byStamp = function (a, b) { return a.stamp - b.stamp; }
  , create = Object.create, parse = JSON.parse, stringify = JSON.stringify;

var TextFileDriver = module.exports = function (dbjs, data) {
	if (!(this instanceof TextFileDriver)) return new TextFileDriver(dbjs, data);
	ensureObject(data);
	this.dirPath = resolve(ensureString(data.path));
	PersistenceDriver.call(this, dbjs, data);
	this.dbDir = mkdir(this.dirPath, { intermediate: true }).aside(null, function (err) {
		this.isClosed = true;
		this.emitError(err);
	}.bind(this));
};
setPrototypeOf(TextFileDriver, PersistenceDriver);

TextFileDriver.prototype = Object.create(PersistenceDriver.prototype, assign({
	constructor: d(TextFileDriver),
	_getCustom: d(function (key) { return this._custom(function (data) { return data[key]; }); }),
	_loadValue: d(function (id) {
		var objId = id.split('/', 1)[0];
		return this._getObjectFile(objId)(function (map) {
			if (!map.regular[id]) return null;
			return this._importValue(id, map.regular[id].value, map.stamp);
		}.bind(this));
	}),
	_loadObject: d(function (id) {
		return this._getObjectFile(id)(function (map) {
			var result = [];
			forEach(map.regular, function (data, id) {
				var event = this._importValue(id, data.value, data.stamp);
				if (event) result.push(event);
			}, this, byStamp);
			return result;
		}.bind(this));
	}),
	_loadAll: d(function () {
		return this.dbDir()(function () {
			return this._allObjectsIds(function (data) {
				var result = [];
				return deferred.map(aFrom(data), function (id) {
					return this._loadObject(id).aside(function (events) { push.apply(result, events); });
				}, this)(result);
			}.bind(this));
		}.bind(this));
	}),
	_storeCustom: d(function (key, value) {
		return this._custom(function (data) {
			if (value === undefined) {
				if (!data.hasOwnProperty(key)) return;
				delete data[key];
			} else {
				if (data[key] === value) return;
				data[key] = value;
			}
			return writeFile(resolve(this.dirPath, '_custom'), stringify(data));
		});
	}),
	_storeEvent: d(function (event) {
		var id = event.object.master.__id__;
		return this._getObjectFile(id)(function (map) {
			map.regular[event.object.__valueId__] = {
				stamp: event.stamp,
				value: serialize(event.value)
			};
			return this._writeObjectFile(map, id);
		}.bind(this));
	}),
	_storeEvents: d(function (events) {
		var data = group.call(events, function (event) { return event.object.master.__id__; });
		return deferred.map(keys(data), function (id) {
			var events = data[id];
			return this._getObjectFile(id)(function (map) {
				events.forEach(function (event) {
					map.regular[event.object.__valueId__] = {
						stamp: event.stamp,
						value: serialize(event.value)
					};
				});
				return this._writeObjectFile(map, id);
			}.bind(this));
		}, this);
	}),
	_close: d(function () {
		// Nothing to do
	}),
	_getComputed: d(function (id) {
		return this._getObjectFile(id.split('/', 1)[0])(function (map) {
			return map.computed[id] || null;
		});
	}),
	_getAllComputed: d(function (keyPath) {
		var map = create(null);
		return this._allObjectIds.map(function (id) {
			return this._getObjectFile(id)(function (objectMap) {
				if (objectMap['=' + keyPath]) map[id] = objectMap['=' + keyPath];
			});
		}, this)(map);
	}),
	_storeComputed: d(function (id, value, stamp) {
		return this._getObjectFile(id.split('/', 1)[0])(function (map) {
			var old = map.computed[id];
			if (old) {
				old.stamp = stamp;
				old.value = value;
			} else {
				map.computed[id] = {
					value: value,
					stamp: stamp
				};
			}
			return this._writeObjectFile(map, id);
		});
	}),
	_writeObjectFile: d(function (map, id) {
		this._allObjectsIds.aside(function (set) { set.add(id); });
		return writeFile(resolve(this.dirPath, id), toArray(map.regular, function (data, id) {
			return id + '\n' + data.stamp + '\n' + data.value;
		}, this, byStamp).concat(toArray(map.computed, function (data, id) {
			return '=' + id + '\n' + data.stamp + '\n' + data.value;
		}, this, byStamp)).join('\n\n'));
	})
}, lazy({
	_allObjectsIds: d(function () {
		return readdir(this.dirPath, { type: { file: true } })(function (data) {
			return new Set(data.filter(isId));
		});
	}),
	_custom: d(function () {
		return this.dbDir()(function () {
			return readFile(resolve(this.dirPath, '_custom'))(function (str) {
				try {
					return parse(String(str));
				} catch (e) { return {}; }
			}, function (err) {
				if (err.code !== 'ENOENT') throw err;
				return {};
			})({});
		});
	})
}), memoizeMethods({
	_getObjectFile: d(function (id) {
		return this.dbDir()(function () {
			var map = { regular: create(null), computed: create(null) };
			return readFile(resolve(this.dirPath, id))(function (data) {
				try {
					String(data).split('\n\n').forEach(function (data) {
						data = data.split('\n');
						if (data[0][0] === '=') {
							map.computed[data[0].slice(1)] = {
								stamp: Number(data[1]),
								value: data[2]
							};
						} else {
							map.regular[data[0]] = {
								stamp: Number(data[1]),
								value: data[2]
							};
						}
					});
				} catch (ignore) {}
				return map;
			}, function (err) {
				if (err.code !== 'ENOENT') throw err;
				return map;
			});
		}.bind(this));
	}, { primitive: true })
})));
<|endoftext|>


<commit_before>var yadda = require('yadda');
var Filter = require('broccoli-filter');
var path = require('path');

/* jshint node: true */
'use strict';

// voorbeeld van de brocolli-filter readme. bah en bah
FeatureParser.prototype = Object.create(Filter.prototype);
FeatureParser.prototype.constructor = FeatureParser;
function FeatureParser(inputNode, testFramework) {
  this.testFramework = testFramework;
  Filter.call(this, inputNode);
}
FeatureParser.prototype.extensions = ['feature', 'spec', 'specification'];
FeatureParser.prototype.targetExtension = 'js';
FeatureParser.prototype.processString = function(content, relativePath) {
  var feature = new yadda.parsers.FeatureParser().parse(content);
  var basePath = relativePath.split('/').slice(0,2).join('/');
  var nestedPath = relativePath.split('/').length > 4 ? relativePath.split('/').slice(3,-1).join('/') + '/' : '';
  var stepsPath = basePath + "/acceptance/steps/";
  var fileName =relativePath.split('/').slice(-1)[0].split('.')[0]; //remove extension
  var head = [
    "import Ember from 'ember';",
    this.getTestFrameworkImport(),
    "import yadda from '" + basePath + "/helpers/yadda';",
    "import * as library from '" + stepsPath + nestedPath + fileName + "-steps';",
    "import startApp from '" + basePath + "/helpers/start-app';",
    "",
    this.getTestFeature(),
    "",
    "testFeature("
  ].join('\n');
  var foot = ');';
  return head + JSON.stringify(feature, null, 2) + foot;
};
FeatureParser.prototype.getDestFilePath = function (relativePath) {
  var ext = path.extname(relativePath);
  if(ext === '.feature' || ext === '.spec' || ext === '.specifiation') {
    return relativePath.replace(ext, '-test.js');
  }
  return null;
};
FeatureParser.prototype.getTestFrameworkImport = function() {
  switch (this.testFramework) {
    case 'mocha':
      return 'import { afterEach, beforeEach, describe, it } from \'mocha\';';
    default: // qunit
      return 'import { module, test } from \'qunit\';';
  }
};
FeatureParser.prototype.getTestFeature = function() {
  var testFeature;
  switch (this.testFramework) {
    case 'mocha':
      testFeature = [
        "function testFeature(feature) {",
        "  describe(`Feature: ${feature.title}`, () => {",
        "    beforeEach(function() {",
        "      this.application = startApp();",
        "    });",
        "    afterEach(function() {",
        "      Ember.run(this.application, 'destroy');",
        "    });",
        "    ",
        "    feature.scenarios.forEach(function(scenario) {",
        "      it(`Scenario: ${scenario.title}`, function() {",
        "        return new Ember.RSVP.Promise(function(resolve) { yadda.Yadda(library.default(), this).yadda(scenario.steps, { ctx: {} }, resolve); });",
        "      });",
        "    });",
        "  });",
        "};"
      ];
      break;
    default: // qunit
      testFeature = [
        "function testFeature(feature) {",
        "  module(`Feature: ${feature.title}`, {",
        "    beforeEach: function() {",
        "      this.application = startApp();",
        "    },",
        "    afterEach: function() {",
        "      Ember.run(this.application, 'destroy');",
        "    }",
        "  });",

        "  feature.scenarios.forEach(function(scenario) {",
        "    test(`Scenario: ${scenario.title}`, function(assert) {",
        "      expect(scenario.steps.length);",
        "      return new Ember.RSVP.Promise(function (resolve) { yadda.Yadda(library.default(assert), this).yadda(scenario.steps, { ctx: {} }, resolve); });",
        "    });",
        "  });",
        "};"
      ];
  }
  return testFeature.join('\n');
};

module.exports = {
  name: 'ember-cli-yadda',
  getTestFramework: function() {
    return require(path.join(process.cwd(), 'testem.json')).framework;
  },
  setupPreprocessorRegistry: function(type, registry) {
    var testFramework = this.getTestFramework();
    registry.add('js', {
      name: 'ember-cli-yadda',
      ext: ['feature', 'spec', 'specification'],
      toTree: function(tree, inputPath, outputPath) {
        return new FeatureParser(tree, testFramework);
      }
    });
  },
  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints', this.getTestFramework());
  },
  included: function(app) {
    this._super.included(app);
    app.import(app.bowerDirectory + '/yadda/dist/yadda-0.15.4.js', { type: 'test' });
  },
  isDevelopingAddon: function() {
   return true;
  }
};
<commit_msg>Change test framework detection to use the package.json<commit_after>var yadda = require('yadda');
var Filter = require('broccoli-filter');
var path = require('path');

/* jshint node: true */
'use strict';

// voorbeeld van de brocolli-filter readme. bah en bah
FeatureParser.prototype = Object.create(Filter.prototype);
FeatureParser.prototype.constructor = FeatureParser;
function FeatureParser(inputNode, testFramework) {
  this.testFramework = testFramework;
  Filter.call(this, inputNode);
}
FeatureParser.prototype.extensions = ['feature', 'spec', 'specification'];
FeatureParser.prototype.targetExtension = 'js';
FeatureParser.prototype.processString = function(content, relativePath) {
  var feature = new yadda.parsers.FeatureParser().parse(content);
  var basePath = relativePath.split('/').slice(0,2).join('/');
  var nestedPath = relativePath.split('/').length > 4 ? relativePath.split('/').slice(3,-1).join('/') + '/' : '';
  var stepsPath = basePath + "/acceptance/steps/";
  var fileName =relativePath.split('/').slice(-1)[0].split('.')[0]; //remove extension
  var head = [
    "import Ember from 'ember';",
    this.getTestFrameworkImport(),
    "import yadda from '" + basePath + "/helpers/yadda';",
    "import * as library from '" + stepsPath + nestedPath + fileName + "-steps';",
    "import startApp from '" + basePath + "/helpers/start-app';",
    "",
    this.getTestFeature(),
    "",
    "testFeature("
  ].join('\n');
  var foot = ');';
  return head + JSON.stringify(feature, null, 2) + foot;
};
FeatureParser.prototype.getDestFilePath = function (relativePath) {
  var ext = path.extname(relativePath);
  if(ext === '.feature' || ext === '.spec' || ext === '.specifiation') {
    return relativePath.replace(ext, '-test.js');
  }
  return null;
};
FeatureParser.prototype.getTestFrameworkImport = function() {
  switch (this.testFramework) {
    case 'mocha':
      return 'import { afterEach, beforeEach, describe, it } from \'mocha\';';
    default: // qunit
      return 'import { module, test } from \'qunit\';';
  }
};
FeatureParser.prototype.getTestFeature = function() {
  var testFeature;
  switch (this.testFramework) {
    case 'mocha':
      testFeature = [
        "function testFeature(feature) {",
        "  describe(`Feature: ${feature.title}`, () => {",
        "    beforeEach(function() {",
        "      this.application = startApp();",
        "    });",
        "    afterEach(function() {",
        "      Ember.run(this.application, 'destroy');",
        "    });",
        "    ",
        "    feature.scenarios.forEach(function(scenario) {",
        "      it(`Scenario: ${scenario.title}`, function() {",
        "        return new Ember.RSVP.Promise(function(resolve) { yadda.Yadda(library.default(), this).yadda(scenario.steps, { ctx: {} }, resolve); });",
        "      });",
        "    });",
        "  });",
        "};"
      ];
      break;
    default: // qunit
      testFeature = [
        "function testFeature(feature) {",
        "  module(`Feature: ${feature.title}`, {",
        "    beforeEach: function() {",
        "      this.application = startApp();",
        "    },",
        "    afterEach: function() {",
        "      Ember.run(this.application, 'destroy');",
        "    }",
        "  });",

        "  feature.scenarios.forEach(function(scenario) {",
        "    test(`Scenario: ${scenario.title}`, function(assert) {",
        "      expect(scenario.steps.length);",
        "      return new Ember.RSVP.Promise(function (resolve) { yadda.Yadda(library.default(assert), this).yadda(scenario.steps, { ctx: {} }, resolve); });",
        "    });",
        "  });",
        "};"
      ];
  }
  return testFeature.join('\n');
};

module.exports = {
  name: 'ember-cli-yadda',
  getTestFramework: function() {
    var packages = Object.keys(this.project.addonPackages);
    if (packages.indexOf('ember-cli-mocha') > -1) {
      return 'mocha';
    } else {
      return 'qunit';
    }
  },
  setupPreprocessorRegistry: function(type, registry) {
    var testFramework = this.getTestFramework();
    registry.add('js', {
      name: 'ember-cli-yadda',
      ext: ['feature', 'spec', 'specification'],
      toTree: function(tree, inputPath, outputPath) {
        return new FeatureParser(tree, testFramework);
      }
    });
  },
  blueprintsPath: function() {
    return path.join(__dirname, 'blueprints', this.getTestFramework());
  },
  included: function(app) {
    this._super.included(app);
    app.import(app.bowerDirectory + '/yadda/dist/yadda-0.15.4.js', { type: 'test' });
  },
  isDevelopingAddon: function() {
   return true;
  }
};
<|endoftext|>


<commit_before>/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;

var days = true;
var hours = true;
var minutes = true;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, opts) {
  opts = opts || {};

  console.log('this: ', this);

  // Handle parsing a time
  if (typeof val === 'string') return parse(val);

  // Set options
  typeof opts.days === 'boolean' ? days = opts.days : days = true;
  typeof opts.hours === 'boolean' ? hours = opts.hours : hours = true;
  typeof opts.minutes === 'boolean' ? minutes = opts.minutes : minutes = true;

  return opts.long ? long(val) : short(val);
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = '' + str;
  if (str.length > 10000) return;

  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);

  if (!match) return;

  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();

  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function short(ms) {
  if (ms >= d && days) return Math.round(ms / d) + 'd';
  if (ms >= h && hours) return Math.round(ms / h) + 'h';
  if (ms >= m && minutes) return Math.round(ms / m) + 'm';
  if (ms >= s) return Math.round(ms / s) + 's';
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function long(ms) {
  if (days && plural(ms, d, 'day')) {
    return plural(ms, d, 'day');
  }

  if (hours && plural(ms, h, 'hour')) {
    return plural(ms, h, 'hour');
  }

  if (minutes && plural(ms, m, 'minute')) {
    return plural(ms, m, 'minute');
  }

  if (plural(ms, s, 'second')) {
    return plural(ms, s, 'second');
  }

  return ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, n, name) {
  if (ms < n) return;

  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  return Math.ceil(ms / n) + ' ' + name + 's';
}
<commit_msg>Remove log<commit_after>/**
 * Helpers.
 */

var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;

var days = true;
var hours = true;
var minutes = true;

/**
 * Parse or format the given `val`.
 *
 * Options:
 *
 *  - `long` verbose formatting [false]
 *
 * @param {String|Number} val
 * @param {Object} options
 * @return {String|Number}
 * @api public
 */

module.exports = function(val, opts) {
  opts = opts || {};

  // Handle parsing a time
  if (typeof val === 'string') return parse(val);

  // Set options
  typeof opts.days === 'boolean' ? days = opts.days : days = true;
  typeof opts.hours === 'boolean' ? hours = opts.hours : hours = true;
  typeof opts.minutes === 'boolean' ? minutes = opts.minutes : minutes = true;

  return opts.long ? long(val) : short(val);
};

/**
 * Parse the given `str` and return milliseconds.
 *
 * @param {String} str
 * @return {Number}
 * @api private
 */

function parse(str) {
  str = '' + str;
  if (str.length > 10000) return;

  var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);

  if (!match) return;

  var n = parseFloat(match[1]);
  var type = (match[2] || 'ms').toLowerCase();

  switch (type) {
    case 'years':
    case 'year':
    case 'yrs':
    case 'yr':
    case 'y':
      return n * y;
    case 'days':
    case 'day':
    case 'd':
      return n * d;
    case 'hours':
    case 'hour':
    case 'hrs':
    case 'hr':
    case 'h':
      return n * h;
    case 'minutes':
    case 'minute':
    case 'mins':
    case 'min':
    case 'm':
      return n * m;
    case 'seconds':
    case 'second':
    case 'secs':
    case 'sec':
    case 's':
      return n * s;
    case 'milliseconds':
    case 'millisecond':
    case 'msecs':
    case 'msec':
    case 'ms':
      return n;
  }
}

/**
 * Short format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function short(ms) {
  if (ms >= d && days) return Math.round(ms / d) + 'd';
  if (ms >= h && hours) return Math.round(ms / h) + 'h';
  if (ms >= m && minutes) return Math.round(ms / m) + 'm';
  if (ms >= s) return Math.round(ms / s) + 's';
  return ms + 'ms';
}

/**
 * Long format for `ms`.
 *
 * @param {Number} ms
 * @return {String}
 * @api private
 */

function long(ms) {
  if (days && plural(ms, d, 'day')) {
    return plural(ms, d, 'day');
  }

  if (hours && plural(ms, h, 'hour')) {
    return plural(ms, h, 'hour');
  }

  if (minutes && plural(ms, m, 'minute')) {
    return plural(ms, m, 'minute');
  }

  if (plural(ms, s, 'second')) {
    return plural(ms, s, 'second');
  }

  return ms + ' ms';
}

/**
 * Pluralization helper.
 */

function plural(ms, n, name) {
  if (ms < n) return;

  if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
  return Math.ceil(ms / n) + ' ' + name + 's';
}
<|endoftext|>


<commit_before>import { connect as connectFela } from 'react-fela'
import { Field, reduxForm as connectForm } from 'redux-form'
import { pipe, isNil, not } from 'ramda'
import { TextField } from 'redux-form-material-ui'
import RaisedButton from 'material-ui/RaisedButton'
import { compose, withState, withHandlers } from 'recompose'
import h from 'react-hyperscript'
import { FormattedMessage } from 'dogstack/intl'
import { required, email } from '@root-systems/redux-form-validators'

import styles from '../styles/Profile'
import AvatarField from '../../app/components/AvatarField'

function Profile (props) {
  const { styles, isEditing, toggleEdit, updateProfile, handleSubmit, agentType } = props

  const updateProfileAndToggleEdit = (nextProfile) => {
    toggleEdit()
    updateProfile(nextProfile)
  }

  const isSupplierProfile = agentType === 'supplier'

  return h('form', {
    className: styles.container,
    onSubmit: handleSubmit(updateProfileAndToggleEdit)
  }, [
    h('p', {
      className: styles.intro
    }, [
      h(FormattedMessage, {
        id: 'agents.profile',
        className: styles.labelText,
        values: {
          agentType
        }
      })
    ]),
    h('div', {
      className: styles.innerContainer
    }, [
      h('div', {
        className: styles.avatarContainer
      }, [
        h(Field, {
          name: 'avatar',
          component: AvatarField,
          isEditingProfile: isEditing
        })
      ]),
      h('div', {
        className: styles.infoContainer
      }, [
        h(Field, {
          name: 'name',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.nameLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing),
          validate: required()
        }),
        h(Field, {
          name: 'description',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.descriptionLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          multiLine: true,
          rowsMax: 5,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'email',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.email',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing),
          validate: [required(), email()]
        }),
        h(Field, {
          name: 'phone',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.phoneLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'website',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.website',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'address',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.address',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          multiLine: true,
          rowsMax: 5,
          disabled: not(isEditing),
          validate: isSupplierProfile ? required() : null
        })
      ])
    ]),

    h('div', {
      className: styles.buttonContainer
    }, [
      isEditing
      ? h(RaisedButton, {
        className: styles.button,
        type: 'submit',
        primary: true
      }, [
        h(FormattedMessage, {
          id: 'agents.saveProfile',
          className: styles.buttonText
        })
      ])
      : h(RaisedButton, {
        className: styles.button,
        type: 'button',
        secondary: true,
        onClick: (ev) => {
          // GK: not entirely clear why this is necessary considering the button type, but preventing default anyway
          ev.preventDefault()
          toggleEdit()
        }
      }, [
        h(FormattedMessage, {
          id: 'agents.editProfile',
          className: styles.buttonText
        })
      ])
    ])

  ])
}

export default compose(
  connectFela(styles),
  withState('isEditing', 'setEditing', false),
  withHandlers({
    toggleEdit: ({ setEditing }) => () => setEditing(not)
  }),
  connectForm({
    form: 'profile',
    enableReinitialize: true
  })
)(Profile)
<commit_msg>feat(profile): remove toggle between edit and save, including state, depend only on isEditing prop<commit_after>import { connect as connectFela } from 'react-fela'
import { Field, reduxForm as connectForm } from 'redux-form'
import { pipe, isNil, not } from 'ramda'
import { TextField } from 'redux-form-material-ui'
import RaisedButton from 'material-ui/RaisedButton'
import { compose, withState, withHandlers } from 'recompose'
import h from 'react-hyperscript'
import { FormattedMessage } from 'dogstack/intl'
import { required, email } from '@root-systems/redux-form-validators'

import styles from '../styles/Profile'
import AvatarField from '../../app/components/AvatarField'

function Profile (props) {
  const { styles, isEditing, updateProfile, handleSubmit, agentType } = props

  const saveProfile = (nextProfile) => {
    updateProfile(nextProfile)
  }

  const isSupplierProfile = agentType === 'supplier'

  return h('form', {
    className: styles.container,
    onSubmit: handleSubmit(saveProfile)
  }, [
    h('p', {
      className: styles.intro
    }, [
      h(FormattedMessage, {
        id: 'agents.profile',
        className: styles.labelText,
        values: {
          agentType
        }
      })
    ]),
    h('div', {
      className: styles.innerContainer
    }, [
      h('div', {
        className: styles.avatarContainer
      }, [
        h(Field, {
          name: 'avatar',
          component: AvatarField,
          isEditingProfile: isEditing
        })
      ]),
      h('div', {
        className: styles.infoContainer
      }, [
        h(Field, {
          name: 'name',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.nameLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing),
          validate: required()
        }),
        h(Field, {
          name: 'description',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.descriptionLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          multiLine: true,
          rowsMax: 5,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'email',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.email',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing),
          validate: [required(), email()]
        }),
        h(Field, {
          name: 'phone',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.phoneLabel',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'website',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.website',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          disabled: not(isEditing)
        }),
        h(Field, {
          name: 'address',
          floatingLabelText: (
            h(FormattedMessage, {
              id: 'agents.address',
              className: styles.labelText
            })
          ),
          component: TextField,
          fullWidth: true,
          multiLine: true,
          rowsMax: 5,
          disabled: not(isEditing),
          validate: isSupplierProfile ? [required()] : null
        })
      ])
    ]),

    h('div', {
      className: styles.buttonContainer
    }, [
      isEditing
      ? h(RaisedButton, {
        className: styles.button,
        type: 'submit',
        primary: true
      }, [
        h(FormattedMessage, {
          id: 'agents.saveProfile',
          className: styles.buttonText
        })
      ])
         : null
    ])

  ])
}

export default compose(
  connectFela(styles),
  connectForm({
    form: 'profile',
    enableReinitialize: true
  })
)(Profile)
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var readline = require('readline');
var colors = require('colors');
var sprequest = require('sp-request');
var spr = null;
var ctxCached = null;

var spf = spf || {};
spf.rest = spf.rest || {};

spf.rest.RestApi = function() {
    var _that = this;
    var getCachedRequest = function(ctx) {
        var env = {};
        if (ctx.hasOwnProperty("domain")) {
            env.domain = ctx.domain;
        }
        if (ctx.hasOwnProperty("workstation")) {
            env.workstation = ctx.workstation;
        }
        if (JSON.stringify(ctxCached) === JSON.stringify(ctx)) {
            spr = spr || require("sp-request").create(ctx, env);
        } else {
            spr = require("sp-request").create(ctx, env);
        }
        return spr;
    };

    var operations = {};
    operations.downloadFile = function (context, options, spFilePath, callback) {

        var spFolderBase = options.spBaseFolder;
        var downloadRoot = options.dlRootFolder || "./downloads";

        var restUrl;
        spr = getCachedRequest(context);
        restUrl = context.siteUrl + "/_api/Web/GetFileByServerRelativeUrl(@FileServerRelativeUrl)/OpenBinaryStream" +
                                    "?@FileServerRelativeUrl='" + encodeURIComponent(spFilePath) + "'";
        spr.get(restUrl, { encoding: null })
            .then(function (response) {
                var saveFilePath = downloadRoot + "/" + decodeURIComponent(spFilePath).replace(decodeURIComponent(spFolderBase), "");
                var saveFolderPath = path.dirname(saveFilePath);
                mkdirp(saveFolderPath, function(err) {
                    fs.writeFile(saveFilePath, response.body, function(err) {
                        if (err) {
                            throw err;
                        };
                        if (callback && typeof callback === "function") {
                            callback(saveFilePath);
                        }
                    });
                });
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.downloadFile:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };
    operations.getFolderContent = function(context, options, spRootFolder, callback) {

        var metaFields = options.metaFields;

        var restUrl;
        spr = getCachedRequest(context);
        if (spRootFolder.charAt(spRootFolder.length - 1) === "/") {
            spRootFolder = spRootFolder.substring(0, spRootFolder.length - 1);
        }

        restUrl = context.siteUrl + "/_api/Web/GetFolderByServerRelativeUrl(@FolderServerRelativeUrl)" +
                    "?$expand=Folders,Files,Folders/ListItemAllFields,Files/ListItemAllFields" +
                    "&$select=" +
                    "##MetadataSrt#" +
                    "Folders/Name,Folders/UniqueID,Folders/ID,Folders/ItemCount,Folders/ServerRelativeUrl,Folder/TimeCreated,Folder/TimeModified," +
                    "Files/Name,Files/UniqueID,Files/ID,Files/ServerRelativeUrl,Files/Length,Files/TimeCreated,Files/TimeModified,Files/ModifiedBy" +
                    "&@FolderServerRelativeUrl='" + encodeURIComponent(spRootFolder) + "'";

        var metadataStr = "";
        if (metaFields.length > 0) {
            metadataStr = metaFields.map(function(fieldName) {
                return "Files/ListItemAllFields/" + fieldName;
            }).join(",") + ",";
        }
        restUrl = restUrl.replace(/##MetadataSrt#/g, metadataStr);

        spr.get(restUrl)
            .then(function (response) {

                var files = response.body.d.Files.results;
                if (metaFields.length > 0) {
                    files.forEach(function(data) {
                        data.metadata = {};
                        metaFields.forEach(function(fd) {
                            if (typeof data.ListItemAllFields !== "undefined") {
                                if (data.ListItemAllFields.hasOwnProperty(fd)) {
                                    data.metadata[fd] = data.ListItemAllFields[fd];
                                }
                            }
                        });
                    });
                }

                var results = {
                    folders: response.body.d.Folders.results,
                    files: files
                };

                if (callback && typeof callback === "function") {
                    callback(results);
                }
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.getFolderContent:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };
    operations.getContentWithCaml = function(context, options, callback) {

        var spDocLibUrl = options.spDocLibUrl;
        var camlStr = options.camlCondition;
        var metaFields = options.metaFields;

        spr = getCachedRequest(context);
        spr.requestDigest(context.siteUrl)
            .then(function (digest) {
                var restUrl;
                restUrl = context.siteUrl + "/_api/Web/GetList(@DocLibUrl)/GetItems" +
                        "?$select=" +
                            "##MetadataSrt#" +
                            "Name,UniqueID,ID,FileDirRef,FileRef,FSObjType,TimeCreated,TimeModified,Length,ModifiedBy" +
                        "&@DocLibUrl='" + encodeURIComponent(spDocLibUrl) + "'";
                var metadataStr = "";
                if (metaFields.length > 0) {
                    metadataStr = metaFields.join(",") + ",";
                }
                restUrl = restUrl.replace(/##MetadataSrt#/g, metadataStr);
                return spr.post(restUrl, {
                    body: {
                        query: {
                            __metadata: {
                                type: "SP.CamlQuery"
                            },
                            ViewXml: "<View Scope='Recursive'><Query><Where>" + camlStr + "</Where></Query></View>" // <Eq><FieldRef Name='MyTestAttr'/><Value Type='Text'>MyTestValue</Value></Eq>
                        }
                    },
                    headers: {
                        "X-RequestDigest": digest,
                        "accept": "application/json; odata=verbose",
                        "content-type": "application/json; odata=verbose"
                    }
                });
            })
            .then(function (response) {
                var filesData = [];
                var foldersData = [];

                response.body.d.results.forEach(function(item) {
                    if (metaFields.length > 0) {
                        item.metadata = {};
                        metaFields.forEach(function(fd) {
                            if (item.hasOwnProperty(fd)) {
                                item.metadata[fd] = item[fd];
                            }
                        });
                    }
                    if (item.FSObjType === 0) {
                        item.ServerRelativeUrl = item.FileRef;
                        filesData.push(item);
                    } else {
                        foldersData.push(item);
                    }
                });

                var results = {
                    files: filesData,
                    folders: foldersData
                };

                if (callback && typeof callback === "function") {
                    callback(results);
                }
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.getContentWithCaml:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };

    return operations;
};

module.exports = spf.rest;<commit_msg>added json fix<commit_after>var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var readline = require('readline');
var colors = require('colors');
var sprequest = require('sp-request');
var spr = null;
var ctxCached = null;

var spf = spf || {};
spf.rest = spf.rest || {};

spf.rest.RestApi = function() {
    var _that = this;
    var getCachedRequest = function(ctx) {
        var env = {};
        if (ctx.hasOwnProperty("domain")) {
            env.domain = ctx.domain;
        }
        if (ctx.hasOwnProperty("workstation")) {
            env.workstation = ctx.workstation;
        }
        if (JSON.stringify(ctxCached) === JSON.stringify(ctx)) {
            spr = spr || require("sp-request").create(ctx, env);
        } else {
            spr = require("sp-request").create(ctx, env);
        }
        return spr;
    };

    var operations = {};
    operations.downloadFile = function (context, options, spFilePath, callback) {

        var spFolderBase = options.spBaseFolder;
        var downloadRoot = options.dlRootFolder || "./downloads";

        var restUrl;
        spr = getCachedRequest(context);
        restUrl = context.siteUrl + "/_api/Web/GetFileByServerRelativeUrl(@FileServerRelativeUrl)/OpenBinaryStream" +
                                    "?@FileServerRelativeUrl='" + encodeURIComponent(spFilePath) + "'";
        spr.get(restUrl, { encoding: null })
            .then(function (response) {
                var saveFilePath = downloadRoot + "/" + decodeURIComponent(spFilePath).replace(decodeURIComponent(spFolderBase), "");
                var saveFolderPath = path.dirname(saveFilePath);
                if (/.json$/.test(saveFilePath)) {
                    response.body = JSON.stringify(response.body, null, 4);
                }
                if (/.map$/.test(saveFilePath)) {
                    response.body = JSON.stringify(response.body);
                }
                mkdirp(saveFolderPath, function(err) {
                    fs.writeFile(saveFilePath, response.body, function(err) {
                        if (err) {
                            throw err;
                        };
                        if (callback && typeof callback === "function") {
                            callback(saveFilePath);
                        }
                    });
                });
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.downloadFile:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };
    operations.getFolderContent = function(context, options, spRootFolder, callback) {

        var metaFields = options.metaFields;

        var restUrl;
        spr = getCachedRequest(context);
        if (spRootFolder.charAt(spRootFolder.length - 1) === "/") {
            spRootFolder = spRootFolder.substring(0, spRootFolder.length - 1);
        }

        restUrl = context.siteUrl + "/_api/Web/GetFolderByServerRelativeUrl(@FolderServerRelativeUrl)" +
                    "?$expand=Folders,Files,Folders/ListItemAllFields,Files/ListItemAllFields" +
                    "&$select=" +
                    "##MetadataSrt#" +
                    "Folders/Name,Folders/UniqueID,Folders/ID,Folders/ItemCount,Folders/ServerRelativeUrl,Folder/TimeCreated,Folder/TimeModified," +
                    "Files/Name,Files/UniqueID,Files/ID,Files/ServerRelativeUrl,Files/Length,Files/TimeCreated,Files/TimeModified,Files/ModifiedBy" +
                    "&@FolderServerRelativeUrl='" + encodeURIComponent(spRootFolder) + "'";

        var metadataStr = "";
        if (metaFields.length > 0) {
            metadataStr = metaFields.map(function(fieldName) {
                return "Files/ListItemAllFields/" + fieldName;
            }).join(",") + ",";
        }
        restUrl = restUrl.replace(/##MetadataSrt#/g, metadataStr);

        spr.get(restUrl)
            .then(function (response) {

                var files = response.body.d.Files.results;
                if (metaFields.length > 0) {
                    files.forEach(function(data) {
                        data.metadata = {};
                        metaFields.forEach(function(fd) {
                            if (typeof data.ListItemAllFields !== "undefined") {
                                if (data.ListItemAllFields.hasOwnProperty(fd)) {
                                    data.metadata[fd] = data.ListItemAllFields[fd];
                                }
                            }
                        });
                    });
                }

                var results = {
                    folders: response.body.d.Folders.results,
                    files: files
                };

                if (callback && typeof callback === "function") {
                    callback(results);
                }
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.getFolderContent:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };
    operations.getContentWithCaml = function(context, options, callback) {

        var spDocLibUrl = options.spDocLibUrl;
        var camlStr = options.camlCondition;
        var metaFields = options.metaFields;

        spr = getCachedRequest(context);
        spr.requestDigest(context.siteUrl)
            .then(function (digest) {
                var restUrl;
                restUrl = context.siteUrl + "/_api/Web/GetList(@DocLibUrl)/GetItems" +
                        "?$select=" +
                            "##MetadataSrt#" +
                            "Name,UniqueID,ID,FileDirRef,FileRef,FSObjType,TimeCreated,TimeModified,Length,ModifiedBy" +
                        "&@DocLibUrl='" + encodeURIComponent(spDocLibUrl) + "'";
                var metadataStr = "";
                if (metaFields.length > 0) {
                    metadataStr = metaFields.join(",") + ",";
                }
                restUrl = restUrl.replace(/##MetadataSrt#/g, metadataStr);
                return spr.post(restUrl, {
                    body: {
                        query: {
                            __metadata: {
                                type: "SP.CamlQuery"
                            },
                            ViewXml: "<View Scope='Recursive'><Query><Where>" + camlStr + "</Where></Query></View>" // <Eq><FieldRef Name='MyTestAttr'/><Value Type='Text'>MyTestValue</Value></Eq>
                        }
                    },
                    headers: {
                        "X-RequestDigest": digest,
                        "accept": "application/json; odata=verbose",
                        "content-type": "application/json; odata=verbose"
                    }
                });
            })
            .then(function (response) {
                var filesData = [];
                var foldersData = [];

                response.body.d.results.forEach(function(item) {
                    if (metaFields.length > 0) {
                        item.metadata = {};
                        metaFields.forEach(function(fd) {
                            if (item.hasOwnProperty(fd)) {
                                item.metadata[fd] = item[fd];
                            }
                        });
                    }
                    if (item.FSObjType === 0) {
                        item.ServerRelativeUrl = item.FileRef;
                        filesData.push(item);
                    } else {
                        foldersData.push(item);
                    }
                });

                var results = {
                    files: filesData,
                    folders: foldersData
                };

                if (callback && typeof callback === "function") {
                    callback(results);
                }
            })
            .catch(function (err) {
                console.log(colors.red.bold("\nError in operations.getContentWithCaml:"), colors.red(err.message));
                if (callback && typeof callback === "function") {
                    callback(err.message);
                }
            });
    };

    return operations;
};

module.exports = spf.rest;<|endoftext|>


<commit_before>#!/usr/bin/env node

const helpers = require('./helpers');
const chokidar = require('chokidar');

/* Main wrapper
 * Get installed modules from package.json
 * Get used modules from all files
 * Install used modules that are not installed
 * Remove installed modules that are not used
 * After setup, initialize watchers
 */

let main = () => {
    let installedModules = [];
    installedModules = helpers.getInstalledModules();

    let usedModules = helpers.getUsedModules();
    usedModules = helpers.filterRegistryModules(usedModules);

    //installModules
    let modulesNotInstalled = helpers.diff(usedModules, installedModules);
    for (let module of modulesNotInstalled) helpers.installModule(module);

    //removeUnusedModules
    let unusedModules = helpers.diff(installedModules, usedModules);
    for (let module of unusedModules) helpers.uninstallModule(module);

    helpers.reinstall();
    if (!watchersInitialized) initializeWatchers();
};

/* Watch files and repeat drill
 * Add a watcher, call main wrapper to repeat cycle
 */

let watchersInitialized = false;

let initializeWatchers = () => {
    let watcher = chokidar.watch('**/*.js', {
        ignored: 'node_modules'
    });
    watcher.on('change', main)
    .on('unlink', main);

    watchersInitialized = true;
    console.log('Watchers initialized');
}

/* Turn the key */
main();

<commit_msg>Cleaned up index.js<commit_after>#!/usr/bin/env node

const helpers = require('./helpers');
const chokidar = require('chokidar');

/* Main wrapper
 * Get installed modules from package.json
 * Get used modules from all files
 * Install used modules that are not installed
 * Remove installed modules that are not used
 * After setup, initialize watchers
 */

let main = () => {
    let installedModules = [];
    installedModules = helpers.getInstalledModules();

    let usedModules = helpers.getUsedModules();
    usedModules = helpers.filterRegistryModules(usedModules);

    // installModules
    let modulesNotInstalled = helpers.diff(usedModules, installedModules);
    for (let module of modulesNotInstalled) helpers.installModule(module);

    // removeUnusedModules

    let unusedModules = helpers.diff(installedModules, usedModules);
    for (let module of unusedModules) helpers.uninstallModule(module);

    helpers.reinstall();
    if (!watchersInitialized) initializeWatchers();
};

/* Watch files and repeat drill
 * Add a watcher, call main wrapper to repeat cycle
 */

let watchersInitialized = false;

let initializeWatchers = () => {
    let watcher = chokidar.watch('**/*.js', {
        ignored: 'node_modules'
    });
    watcher.on('change', main)
    .on('unlink', main);

    watchersInitialized = true;
    console.log('Watchers initialized');
};

/* Turn the key */
main();

<|endoftext|>