UNPKG

jupyterlab-slurm

Version:

A JupyterLab extension to interface with the Slurm workload manager.

192 lines 9.94 kB
"use strict"; 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