From 764acd14276c8e7d78e9f97adb00dbd6acabd808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Fri, 29 May 2020 02:13:53 +0200
Subject: [PATCH] [dome] complete table view

---
 ivette/src/dome/src/renderer/table/views.tsx | 144 ++++++++++++-------
 1 file changed, 89 insertions(+), 55 deletions(-)

diff --git a/ivette/src/dome/src/renderer/table/views.tsx b/ivette/src/dome/src/renderer/table/views.tsx
index cb2feb1e8fb..9dc62d797d3 100644
--- a/ivette/src/dome/src/renderer/table/views.tsx
+++ b/ivette/src/dome/src/renderer/table/views.tsx
@@ -8,9 +8,9 @@
  */
 
 import React from 'react';
-import * as Dome from 'dome';
+//import * as Dome from 'dome';
 import { Trigger, Client, Sorting, Fetching, Model } from './models';
-import { DraggableCore, DraggableEventHandler } from 'react-draggable';
+//import { DraggableCore, DraggableEventHandler } from 'react-draggable';
 import { SVG as SVGraw } from 'dome/controls/icons';
 import {
   AutoSizer, Size,
@@ -114,8 +114,8 @@ export interface TableProps<Key, Row> {
   settings?: string;
   /** Selected row (identified by key). */
   selection?: Key;
-  /** Selection callback (identified by key). */
-  onSelection?: (selected?: Key) => void;
+  /** Selection callback. */
+  onSelection?: (row: Row, key: Key, index: number) => void;
   /** Ensures the item is visible (if displayed at all). */
   scrollTo?: Key;
   /** Fallback for rendering an empty table. */
@@ -212,14 +212,14 @@ class TableState<Row> {
 
   // --- User Table properties
 
-  setSorting(sorting: Sorting) {
+  setSorting(sorting?: Sorting) {
     if (sorting !== this.sorting) {
       this.sorting = sorting;
       this.reload();
     }
   }
 
-  setFetching(fetching: Fetching<Row>) {
+  setFetching(fetching?: Fetching<Row>) {
     if (fetching !== this.fetching) {
       this.client?.unlink();
       this.fetching = fetching;
@@ -236,7 +236,7 @@ class TableState<Row> {
     }
   }
 
-  setRendering(fields: RenderByFields<Row>) {
+  setRendering(fields?: RenderByFields<Row>) {
     if (fields !== this.fields) {
       this.fields = fields;
       this.render.clear();
@@ -383,7 +383,7 @@ function makeColumns<Row>(state: TableState<Row>) {
 }
 
 // --------------------------------------------------------------------------
-// --- Header Renderer
+// --- Table Utility Renderers
 // --------------------------------------------------------------------------
 
 const headerIcon = (icon?: string) => (
@@ -443,52 +443,12 @@ function headerRenderer(props: TableHeaderProps) {
   );
 }
 
-// --------------------------------------------------------------------------
-// --- Table Rows
-// --------------------------------------------------------------------------
-
 const rowClassName =
   (selected?: number) =>
     ({ index }: { index: number }) =>
       (selected === index ? 'dome-color-selected' :
         (index & 1 ? 'dome-xTable-even' : 'dome-xTable-odd'));
 
-// --------------------------------------------------------------------------
-// --- Column Resizer
-// --------------------------------------------------------------------------
-
-const DRAGGING = 'dome-xTable-resizer dome-color-dragging';
-const DRAGZONE = 'dome-xTable-resizer dome-color-dragzone';
-
-interface ResizerProps {
-  id: number;
-  dragging: undefined | number;
-  left: string; // resized column-id on the left
-  right: string; // resized column-id on the right
-  offset: number; // drag-start offset
-  onStart: DraggableEventHandler;
-  onStop: DraggableEventHandler;
-  onDrag: (left: string, right: string, offset: number) => void;
-}
-
-const Resizer = (props: ResizerProps) => (
-  <DraggableCore
-    onStart={props.onStart}
-    onStop={props.onStop}
-    onDrag={(_elt, data) => props.onDrag(props.left, props.right, data.x - props.offset)}
-  >
-    <div
-      className={props.id === props.dragging ? DRAGGING : DRAGZONE}
-      style={{ left: props.offset - 2 }}
-    />
-  </DraggableCore>
-);
-
-const computeWidth = (elt: Element) => {
-  const parent = elt && elt.parentElement;
-  return parent && parent.getBoundingClientRect().width;
-};
-
 // --------------------------------------------------------------------------
 // --- Virtualized Table View
 // --------------------------------------------------------------------------
@@ -510,7 +470,6 @@ function makeTable<Key, Row>(
   const rowCount = (smallHeight ? itemCount + 1 : itemCount);
   const selection = props.selection;
   const selected = selection && model.getIndexOf(selection);
-  const resizers = null; // this.computeResizers(columns);
   const columns = makeColumns(state);
   return (
     <React.Fragment>
@@ -528,18 +487,93 @@ function makeTable<Key, Row>(
         headerHeight={CSS_HEADER_HEIGHT}
         headerRowRenderer={headerRowRenderer}
         onRowsRendered={state.watchRange}
-        onRowClick={onSelection && this.selectRow}
-        sortBy={ordering && ordering.sortBy}
-        sortDirection={ordering && ordering.sortDirection}
-        sort={model.setOrdering.bind(model)}
-        scrollToIndex={scrollToIndex}
+        onRowClick={undefined}
+        sortBy={undefined}
+        sortDirection={undefined}
+        sort={undefined}
+        scrollToIndex={undefined}
         scrollToAlignment='auto'
       >
         {columns}
       </VTable>
-      {resizers}
+      {/*resizers*/null}
     </React.Fragment>
   );
 };
 
 // --------------------------------------------------------------------------
+// --- Table View
+// --------------------------------------------------------------------------
+
+/**
+   Table View.
+
+   This component is base on [React-Virtualized
+   Tables](https://bvaughn.github.io/react-virtualized/#/components/Table),
+   offering a lazy, super-optimized rendering process that scales on huge
+   datasets.
+
+   A table shall be connected to an instance of
+   [[Model]] class to retrieve the data and
+   get informed of data updates.
+
+   The table columns shall be instances of
+   [[Column]] class.
+
+   Clicking on table headers trigger re-ordering callback on the model with the
+   expected column and direction, unless disabled _via_ the column
+   x   specification. However, actual sorting (and corresponding feedback on table
+   headers) would only take place if the model supports re-ordering and
+   eventually triggers a reload.
+
+   Right-clicking the table headers displays a popup-menu with actions to reset natural ordering,
+   reset column widths and select column visibility.
+
+   Tables do not control item selection state. Instead, you shall supply the selection
+   state and callback _via_ properties, like any other controlled React components.
+
+   Item selection can be based either on single-row or multiple-row. In case of
+   single-row selection (`multipleSelection:false`, the default), selection state
+   must be a single item or `undefined`, and the `onSelection` callback is called
+   with the same type of values.
+
+   In case of multiple-row selection (`multipleSelection:true`), the selection state
+   shall be an _array_ of items, and `onSelection` callback also. Single items are _not_
+   accepted, but `undefined` selection can be used in place of an empty array.
+
+   Clicking on a row triggers the `onSelection` callback with the updated selection.
+   In single-selection mode, the clicked item is sent to the callback. In
+   multiple-selection mode, key modifiers are taken into account for determining the new
+   slection. By default, the new selection only contains the clicked item. If the `Shift`
+   modifier has been pressed, the current selection is extended with a range of items
+   from the last selected one, to the newly selected one. If the `CtrlOrCmd` modifier
+   has been pressed, the selection is extended with the newly clicked item.
+   Clicking an already selected item with the `CtrlOrCmd` modifier removes it from
+   the current selection.
+
+ */
+
+export function Table<Key, Row>(props: TableProps<Key, Row>) {
+
+  const state = React.useMemo(() => new TableState<Row>(), []);
+  const [age, setAge] = React.useState(0);
+  React.useEffect(() => {
+    state.signal = () => setAge(age + 1);
+    state.setFetching(props.model);
+    state.setSorting(props.sorting);
+    state.setRendering(props.rendering);
+  });
+
+  return (
+    <div className='dome-xTable'>
+      <ColumnContext.Provider value={state}>
+        {props.children}
+      </ColumnContext.Provider>
+      <AutoSizer key='table'>
+        {(size: Size) => makeTable(size, props, state)}
+      </AutoSizer>
+    </div>
+  );
+}
+
+// --------------------------------------------------------------------------
-- 
GitLab