<commit_before>/*
 * Chat log viewer plugin by jd
 */
'use strict';

const fs = require('fs');
const Autolinker = require('autolinker');
const MAX_LINES = 1000;

exports.commands = {
	viewlogs: function (target, room, user) {
		if (target) {
			let targets = target.split(',');
			for (let u in targets) targets[u] = targets[u].trim();
			if (!targets[1]) return this.errorReply("Please use /viewlogs with no target.");
			switch (toId(targets[0])) {
			case 'month':
				if (!targets[1]) return this.errorReply("Please use /viewlogs with no target.");
				if (!permissionCheck(user, targets[1])) return this.errorReply("/viewlogs - Access denied.");
				let months = fs.readdirSync('logs/chat/' + targets[1]);
				user.send("|popup||html|Choose a month:" + generateTable(months, "/viewlogs date," + targets[1] + ","));
				return;
			case 'date':
				if (!targets[2]) return this.errorReply("Please use /viewlogs with no target.");
				if (!permissionCheck(user, targets[1])) return this.errorReply("/viewlogs - Access denied.");
				let days = fs.readdirSync('logs/chat/' + targets[1] + '/' + targets[2]);
				user.send("|popup||html|Choose a date:" + generateTable(days, "/viewlogspopup " + targets[1] + ","));
				return;
			default:
				this.errorReply("/viewlogs - Command not recognized.");
				break;
			}
		}

		let rooms = fs.readdirSync('logs/chat');
		let roomList = [];

		for (let u in rooms) {
			if (!rooms[u]) continue;
			if (rooms[u] === 'README.md') continue;
			if (!permissionCheck(user, rooms[u])) continue;
			roomList.push(rooms[u]);
		}
		if (roomList.length < 1) return this.errorReply("You don't have access to view the logs of any rooms.");

		let output = "Choose a room to view the logs:";
		output += generateTable(roomList, "/viewlogs month,");
		user.send("|popup||wide||html|" + output);
	},

	viewlogspopup: 'viewlogs2',
	viewlogs2: function (target, room, user, connection, cmd) {
		if (!target) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] - Provides you with a temporary link to view the target rooms chat logs.");
		let targetSplit = target.split(',');
		if (!targetSplit[1]) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] -Provides you with a temporary link to view the target rooms chat logs.");
		for (let u in targetSplit) targetSplit[u] = targetSplit[u].trim();
		let targetRoom = targetSplit[0];
		if (!permissionCheck(user, targetRoom)) return this.errorReply("/viewlogs - Access denied.");
		let date;
		if (toId(targetSplit[1]) === 'today' || toId(targetSplit[1]) === 'yesterday') {
			date = new Date();
			if (toId(targetSplit[1]) === 'yesterday') date.setDate(date.getDate() - 1);
			targetSplit[1] = date.format('{yyyy}-{MM}-{dd}');
		}
		date = targetSplit[1].replace(/\.txt/, '');
		let splitDate = date.split('-');
		if (splitDate.length < 3) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] -Provides you with a temporary link to view the target rooms chat logs.");

		fs.readFile('logs/chat/' + targetRoom.toLowerCase() + '/' + splitDate[0] + '-' + splitDate[1] + '/' + date + '.txt', 'utf8', (err, data) => {
			if (err && err.code === "ENOENT") return user.send("|popup||html|No logs found.");
			if (err) return this.errorReply("/viewlogs - Error: " + err);
			fs.appendFile('logs/viewlogs.log', '[' + new Date().toUTCString() + '] ' + user.name + " viewed the logs of " + toId(targetRoom) + ". Date: " + date + '\n');
			let filename = require('crypto').randomBytes(4).toString('hex');

			if (!user.can('warn', null, Rooms(targetRoom))) {
				let lines = data.split('\n');
				for (let line in lines) {
					if (lines[line].substr(9).trim().charAt(0) === '(') lines.slice(line, 1);
				}
				data = lines.join('\n');
			}

			if (cmd === 'viewlogspopup') {
				let output = 'Displaying room logs of room "' + Tools.escapeHTML(targetRoom) + '" on ' + Tools.escapeHTML(date) + '
';
				data = data.split('\n');
				for (let u in data) {
					if (data[u].length < 1) continue;
					let message = parseMessage(data[u], user.userid);
					if (message.length < 1) continue;
					output += message + '
';
				}
				return user.send("|popup||wide||html|" + output);
			}

			data = targetRoom + "|" + date + "|" + fs.readFileSync('config/customcolors.json', 'utf8') + "\n" + data;

			fs.writeFile('static/logs/' + filename, data, err => {
				if (err) return this.errorReply("/viewlogs - " + err);
				this.sendReply(
					"|raw|You can view the logs at http://goldservers.info:" + Config.port +
					"/logs/logviewer.html?file=" + filename + ""
				);
				setTimeout(function () {
					fs.unlink('static/logs/' + filename);
				}, 1 * 1000 * 60);
			});
		});
	},

	searchlogs: function (target, room, user) {
		if (!target) return this.parse('/help searchlogs');
		let targets = target.split(',');
		for (let u in targets) targets[u] = targets[u].trim();
		if (!targets[1]) return this.errorReply("Please specify a phrase to search.");

		if (toId(targets[0]) === 'all' && !this.can('hotpatch')) return false;
		if (!Rooms(targets[0]) && !this.can('hotpatch') || !this.can('mute', null, Rooms(targets[0]))) return false;

		let pattern = escapeRegExp(targets[1]).replace(/\\\*/g, '.*');
		let command = 'grep -Rnw \'./logs/chat/' + (toId(targets[0]) === 'all' ? '' : toId(targets[0])) + '\' -e "' + pattern + '"';

		require('child_process').exec(command, function (error, stdout, stderr) {
			if (error && stderr) {
				user.popup("/searchlogs doesn't support Windows.");
				console.log("/searchlogs error: " + error);
				return false;
			}
			if (!stdout) return user.popup('Could not find any logs containing "' + pattern + '".');
			let output = '';
			stdout = stdout.split('\n');
			for (let i = 0; i < stdout.length; i++) {
				if (stdout[i].length < 1 || i > MAX_LINES) continue;
				let file = stdout[i].substr(0, stdout[i].indexOf(':'));
				let lineNumber = stdout[i].split(':')[1];
				let line = stdout[i].split(':');
				line.splice(0, 2);
				line = line.join(':');
				let message = parseMessage(line, user.userid);
				if (message.length < 1) continue;
				output += '' + Tools.escapeHTML(file) + ':' + lineNumber +
					':' + message + '
';
			}
			user.send('|popup||wide||html|Displaying last ' + MAX_LINES + ' lines containing "' + Tools.escapeHTML(pattern) + '"' +
				(toId(targets[0]) === 'all' ? '' : ' in "' + Tools.escapeHTML(targets[0]) + '"') + ':

' + output);
		});
	},
	searchlogshelp: ["/searchlogs [room / all], [phrase] - Phrase may contain * wildcards."],
};

function permissionCheck(user, room) {
	if (!Rooms(room) && !user.can('seniorstaff')) {
		return false;
	}
	if (!user.can('lock') && !user.can('warn', null, Rooms(room))) {
		return false;
	}
	if (Rooms(room) && Rooms(room).isPrivate && (!user.can('seniorstaff') && !user.can('warn', null, Rooms(room)))) {
		return false;
	}
	if (Rooms(room) && Rooms(room).isPersonal && (!user.can('seniorstaff') && !user.can('warn', null, Rooms(room)))) {
		return false;
	}
	return true;
}

function generateTable(array, command) {
	let output = "
";
	let count = 0;
	for (let u in array) {
		if (array[u] === 'today.txt') continue;
		if (count === 0) output += "
";
		output += '<button style="width: 100%" name="send" value="' + command + Tools.escapeHTML(array[u]) + '">' + Tools.escapeHTML(array[u]) + '</button>	';
		count++;
		if (count > 3) {
			output += '
';
			count = 0;
		}
	}
	output += '
';
	return output;
}

