From 9508c5da088be36b16288a680e7dfc076440d347 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Wed, 18 May 2022 14:22:00 +0200
Subject: [PATCH] [dome] more types in dome/table

---
 ivette/src/dome/renderer/table/arrays.ts |  56 ++++-----
 ivette/src/dome/renderer/table/views.tsx | 140 +++++++++++++----------
 2 files changed, 105 insertions(+), 91 deletions(-)

diff --git a/ivette/src/dome/renderer/table/arrays.ts b/ivette/src/dome/renderer/table/arrays.ts
index 4d084ff3f17..82b0ff01c9f 100644
--- a/ivette/src/dome/renderer/table/arrays.ts
+++ b/ivette/src/dome/renderer/table/arrays.ts
@@ -20,8 +20,6 @@
 /*                                                                          */
 /* ************************************************************************ */
 
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
-
 // --------------------------------------------------------------------------
 // --- Array Models
 // --------------------------------------------------------------------------
@@ -64,8 +62,8 @@ function orderBy<K, R>(
   const byData = columns[dataKey] ?? Compare.equal;
   const rv = ord.sortDirection === 'DESC';
   type D = PACK<K, R>;
-  const byEntry = (x: D, y: D) => byData(x.row, y.row);
-  const byIndex = (x: D, y: D) => (x.index ?? 0) - (y.index ?? 0);
+  const byEntry = (x: D, y: D): number => byData(x.row, y.row);
+  const byIndex = (x: D, y: D): number => (x.index ?? 0) - (y.index ?? 0);
   return Compare.direction(Compare.sequence(byEntry, byIndex), rv);
 }
 
@@ -165,20 +163,20 @@ export class ArrayModel<Key, Row>
   // --------------------------------------------------------------------------
 
   /** Non filtered. */
-  getTotalRowCount() { return this.getRowCount() + this.filtered; }
+  getTotalRowCount(): number { return this.getRowCount() + this.filtered; }
 
-  getRowCount() { return this.rebuild().length; }
+  getRowCount(): number { return this.rebuild().length; }
 
-  getRowAt(k: number) { return this.rebuild()[k]?.row; }
+  getRowAt(k: number): Row { return this.rebuild()[k]?.row; }
 
