Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-empty-function": "warn",
"react/no-find-dom-node": "off",
"react/no-deprecated": "warn"
"react/no-deprecated": "warn",
"react/prop-types": "warn"
}
};
4,805 changes: 2,351 additions & 2,454 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "dynamictable",
"widgetName": "DynamicTable",
"version": "1.3.2",
"version": "1.3.3",
"description": "Dynamic (Tree) Table for Mendix",
"copyright": "Jelte Lagendijk 2019",
"author": "Jelte Lagendijk <jelte.lagendijk@mendix.com>",
Expand Down Expand Up @@ -32,7 +32,7 @@
},
"license": "Apache-2.0",
"devDependencies": {
"@mendix/pluggable-widgets-tools": "^8.6.0",
"@mendix/pluggable-widgets-tools": "8.6.0",
"@types/big.js": "^4.0.5",
"@types/classnames": "^2.2.9",
"@types/enzyme": "^3.1.10",
Expand Down
134 changes: 115 additions & 19 deletions src/DynamicTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ import {
entityIsPersistable
} from "@jeltemx/mendix-react-widget-utils";
import { createHelperObject } from "./util/helperobject";
import { getTitleFromObject, ClickCellType } from "./util/titlehelper";
import { TitleMethod } from "./store/objects/abstract/table-object";
import { getTitleFromObject, ClickCellType, getStaticTitleFromObject } from "./util/titlehelper";
import { TitleMethod, TableObjectGetOptions, StaticTitleMethod } from "./store/objects/abstract/table-object";
import { TableRecord } from "./util/table";
import { getObject } from "@jeltemx/mendix-react-widget-utils";
import { ValidateExtraProps, validateProps } from "./util/validation";
Expand Down Expand Up @@ -263,17 +263,52 @@ class DynamicTable extends Component<DynamicTableContainerProps> {
columnSortingAttribute
} = this.props;
if (axis === "row") {
this.store.setRows(objects, this.rowChildReference, this.hasChildAttr, parent, clean, {
const tableOptions: TableObjectGetOptions = {
classMethod: this.getClassMethod(rowClassAttr),
sortMethod: this.getSortMethod(rowSortingAttribute),
titleMethod: this.getTitleMethod(rowTitleType, rowTitleAttr, rowTitleNanoflow, "row")
});
sortMethod: this.getSortMethod(rowSortingAttribute)
};

if (rowTitleType === "attribute" && rowTitleAttr) {
tableOptions.staticTitleMethod = this.getTitleMethod(
rowTitleType,
rowTitleAttr,
rowTitleNanoflow,
"row"
) as StaticTitleMethod;
} else {
tableOptions.titleMethod = this.getTitleMethod(
rowTitleType,
rowTitleAttr,
rowTitleNanoflow,
"row"
) as TitleMethod;
}

this.store.setRows(objects, this.rowChildReference, this.hasChildAttr, parent, clean, tableOptions);
} else {
this.store.setColumns(objects, {
const tableOptions: TableObjectGetOptions = {
classMethod: this.getClassMethod(columnClassAttr),
sortMethod: this.getSortMethod(columnSortingAttribute),
titleMethod: this.getTitleMethod(columnTitleType, columnTitleAttr, columnTitleNanoflow, "column")
});
sortMethod: this.getSortMethod(columnSortingAttribute)
// titleMethod: this.getTitleMethod(columnTitleType, columnTitleAttr, columnTitleNanoflow, "column")
};

if (columnTitleType === "attribute" && columnTitleAttr) {
tableOptions.staticTitleMethod = this.getTitleMethod(
columnTitleType,
columnTitleAttr,
columnTitleNanoflow,
"column"
) as StaticTitleMethod;
} else {
tableOptions.titleMethod = this.getTitleMethod(
columnTitleType,
columnTitleAttr,
columnTitleNanoflow,
"column"
) as TitleMethod;
}

this.store.setColumns(objects, tableOptions);
}
}

