jupyterlab-slurm
Version:
A JupyterLab extension to interface with the Slurm workload manager.
192 lines • 9.94 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const react_bootstrap_1 = require("react-bootstrap");
const fp_1 = require("lodash/fp");
// Local
const Select_1 = __importDefault(require("./Select"));
const Pager_1 = __importDefault(require("./Pager"));
const utils_1 = require("../utils");
class DataTable extends react_1.Component {
constructor(props) {
super(props);
this.state = {
rows: [],
focusedRowIdx: -1,
selectedRowIdxs: [],
displayedColumns: props.defaultColumns ? props.defaultColumns : props.availableColumns,
itemsPerPage: 10,
currentPage: 1,
filterQuery: '',
};
}
changeItemsPerPage(value) {
this.setState({ itemsPerPage: parseInt(value) });
this.clearSelectedRows();
}
changePage(value) {
this.setState({ currentPage: value });
this.clearSelectedRows();
}
clearSelectedRows() {
this.setState({ focusedRowIdx: -1, selectedRowIdxs: [] });
}
selectRow(rowIdx, event) {
event.stopPropagation();
if (this.props.processing)
return;
let { focusedRowIdx, selectedRowIdxs } = this.state;
if (focusedRowIdx != -1) {
if (event.shiftKey) {
const [start, end] = [focusedRowIdx, rowIdx].sort();
selectedRowIdxs = fp_1.range(start, end + 1);
}
else if (event.ctrlKey || event.metaKey) {
const selectionIdx = selectedRowIdxs.indexOf(rowIdx);
if (selectionIdx) { // The row was already selected
let i = 1;
while (selectedRowIdxs[selectionIdx - i] === rowIdx - i) {
i++;
}
if (i === 1) { // The rowIdx is the beginning of a contiguous selection
// Focus in-block, if possible
if (selectedRowIdxs[selectionIdx + 1] === rowIdx + 1) {
focusedRowIdx = rowIdx + 1;
}
else { // Focus the beginning of the previous block
const prevBlockEndIdx = selectionIdx - 1;
if (selectedRowIdxs[prevBlockEndIdx] === undefined) {
focusedRowIdx = -1;
}
else {
while (selectedRowIdxs[prevBlockEndIdx - i] === selectedRowIdxs[prevBlockEndIdx] - i) {
i++;
}
const candidateRow = selectedRowIdxs[prevBlockEndIdx] - i + 1;
focusedRowIdx = candidateRow ? candidateRow : -1;
}
}
}
else { // Focus beginning of contiguous block containing rowIdx
focusedRowIdx = rowIdx - i + 1;
}
selectedRowIdxs = selectedRowIdxs.filter(r => r !== rowIdx);
}
else { // The row was not selected
focusedRowIdx = rowIdx;
selectedRowIdxs = selectedRowIdxs.concat([rowIdx]).sort();
}
}
}
else {
focusedRowIdx = rowIdx;
selectedRowIdxs = [rowIdx];
}
this.setState({ focusedRowIdx, selectedRowIdxs });
}
getData() {
return __awaiter(this, void 0, void 0, function* () {
const { userOnly } = this.props;
const data = yield utils_1.makeRequest({
route: 'squeue',
method: 'GET',
query: `?userOnly=${userOnly}`,
afterResponse: (response) => __awaiter(this, void 0, void 0, function* () {
if (response.status !== 200) {
throw Error(response.statusText);
}
else {
let data = yield response.json();
return data.data;
}
}),
});
return data;
});
}
reload() {
return __awaiter(this, void 0, void 0, function* () {
const rows = yield this.getData();
this.setState({ rows, focusedRowIdx: -1, selectedRowIdxs: [] });
});
}
componentWillMount() {
this.reload();
}
render() {
const { rows, displayedColumns, itemsPerPage, currentPage, selectedRowIdxs, } = this.state;
const numPages = Math.ceil(rows.length / itemsPerPage);
const currentSliceStart = (currentPage - 1) * itemsPerPage;
const currentSliceEnd = currentSliceStart + itemsPerPage;
const currentRows = rows.slice(currentSliceStart, currentSliceEnd);
const selectedRows = selectedRowIdxs.map(r => rows[r]);
const { buttons } = this.props;
return (react_1.default.createElement("div", null,
buttons && react_1.default.createElement(react_bootstrap_1.ButtonToolbar, null, (buttons).map((button, idx) => {
switch (button.id) {
case 'reload':
return react_1.default.createElement(react_bootstrap_1.Button, Object.assign({}, button.props, { onClick: this.reload.bind(this), key: idx }), button.name ? button.name : 'Reload');
case 'clear-selected':
return react_1.default.createElement(react_bootstrap_1.Button, Object.assign({}, button.props, { disabled: !selectedRowIdxs.length, onClick: this.clearSelectedRows.bind(this), key: idx }), button.name ? button.name : 'Clear Selection');
case 'submit-job':
return react_1.default.createElement(react_bootstrap_1.Button, Object.assign({}, button.props, { onClick: () => button.action(selectedRows), key: idx }), button.name ? button.name : 'Submit Job');
default:
return react_1.default.createElement(react_bootstrap_1.Button, Object.assign({}, button.props, { disabled: !selectedRowIdxs.length, onClick: (e) => { button.action(selectedRows); }, key: idx }), button.name);
}
})),
react_1.default.createElement(react_bootstrap_1.Table, { striped: true, bordered: true, hover: true, className: "dataTable" },
react_1.default.createElement("thead", null,
react_1.default.createElement("tr", null, displayedColumns.map(header => react_1.default.createElement("th", { key: header }, header)))),
react_1.default.createElement("tbody", null, currentRows.map((row, rowIdx) => {
let selectedComposition = "";
let selected = false;
if (this.state.selectedRowIdxs.length) {
selectedComposition = this.state.selectedRowIdxs.includes(rowIdx) ? "selected" : "unselected";
selected = this.state.selectedRowIdxs.includes(rowIdx);
}
else {
selectedComposition = this.state.focusedRowIdx == rowIdx ? "selected" : "";
selected = this.state.focusedRowIdx == rowIdx;
}
if (selected && this.props.processing) {
selectedComposition += " processing";
}
return react_1.default.createElement("tr", { onClick: this.selectRow.bind(this, rowIdx), key: `${rowIdx}`, className: selectedComposition }, row.map((field, fieldIdx) => react_1.default.createElement("td", { key: `${rowIdx}-${fieldIdx}` }, field)));
}))),
react_1.default.createElement(Select_1.default, { options: ['10', '25', '50', '100'], onChange: this.changeItemsPerPage.bind(this) }),
react_1.default.createElement(Pager_1.default, { numPages: numPages, onChange: this.changePage.bind(this) })));
}
}
exports.default = DataTable;
//# sourceMappingURL=DataTable.js.map