UNPKG

maniajs

Version:

ManiaPlanet (Dedicated) Server Controller.

470 lines (382 loc) 12.9 kB
/** * List View */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _events = require('events'); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** * List View * * @class ListView * @type {ListView} * * @property {App} app * @property {string} title Title of list. * @property {Player} player Player Login (single login!). * @property {[{name: {string}, field: {string}, width: {number}, [level]: {number}, [event]: {string}}]} columns Columns to define. * @property {[{}]} data Array with objects. Give a custom manialink with the 'custom' key. This will be injected into the row! */ var ListView = function (_EventEmitter) { _inherits(ListView, _EventEmitter); /** * Construct List View * @param {App} app * @param {string} title * @param {Player} player * @param {[{name: {string}, field: {string}, width: {number}, [level]: {number}, [event]: {string}}]} columns Columns to define. * @param {[{}]} data Array with objects. Give a custom manialink with the 'custom' key. This will be injected into the row! */ function ListView(app, title, player, columns, data) { _classCallCheck(this, ListView); var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ListView).call(this)); _this.setMaxListeners(0); _this.app = app; _this.title = title; _this.player = player; _this.columns = columns; _this.data = data; _this.ui = _this.app.uiFacade.build(_this.app, 'list', 2, '|' + _this.player.login); _this.range = { start: 0, stop: 15 }; return _this; } /** * Parse Data and Columns and Prepare the UI. Must be called before the display or update command! */ _createClass(ListView, [{ key: 'parse', value: function parse() { var _this2 = this; this.width = 210; this.totalWidth = 0; this.page = 0; // Current Page NR. this.numRows = this.data.length; // Total Rows data this.numCols = this.columns.length; // Total Columns. this.header = []; // Contains Headers, ready for view. this.body = []; // Contains Body, ready for view. this.events = []; // Possible events, we use a | to separate from the index of the record! this.send = {}; // Will be the data to send to the view. // Create header for player. var left = 0; // Current left position this.columns.forEach(function (raw) { if (raw.hasOwnProperty('level') && _this2.player.level < raw.level) { return; // Skip, the player has no rights for this col! } if (raw.hasOwnProperty('event')) { _this2.events.push(raw.event); } if (raw.hasOwnProperty('sort') && typeof raw.sort === 'function') { raw.sortEvent = 'action="_sort|' + _this2.header.length + '"'; if (_this2.events.indexOf('_sort') === -1) { _this2.events.push('_sort'); } } else { raw.sort = null; raw.sortEvent = ''; } _this2.totalWidth += raw.width; raw.colStyle = raw.sort ? 'TextRaceChat' : ''; raw.left = left + 2; left += raw.width; raw.sepLeft = left; // TODO: ? separator? _this2.header.push(raw); }); // Update number of cols. this.numCols = this.header.length; if (this.totalWidth > this.width) { throw new Error('Total Column Width is greater than the maximum of ' + width + '!'); } // Current page, items. var pageItems = 0; // Make body! this.data.forEach(function (rawRow, rowIdx) { // Current left position var left = 0; // Reset page items if on new page. if (pageItems === 15) { pageItems = 0; } // Row data. var row = { data: [], top: pageItems * 6, even: pageItems % 2 === 1 }; _this2.header.forEach(function (rawCol, colIdx) { if (rawCol.field && !rawRow.hasOwnProperty(rawCol.field)) { _this2.app.log.info('List View: Data has no field as defined in column! Will be skipped!'); return; } var col = {}; // Text/ManiaLink/button col.text = ''; var text = rawRow.hasOwnProperty(rawCol.field) ? rawRow[rawCol.field] : ''; if (rawCol.hasOwnProperty('custom') && rawCol.custom) { // Custom MANIALINK!; col.text = false; col.button = false; col.custom = text; } else if (rawCol.hasOwnProperty('button') && rawCol.button) { col.custom = false; col.text = false; col.button = true; col.style = rawCol.style || 'Icons64x64_1'; col.substyle = rawCol.substyle || 'LvlRed'; } else { col.text = text; col.style = rawCol.style || ''; col.custom = false; col.button = false; } // Event if (rawCol.hasOwnProperty('event') && rawCol.event) { col.event = 'action="' + rawCol.event + '|' + rowIdx + '"'; if (col.style === '') { col.style = 'TextCardSmallScores2'; } } else { col.event = ''; } // Width and height col.width = rawCol.width; col.height = 5; // Position col.left = left + 2; col.top = pageItems * 6; left += col.width; // Add to row row.data.push(col); }); // Add to body _this2.body.push(row); // Page Items pageItems++; }); // Calculate total pages. this.numRows = this.body.length; this.pages = Math.ceil(this.numRows / 15); // Prepare the UI. this.prepare(); } /** * Prepare the UI. */ }, { key: 'prepare', value: function prepare() { var _this3 = this; this.ui.timeout = 0; this.ui.hideClick = false; this.ui.global({ title: this.title, header: this.header, body: this.body.slice(this.range.start, this.range.stop), page: this.page + 1, pages: this.pages, total: this.numRows, range: { start: this.range.start + 1, stop: this.range.stop }, next: this.page + 1 < this.pages, prev: this.page > 0 }); this.ui.player(this.player.login); // Callbacks on every event that we have. this.events.forEach(function (event) { _this3.ui.on(event, function (params) { _this3.handle(event, params); }); }); // View Handlers. this.ui.on('close', function (params) { return _this3.handleClose(params.login); }); this.on('_sort', function (params) { return _this3.handleSort(params.login, params.idx); }); this.ui.on('first', function (params) { return _this3.handleFirst(params.login); }); this.ui.on('prev_10', function (params) { return _this3.handlePrev(params.login, 10); }); this.ui.on('prev', function (params) { return _this3.handlePrev(params.login, 1); }); this.ui.on('next', function (params) { return _this3.handleNext(params.login, 1); }); this.ui.on('next_10', function (params) { return _this3.handleNext(params.login, 10); }); this.ui.on('last', function (params) { return _this3.handleLast(params.login); }); } /** * Handle Sorting Action * @todo: */ }, { key: 'handleSort', value: function handleSort(login, column) { if (this.header.length <= column) { return; } var col = this.header[column]; this.body.sort(function (a, b) { return col.sort(a.data[column].text, b.data[column].text); }); this.handleFirst(login); } /** * Handle Close Button. */ }, { key: 'handleClose', value: function handleClose(login) { if (this.player.login === login) { this.close(); this.emit('close', login); } } }, { key: 'handleLast', value: function handleLast(login) { if (this.player.login !== login) { return; } this.page = this.pages - 1; this.range.start = 15 * this.pages - 15; this.range.stop = 15 * this.pages; this._pageUpdate(); this.emit('last', login); } }, { key: 'handleFirst', value: function handleFirst(login) { if (this.player.login !== login) { return; } this.page = 0; this.range.start = 0; this.range.stop = 15; this._pageUpdate(); this.emit('first', login); } }, { key: 'handleNext', value: function handleNext(login, skip) { if (this.player.login !== login) { return; } if (this.page + skip > this.pages) { return false; } this.range.start += 15 * skip; this.range.stop += 15 * skip; this.page += skip; this._pageUpdate(); this.emit('next', login); } }, { key: 'handlePrev', value: function handlePrev(login, skip) { if (this.player.login !== login) { return; } if (this.page - skip < 0) { return false; } this.range.start -= 15 * skip; this.range.stop -= 15 * skip; this.page -= skip; this._pageUpdate(); this.emit('prev', login); } /** * Update Page, send new slice to client! * @returns {Promise} * @private */ }, { key: '_pageUpdate', value: function _pageUpdate() { // Change page, change the slice! return this.ui.global({ title: this.title, header: this.header, body: this.body.slice(this.range.start, this.range.stop), page: this.page + 1, pages: this.pages, total: this.numRows, range: { start: this.range.start + 1, stop: this.range.stop }, next: this.page + 1 < this.pages, prev: this.page > 0 }).update(); } /** * List Event Handler. * * @param {string} event * @param {{}} params */ }, { key: 'handle', value: function handle(event, params) { if (params.answer.indexOf('|') === -1) { return false; } if (params.login !== this.player.login) { return false; } // Parse var idx = parseInt(params.answer.substr(params.answer.indexOf('|') + 1)); if (!isNaN(idx)) { var row = this.data[idx] || false; // Emit this.emit(event, { login: params.login, idx: idx, entry: row }); } } /** * Start displaying to player. * * @returns {Promise} */ }, { key: 'display', value: function display() { return this.ui.display(); } /** * Stop displaying to player. * * @returns {Promise} */ }, { key: 'close', value: function close() { // Send empty manialink to the player with the same ID. return this.ui.destroy(); } /** * Get UI instance. * @returns {InterfaceBuilder} */ }, { key: 'toUI', value: function toUI() { return this.ui; } }]); return ListView; }(_events.EventEmitter); exports.default = ListView;