Files
tubestation/devtools/client/webconsole/new-console-output/components/console-table.js
2017-03-14 04:28:43 +01:00

207 lines
5.4 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
createClass,
createFactory,
DOM: dom,
PropTypes
} = require("devtools/client/shared/vendor/react");
const { ObjectClient } = require("devtools/shared/client/main");
const actions = require("devtools/client/webconsole/new-console-output/actions/messages");
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
const { MODE } = require("devtools/client/shared/components/reps/reps");
const GripMessageBody = createFactory(require("devtools/client/webconsole/new-console-output/components/grip-message-body"));
const TABLE_ROW_MAX_ITEMS = 1000;
const TABLE_COLUMN_MAX_ITEMS = 10;
const ConsoleTable = createClass({
displayName: "ConsoleTable",
propTypes: {
dispatch: PropTypes.func.isRequired,
parameters: PropTypes.array.isRequired,
serviceContainer: PropTypes.shape({
hudProxyClient: PropTypes.object.isRequired,
}),
id: PropTypes.string.isRequired,
tableData: PropTypes.object,
},
componentWillMount: function () {
const {id, dispatch, serviceContainer, parameters} = this.props;
if (!Array.isArray(parameters) || parameters.length === 0) {
return;
}
const client = new ObjectClient(serviceContainer.hudProxyClient, parameters[0]);
let dataType = getParametersDataType(parameters);
// Get all the object properties.
dispatch(actions.messageTableDataGet(id, client, dataType));
},
getHeaders: function (columns) {
let headerItems = [];
columns.forEach((value, key) => headerItems.push(dom.th({}, value)));
return headerItems;
},
getRows: function (columns, items) {
return items.map(item => {
let cells = [];
columns.forEach((value, key) => {
cells.push(
dom.td(
{},
GripMessageBody({
grip: item[key],
mode: MODE.SHORT,
useQuotes: false,
})
)
);
});
return dom.tr({}, cells);
});
},
render: function () {
const {parameters, tableData} = this.props;
const headersGrip = parameters[1];
const headers = headersGrip && headersGrip.preview ? headersGrip.preview.items : null;
// if tableData is nullable, we don't show anything.
if (!tableData) {
return null;
}
const {columns, items} = getTableItems(
tableData,
getParametersDataType(parameters),
headers
);
return (
dom.table({className: "new-consoletable devtools-monospace"},
dom.thead({}, this.getHeaders(columns)),
dom.tbody({}, this.getRows(columns, items))
)
);
}
});
function getParametersDataType(parameters = null) {
if (!Array.isArray(parameters) || parameters.length === 0) {
return null;
}
return parameters[0].class;
}
function getTableItems(data = {}, type, headers = null) {
const INDEX_NAME = "_index";
const VALUE_NAME = "_value";
const namedIndexes = {
[INDEX_NAME]: (
["Object", "Array"].includes(type) ?
l10n.getStr("table.index") : l10n.getStr("table.iterationIndex")
),
[VALUE_NAME]: l10n.getStr("table.value"),
key: l10n.getStr("table.key")
};
let columns = new Map();
let items = [];
let addItem = function (item) {
items.push(item);
Object.keys(item).forEach(key => addColumn(key));
};
let addColumn = function (columnIndex) {
let columnExists = columns.has(columnIndex);
let hasMaxColumns = columns.size == TABLE_COLUMN_MAX_ITEMS;
let hasCustomHeaders = Array.isArray(headers);
if (
!columnExists &&
!hasMaxColumns && (
!hasCustomHeaders ||
headers.includes(columnIndex) ||
columnIndex === INDEX_NAME
)
) {
columns.set(columnIndex, namedIndexes[columnIndex] || columnIndex);
}
};
for (let index of Object.keys(data)) {
if (type !== "Object" && index == parseInt(index, 10)) {
index = parseInt(index, 10);
}
let item = {
[INDEX_NAME]: index
};
let property = data[index].value;
if (property.preview) {
let {preview} = property;
let entries = preview.ownProperties || preview.items;
if (entries) {
for (let key of Object.keys(entries)) {
let entry = entries[key];
item[key] = entry.value || entry;
}
} else {
if (preview.key) {
item.key = preview.key;
}
item[VALUE_NAME] = preview.value || property;
}
} else {
item[VALUE_NAME] = property;
}
addItem(item);
if (items.length === TABLE_ROW_MAX_ITEMS) {
break;
}
}
// Some headers might not be present in the items, so we make sure to
// return all the headers set by the user.
if (Array.isArray(headers)) {
headers.forEach(header => addColumn(header));
}
// We want to always have the index column first
if (columns.has(INDEX_NAME)) {
let index = columns.get(INDEX_NAME);
columns.delete(INDEX_NAME);
columns = new Map([[INDEX_NAME, index], ...columns.entries()]);
}
// We want to always have the values column last
if (columns.has(VALUE_NAME)) {
let index = columns.get(VALUE_NAME);
columns.delete(VALUE_NAME);
columns.set(VALUE_NAME, index);
}
return {
columns,
items
};
}
module.exports = ConsoleTable;