-  getKeyAt(k: number) {
+  getKeyAt(k: number): Key | undefined {
     const current = this.table;
     return current ? current[k]?.key : undefined;
   }
 
-  getKeyFor(k: number, _: Row) { return this.getKeyAt(k); }
+  getKeyFor(k: number, _: Row): Key | undefined { return this.getKeyAt(k); }
 
-  getIndexOf(key: Key) {
+  getIndexOf(key: Key): number | undefined {
     const pack = this.index.get(key);
     if (!pack) return undefined;
     const k = pack.index;
@@ -197,7 +195,7 @@ export class ArrayModel<Key, Row>
       [[setNaturalOrder]] in response to user column selection with
       [[setSorting]] provided you enable by-column sorting from the table view.
       Finally triggers a reload. */
-  setColumnOrder(columns?: ByColumns<Row>) {
+  setColumnOrder(columns?: ByColumns<Row>): void {
     this.columns = { ...this.columns, ...columns };
     this.reload();
   }
@@ -207,7 +205,7 @@ export class ArrayModel<Key, Row>
       primary ordering can be refined in response to user column selection with
       [[setSorting]] provided you enable by-column sorting from the table view.
       Finally triggers a reload. */
-  setNaturalOrder(order?: Order<Row>) {
+  setNaturalOrder(order?: Order<Row>): void {
     this.natural = order;
     this.reload();
   }
@@ -217,7 +215,7 @@ export class ArrayModel<Key, Row>
      orders by fields. This is a combination of [[setColumnOrder]] and
      [[setNaturalOrder]] with [[dome/data/compare.byFields]].
    */
-  setOrderingByFields(byfields: ByFields<Row>) {
+  setOrderingByFields(byfields: ByFields<Row>): void {
     this.natural = Compare.byFields(byfields);
     const columns = this.columns ?? {};
     const keys = Object.keys(byfields);
@@ -240,7 +238,7 @@ export class ArrayModel<Key, Row>
   /**
      Remove the sorting function for the provided column.
    */
-  deleteColumnOrder(dataKey: string) {
+  deleteColumnOrder(dataKey: string): void {
     const { columns } = this;
     if (columns) delete columns[dataKey];
     this.ring = this.ring.filter((ord) => ord.sortBy !== dataKey);
@@ -250,7 +248,7 @@ export class ArrayModel<Key, Row>
   /** Reorder rows with the provided column and direction.
       Previous ordering is kept and refined by the new one.
       Use `undefined` or `null` to reset the natural ordering. */
-  setSorting(ord?: undefined | null | SortingInfo) {
+  setSorting(ord?: undefined | null | SortingInfo): void {
     if (ord) {
       const { ring } = this;
       const cur = ring[0];
@@ -284,7 +282,7 @@ export class ArrayModel<Key, Row>
   // --- Filtering
   // --------------------------------------------------------------------------
 
-  setFilter(fn?: Filter<Key, Row>) {
+  setFilter(fn?: Filter<Key, Row>): void {
     const phi = this.filter;
     if (phi !== fn) {
       this.filter = fn;
@@ -297,7 +295,7 @@ export class ArrayModel<Key, Row>
   // --------------------------------------------------------------------------
 
   /** Trigger a complete reload of the table. */
-  reload() {
+  reload(): void {
     this.array = undefined;
     this.table = undefined;
     this.order = undefined;
@@ -305,7 +303,7 @@ export class ArrayModel<Key, Row>
   }
 
   /** Remove all data and reload. */
-  clear() {
+  clear(): void {
     this.index.clear();
     this.reload();
   }
@@ -370,7 +368,7 @@ export class ArrayModel<Key, Row>
      @param key - the entry identifier
      @param row - new value of `null` for removal
    */
-  update(key: Key, row?: undefined | null | Row) {
+  update(key: Key, row?: undefined | null | Row): void {
     if (row === undefined) return;
     const pack = this.index.get(key);
     let doReload = false;
@@ -406,7 +404,7 @@ export class ArrayModel<Key, Row>
      Modification will be only visible after a final [[reload]].
      Useful for a large number of batched updates.
   */
-  removeAllData() {
+  removeAllData(): void {
     this.index.clear();
   }
 
@@ -416,7 +414,7 @@ export class ArrayModel<Key, Row>
      Useful for a large number of batched updates.
      @param key - the removed entry.
    */
-  removeData(keys: Collection<Key>) {
+  removeData(keys: Collection<Key>): void {
     forEach(keys, (k) => this.index.delete(k));
   }
 
@@ -427,7 +425,7 @@ export class ArrayModel<Key, Row>
      @param key - the entry to update.
      @param row - the new row data or `null` for removal.
    */
-  setData(key: Key, row: null | Row) {
+  setData(key: Key, row: null | Row): void {
     if (row !== null) {
       this.index.set(key, { key, row, index: undefined });
     } else {
@@ -471,19 +469,21 @@ export class CompactModel<Key, Row> extends ArrayModel<Key, Row> {
   }
 
   /** Use the key getter directly. */
-  getKeyFor(_: number, data: Row) { return this.getkey(data); }
+  getKeyFor(_: number, data: Row): Key | undefined { return this.getkey(data); }
 
-  /** Silently add or update a collection of data.
-      Requires a final trigger to update views. */
-  updateData(data: Collection<Row>) {
+  /**
+     Silently add or update a collection of data.
+     Requires a final trigger to update views.
+  */
+  updateData(data: Collection<Row>): void {
     forEach(data, (row: Row) => this.setData(this.getkey(row), row));
   }
 
   /**
      Replace all previous data with the new ones.
      Finally triggers a reload.
-   */
-  replaceAllDataWith(data: Collection<Row>) {
+  */
+  replaceAllDataWith(data: Collection<Row>): void {
     this.removeAllData();
     this.updateData(data);
     this.reload();
diff --git a/ivette/src/dome/renderer/table/views.tsx b/ivette/src/dome/renderer/table/views.tsx
index 128b6404dd6..9277450ebf6 100644
--- a/ivette/src/dome/renderer/table/views.tsx
+++ b/ivette/src/dome/renderer/table/views.tsx
@@ -20,7 +20,6 @@
 /*                                                                          */
 /* ************************************************************************ */
 
-/* eslint-disable @typescript-eslint/explicit-function-return-type */
 /* eslint-disable @typescript-eslint/no-explicit-any */
 
 // --------------------------------------------------------------------------
@@ -218,7 +217,7 @@ type Cprops = ColProps<any>;
 // --- Column Utilities
 // --------------------------------------------------------------------------
 
-const isVisible = (visible: Cmap<boolean>, col: Cprops) => {
+const isVisible = (visible: Cmap<boolean>, col: Cprops): boolean => {
   const defaultVisible = col.visible ?? true;
   switch (defaultVisible) {
     case 'never': return false;
@@ -228,12 +227,12 @@ const isVisible = (visible: Cmap<boolean>, col: Cprops) => {
   }
 };
 
-const defaultGetter = (row: any, dataKey: string) => {
+const defaultGetter = (row: any, dataKey: string): any => {
   if (typeof row === 'object') return row[dataKey];
   return undefined;
 };
 
-const defaultRenderer = (d: any) => (
+const defaultRenderer = (d: any): JSX.Element => (
   <div className="dome-xTable-renderer dome-text-label">
     {String(d)}
   </div>
@@ -271,7 +270,7 @@ function makeDataRenderer(
     try {
       const contents = cellData ? render(cellData) : null;
       if (onContextMenu) {
-        const callback = (evt: React.MouseEvent) => {
+        const callback = (evt: React.MouseEvent): void => {
           evt.stopPropagation();
           onContextMenu(props.rowData, props.rowIndex, props.dataKey);
         };
@@ -354,28 +353,28 @@ class TableState<Key, Row> {
 
   // --- Static Callbacks
 
-  unwind() {
+  unwind(): void {
     this.signal = undefined;
     this.onSelection = undefined;
     this.onContextMenu = undefined;
   }
 
-  forceUpdate() {
+  forceUpdate(): void {
     const s = this.signal;
     if (s) { this.signal = undefined; s(); }
   }
 
-  updateGrid() {
+  updateGrid(): void {
     this.tableRef.current?.forceUpdateGrid();
   }
 
-  fullReload() {
+  fullReload(): void {
     this.scrolledKey = undefined;
     this.forceUpdate();
     this.updateGrid();
   }
 
-  getRef(id: string) {
+  getRef(id: string): divRef {
     const href = this.headerRef.get(id);
     if (href) return href;
     const nref: divRef = React.createRef();
@@ -394,13 +393,13 @@ class TableState<Key, Row> {
     return cw;
   }
 
-  startResizing(idx: number) {
+  startResizing(idx: number): void {
     this.resizing = idx;
     this.offset = 0;
     this.forceUpdate();
   }
 
-  stopResizing() {
+  stopResizing(): void {
     this.resizing = undefined;
     this.offset = undefined;
     this.columnWith.clear();
@@ -408,7 +407,7 @@ class TableState<Key, Row> {
   }
 
   // Debounced
-  setResizeOffset(lcol: string, rcol: string, offset: number) {
+  setResizeOffset(lcol: string, rcol: string, offset: number): void {
     const colws = this.columnWith;
     const cwl = colws.get(lcol);
     const cwr = colws.get(rcol);
@@ -425,7 +424,7 @@ class TableState<Key, Row> {
 
   // --- Table settings
 
-  updateSettings() {
+  updateSettings(): void {
     const userSettings = this.settings;
     if (userSettings) {
       const cws: Json.dict<number> = {};
@@ -444,7 +443,7 @@ class TableState<Key, Row> {
     this.forceUpdate();
   }
 
-  importSettings(settings?: string) {
+  importSettings(settings?: string): void {
     if (settings !== this.settings) {
       this.settings = settings;
       const { resize } = this;
@@ -467,7 +466,7 @@ class TableState<Key, Row> {
 
   // --- User Table properties
 
-  setSorting(sorting?: Sorting) {
+  setSorting(sorting?: Sorting): void {
     const info = sorting?.getSorting();
     this.sortBy = info?.sortBy;
     this.sortDirection = info?.sortDirection;
@@ -477,7 +476,7 @@ class TableState<Key, Row> {
     }
   }
 
-  setModel(model?: Model<Key, Row>) {
+  setModel(model?: Model<Key, Row>): void {
     if (model !== this.model) {
       this.client?.unlink();
       this.model = model;
@@ -494,7 +493,7 @@ class TableState<Key, Row> {
     }
   }
 
-  setRendering(rendering?: RenderByFields<Row>) {
+  setRendering(rendering?: RenderByFields<Row>): void {
     if (rendering !== this.rendering) {
       this.rendering = rendering;
       this.render.clear();
@@ -506,7 +505,7 @@ class TableState<Key, Row> {
 
   onSelection?: (data: Row, key: Key, index: number) => void;
 
-  onRowClick(info: RowMouseEventHandlerParams) {
+  onRowClick(info: RowMouseEventHandlerParams): void {
     const { index } = info;
     const data = info.rowData as (Row | undefined);
     const { model } = this;
@@ -517,7 +516,7 @@ class TableState<Key, Row> {
       onSelection(data, key, index);
   }
 
-  onRowsRendered(info: IndexRange) {
+  onRowsRendered(info: IndexRange): void {
     this.range = info;
     this.client?.watch(info.startIndex, info.stopIndex);
   }
@@ -527,7 +526,7 @@ class TableState<Key, Row> {
     return (index & 1 ? 'dome-xTable-even' : 'dome-xTable-odd'); // eslint-disable-line no-bitwise
   }
 
-  keyStepper(index: number) {
+  keyStepper(index: number): void {
     const { onSelection } = this;
     const key = this.model?.getKeyAt(index);
     const data = this.model?.getRowAt(index);
@@ -546,7 +545,7 @@ class TableState<Key, Row> {
     return undefined;
   }
 
-  onSorting(ord?: SortingInfo) {
+  onSorting(ord?: SortingInfo): void {
     const { sorting } = this;
     if (sorting) {
       sorting.setSorting(ord);
@@ -558,7 +557,7 @@ class TableState<Key, Row> {
 
   // ---- Row Events
 
-  onRowRightClick({ event, rowData, index }: RowMouseEventHandlerParams) {
+  onRowRightClick({ event, rowData, index }: RowMouseEventHandlerParams): void {
     const callback = this.onContextMenu;
     if (callback) {
       event.stopPropagation();
@@ -566,7 +565,7 @@ class TableState<Key, Row> {
     }
   }
 
-  onKeyDown(evt: React.KeyboardEvent) {
+  onKeyDown(evt: React.KeyboardEvent): void {
     const index = this.selectedIndex;
     switch (evt.key) {
       case 'ArrowUp':
@@ -586,7 +585,7 @@ class TableState<Key, Row> {
 
   // ---- Header Context Menu
 
-  onHeaderMenu() {
+  onHeaderMenu(): void {
     let hasOrder = false;
     let hasResize = false;
     let hasVisible = false;
@@ -598,11 +597,11 @@ class TableState<Key, Row> {
       if (col.visible !== 'never' && col.visible !== 'always')
         hasVisible = true;
     });
-    const resetSizing = () => {
+    const resetSizing = (): void => {
       this.resize.clear();
       this.updateSettings();
     };
-    const resetColumns = () => {
+    const resetColumns = (): void => {
       this.visible.clear();
       this.resize.clear();
       this.updateSettings();
@@ -633,7 +632,7 @@ class TableState<Key, Row> {
         default: {
           const { id, label, title } = col;
           const checked = isVisible(visible, col);
-          const onClick = () => {
+          const onClick = (): void => {
             visible.set(id, !checked);
             this.updateSettings();
           };
@@ -646,7 +645,11 @@ class TableState<Key, Row> {
 
   // --- Getter & Setters
 
-  computeGetter(id: string, dataKey: string, props: Cprops) {
+  computeGetter(
+    id: string,
+    dataKey: string,
+    props: Cprops
+  ): TableCellDataGetter {
     const current = this.getter.get(id);
     if (current) return current;
     const dataGetter = makeDataGetter(dataKey, props.getter);
@@ -654,7 +657,11 @@ class TableState<Key, Row> {
     return dataGetter;
   }
 
-  computeRender(id: string, dataKey: string, props: Cprops) {
+  computeRender(
+    id: string,
+    dataKey: string,
+    props: Cprops
+  ): TableCellRenderer {
     const current = this.render.get(id);
     if (current) return current;
     let renderer = props.render;
@@ -671,7 +678,7 @@ class TableState<Key, Row> {
 
   private registry = new Map<string, null | ColProps<Row>>();
 
-  setRegistry(id: string, props: null | ColProps<Row>) {
+  setRegistry(id: string, props: null | ColProps<Row>): void {
     this.registry.set(id, props);
     this.rebuild();
   }
@@ -688,7 +695,7 @@ class TableState<Key, Row> {
     return () => this.setRegistry(id, null);
   }
 
-  rebuild() {
+  rebuild(): void {
     const current = this.columns;
     const cols: ColProps<Row>[] = [];
     this.registry.forEach((col) => col && cols.push(col));
@@ -715,10 +722,13 @@ const ColumnContext = React.createContext<undefined | ColumnIndex>(undefined);
 
 /**
    Table Column.
+
    @template Row - table row data of some table entries
    @template Cell - type of cell data to render in this column
  */
-export function Column<Row, Cell>(props: ColumnProps<Row, Cell>) {
+export function Column<Row, Cell>(
+  props: ColumnProps<Row, Cell>
+): JSX.Element | null {
   const context = React.useContext(ColumnContext);
   React.useEffect(() => {
     if (context) {
@@ -733,8 +743,8 @@ function spawnIndex(
   state: TableState<any, any>,
   path: number[],
   children: React.ReactElement | React.ReactElement[],
-) {
-  const indexChild = (elt: React.ReactElement, k: number) => (
+): JSX.Element {
+  const indexChild = (elt: React.ReactElement, k: number): JSX.Element => (
     <ColumnContext.Provider value={{ state, path, index: k }}>
       {elt}
     </ColumnContext.Provider>
@@ -790,7 +800,7 @@ export interface ColumnGroupProps {
    this implicit root column group, just pack your columns inside a classical
    React fragment: `<Table … ><>{children}</></Table>`.
  */
-export function ColumnGroup(props: ColumnGroupProps) {
+export function ColumnGroup(props: ColumnGroupProps): JSX.Element | null {
   const context = React.useContext(ColumnContext);
   if (!context) return null;
   const { state, path, index: defaultIndex } = context;
@@ -807,7 +817,7 @@ function makeColumn<Key, Row>(
   state: TableState<Key, Row>,
   props: ColProps<Row>,
   fill: boolean,
-) {
+): JSX.Element {
   const { id } = props;
   const align = { textAlign: props.align };
   const dataKey = props.dataKey ?? id;
@@ -842,7 +852,7 @@ function makeColumn<Key, Row>(
   );
 }
 
-const byIndex = (a: Cprops, b: Cprops) => {
+const byIndex = (a: Cprops, b: Cprops): number => {
   const ak = a.index ?? 0;
   const bk = b.index ?? 0;
   if (ak < bk) return -1;
@@ -850,7 +860,7 @@ const byIndex = (a: Cprops, b: Cprops) => {
   return 0;
 };
 
-function makeCprops<Key, Row>(state: TableState<Key, Row>) {
+function makeCprops<Key, Row>(state: TableState<Key, Row>): Cprops[] {
   const cols: Cprops[] = [];
   state.columns.forEach((col) => {
     if (col && isVisible(state.visible, col)) {
@@ -861,7 +871,10 @@ function makeCprops<Key, Row>(state: TableState<Key, Row>) {
   return cols;
 }
 
-function makeColumns<Key, Row>(state: TableState<Key, Row>, cols: Cprops[]) {
+function makeColumns<Key, Row>(
+  state: TableState<Key, Row>,
+  cols: Cprops[]
+): JSX.Element[] {
   let fill: undefined | Cprops;
   let lastExt: undefined | Cprops;
   cols.forEach((col) => {
@@ -877,25 +890,25 @@ function makeColumns<Key, Row>(state: TableState<Key, Row>, cols: Cprops[]) {
 // --- Table Utility Renderers
 // --------------------------------------------------------------------------
 
-const headerIcon = (icon?: string) => (
-  icon &&
-  (
-    <div className="dome-xTable-header-icon">
-      <SVG id={icon} />
-    </div>
-  )
+const headerIcon = (icon?: string): JSX.Element | null => (
+  icon ?
+    (
+      <div className="dome-xTable-header-icon">
+        <SVG id={icon} />
+      </div>
+    ) : null
 );
 
-const headerLabel = (label?: string) => (
-  label &&
-  (
-    <label className="dome-xTable-header-label dome-text-label">
-      {label}
-    </label>
-  )
+const headerLabel = (label?: string): JSX.Element | null => (
+  label ?
+    (
+      <label className="dome-xTable-header-label dome-text-label">
+        {label}
+      </label>
+    ) : null
 );
 
-const makeSorter = (id: string) => (
+const makeSorter = (id: string): JSX.Element => (
   <div className="dome-xTable-header-sorter">
     <SVG id={id} size={8} />
   </div>
@@ -904,7 +917,7 @@ const makeSorter = (id: string) => (
 const sorterASC = makeSorter('ANGLE.UP');
 const sorterDESC = makeSorter('ANGLE.DOWN');
 
-function headerRowRenderer(props: TableHeaderRowProps) {
+function headerRowRenderer(props: TableHeaderRowProps): JSX.Element {
   return (
     <div
       role="row"
@@ -916,7 +929,7 @@ function headerRowRenderer(props: TableHeaderRowProps) {
   );
 }
 
-function headerRenderer(props: TableHeaderProps) {
+function headerRenderer(props: TableHeaderProps): JSX.Element {
   const data: ColumnData = props.columnData;
   const { sortBy, sortDirection, dataKey } = props;
   const { icon, label, title, headerRef, headerMenu } = data;
@@ -954,7 +967,7 @@ interface ResizerProps {
   onDrag: (offset: number) => void;
 }
 
-const Resizer = (props: ResizerProps) => (
+const Resizer = (props: ResizerProps): JSX.Element => (
   <DraggableCore
     onStart={props.onStart}
     onStop={props.onStop}
@@ -1003,9 +1016,10 @@ function makeResizers(
       const lcol = b.left;
       const offset = state.offset ?? 0;
       const dragging = state.resizing === index;
-      const onStart = () => state.startResizing(index);
-      const onStop = () => state.stopResizing();
-      const onDrag = (ofs: number) => state.setResizeOffset(lcol, rcol, ofs);
+      const onStart = (): void => state.startResizing(index);
+      const onStop = (): void => state.stopResizing();
+      const onDrag =
+        (ofs: number): void => state.setResizeOffset(lcol, rcol, ofs);
       const resizer = (
         <Resizer
           key={index}
@@ -1036,7 +1050,7 @@ function makeTable<Key, Row>(
   props: TableProps<Key, Row>,
   state: TableState<Key, Row>,
   size: Size,
-) {
+): JSX.Element {
 
   const { width, height } = size;
   const { model } = props;
@@ -1121,7 +1135,7 @@ function makeTable<Key, Row>(
    @template Row - data associated to each key in the table entries.
  */
 
-export function Table<Key, Row>(props: TableProps<Key, Row>) {
+export function Table<Key, Row>(props: TableProps<Key, Row>): JSX.Element {
 
   const state = React.useMemo(() => new TableState<Key, Row>(), []);
   const [age, setAge] = React.useState(0);
-- 
GitLab