function escapeRegExp(s) {
	return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

function parseMessage(message, user) {
	let timestamp = message.substr(0, 9).trim();
	message = message.substr(9).trim();
	let lineSplit = message.split('|');

	switch (lineSplit[1]) {
	case 'c':
		let name = lineSplit[2];
		if (name === '~') break;
		let highlight = new RegExp("\\b" + toId(user) + "\\b", 'gi');
		let div = "chat";
		if (lineSplit.slice(3).join('|').match(highlight)) div = "chat highlighted";
		message = '[' + timestamp + '] ' + '' + name.substr(0, 1) +
		'' + name.substr(1, name.length) + ':' +
		parseFormatting(lineSplit.slice(3).join('|')) + '';
		break;
	case 'uhtml':
		message = '' + lineSplit.slice(3).join('|').trim() + '';
		break;
	case 'raw':
	case 'html':
		message = '' + lineSplit.slice(2).join('|').trim() + '';
		break;
	case '':
		message = '' + Tools.escapeHTML(lineSplit.slice(1).join('|')) + '';
		break;
	case 'j':
	case 'J':
	case 'l':
	case 'L':
	case 'N':
	case 'unlink':
	case 'userstats':
	case 'tournament':
	case 'uhtmlchange':
		message = "";
		break;
	default:
		message = '' + Tools.escapeHTML(message) + '';
		break;
	}
	return message;
}

function parseFormatting(message) {
	if (message.substr(0, 5) === "/html") {
		message = message.substr(5);
		message = message.replace(/\_\_([^< ](?:[^<]*?[^< ])?)\_\_(?![^<]*?<\/a)/g, '$1'); // italics
		message = message.replace(/\*\*([^< ](?:[^<]*?[^< ])?)\*\*/g, '$1'); // bold
		message = message.replace(/\~\~([^< ](?:[^<]*?[^< ])?)\~\~/g, '$1'); // strikethrough
		message = message.replace(/<<([a-z0-9-]+)>>/g, '«$1»'); // <<roomid>>
		message = Autolinker.link(message.replace(///g, '/'), {stripPrefix: false, phone: false, twitter: false});
		return message;
	}
	message = Tools.escapeHTML(message).replace(///g, '/');
	message = message.replace(/\_\_([^< ](?:[^<]*?[^< ])?)\_\_(?![^<]*?<\/a)/g, '$1'); // italics
	message = message.replace(/\*\*([^< ](?:[^<]*?[^< ])?)\*\*/g, '$1'); // bold
	message = message.replace(/\~\~([^< ](?:[^<]*?[^< ])?)\~\~/g, '$1'); // strikethrough
	message = message.replace(/<<([a-z0-9-]+)>>/g, '«$1»'); // <<roomid>>
	message = Autolinker.link(message, {stripPrefix: false, phone: false, twitter: false});
	return message;
}
<commit_msg>Optimize the new viewlogs system some more<commit_after>/*
 * Chat log viewer plugin by jd
 */
'use strict';

const fs = require('fs');
const Autolinker = require('autolinker');
const MAX_LINES = 1000;

exports.commands = {
	viewlogs: function (target, room, user) {
		if (target) {
			let targets = target.split(',');
			for (let u in targets) targets[u] = targets[u].trim();
			if (!targets[1]) return this.errorReply("Please use /viewlogs with no target.");
			switch (toId(targets[0])) {
			case 'month':
				if (!targets[1]) return this.errorReply("Please use /viewlogs with no target.");
				if (!permissionCheck(user, targets[1])) return this.errorReply("/viewlogs - Access denied.");
				let months = fs.readdirSync('logs/chat/' + targets[1]);
				user.send("|popup||html|Choose a month:" + generateTable(months, "/viewlogs date," + targets[1] + ","));
				return;
			case 'date':
				if (!targets[2]) return this.errorReply("Please use /viewlogs with no target.");
				if (!permissionCheck(user, targets[1])) return this.errorReply("/viewlogs - Access denied.");
				let days = fs.readdirSync('logs/chat/' + targets[1] + '/' + targets[2]);
				user.send("|popup||html|Choose a date:" + generateTable(days, "/viewlogspopup " + targets[1] + ","));
				return;
			default:
				this.errorReply("/viewlogs - Command not recognized.");
				break;
			}
		}

		let rooms = fs.readdirSync('logs/chat');
		let roomList = [], groupChats = [];

		for (let u in rooms) {
			if (!rooms[u]) continue;
			if (rooms[u] === 'README.md') continue;
			if (!permissionCheck(user, rooms[u])) continue;
			rooms[u].substr(0, 9) === 'groupchat' ? groupChats.push(rooms[u]) : roomList.push(rooms[u]);
		}
		if (roomList.length < 1) return this.errorReply("You don't have access to view the logs of any rooms.");

		let output = "Choose a room to view the logs:
";
		output += "Chat rooms:
" + generateTable(roomList, "/viewlogs month,");
		output += "Group chats:
" + generateTable(groupChats, "/viewlogs month,");
		user.send("|popup||wide||html|" + output);
	},

	viewlogspopup: 'viewlogs2',
	viewlogs2: function (target, room, user, connection, cmd) {
		if (!target) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] - Provides you with a temporary link to view the target rooms chat logs.");
		let targetSplit = target.split(',');
		if (!targetSplit[1]) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] -Provides you with a temporary link to view the target rooms chat logs.");
		for (let u in targetSplit) targetSplit[u] = targetSplit[u].trim();
		let targetRoom = targetSplit[0];
		if (!permissionCheck(user, targetRoom)) return this.errorReply("/viewlogs - Access denied.");
		let date;
		if (toId(targetSplit[1]) === 'today' || toId(targetSplit[1]) === 'yesterday') {
			date = new Date();
			if (toId(targetSplit[1]) === 'yesterday') date.setDate(date.getDate() - 1);
			targetSplit[1] = date.format('{yyyy}-{MM}-{dd}');
		}
		date = targetSplit[1].replace(/\.txt/, '');
		let splitDate = date.split('-');
		if (splitDate.length < 3) return this.sendReply("Usage: /viewlogs [room], [year-month-day / 2014-12-08] -Provides you with a temporary link to view the target rooms chat logs.");

		fs.readFile('logs/chat/' + targetRoom.toLowerCase() + '/' + splitDate[0] + '-' + splitDate[1] + '/' + date + '.txt', 'utf8', (err, data) => {
			if (err && err.code === "ENOENT") return user.send("|popup||html|No logs found.");
			if (err) return this.errorReply("/viewlogs - Error: " + err);
			fs.appendFile('logs/viewlogs.log', '[' + new Date().toUTCString() + '] ' + user.name + " viewed the logs of " + toId(targetRoom) + ". Date: " + date + '\n');
			let filename = require('crypto').randomBytes(4).toString('hex');

			if (!user.can('warn', null, Rooms(targetRoom))) {
				let lines = data.split('\n');
				for (let line in lines) {
					if (lines[line].substr(9).trim().charAt(0) === '(') lines.slice(line, 1);
				}
				data = lines.join('\n');
			}

			if (cmd === 'viewlogspopup') {
				let output = 'Displaying room logs of room "' + Tools.escapeHTML(targetRoom) + '" on ' + Tools.escapeHTML(date) + '
';
				data = data.split('\n');
				for (let u in data) {
					if (data[u].length < 1) continue;
					let message = parseMessage(data[u], user.userid);
					if (message.length < 1) continue;
					output += message + '
';
				}
				return user.send("|popup||wide||html|" + output);
			}

			data = targetRoom + "|" + date + "|" + fs.readFileSync('config/customcolors.json', 'utf8') + "\n" + data;

			fs.writeFile('static/logs/' + filename, data, err => {
				if (err) return this.errorReply("/viewlogs - " + err);
				this.sendReply(
					"|raw|You can view the logs at http://goldservers.info:" + Config.port +
					"/logs/logviewer.html?file=" + filename + ""
				);
				setTimeout(function () {
					fs.unlink('static/logs/' + filename);
				}, 1 * 1000 * 60);
			});
		});
	},

	logsearch: 'searchlogs',
	searchlogs: function (target, room, user) {
		if (!target) return this.parse('/help searchlogs');
		let targets = target.split(',');
		for (let u in targets) targets[u] = targets[u].trim();
		if (!targets[1]) return this.errorReply("Please specify a phrase to search.");

		if (toId(targets[0]) === 'all' && !this.can('hotpatch')) return false;
		if (!Rooms(targets[0]) && !this.can('hotpatch') || !this.can('mute', null, Rooms(targets[0]))) return false;

		let pattern = escapeRegExp(targets[1]).replace(/\\\*/g, '.*');
		let command = 'grep -Rnw \'./logs/chat/' + (toId(targets[0]) === 'all' ? '' : toId(targets[0])) + '\' -e "' + pattern + '"';

		require('child_process').exec(command, function (error, stdout, stderr) {
			if (error && stderr) {
				user.popup("/searchlogs doesn't support Windows.");
				return false;
			}
			if (!stdout) return user.popup('Could not find any logs containing "' + pattern + '".');
			let output = '';
			stdout = stdout.split('\n');
			for (let i = 0; i < stdout.length; i++) {
				if (stdout[i].length < 1 || i > MAX_LINES) continue;
				let file = stdout[i].substr(0, stdout[i].indexOf(':'));
				let lineNumber = stdout[i].split(':')[1];
				let line = stdout[i].split(':');
				line.splice(0, 2);
				line = line.join(':');
				let message = parseMessage(line, user.userid);
				if (message.length < 1) continue;
				output += '' + Tools.escapeHTML(file) + ':' + lineNumber +
					':' + message + '
';
			}
			user.send('|popup||wide||html|Displaying last ' + MAX_LINES + ' lines containing "' + Tools.escapeHTML(pattern) + '"' +
				(toId(targets[0]) === 'all' ? '' : ' in "' + Tools.escapeHTML(targets[0]) + '"') + ':

' + output);
		});
	},
	searchlogshelp: ["/searchlogs [room / all], [phrase] - Phrase may contain * wildcards."],
};

function permissionCheck(user, room) {
	if (!Rooms(room) && !user.can('seniorstaff')) {
		return false;
	}
	if (!user.can('lock') && !user.can('warn', null, Rooms(room))) {
		return false;
	}
	if (Rooms(room) && Rooms(room).isPrivate && (!user.can('seniorstaff') && !user.can('warn', null, Rooms(room)))) {
		return false;
	}
	if (Rooms(room) && Rooms(room).isPersonal && (!user.can('seniorstaff') && !user.can('warn', null, Rooms(room)))) {
		return false;
	}
	return true;
}

function generateTable(array, command) {
	let output = "
";
	let count = 0;
	for (let u in array) {
		if (array[u] === 'today.txt') continue;
		if (count === 0) output += "
";
		output += '<button style="width: 100%" name="send" value="' + command + Tools.escapeHTML(array[u]) + '">' + Tools.escapeHTML(array[u]) + '</button>	';
		count++;
		if (count > 3) {
			output += '
';
			count = 0;
		}
	}
	output += '
';
	return output;
}

function escapeRegExp(s) {
	return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}

function parseMessage(message, user) {
	let timestamp = message.substr(0, 9).trim();
	message = message.substr(9).trim();
	let lineSplit = message.split('|');
	let highlight = new RegExp("\\b" + toId(user) + "\\b", 'gi');
	let div = "chat", name = '';

	switch (lineSplit[1]) {
	case 'c':
		name = lineSplit[2];
		if (name === '~') break;
		if (lineSplit.slice(3).join('|').match(highlight)) div = "chat highlighted";
		message = '[' + timestamp + '] ' + '' + name.substr(0, 1) +
		'' + name.substr(1, name.length) + ':' +
		parseFormatting(lineSplit.slice(3).join('|')) + '';
		break;
	case 'c:':
		name = lineSplit[3];
		if (name === '~') break;
		if (lineSplit.slice(4).join('|').match(highlight)) div = "chat highlighted";
		message = '[' + timestamp + '] ' + '' + name.substr(0, 1) +
		'' + name.substr(1, name.length) + ':' +
		parseFormatting(lineSplit.slice(4).join('|')) + '';
		break;
	case 'uhtml':
		message = '' + lineSplit.slice(3).join('|').trim() + '';
		break;
	case 'raw':
	case 'html':
		message = '' + lineSplit.slice(2).join('|').trim() + '';
		break;
	case '':
		message = '' + Tools.escapeHTML(lineSplit.slice(1).join('|')) + '';
		break;
	case 'j':
	case 'J':
	case 'l':
	case 'L':
	case 'n':
	case 'N':
	case 'unlink':
	case 'userstats':
	case 'tournament':
	case 'uhtmlchange':
		message = "";
		break;
	default:
		message = '' + Tools.escapeHTML(message) + '';
		break;
	}
	return message;
}

function parseFormatting(message) {
	if (message.substr(0, 5) === "/html") {
		message = message.substr(5);
		message = message.replace(/\_\_([^< ](?:[^<]*?[^< ])?)\_\_(?![^<]*?<\/a)/g, '$1'); // italics
		message = message.replace(/\*\*([^< ](?:[^<]*?[^< ])?)\*\*/g, '$1'); // bold
		message = message.replace(/\~\~([^< ](?:[^<]*?[^< ])?)\~\~/g, '$1'); // strikethrough
		message = message.replace(/<<([a-z0-9-]+)>>/g, '«$1»'); // <<roomid>>
		message = Autolinker.link(message.replace(///g, '/'), {stripPrefix: false, phone: false, twitter: false});
		return message;
	}
	message = Tools.escapeHTML(message).replace(///g, '/');
	message = message.replace(/\_\_([^< ](?:[^<]*?[^< ])?)\_\_(?![^<]*?<\/a)/g, '$1'); // italics
	message = message.replace(/\*\*([^< ](?:[^<]*?[^< ])?)\*\*/g, '$1'); // bold
	message = message.replace(/\~\~([^< ](?:[^<]*?[^< ])?)\~\~/g, '$1'); // strikethrough
	message = message.replace(/<<([a-z0-9-]+)>>/g, '«$1»'); // <<roomid>>
	message = Autolinker.link(message, {stripPrefix: false, phone: false, twitter: false});
	return message;
}
<|endoftext|>


<commit_before>'use strict';
/**
 * @ngdoc function
 * @name sbAdminApp.sercice:DenunciationsService
 * @description
 * # DenunciationsService
 * Controller of the sbAdminApp
 */
angular.module('sbAdminApp')
  .service('DenunciationsService', function($http,$q ,RequestService) {

    /*Atributes*/

    /*Functions*/

    this.getDenunciations = function(filters) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "GET",
            url: "/pets/denunciations"
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
	}

    /*
        PUT    /pet/{petId}/report/accepted
        Header: application/json
        Body de ejemplo:
        {
        "petId": "5646013b44ae767f48567d7c",
        "informer": "5645e44e44ae767f48567d7a",
        "publicationType": ""
        }
    */
    this.acceptDenunciation = function(object) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "PUT",
            url: "/pet/" + object.publication.petId + "/report/accepted",
            params: {
                petId: object.publication.petId,
                informer:  object.complainantUserId,
                publicationType: object.publication.type,
            }
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    }

    /*  PUT    /pet/{petId}/report/rejected
        Header: application/json
        Body de ejemplo:
        {
        "petId": "5646013b44ae767f48567d7c",
        "informer": "5645e44e44ae767f48567d7a"
        "publicationType": ""
        }
    */
    this.rejectDenunciation = function(object) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "PUT",
            url: "/pet/" + object.publication.petId + "/report/rejected",
            params: {
                petId: object.publication.petId,
                informer:  object.complainantUserId,
                publicationType: object.publication.type
            }
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    }

});<commit_msg>denuncias<commit_after>'use strict';
/**
 * @ngdoc function
 * @name sbAdminApp.sercice:DenunciationsService
 * @description
 * # DenunciationsService
 * Controller of the sbAdminApp
 */
angular.module('sbAdminApp')
  .service('DenunciationsService', function($http,$q ,RequestService) {

    /*Atributes*/

    /*Functions*/

    this.getDenunciations = function(filters) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "GET",
            url: "/pets/denunciations"
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
	}

    /*
        PUT    /pet/{petId}/report/accepted
        Header: application/json
        Body de ejemplo:
        {
        "petId": "5646013b44ae767f48567d7c",
        "informer": "5645e44e44ae767f48567d7a",
        "publicationType": ""
        }
    */
    this.acceptDenunciation = function(object) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "PUT",
            url: "/pet/" + object.publication.publicationId + "/report/accepted",
            params: {
                petId: object.publication.publicationId,
                informer:  object.complainantUserId,
                publicationType: object.publication.type,
            }
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    }

    /*  PUT    /pet/{petId}/report/rejected
        Header: application/json
        Body de ejemplo:
        {
        "petId": "5646013b44ae767f48567d7c",
        "informer": "5645e44e44ae767f48567d7a"
        "publicationType": ""
        }
    */
    this.rejectDenunciation = function(object) {
        var deferred  = $q.defer();
        var requestData =  {
            method: "PUT",
            url: "/pet/" + object.publication.publicationId + "/report/rejected",
            params: {
                petId: object.publication.publicationId,
                informer:  object.complainantUserId,
                publicationType: object.publication.type
            }
        };
        RequestService.callApi(requestData)
        .then(
            function successCallback(response) {
                deferred.resolve(response);
            },
            function errorCallback(response) {
                deferred.reject(response);
            }
        );
        return deferred.promise;
    }

});<|endoftext|>


<commit_before>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var EntityCrud = require('crude/entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  EntityCrud.call(this, Model, optUdo);
};
util.inherits(Entity, EntityCrud);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read all items, do practice common sense!
 *
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readAll = function(done) {
  this.Model.find(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<commit_msg>fix typos in mongoose entity<commit_after>/**
 * @fileOverview The entities base class.
 */
var util = require('util');

var __ = require('lodash');
var Entity = require('../entity');

/**
 * The base Entity Class all entities extend from.
 *
 * @param {mongoose.Model} Model the model that this entity relates to.
 * @param {Object=} optUdo Optionally define the current handling user.
 * @constructor
 * @extends {crude.Entity}
 */
var Entity = module.exports = function(Model, optUdo) {
  Entity.call(this, Model, optUdo);
};
util.inherits(Entity, Entity);

/**
 * Create an entity item.
 *
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.create = function(itemData, done) {
  var item = new this.Model(itemData);
  item.save(done);
};

/**
 * Read one entity item.
 *
 * @param {string|Object} id the item id or an Object to query against.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readOne = function(id, done) {
  var query = new Object(null);

  if (__.isObject(id)) {
    query = id;
  } else {
    query.id = id;
  }

  this.Model.findOne(query, done);
};

/**
 * Read all items, do practice common sense!
 *
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.readAll = function(done) {
  this.Model.find(done);
};

/**
 * Read a limited set of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {number} skip starting position.
 * @param {number} limit how many records to fetch.
 * @param {Function(ts.error.Abstract=, Array.<mongoose.Document>=)} done callback.
 */
Entity.prototype.readLimit = function(query, skip, limit, done) {
  this.Model.find(query)
    .skip(skip)
    .limit(limit)
    .exec(done);
};

/**
 * Get the count of items.
 *
 * @param {?Object} query Narrow down the set, set to null for all.
 * @param {Function(ts.error.Abstract=, number=)} done callback.
 */
Entity.prototype.count = function(query, done) {
  this.Model.count(query).exec(done);
};

/**
 * Update an entity item.
 *
 * @param {string} id the item id.
 * @param {Object} itemData The data to use for creating.
 * @param {Function(ts.error.Abstract=, mongoose.Document=)} done callback.
 */
Entity.prototype.update = function(id, itemData, done) {
  this.Model.findById(id, function(err, doc){
    if (err) {
      return done(err);
    }

    __.forOwn(itemData, function(value, key) {
      doc[key] = value;
    }, this);

    doc.save(done);

  }.bind(this));
};

<|endoftext|>


<commit_before>/**
 * transform elastic search related entity query to display format.  See data-model.json
 */

/* globals _, commonTransforms */
/* exported relatedEntityTransform */
var relatedEntityTransform = (function(_, commonTransforms) {

    function getOfferSummary(record) {
        /**  build offer summary record:
            {
                "_id": "http://someuri",
                "_type": "offer",
                "title": "1234567890", // just gets first phone number
                "subtitle": "*Hello World -- google.com", // title of offer
                "details": {
                    "date": "2012-04-23T18:25:43.511Z",
                    "address": "Los Angeles", // just use locality
                    "publisher": "backpage.com"
                }
            }
        */
        var mentions = _.get(record, '_source.mainEntityOfPage.mentions');
        var phoneAndEmails = '';
        if (mentions) {
            var phones = commonTransforms.getEmailAndPhoneFromMentions(mentions).phones;
            var emails = commonTransforms.getEmailAndPhoneFromMentions(mentions).emails;
            if(phones && phones.length > 0 && emails && emails.length > 0) {
                joined = phones.concat(emails);
                _.each(joined, function(val) {
                    phoneAndEmails += val.title + ", ";
                });
            }
            else if(phones && phones.length > 0) {
                _.each(phones, function(val) {
                    phoneAndEmails += val.title + ", ";
                });
            }
            else if(emails && emails.length > 0) {
                _.each(emails, function(val) {
                    phoneAndEmails += val.title + ", ";
                });
            }
            phoneAndEmails = phoneAndEmails.substring(0, phoneAndEmails.lastIndexOf(','));
        }

        var validFromDate = dateFormat(new Date(_.get(record, '_source.validFrom')), "mmmm dd, yyyy");
        var datePhoneEmail = phoneAndEmails;
        if(validFromDate) {
            datePhoneEmail = validFromDate + ', ' + phoneAndEmails;
        }

        var offerObj = {
            _id: record._id,
            _type: record._type,
            subtitle: datePhoneEmail,
            title: _.get(record, '_source.mainEntityOfPage.name', 'Title N/A'),
            details: {
                description: _.get(record, '_source.mainEntityOfPage.description'),
                address: _.get(record, '_source.availableAtOrFrom.address[0].addressLocality'),
                publisher: _.get(record, '_source.mainEntityOfPage.publisher.name')
            }
        };

        return offerObj;
    }

    function getPhoneSummary(record) {
        /**
            build phone summary object:
            {
                "_id": "http://someuri",
                "_type": "phone",
                "title": "1234567890", // phone number
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var phoneObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Phone N/A'),
            subtitle: _.get(record, '_source.owner[0].makesOffer.length', 0) + ' offer(s)'
        };
        return phoneObj;
    }

    function getEmailSummary(record) {
        /**
            build email summary object:
            {
                "_id": "http://someuri",
                "_type": "email",
                "title": "abc@xyz.com", // email address
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var emailObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Email N/A'),
            subtitle: _.get(record, '_source.owner[0].makesOffer.length', 0) + ' offer(s)'
        };
        return emailObj;
    }

    function getSellerSummary(record) {
        /**
            build seller summary object:
            {
                "_id": "http://someuri",
                "_type": "seller",
                "title": "1234567890", // phone number associated with seller
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var sellerObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.telephone.name', 'Phone N/A'),
            subtitle: _.get(record, '_source.makesOffer.length', 0) + ' offer(s)'
        };
        return sellerObj;
    }

    function getAddressArray(record) {
        /** build address array:
            "addresses": ["Los Angeles"]
        */
        var addresses = [];
        var addressesArr = _.get(record, '_source.mainEntity.availableAtOrFrom.address', []);

        addressesArr.forEach(function(addressElem) {
            var locality = _.get(addressElem, 'addressLocality');
            var region = _.get(addressElem, 'addressRegion');
            var country = _.get(addressElem, 'addressCountry');

            if(locality) {
                var address = locality + ', ' + region + ', ' + country;
                addresses.push(address);
            }
        });
        return addresses;
    }

    function getWebpageSummary(record) {
        /*  build webpage summary object:
            {
                "_id": "http://someuri",
                "_type": "webpage",
                "title": "yahoo.com",   // publisher
                "subtitle": "*Hello World -- google.com", // title of webpage
                "details": {
                    "url": "http://someurlhere.com",
                    "body": "description text here",
                    "addresses": ["Los Angeles"],
                    """if phone exists"""
                    "phone": "<phonenumber>",
                    """if email exists"""
                    "email": "<email>"
                    "date": "2012-04-23T18:25:43.511Z"
                }
            }
        */
        var webpageObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Title N/A'),
            subtitle: [_.get(record, '_source.publisher.name', 'Publisher N/A')],
            offer: _.get(record, '_source.mainEntity.uri'),
            details: {
                url: _.get(record, '_source.url'),
                body: _.get(record, '_source.description'),
                addresses: getAddressArray(record),
                _sortedKeys: ['url', 'body', 'addresses', 'phone', 'email', 'date']
            }

        };
        var mentions = _.get(record, '_source.mentions');
        if(mentions) {
            phoneEmails = commonTransforms.getEmailAndPhoneFromMentions(mentions);
            if(phoneEmails.phones.length > 0) {
                var sep = "";
                phones = "";
                phoneEmails.phones.forEach(function(phoneObj) {
                    phones += sep + phoneObj.title;
                    sep = ", ";
                });
                webpageObj.details.phone = phones;
            }
            if(phoneEmails.emails.length > 0) {
                var sep = "";
                emails = "";
                phoneEmails.emails.forEach(function(emailObj) {
                    emails += sep + emailObj.title;
                    sep = ", ";
                });
                webpageObj.details.email = emails;
            }
        }

        var xDate = _.get(record, '_source.dateCreated');
        webpageObj.details.date = dateFormat(new Date(xDate), "mmmm dd, yyyy");

        webpageObj.subtitle.push(webpageObj.details.date)
        if(webpageObj.details.phone)
            webpageObj.subtitle.push(webpageObj.details.phone)
        if(webpageObj.details.email)
            webpageObj.subtitle.push(webpageObj.details.email)
        return webpageObj;
    }

    function getServiceSummary(record) {
        /*
            build service/person summary object:
            {
                "_id": "http://someuri",
                "_type": "person",
                "title": "Emily", // person name
                "subtitle": "Age: 20", // age
                "details": {
                    "height": 64,
                    "weight": 115,
                    "ethnicity": "white"
                }
            }
        */
        var serviceObj = {
            _id: record._id,
            _type: 'person', // hardcode 'person' value for now
            title: _.get(record, '_source.name', 'Name N/A'),
            subtitle: 'Age: ' + _.get(record, '_source.age', 'N/A'),
            details: {
                height: _.get(record, '_source.height'),
                weight: _.get(record, '_source.weight'),
                ethnicity: _.get(record, '_source.ethnicity'),
            }
        };
        return serviceObj;
    }

    return {
        // expected data is from an elasticsearch query
        offer: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getOfferSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        phone: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getPhoneSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        email: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getEmailSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        seller: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getSellerSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        service: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getServiceSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        webpage: function(data) {
            var newObj = {data: [], count: 0};
            if(data && data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    var webpageSummary = getWebpageSummary(record);
                    //We do not want to show webpage page, but instead direct
                    //to offer. The below handles that.
                    if(webpageSummary.offer) {
                        webpageSummary._type = "offer";
                        webpageSummary._id = webpageSummary.offer;
                    }
                    newObj.data.push(webpageSummary);
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        // transform for combined sets of results not separated by type
        combinedResults: function(data) {
            var newObj = {data: [], count: 0};
            if(data && data.hits && data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    switch(record._type) {
                        case 'email': newObj.data.push(getEmailSummary(record));
                            break;
                        case 'adultservice': newObj.data.push(getServiceSummary(record));
                            break;
                        case 'phone': newObj.data.push(getPhoneSummary(record));
                            break;
                        case 'offer': newObj.data.push(getOfferSummary(record));
                            break;
                        case 'seller': newObj.data.push(getSellerSummary(record));
                            break;
                        case 'webpage': newObj.data.push(getWebpageSummary(record));
                            break;
                    }
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },

        cityResults: function(data) {
            var newObject = {};

           if(data && data.aggregations && data.aggregations.webpageCityAgg && data.aggregations.webpageCityAgg.webpageCityAgg.buckets) {
                newObject.aggregations = {};
                newObject.aggregations.webpageCityAgg = {};
                newObject.aggregations.webpageCityAgg.webpageCityAgg = {};
                newObject.aggregations.webpageCityAgg.webpageCityAgg.buckets = [];
                _.each(data.aggregations.webpageCityAgg.webpageCityAgg.buckets, function(record) {

                    var newObj = {};
                    newObj.key = record.key;
                    var keys = record.key.split(':');
                    newObj.text = keys[0];
                    newObj.doc_count = record.doc_count;

                    newObject.aggregations.webpageCityAgg.webpageCityAgg.buckets.push(newObj);
                    //record['key'] = keys[0] + ',' + keys[1];
                    // record['text'] = keys[0];
                });
            }
            // console.log(data);
            return newObject;
        }
    };

})(_, commonTransforms);

<commit_msg>have subtitle as array for offer<commit_after>/**
 * transform elastic search related entity query to display format.  See data-model.json
 */

/* globals _, commonTransforms */
/* exported relatedEntityTransform */
var relatedEntityTransform = (function(_, commonTransforms) {

    function getOfferSummary(record) {
        /**  build offer summary record:
            {
                "_id": "http://someuri",
                "_type": "offer",
                "title": "1234567890", // just gets first phone number
                "subtitle": "*Hello World -- google.com", // title of offer
                "details": {
                    "date": "2012-04-23T18:25:43.511Z",
                    "address": "Los Angeles", // just use locality
                    "publisher": "backpage.com"
                }
            }
        */
        var validFromDate = dateFormat(new Date(_.get(record, '_source.validFrom')), "mmmm dd, yyyy");
        var datePhoneEmail = [];
        if(validFromDate) {
            datePhoneEmail.push(validFromDate);
        }
        var mentions = _.get(record, '_source.mainEntityOfPage.mentions');

        if (mentions) {
            var phones = commonTransforms.getEmailAndPhoneFromMentions(mentions).phones;
            var emails = commonTransforms.getEmailAndPhoneFromMentions(mentions).emails;
            if(phones && phones.length > 0 && emails && emails.length > 0) {
                //get only first phone and email to show in the subtitle
                datePhoneEmail.push(phones[0].title);
                datePhoneEmail.push(emails[0].title);
            }
            else if(phones && phones.length > 0) {
                //get only first phone to show in title
                datePhoneEmail.push(phones[0].title);
            }
            else if(emails && emails.length > 0) {
                //get only first email to show in title
                datePhoneEmail.push(emails[0].title);
            }
        }

        var offerObj = {
            _id: record._id,
            _type: record._type,
            subtitle: datePhoneEmail,
            title: _.get(record, '_source.mainEntityOfPage.name', 'Title N/A'),
            details: {
                description: _.get(record, '_source.mainEntityOfPage.description'),
                address: _.get(record, '_source.availableAtOrFrom.address[0].addressLocality'),
                publisher: _.get(record, '_source.mainEntityOfPage.publisher.name')
            }
        };

        return offerObj;
    }

    function getPhoneSummary(record) {
        /**
            build phone summary object:
            {
                "_id": "http://someuri",
                "_type": "phone",
                "title": "1234567890", // phone number
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var phoneObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Phone N/A'),
            subtitle: _.get(record, '_source.owner[0].makesOffer.length', 0) + ' offer(s)'
        };
        return phoneObj;
    }

    function getEmailSummary(record) {
        /**
            build email summary object:
            {
                "_id": "http://someuri",
                "_type": "email",
                "title": "abc@xyz.com", // email address
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var emailObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Email N/A'),
            subtitle: _.get(record, '_source.owner[0].makesOffer.length', 0) + ' offer(s)'
        };
        return emailObj;
    }

    function getSellerSummary(record) {
        /**
            build seller summary object:
            {
                "_id": "http://someuri",
                "_type": "seller",
                "title": "1234567890", // phone number associated with seller
                "subtitle": "2 offer(s)" // number of offers
            }
        */
        var sellerObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.telephone.name', 'Phone N/A'),
            subtitle: _.get(record, '_source.makesOffer.length', 0) + ' offer(s)'
        };
        return sellerObj;
    }

    function getAddressArray(record) {
        /** build address array:
            "addresses": ["Los Angeles"]
        */
        var addresses = [];
        var addressesArr = _.get(record, '_source.mainEntity.availableAtOrFrom.address', []);

        addressesArr.forEach(function(addressElem) {
            var locality = _.get(addressElem, 'addressLocality');
            var region = _.get(addressElem, 'addressRegion');
            var country = _.get(addressElem, 'addressCountry');

            if(locality) {
                var address = locality + ', ' + region + ', ' + country;
                addresses.push(address);
            }
        });
        return addresses;
    }

    function getWebpageSummary(record) {
        /*  build webpage summary object:
            {
                "_id": "http://someuri",
                "_type": "webpage",
                "title": "yahoo.com",   // publisher
                "subtitle": "*Hello World -- google.com", // title of webpage
                "details": {
                    "url": "http://someurlhere.com",
                    "body": "description text here",
                    "addresses": ["Los Angeles"],
                    """if phone exists"""
                    "phone": "<phonenumber>",
                    """if email exists"""
                    "email": "<email>"
                    "date": "2012-04-23T18:25:43.511Z"
                }
            }
        */
        var webpageObj = {
            _id: record._id,
            _type: record._type,
            title: _.get(record, '_source.name', 'Title N/A'),
            subtitle: [_.get(record, '_source.publisher.name', 'Publisher N/A')],
            offer: _.get(record, '_source.mainEntity.uri'),
            details: {
                url: _.get(record, '_source.url'),
                body: _.get(record, '_source.description'),
                addresses: getAddressArray(record),
                _sortedKeys: ['url', 'body', 'addresses', 'phone', 'email', 'date']
            }

        };
        var mentions = _.get(record, '_source.mentions');
        if(mentions) {
            phoneEmails = commonTransforms.getEmailAndPhoneFromMentions(mentions);
            if(phoneEmails.phones.length > 0) {
                var sep = "";
                phones = "";
                phoneEmails.phones.forEach(function(phoneObj) {
                    phones += sep + phoneObj.title;
                    sep = ", ";
                });
                webpageObj.details.phone = phones;
            }
            if(phoneEmails.emails.length > 0) {
                var sep = "";
                emails = "";
                phoneEmails.emails.forEach(function(emailObj) {
                    emails += sep + emailObj.title;
                    sep = ", ";
                });
                webpageObj.details.email = emails;
            }
        }

        var xDate = _.get(record, '_source.dateCreated');
        webpageObj.details.date = dateFormat(new Date(xDate), "mmmm dd, yyyy");

        webpageObj.subtitle.push(webpageObj.details.date)
        if(webpageObj.details.phone)
            webpageObj.subtitle.push(webpageObj.details.phone)
        if(webpageObj.details.email)
            webpageObj.subtitle.push(webpageObj.details.email)
        return webpageObj;
    }

    function getServiceSummary(record) {
        /*
            build service/person summary object:
            {
                "_id": "http://someuri",
                "_type": "person",
                "title": "Emily", // person name
                "subtitle": "Age: 20", // age
                "details": {
                    "height": 64,
                    "weight": 115,
                    "ethnicity": "white"
                }
            }
        */
        var serviceObj = {
            _id: record._id,
            _type: 'person', // hardcode 'person' value for now
            title: _.get(record, '_source.name', 'Name N/A'),
            subtitle: 'Age: ' + _.get(record, '_source.age', 'N/A'),
            details: {
                height: _.get(record, '_source.height'),
                weight: _.get(record, '_source.weight'),
                ethnicity: _.get(record, '_source.ethnicity'),
            }
        };
        return serviceObj;
    }

    return {
        // expected data is from an elasticsearch query
        offer: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getOfferSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        phone: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getPhoneSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        email: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getEmailSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        seller: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getSellerSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        service: function(data) {
            var newObj = {data: [], count: 0};
            if(data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    newObj.data.push(getServiceSummary(record));
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        webpage: function(data) {
            var newObj = {data: [], count: 0};
            if(data && data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    var webpageSummary = getWebpageSummary(record);
                    //We do not want to show webpage page, but instead direct
                    //to offer. The below handles that.
                    if(webpageSummary.offer) {
                        webpageSummary._type = "offer";
                        webpageSummary._id = webpageSummary.offer;
                    }
                    newObj.data.push(webpageSummary);
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },
        // transform for combined sets of results not separated by type
        combinedResults: function(data) {
            var newObj = {data: [], count: 0};
            if(data && data.hits && data.hits.hits.length > 0) {
                _.each(data.hits.hits, function(record) {
                    switch(record._type) {
                        case 'email': newObj.data.push(getEmailSummary(record));
                            break;
                        case 'adultservice': newObj.data.push(getServiceSummary(record));
                            break;
                        case 'phone': newObj.data.push(getPhoneSummary(record));
                            break;
                        case 'offer': newObj.data.push(getOfferSummary(record));
                            break;
                        case 'seller': newObj.data.push(getSellerSummary(record));
                            break;
                        case 'webpage': newObj.data.push(getWebpageSummary(record));
                            break;
                    }
                });
                newObj.count = data.hits.total;
            }
            return newObj;
        },

        cityResults: function(data) {
            var newObject = {};

           if(data && data.aggregations && data.aggregations.webpageCityAgg && data.aggregations.webpageCityAgg.webpageCityAgg.buckets) {
                newObject.aggregations = {};
                newObject.aggregations.webpageCityAgg = {};
                newObject.aggregations.webpageCityAgg.webpageCityAgg = {};
                newObject.aggregations.webpageCityAgg.webpageCityAgg.buckets = [];
                _.each(data.aggregations.webpageCityAgg.webpageCityAgg.buckets, function(record) {

                    var newObj = {};
                    newObj.key = record.key;
                    var keys = record.key.split(':');
                    newObj.text = keys[0];
                    newObj.doc_count = record.doc_count;

                    newObject.aggregations.webpageCityAgg.webpageCityAgg.buckets.push(newObj);
                    //record['key'] = keys[0] + ',' + keys[1];
                    // record['text'] = keys[0];
                });
            }
            // console.log(data);
            return newObject;
        }
    };

})(_, commonTransforms);

<|endoftext|>


<commit_before>/* global
  ConversationController,
  extension,
  getInboxCollection,
  i18n,
  Whisper,
  Signal
*/

// eslint-disable-next-line func-names
(function() {
  'use strict';

  window.Whisper = window.Whisper || {};

  Whisper.StickerPackInstallFailedToast = Whisper.ToastView.extend({
    render_attributes() {
      return { toastMessage: i18n('stickers--toast--InstallFailed') };
    },
  });

  Whisper.ConversationStack = Whisper.View.extend({
    className: 'conversation-stack',
    open(conversation) {
      const id = `conversation-${conversation.cid}`;
      if (id !== this.el.firstChild.id) {
        this.$el
          .first()
          .find('video, audio')
          .each(function pauseMedia() {
            this.pause();
          });
        let $el = this.$(`#${id}`);
        if ($el === null || $el.length === 0) {
          const view = new Whisper.ConversationView({
            model: conversation,
            window: this.model.window,
          });
          // eslint-disable-next-line prefer-destructuring
          $el = view.$el;
        }
        $el.prependTo(this.el);
      }
      conversation.trigger('opened');
      // Make sure poppers are positioned properly
      window.dispatchEvent(new Event('resize'));
    },
  });

  Whisper.AppLoadingScreen = Whisper.View.extend({
    templateName: 'app-loading-screen',
    className: 'app-loading-screen',
    updateProgress(count) {
      if (count > 0) {
        const message = i18n('loadingMessages', count.toString());
        this.$('.message').text(message);
      }
    },
    render_attributes: {
      message: i18n('loading'),
    },
  });

  Whisper.InboxView = Whisper.View.extend({
    templateName: 'two-column',
    className: 'inbox index',
    initialize(options = {}) {
      this.ready = false;
      this.render();
      this.$el.attr('tabindex', '1');

      this.conversation_stack = new Whisper.ConversationStack({
        el: this.$('.conversation-stack'),
        model: { window: options.window },
      });

      if (!options.initialLoadComplete) {
        this.appLoadingScreen = new Whisper.AppLoadingScreen();
        this.appLoadingScreen.render();
        this.appLoadingScreen.$el.prependTo(this.el);
        this.startConnectionListener();
      }

      const inboxCollection = getInboxCollection();

      this.listenTo(inboxCollection, 'messageError', () => {
        if (this.networkStatusView) {
          this.networkStatusView.render();
        }
      });

      this.networkStatusView = new Whisper.NetworkStatusView();
      this.$el
        .find('.network-status-container')
        .append(this.networkStatusView.render().el);

      if (extension.expired()) {
        const banner = new Whisper.ExpiredAlertBanner().render();
        banner.$el.prependTo(this.$el);
        this.$el.addClass('expired');
      }

      Whisper.events.on('pack-install-failed', () => {
        const toast = new Whisper.StickerPackInstallFailedToast();
        toast.$el.appendTo(this.$el);
        toast.render();
      });

      this.setupLeftPane();
    },
    render_attributes: {
      welcomeToSignal: i18n('welcomeToSignal'),
      selectAContact: i18n('selectAContact'),
    },
    events: {
      click: 'onClick',
    },
    setupLeftPane() {
      this.leftPaneView = new Whisper.ReactWrapperView({
        JSX: Signal.State.Roots.createLeftPane(window.reduxStore),
        className: 'left-pane-wrapper',
      });

      // Finally, add it to the DOM
      this.$('.left-pane-placeholder').append(this.leftPaneView.el);
    },
    startConnectionListener() {
      this.interval = setInterval(() => {
        const status = window.getSocketStatus();
        switch (status) {
          case WebSocket.CONNECTING:
            break;
          case WebSocket.OPEN:
            clearInterval(this.interval);
            // if we've connected, we can wait for real empty event
            this.interval = null;
            break;
          case WebSocket.CLOSING:
          case WebSocket.CLOSED:
            clearInterval(this.interval);
            this.interval = null;
            // if we failed to connect, we pretend we got an empty event
            this.onEmpty();
            break;
          default:
            // We also replicate empty here
            this.onEmpty();
            break;
        }
      }, 1000);
    },
    onEmpty() {
      const view = this.appLoadingScreen;
      if (view) {
        this.appLoadingScreen = null;
        view.remove();
      }
    },
    onProgress(count) {
      const view = this.appLoadingScreen;
      if (view) {
        view.updateProgress(count);
      }
    },
    focusConversation(e) {
      if (e && this.$(e.target).closest('.placeholder').length) {
        return;
      }

      this.$('#header, .gutter').addClass('inactive');
      this.$('.conversation-stack').removeClass('inactive');
    },
    focusHeader() {
      this.$('.conversation-stack').addClass('inactive');
      this.$('#header, .gutter').removeClass('inactive');
      this.$('.conversation:first .menu').trigger('close');
    },
    reloadBackgroundPage() {
      window.location.reload();
    },
    async openConversation(id, messageId) {
      const conversation = await ConversationController.getOrCreateAndWait(
        id,
        'private'
      );

      const { openConversationExternal } = window.reduxActions.conversations;
      if (openConversationExternal) {
        openConversationExternal(id, messageId);
      }

      this.conversation_stack.open(conversation);
      this.focusConversation();
    },
    closeRecording(e) {
      if (e && this.$(e.target).closest('.capture-audio').length > 0) {
        return;
      }
      this.$('.conversation:first .recorder').trigger('close');
    },
    onClick(e) {
      this.closeRecording(e);
    },
  });

  Whisper.ExpiredAlertBanner = Whisper.View.extend({
    templateName: 'expired_alert',
    className: 'expiredAlert clearfix',
    render_attributes() {
      return {
        expiredWarning: i18n('expiredWarning'),
        upgrade: i18n('upgrade'),
      };
    },
  });
})();
<commit_msg>Update NetworkStatusView on message error instead of plain render<commit_after>/* global
  ConversationController,
  extension,
  getInboxCollection,
  i18n,
  Whisper,
  Signal
*/

// eslint-disable-next-line func-names
(function() {
  'use strict';

  window.Whisper = window.Whisper || {};

  Whisper.StickerPackInstallFailedToast = Whisper.ToastView.extend({
    render_attributes() {
      return { toastMessage: i18n('stickers--toast--InstallFailed') };
    },
  });

  Whisper.ConversationStack = Whisper.View.extend({
    className: 'conversation-stack',
    open(conversation) {
      const id = `conversation-${conversation.cid}`;
      if (id !== this.el.firstChild.id) {
        this.$el
          .first()
          .find('video, audio')
          .each(function pauseMedia() {
            this.pause();
          });
        let $el = this.$(`#${id}`);
        if ($el === null || $el.length === 0) {
          const view = new Whisper.ConversationView({
            model: conversation,
            window: this.model.window,
          });
          // eslint-disable-next-line prefer-destructuring
          $el = view.$el;
        }
        $el.prependTo(this.el);
      }
      conversation.trigger('opened');
      // Make sure poppers are positioned properly
      window.dispatchEvent(new Event('resize'));
    },
  });

  Whisper.AppLoadingScreen = Whisper.View.extend({
    templateName: 'app-loading-screen',
    className: 'app-loading-screen',
    updateProgress(count) {
      if (count > 0) {
        const message = i18n('loadingMessages', count.toString());
        this.$('.message').text(message);
      }
    },
    render_attributes: {
      message: i18n('loading'),
    },
  });

  Whisper.InboxView = Whisper.View.extend({
    templateName: 'two-column',
    className: 'inbox index',
    initialize(options = {}) {
      this.ready = false;
      this.render();
      this.$el.attr('tabindex', '1');

      this.conversation_stack = new Whisper.ConversationStack({
        el: this.$('.conversation-stack'),
        model: { window: options.window },
      });

      if (!options.initialLoadComplete) {
        this.appLoadingScreen = new Whisper.AppLoadingScreen();
        this.appLoadingScreen.render();
        this.appLoadingScreen.$el.prependTo(this.el);
        this.startConnectionListener();
      }

      const inboxCollection = getInboxCollection();

      this.listenTo(inboxCollection, 'messageError', () => {
        if (this.networkStatusView) {
          this.networkStatusView.update();
        }
      });

      this.networkStatusView = new Whisper.NetworkStatusView();
      this.$el
        .find('.network-status-container')
        .append(this.networkStatusView.render().el);

      if (extension.expired()) {
        const banner = new Whisper.ExpiredAlertBanner().render();
        banner.$el.prependTo(this.$el);
        this.$el.addClass('expired');
      }

      Whisper.events.on('pack-install-failed', () => {
        const toast = new Whisper.StickerPackInstallFailedToast();
        toast.$el.appendTo(this.$el);
        toast.render();
      });

      this.setupLeftPane();
    },
    render_attributes: {
      welcomeToSignal: i18n('welcomeToSignal'),
      selectAContact: i18n('selectAContact'),
    },
    events: {
      click: 'onClick',
    },
    setupLeftPane() {
      this.leftPaneView = new Whisper.ReactWrapperView({
        JSX: Signal.State.Roots.createLeftPane(window.reduxStore),
        className: 'left-pane-wrapper',
      });

      // Finally, add it to the DOM
      this.$('.left-pane-placeholder').append(this.leftPaneView.el);
    },
    startConnectionListener() {
      this.interval = setInterval(() => {
        const status = window.getSocketStatus();
        switch (status) {
          case WebSocket.CONNECTING:
            break;
          case WebSocket.OPEN:
            clearInterval(this.interval);
            // if we've connected, we can wait for real empty event
            this.interval = null;
            break;
          case WebSocket.CLOSING:
          case WebSocket.CLOSED:
            clearInterval(this.interval);
            this.interval = null;
            // if we failed to connect, we pretend we got an empty event
            this.onEmpty();
            break;
          default:
            // We also replicate empty here
            this.onEmpty();
            break;
        }
      }, 1000);
    },
    onEmpty() {
      const view = this.appLoadingScreen;
      if (view) {
        this.appLoadingScreen = null;
        view.remove();
      }
    },
    onProgress(count) {
      const view = this.appLoadingScreen;
      if (view) {
        view.updateProgress(count);
      }
    },
    focusConversation(e) {
      if (e && this.$(e.target).closest('.placeholder').length) {
        return;
      }

      this.$('#header, .gutter').addClass('inactive');
      this.$('.conversation-stack').removeClass('inactive');
    },
    focusHeader() {
      this.$('.conversation-stack').addClass('inactive');
      this.$('#header, .gutter').removeClass('inactive');
      this.$('.conversation:first .menu').trigger('close');
    },
    reloadBackgroundPage() {
      window.location.reload();
    },
    async openConversation(id, messageId) {
      const conversation = await ConversationController.getOrCreateAndWait(
        id,
        'private'
      );

      const { openConversationExternal } = window.reduxActions.conversations;
      if (openConversationExternal) {
        openConversationExternal(id, messageId);
      }

      this.conversation_stack.open(conversation);
      this.focusConversation();
    },
    closeRecording(e) {
      if (e && this.$(e.target).closest('.capture-audio').length > 0) {
        return;
      }
      this.$('.conversation:first .recorder').trigger('close');
    },
    onClick(e) {
      this.closeRecording(e);
    },
  });

  Whisper.ExpiredAlertBanner = Whisper.View.extend({
    templateName: 'expired_alert',
    className: 'expiredAlert clearfix',
    render_attributes() {
      return {
        expiredWarning: i18n('expiredWarning'),
        upgrade: i18n('upgrade'),
      };
    },
  });
})();
<|endoftext|>


<commit_before>import React from 'react';
import Relay from 'react-relay';
import DocumentTitle from 'react-document-title';
import { seconds } from 'metrick/duration';

import Button from '../shared/Button';
import FlashesStore from '../../stores/FlashesStore';
import FriendlyTime from "../shared/FriendlyTime";
import JobLink from '../shared/JobLink';
import PageWithContainer from '../shared/PageWithContainer';
import Panel from '../shared/Panel';
import permissions from '../../lib/permissions';
import { getColourForConnectionState, getLabelForConnectionState } from './shared';

import AgentStopMutation from '../../mutations/AgentStop';

class AgentShow extends React.Component {
  static propTypes = {
    agent: React.PropTypes.shape({
      id: React.PropTypes.string.isRequired,
      name: React.PropTypes.string.isRequired,
      connectionState: React.PropTypes.string.isRequired,
      permissions: React.PropTypes.shape({
        agentStop: React.PropTypes.shape({
          allowed: React.PropTypes.bool.isRequired
        }).isRequired
      }).isRequired
    }),
    relay: React.PropTypes.object.isRequired
  };

  state = {
    stopping: false
  };

  componentDidMount() {
    this._agentRefreshInterval = setInterval(this.fetchUpdatedData, 5::seconds);
  }

  componentWillUnmount() {
    clearInterval(this._agentRefreshInterval);
  }

  fetchUpdatedData = () => {
    this.props.relay.forceFetch(true);
  };

  renderExtraItem(title, content) {
    return (

        {title}: {content}

    );
  }

  renderExtras(agent) {
    const extras = [];

    if (agent.version) {
      extras.push(this.renderExtraItem('Version', agent.version));
    }

    if (agent.hostname) {
      extras.push(this.renderExtraItem('Hostname', agent.hostname));
    }

    if (agent.pid) {
      extras.push(this.renderExtraItem('PID', agent.pid));
    }

    if (agent.ipAddress) {
      extras.push(this.renderExtraItem('IP Address', agent.ipAddress));
    }

    if (agent.userAgent) {
      extras.push(this.renderExtraItem('User Agent', agent.userAgent));
    }

    if (agent.operatingSystem) {
      extras.push(this.renderExtraItem('OS', agent.operatingSystem));
    }

    if (agent.priority) {
      extras.push(this.renderExtraItem('Priority', agent.priority));
    }

    if (agent.job) {
      extras.push(this.renderExtraItem('Running', <JobLink job={agent.job} />));
    }

    if (agent.connectedAt) {
      extras.push(this.renderExtraItem(
        'Connected',

          <FriendlyTime value={agent.connectedAt} />
          {agent.pingedAt && agent.connectionState === 'connected' &&
             (last check-in was <FriendlyTime value={agent.pingedAt} capitalized={false} />)
          }

      ));
    }

    if (agent.connectionState === 'disconnected') {
      extras.push(this.renderExtraItem(
        'Disconnected',
        <FriendlyTime value={agent.disconnectedAt} />
      ));
    } else if (agent.connectionState === 'lost') {
      extras.push(this.renderExtraItem(
        'Lost',
        <FriendlyTime value={agent.lostAt} />
      ));
    } else if (agent.connectionState === 'stopped' || agent.connectionState === 'stopping') {
      extras.push(this.renderExtraItem(
        'Stopped',

          <FriendlyTime value={agent.stoppedAt} /> by {agent.stoppedBy.name}

      ));

      // Also show when the agent eventually disconnected
      if (agent.disconnectedAt) {
        extras.push(this.renderExtraItem(
          'Disconnected',
          <FriendlyTime value={agent.disconnectedAt} />
        ));
      }
    }

    return extras;
  }

  handleStopButtonClick = (evt) => {
    evt.preventDefault();

    this.setState({ stopping: true });

    const mutation = new AgentStopMutation({
      agent: this.props.agent,
      graceful: false
    });

    Relay.Store.commitUpdate(mutation, {
      onSuccess: this.handleMutationSuccess,
      onFailure: this.handleMutationError
    });
  };

  handleMutationSuccess = () => {
    this.setState({ stopping: false });
  };

  handleMutationError = (transaction) => {
    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());

    this.setState({ stopping: false });
  };

  render() {
    const agent = this.props.agent;

    const connectionStateClassName = getColourForConnectionState(agent.connectionState);

    let metaDataContent = 'None';
    if (agent.metaData && agent.metaData.length) {
      metaDataContent = agent.metaData.sort().join('\n');
    }

    return (
      <DocumentTitle title={`Agents / ${agent.name} · ${agent.organization.name}`}>
        <PageWithContainer>
          <Panel>
            <Panel.Header>{agent.name}</Panel.Header>

            <Panel.Row>

                Status

                  {getLabelForConnectionState(agent.connectionState)}

                    {this.renderExtras(agent)}

            </Panel.Row>

            <Panel.Row>

                Meta Data

{metaDataContent}

                  You can use the agent’s meta-data to target the agent in your pipeline’s step configuration, or to set the agent’s queue.
                  See the Agent Meta-data Documentation and Agent Queues Documentation for more details.

            </Panel.Row>

            {this.renderStopRow()}
          </Panel>
        </PageWithContainer>
      </DocumentTitle>
    );
  }

  renderStopRow() {
    if (this.props.agent.connectionState !== 'connected') {
      return null;
    }

    return permissions(this.props.agent.permissions).collect(
      {
        allowed: "agentStop",
        render: (idx) => (
          <Panel.Row key={idx}>

              <Button
                theme="default"
                outline={true}
                loading={this.state.stopping ? "Stopping…" : false}
                onClick={this.handleStopButtonClick}
              >
                Stop Agent
              </Button>

                Remotely stop this agent process.
                Any running build job will be canceled.

          </Panel.Row>
        )
      }
    );
  }
}

export default Relay.createContainer(AgentShow, {
  fragments: {
    agent: () => Relay.QL`
      fragment on Agent {
        ${AgentStopMutation.getFragment('agent')}
        connectedAt
        connectionState
        disconnectedAt
        hostname
        id
        ipAddress
        job {
          ${JobLink.getFragment('job')}
        }
        lostAt
        name
        metaData
        operatingSystem
        organization {
          name
          slug
        }
        permissions {
          agentStop {
            allowed
            code
            message
          }
        }
        pid
        pingedAt
        stoppedAt
        stoppedBy {
          name
        }
        userAgent
        uuid
        version
      }
    `
  }
});
<commit_msg>Defer a ton of data loading on the agents show page<commit_after>import React from 'react';
import Relay from 'react-relay';
import DocumentTitle from 'react-document-title';
import { seconds } from 'metrick/duration';

import Button from '../shared/Button';
import FlashesStore from '../../stores/FlashesStore';
import FriendlyTime from "../shared/FriendlyTime";
import JobLink from '../shared/JobLink';
import PageWithContainer from '../shared/PageWithContainer';
import Panel from '../shared/Panel';
import Spinner from '../shared/Spinner';
import permissions from '../../lib/permissions';
import { getColourForConnectionState, getLabelForConnectionState } from './shared';

import AgentStopMutation from '../../mutations/AgentStop';

class AgentShow extends React.Component {
  static propTypes = {
    agent: React.PropTypes.shape({
      id: React.PropTypes.string,
      name: React.PropTypes.string.isRequired,
      connectionState: React.PropTypes.string,
      permissions: React.PropTypes.shape({
        agentStop: React.PropTypes.shape({
          allowed: React.PropTypes.bool
        })
      })
    }),
    relay: React.PropTypes.object.isRequired
  };

  state = {
    stopping: false
  };

  componentDidMount() {
    this._agentRefreshInterval = setInterval(this.fetchUpdatedData, 5::seconds);

    // Once the agent's show page has mounted in DOM, switch `isMounted` to
    // true which will trigger a load of all the additional information we need
    // to show this page.
    this.props.relay.setVariables({ isMounted: true });
  }

  componentWillUnmount() {
    clearInterval(this._agentRefreshInterval);
  }

  fetchUpdatedData = () => {
    this.props.relay.forceFetch(true);
  };

  renderExtraItem(title, content) {
    return (

        {title}: {content}

    );
  }

  renderExtras(agent) {
    const extras = [];

    if (agent.version) {
      extras.push(this.renderExtraItem('Version', agent.version));
    }

    if (agent.hostname) {
      extras.push(this.renderExtraItem('Hostname', agent.hostname));
    }

    if (agent.pid) {
      extras.push(this.renderExtraItem('PID', agent.pid));
    }

    if (agent.ipAddress) {
      extras.push(this.renderExtraItem('IP Address', agent.ipAddress));
    }

    if (agent.userAgent) {
      extras.push(this.renderExtraItem('User Agent', agent.userAgent));
    }

    if (agent.operatingSystem) {
      extras.push(this.renderExtraItem('OS', agent.operatingSystem));
    }

    if (agent.priority) {
      extras.push(this.renderExtraItem('Priority', agent.priority));
    }

    if (agent.job) {
      extras.push(this.renderExtraItem('Running', <JobLink job={agent.job} />));
    }

    if (agent.connectedAt) {
      extras.push(this.renderExtraItem(
        'Connected',

          <FriendlyTime value={agent.connectedAt} />
          {agent.pingedAt && agent.connectionState === 'connected' &&
             (last check-in was <FriendlyTime value={agent.pingedAt} capitalized={false} />)
          }

      ));
    }

    if (agent.connectionState === 'disconnected') {
      extras.push(this.renderExtraItem(
        'Disconnected',
        <FriendlyTime value={agent.disconnectedAt} />
      ));
    } else if (agent.connectionState === 'lost') {
      extras.push(this.renderExtraItem(
        'Lost',
        <FriendlyTime value={agent.lostAt} />
      ));
    } else if (agent.connectionState === 'stopped' || agent.connectionState === 'stopping') {
      extras.push(this.renderExtraItem(
        'Stopped',

          <FriendlyTime value={agent.stoppedAt} /> by {agent.stoppedBy.name}

      ));

      // Also show when the agent eventually disconnected
      if (agent.disconnectedAt) {
        extras.push(this.renderExtraItem(
          'Disconnected',
          <FriendlyTime value={agent.disconnectedAt} />
        ));
      }
    }

    return extras;
  }

  handleStopButtonClick = (evt) => {
    evt.preventDefault();

    this.setState({ stopping: true });

    const mutation = new AgentStopMutation({
      agent: this.props.agent,
      graceful: false
    });

    Relay.Store.commitUpdate(mutation, {
      onSuccess: this.handleMutationSuccess,
      onFailure: this.handleMutationError
    });
  };

  handleMutationSuccess = () => {
    this.setState({ stopping: false });
  };

  handleMutationError = (transaction) => {
    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());

    this.setState({ stopping: false });
  };

  render() {
    let contents;
    if (this.props.relay.variables.isMounted) {
      contents = this.renderContents();
    } else {
      contents = this.renderSpinner();
    }

    return (
      <DocumentTitle title={`Agents / ${this.props.agent.name} · ${this.props.agent.organization.name}`}>
        <PageWithContainer>
          <Panel>
            <Panel.Header>{this.props.agent.name}</Panel.Header>
            {contents}
          </Panel>
        </PageWithContainer>
      </DocumentTitle>
    );
  }

  renderSpinner() {
    return (
      <Panel.Row>

          <Spinner />

      </Panel.Row>
    );
  }

  renderContents() {
    const agent = this.props.agent;
    const connectionStateClassName = getColourForConnectionState(agent.connectionState);

    let metaDataContent = 'None';
    if (agent.metaData && agent.metaData.length) {
      metaDataContent = agent.metaData.sort().join('\n');
    }

    return [
      <Panel.Row key="info">

          Status

            {getLabelForConnectionState(agent.connectionState)}

              {this.renderExtras(agent)}

      </Panel.Row>,

      <Panel.Row key="meta-data">

          Meta Data

{metaDataContent}

            You can use the agent’s meta-data to target the agent in your pipeline’s step configuration, or to set the agent’s queue.
            See the Agent Meta-data Documentation and Agent Queues Documentation for more details.

      </Panel.Row>,

      this.renderStopRow()
    ];
  }

  renderStopRow() {
    if (this.props.agent.connectionState !== 'connected') {
      return null;
    }

    return permissions(this.props.agent.permissions).collect(
      {
        allowed: "agentStop",
        render: (idx) => (
          <Panel.Row key={idx}>

              <Button
                theme="default"
                outline={true}
                loading={this.state.stopping ? "Stopping…" : false}
                onClick={this.handleStopButtonClick}
              >
                Stop Agent
              </Button>

                Remotely stop this agent process.
                Any running build job will be canceled.

          </Panel.Row>
        )
      }
    );
  }
}

// The $isMounted gear here is a little crappy. It should be nicer, but looks
// like there's a bug in grpahql-ruby at the moment:
// https://github.com/rmosolgo/graphql-ruby/issues/518

export default Relay.createContainer(AgentShow, {
  initialVariables: {
    isMounted: false
  },

  fragments: {
    agent: () => Relay.QL`
      fragment on Agent {
        ${AgentStopMutation.getFragment('agent')}
        name
        organization {
          name
          slug
        }
        connectedAt @include(if: $isMounted)
        connectionState @include(if: $isMounted)
        disconnectedAt @include(if: $isMounted)
        hostname @include(if: $isMounted)
        id @include(if: $isMounted)
        ipAddress @include(if: $isMounted)
        job @include(if: $isMounted) {
          ${JobLink.getFragment('job')}
        }
        lostAt @include(if: $isMounted)
        metaData @include(if: $isMounted)
        operatingSystem @include(if: $isMounted)
        permissions @include(if: $isMounted) {
          agentStop {
            allowed
            code
            message
          }
        }
        pid @include(if: $isMounted)
        pingedAt @include(if: $isMounted)
        stoppedAt @include(if: $isMounted)
        stoppedBy @include(if: $isMounted) {
          name
        }
        userAgent @include(if: $isMounted)
        uuid @include(if: $isMounted)
        version @include(if: $isMounted)
      }
    `
  }
});
<|endoftext|>


<commit_before>var request = require('request');

module.exports = {

  // scan repo for "geojson files"
  repo: function( user, repo, path, callback ){
    var url = 'https://raw.github.com/'+ user + '/' + repo + '/master/' + path + '.geojson';
    request(url, function( error, response, body ){
      if (!error && response.statusCode == 200) {
        var json = JSON.parse( body );
        try {
          if (json.type && json.type == 'FeatureCollection'){
            callback( null, json );
          }
        } catch (e){
          callback('Error: could not parse file contents' + e, null);
        }
      }
    });
  },

  gist: function( options, callback ){
    var url = 'https://api.github.com/gists/' + options.id + ((options.token) ? '?access_token=' + options.token : '');
    request.get(url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var files = JSON.parse( body ).files,
          geojson = [];

        for ( var f in files ){
          var file = files[f],
            content = file.content;

          try {
            var json = JSON.parse( content );
            if (json.type && json.type == 'FeatureCollection'){
              geojson.push( json );
            }
          } catch (e){
            callback('Error: could not parse file contents'+e, null);
          }

        }
        // got some geojson
        if ( geojson.length ){
          callback( null, geojson );
        } else {
          callback('Error: could not find any geojson in gist #' + id, null);
        }
      }
    });

  }

};
<commit_msg>Refactor slightly to avoid reentrancy in the case of an unhandled error in a callback function.<commit_after>var request = require('request');

module.exports = {

  // scan repo for "geojson files"
  repo: function( user, repo, path, callback ){
    var url = 'https://raw.github.com/'+ user + '/' + repo + '/master/' + path + '.geojson';
    request(url, function( error, response, body ){
      if (!error && response.statusCode == 200) {
      	var geojson = null;
        try {
          var json = JSON.parse( body );
          if (json.type && json.type == 'FeatureCollection'){
          	geojson = json;
          }
        } catch (e){
          callback('Error: could not parse file contents' + e, null);
          return;
        }

        if ( geojson ) {
        	callback( null, geojson );
        } else {
        	callback('Error: could not find any geojson at ' + url, null);
        }
      } else if (response.statusCode == 404) {
      	callback("File not found at: " + url, null);
      } else {
      	callback("Error '" + error + "' occurred reading from " + url, null);
      }
    });
  },

  gist: function( options, callback ){
    var url = 'https://api.github.com/gists/' + options.id + ((options.token) ? '?access_token=' + options.token : '');
    request.get(url, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var files = JSON.parse( body ).files,
          geojson = [];

        for ( var f in files ){
          var file = files[f],
            content = file.content;

          try {
            var json = JSON.parse( content );
            if (json.type && json.type == 'FeatureCollection'){
              geojson.push( json );
            }
          } catch (e){
            callback('Error: could not parse file contents'+e, null);
          }

        }
        // got some geojson
        if ( geojson.length ){
          callback( null, geojson );
        } else {
          callback('Error: could not find any geojson in gist #' + id, null);
        }
      } else if (response.statusCode == 404) {
      	callback("Gist not found at: " + url, null);
      } else {
      	callback("Error '" + error + "' occurred reading from " + url, null);
      }
    });

  }
};
<|endoftext|>