199 lines
6.0 KiB
JavaScript
199 lines
6.0 KiB
JavaScript
|
|
import { Meteor } from 'meteor/meteor';
|
|
import React, { useState } from 'react';
|
|
import { useTracker } from 'meteor/react-meteor-data';
|
|
import _ from 'lodash';
|
|
|
|
|
|
|
|
//{columns.map((column) => <td>{column.value(row)}</td>)}
|
|
const WholeRow = ({row, columns}) => {
|
|
return <tr><td>Test</td></tr>
|
|
}
|
|
|
|
const ColumnHeader = ({column}) => {
|
|
// console.log("Rendering column header")
|
|
return <td>
|
|
{column.isActions ?
|
|
"TODO: Add widgets"
|
|
:
|
|
column.title
|
|
}
|
|
</td>
|
|
}
|
|
|
|
const Row = ({columns, row, getRowKey, editedRowKey, editor, setEdited}) => {
|
|
return <tr><td>Test</td></tr>
|
|
}
|
|
/*
|
|
<tr>
|
|
{!editedRowKey || getRowKey(row) !== editedRowKey ?
|
|
columns.map((column, i) => <Cell column={column} row={row}/>)
|
|
:
|
|
editor
|
|
}
|
|
</tr>
|
|
*/
|
|
// onDoubleClick={(e) => {(!editedRowKey || getRowKey(row) !== editedRowKey) && setEdited(row)}}
|
|
const Cell = ({row, column}) => {
|
|
return <td>test</td>
|
|
}
|
|
/*
|
|
<td>
|
|
{column.isActions ?
|
|
"TODO"
|
|
:
|
|
column.value(row)
|
|
}
|
|
</td>
|
|
*/
|
|
|
|
/**
|
|
* Example:
|
|
* import {useState} from 'react';
|
|
* const[edited, setEdited] = useState(undefined);
|
|
* <GridTable setEdited={setEdited} edited={edited} rows={rows} columns={columnns} actions={actions}>
|
|
* <!-- Editor JSX here. -->
|
|
* </GridTable>
|
|
*
|
|
* export let rows;
|
|
export let columns;
|
|
export let rowKey; //Must only be null/undefined if the row is a new object (not associated with a row in the table). Should not change.
|
|
export let edited;
|
|
export let actions;
|
|
export let selection;
|
|
* @param props
|
|
* @returns {JSX.Element}
|
|
*/
|
|
export default ({columns, rows, actions, getRowKey, edited, setEdited, children}) => {
|
|
// Setup a width for each column.
|
|
columns.forEach(column => {
|
|
let min = column.minWidth ? Math.max(10, column.minWidth) : 10;
|
|
let weight = column.weight ? Math.max(1, column.weight) : 1;
|
|
column.width = 'minmax(' + min + 'px, ' + weight + 'fr)';
|
|
column.isActions = false;
|
|
});
|
|
|
|
// Add the actions column to the end.
|
|
// TODO: Allow it to be positioned.
|
|
if(actions) {
|
|
// TODO: make this fixed width based on the possible widget widths.
|
|
actions.width = 'minmax(10px, 1fr)';
|
|
actions.isActions = true;
|
|
columns[columns.length] = actions;
|
|
}
|
|
|
|
// Collect the column widths for the layout.
|
|
let gridTemplateColumns = columns.map(({width}) => width).join(' ');
|
|
|
|
// Resize column code.
|
|
let headerBeingResized = null;
|
|
let horizontalScrollOffset = 0;
|
|
const initResize = ({target}) => {
|
|
headerBeingResized = target.parentNode;
|
|
window.addEventListener('mousemove', onMouseMove);
|
|
window.addEventListener('mouseup', completeResize);
|
|
headerBeingResized.classList.add('header--being-resized');
|
|
};
|
|
const completeResize = () => {
|
|
window.removeEventListener('mousemove', onMouseMove);
|
|
window.removeEventListener('mouseup', completeResize);
|
|
headerBeingResized.classList.remove('header--being-resized');
|
|
headerBeingResized = null;
|
|
};
|
|
const onMouseMove = e => {
|
|
try {
|
|
// Calculate the desired width.
|
|
horizontalScrollOffset = document.documentElement.scrollLeft;
|
|
let parentX = Math.round(headerBeingResized.getBoundingClientRect().x);
|
|
const width = horizontalScrollOffset + (e.clientX - parentX);
|
|
// Update the column object with the new size value.
|
|
const column = columns.find(({element}) => element === headerBeingResized);
|
|
column.width = Math.max(column.minWidth, width) + "px";
|
|
// Ensure all the column widths are converted to fixed sizes.
|
|
columns.forEach((column, index) => {
|
|
if((index < columns.length - 1) && (column.width.startsWith('minmax'))) {
|
|
column.width = parseInt(column.element.clientWidth, 10) + 'px';
|
|
}
|
|
});
|
|
// Render the new column sizes.
|
|
gridTemplateColumns = columns.map(({width}) => width).join(' ');
|
|
} catch(e) {console.log(e);}
|
|
}
|
|
|
|
// Select row code.
|
|
let selectedRowElement = null;
|
|
const selectRow = (e, row) => {
|
|
let element = e.target;
|
|
|
|
while(element && element.nodeName !== "TR") element = element.parentNode;
|
|
|
|
if(selectedRowElement) {
|
|
selectedRowElement.classList.remove('selected');
|
|
}
|
|
|
|
selectedRowElement = element;
|
|
element.classList.add('selected');
|
|
dispatch('selection', selectedRowElement.dataset.key);
|
|
}
|
|
|
|
// Edit row code.
|
|
let editorContainer;
|
|
let editorTable;
|
|
// Listen for changes to the edited variable. Move the editor row and display it when there is a value.
|
|
// Relies on the table row being hidden when the edited value matches the row's value.
|
|
useTracker(() => {
|
|
if(editorContainer) {
|
|
if(edited) {
|
|
let id = rowKey($edited);
|
|
let hiddenRow = editorTable.querySelector('tbody tr[data-key="' + id + '"]');
|
|
|
|
if(!hiddenRow) {
|
|
let body = editorTable.querySelector('tbody');
|
|
body.firstChild ? body.insertBefore(editorContainer, body.firstChild) : body.appendChild(editorContainer);
|
|
editorContainer.classList.remove('hidden');
|
|
}
|
|
else {
|
|
//let editor = hiddenRow.querySelector('.editor');
|
|
let body = editorTable.querySelector('tbody');
|
|
let next = hiddenRow.nextSibling;
|
|
//editor.appendChild(editorContainer);
|
|
next ? body.insertBefore(editorContainer, next) : body.appendChild(editorContainer);
|
|
editorContainer.classList.remove('hidden');
|
|
}
|
|
}
|
|
else {
|
|
console.log("Edited cleared");
|
|
editorContainer.classList.add('hidden');
|
|
}
|
|
}
|
|
});
|
|
|
|
let editedRowKey = edited ? getRowKey(edited) : undefined;
|
|
console.log("Rendering grid table")
|
|
|
|
// let contents = "";
|
|
//
|
|
// for(let row of rows) {
|
|
// contents += <WholeRow row={row} columns={columns}/>
|
|
// // contents += <tr>
|
|
// // for(let column of columns) {
|
|
// // contents += <CellValue row={row} column={column}></CellValue>
|
|
// // }
|
|
// // contents += </tr>
|
|
// }
|
|
|
|
return <div className={'grid-table-container'}>
|
|
<table style={{gridTemplateColumns}}>
|
|
<thead>
|
|
<tr>
|
|
{columns.map((column, i) => <ColumnHeader key={column.key} column={column}/>)}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{/*{rows.map((row, i) => <Row key={getRowKey(row)} row={row} columns={columns} getRowKey={getRowKey} editedRowKey={editedRowKey} editor={children} setEdited={setEdited}/>)}*/}
|
|
{rows.map((row)=><WholeRow row={row} columns={columns}/>)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
} |