Expand All @@ -282,11 +317,25 @@ class DynamicTable extends Component<DynamicTableContainerProps> {
attribute: string,
nanoflow: Nanoflow,
nodeType: NodeType = "unknown"
): TitleMethod {
): TitleMethod | StaticTitleMethod {
const renderAsHTML =
(this.props.rowRenderAsHTML && nodeType === "row") ||
(this.props.columnRenderAsHTML && nodeType === "column") ||
(this.props.entryRenderAsHTML && nodeType === "entry");

if (titleType === "attribute" && attribute) {
return (obj: mendix.lib.MxObject): ReactNode =>
getStaticTitleFromObject(obj, {
attribute,
executeAction: this.executeAction,
nanoflow,
titleType,
nodeType,
onClickMethod: () => this.clickTypeHandler(obj, nodeType, "single"),
onDoubleClickMethod: () => this.clickTypeHandler(obj, nodeType, "double"),
renderAsHTML
});
}
return (obj: mendix.lib.MxObject): Promise<ReactNode> =>
getTitleFromObject(obj, {
attribute,
Expand Down Expand Up @@ -486,10 +535,33 @@ class DynamicTable extends Component<DynamicTableContainerProps> {

if (entryObjects) {
if (setStore) {
this.store.setEntries(entryObjects, this.entryRowReference, this.entryColumnReference, clean, {
classMethod: this.getClassMethod(entryClassAttr),
titleMethod: this.getTitleMethod(entryTitleType, entryTitleAttr, entryTitleNanoflow, "entry")
});
const entriesOptions: TableObjectGetOptions = {
classMethod: this.getClassMethod(entryClassAttr)
};

if (entryTitleType === "attribute" && entryTitleAttr) {
entriesOptions.staticTitleMethod = this.getTitleMethod(
entryTitleType,
entryTitleAttr,
entryTitleNanoflow,
"entry"
) as StaticTitleMethod;
} else {
entriesOptions.titleMethod = this.getTitleMethod(
entryTitleType,
entryTitleAttr,
entryTitleNanoflow,
"entry"
) as TitleMethod;
}

this.store.setEntries(
entryObjects,
this.entryRowReference,
this.entryColumnReference,
clean,
entriesOptions
);
} else {
return entryObjects;
}
Expand Down Expand Up @@ -541,10 +613,34 @@ class DynamicTable extends Component<DynamicTableContainerProps> {
const entries = await this.entriesLoad(guids, false);
if (entries) {
const { entryTitleType, entryTitleAttr, entryTitleNanoflow, entryClassAttr } = this.props;
this.store.setEntries(entries, this.entryRowReference, this.entryColumnReference, false, {
classMethod: this.getClassMethod(entryClassAttr),
titleMethod: this.getTitleMethod(entryTitleType, entryTitleAttr, entryTitleNanoflow, "entry")
});

const entriesOptions: TableObjectGetOptions = {
classMethod: this.getClassMethod(entryClassAttr)
};

if (entryTitleType === "attribute" && entryTitleAttr) {
entriesOptions.staticTitleMethod = this.getTitleMethod(
entryTitleType,
entryTitleAttr,
entryTitleNanoflow,
"entry"
) as StaticTitleMethod;
} else {
entriesOptions.titleMethod = this.getTitleMethod(
entryTitleType,
entryTitleAttr,
entryTitleNanoflow,
"entry"
) as TitleMethod;
}

this.store.setEntries(
entries,
this.entryRowReference,
this.entryColumnReference,
false,
entriesOptions
);
}
}
this.store.setLoading(false);
Expand Down
6 changes: 3 additions & 3 deletions src/DynamicTable.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
<propertyGroup caption="UI Title">
<property key="rowTitleType" type="enumeration" defaultValue="attribute">
<caption>Row Title Type</caption>
<description></description>
<description>Warning: When rendering large datasets, it is advised to only use an Attribute, not a Nanoflow. Using a Nanoflow for your title slows down the rendering of the table.</description>
<enumerationValues>
<enumerationValue key="attribute">Attribute</enumerationValue>
<enumerationValue key="nanoflow">Nanoflow</enumerationValue>
Expand Down Expand Up @@ -204,7 +204,7 @@
<propertyGroup caption="UI Title">
<property key="columnTitleType" type="enumeration" defaultValue="attribute">
<caption>Column Title Type</caption>
<description></description>
<description>Warning: When rendering large datasets, it is advised to only use an Attribute, not a Nanoflow. Using a Nanoflow for your title slows down the rendering of the table.</description>
<enumerationValues>
<enumerationValue key="attribute">Attribute</enumerationValue>
<enumerationValue key="nanoflow">Nanoflow</enumerationValue>
Expand Down Expand Up @@ -280,7 +280,7 @@
<propertyGroup caption="UI Title">
<property key="entryTitleType" type="enumeration" defaultValue="attribute">
<caption>Entry Title Type</caption>
<description></description>
<description>Warning: When rendering large datasets, it is advised to only use an Attribute, not a Nanoflow. Using a Nanoflow for your title slows down the rendering of the table.</description>
<enumerationValues>
<enumerationValue key="attribute">Attribute</enumerationValue>
<enumerationValue key="nanoflow">Nanoflow</enumerationValue>
Expand Down
20 changes: 9 additions & 11 deletions src/components/DynamicTreeTableContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ export class DynamicTreeTableContainer extends Component<DynamicTreeTableContain

render(): ReactNode {
const { selectMode, clickToSelect, store, hideSelectBoxes, className, ui } = this.props;
const { tableColumns, tableRows, isLoading, selectedRowsIds, width } = store;

const { removeValidationMessage, validationMessages } = store;
const removeValidation = removeValidationMessage.bind(store);
const removeValidation = store.removeValidationMessage.bind(store);

const clearDebounce = (): void => {
if (this.debounce !== null) {
Expand All @@ -58,7 +56,7 @@ export class DynamicTreeTableContainer extends Component<DynamicTreeTableContain
this.debounce = window.setTimeout(() => {
// this.onRowClick(record);
if (selectMode && selectMode !== "none" && clickToSelect) {
const selected = [...selectedRowsIds];
const selected = [...store.selectedRowsIds];
const findKey = selected.findIndex(s => s === record.key);
const isSelected = findKey !== -1;
if (isSelected && selectMode === "single") {
Expand Down Expand Up @@ -89,14 +87,14 @@ export class DynamicTreeTableContainer extends Component<DynamicTreeTableContain
if (selectMode && selectMode !== "none") {
rowSelection = {
type: "checkbox",
selectedRowKeys: selectedRowsIds,
selectedRowKeys: store.selectedRowsIds,
onChange: (keys: string[]): void => {
if (selectMode === "multi") {
store.setSelected(keys);
}
},
onSelectAll: (): void => {
if (selectMode === "single" && selectedRowsIds.length > 0) {
if (selectMode === "single" && store.selectedRowsIds.length > 0) {
store.setSelected([]);
}
},
Expand Down Expand Up @@ -128,15 +126,15 @@ export class DynamicTreeTableContainer extends Component<DynamicTreeTableContain
heightUnit={ui.settingsHeightUnit}
>
<Table
columns={this.getColumns(tableColumns)}
dataSource={tableRows}
loading={isLoading}
columns={this.getColumns(store.tableColumns)}
dataSource={store.tableRows}
loading={store.isLoading}
onExpand={this.onExpand}
onRow={onRow}
rowSelection={rowSelection}
pagination={false}
rowClassName={this.onRowClassName}
scroll={{ x: width || true, y: scrollY }}
scroll={{ x: store.width || true, y: scrollY }}
size="small"
/>
<ReactResizeDetector
Expand All @@ -157,7 +155,7 @@ export class DynamicTreeTableContainer extends Component<DynamicTreeTableContain
className
)}
>
<Alerts validationMessages={validationMessages} remove={removeValidation} />
<Alerts validationMessages={store.validationMessages} remove={removeValidation} />
{containerIfNotDisabled}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/package.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<package xmlns="http://www.mendix.com/package/1.0/">
<clientModule name="DynamicTable" version="1.3.2" xmlns="http://www.mendix.com/clientModule/1.0/">
<clientModule name="DynamicTable" version="1.3.3" xmlns="http://www.mendix.com/clientModule/1.0/">
<widgetFiles>
<widgetFile path="DynamicTable.xml"/>
</widgetFiles>
Expand Down
20 changes: 17 additions & 3 deletions src/store/objects/abstract/table-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { computed, flow, observable, action } from "mobx";
import { ReactNode } from "react";

export type TitleMethod = ((obj: mendix.lib.MxObject) => Promise<ReactNode | string>) | null;
export type StaticTitleMethod = ((obj: mendix.lib.MxObject) => ReactNode | string) | null;
export type SortMethod = ((obj: mendix.lib.MxObject) => string | number | null) | null;
export type ClassMethod = ((obj: mendix.lib.MxObject) => string) | null;

export interface TableObjectGetOptions {
titleMethod?: TitleMethod;
staticTitleMethod?: StaticTitleMethod;
classMethod?: ClassMethod;
sortMethod?: SortMethod;
}
Expand All @@ -15,6 +17,7 @@ export interface TableObjectOptions {
mxObject: mendix.lib.MxObject;
changeHandler?: (guid?: string, removedCb?: (removed: boolean) => void) => void | Promise<void>;
getMethods: TableObjectGetOptions;
title?: string;
}

export class TableObject {
Expand All @@ -24,6 +27,7 @@ export class TableObject {
public _changeHandler: (guid?: string, removedCb?: (removed: boolean) => void) => void;

public _titleMethod: TitleMethod;
public _staticTitleMethod: StaticTitleMethod;
public _classMethod: ClassMethod;
public _sortMethod: SortMethod;

Expand All @@ -40,13 +44,14 @@ export class TableObject {

constructor(opts: TableObjectOptions) {
const { mxObject, changeHandler, getMethods } = opts;
const { titleMethod, classMethod, sortMethod } = getMethods;
const { titleMethod, staticTitleMethod, classMethod, sortMethod } = getMethods;
this._obj = mxObject;

this._title = "";
this._title = opts.title || "";
this._sortKey = null;
this._class = "";
this._titleMethod = titleMethod || null;
this._staticTitleMethod = staticTitleMethod || null;
this._classMethod = classMethod || null;
this._sortMethod = sortMethod || null;
this._changeHandler = changeHandler || ((): void => {});
Expand All @@ -58,6 +63,9 @@ export class TableObject {

if (titleMethod) {
this.fixTitle();
} else if (staticTitleMethod) {
// @ts-ignore
this._title = staticTitleMethod(mxObject);
}

if (classMethod) {
Expand Down Expand Up @@ -111,7 +119,13 @@ export class TableObject {
window.logger.debug(`Removed: ${this._type} || ${guid}`);
}
} else {
this.fixTitle();
if (this._titleMethod) {
this.fixTitle();
} else if (this._staticTitleMethod) {
// @ts-ignore
this._title = this._staticTitleMethod(this._obj);
}

this.fixSorting();
this.fixClass();
}
Expand Down
Loading