@topconsultnpm/sdkui-react-beta 6.10.13 → 6.10.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ export declare enum CounterItemKey {
2
+ visibleItems = "visibleItems",
3
+ selectedItems = "selectedItems"
4
+ }
5
+ export interface ITMCounterItemData {
6
+ key?: string;
7
+ show: boolean;
8
+ caption?: string;
9
+ icon?: JSX.Element;
10
+ value?: number | string;
11
+ order?: number;
12
+ }
13
+ export interface ITMCounterContainerProps {
14
+ show?: boolean;
15
+ items?: Map<string, ITMCounterItemData>;
16
+ bgColorContainer?: string;
17
+ bgColorItem?: string;
18
+ textColorItem?: string;
19
+ hoverColorItem?: string;
20
+ }
21
+ declare const TMCounterContainer: (props: ITMCounterContainerProps) => import("react/jsx-runtime").JSX.Element | undefined;
22
+ export default TMCounterContainer;
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styled from "styled-components";
3
+ import TMTooltip from './TMTooltip';
4
+ /* Styled container component that holds all counter items */
5
+ const Container = styled.div `
6
+ background: ${({ bgColor }) => bgColor || 'linear-gradient(to right, #f8f9fa, #e9ecef)'};
7
+ display: flex;
8
+ align-items: center;
9
+ width: 100%;
10
+ padding: 4px 8px;
11
+ box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.1);
12
+ gap: 8px;
13
+ `;
14
+ /* Styled counter item component with customizable styles */
15
+ const Counter = styled.div `
16
+ display: flex;
17
+ align-items: center;
18
+ border-right: 1px solid rgba(211, 211, 211, 0.5);
19
+ padding: 4px 10px;
20
+ gap: 8px;
21
+ transition: all 0.3s ease-in-out;
22
+ cursor: pointer;
23
+ background: ${({ color }) => color || 'rgba(255, 255, 255, 0.6)'};
24
+
25
+ &:hover {
26
+ background: ${({ hoverColor }) => hoverColor || '#ff9800'};
27
+ transform: translateY(-2px);
28
+ box-shadow: 0px 5px 12px rgba(0, 0, 0, 0.15);
29
+
30
+ svg, span {
31
+ color: #fff;
32
+ }
33
+ }
34
+
35
+ &:last-child {
36
+ border-right: none;
37
+ }
38
+
39
+ svg {
40
+ color: ${({ textColor }) => textColor || '#495057'};
41
+ transition: color 0.3s ease-in-out;
42
+ }
43
+
44
+ span {
45
+ color: ${({ textColor }) => textColor || '#495057'};
46
+ transition: color 0.3s ease-in-out;
47
+ }
48
+ `;
49
+ /* Enum for possible counter item keys */
50
+ export var CounterItemKey;
51
+ (function (CounterItemKey) {
52
+ /* Key for visible item count */
53
+ CounterItemKey["visibleItems"] = "visibleItems";
54
+ /* Key for selected item count */
55
+ CounterItemKey["selectedItems"] = "selectedItems";
56
+ })(CounterItemKey || (CounterItemKey = {}));
57
+ ;
58
+ ;
59
+ const TMCounterContainer = (props) => {
60
+ const { items, bgColorContainer, hoverColorItem, bgColorItem, textColorItem } = props;
61
+ return (items && _jsx(Container, { bgColor: bgColorContainer, children: [...items.values()].map((item) => {
62
+ if (!item.show)
63
+ return null;
64
+ return _jsx(TMTooltip, { content: item.caption ?? '', children: _jsxs(Counter, { bgColor: bgColorContainer, color: bgColorItem, hoverColor: hoverColorItem, textColor: textColorItem, children: [item.icon ?? null, _jsx("span", { children: item.value?.toString() ?? '' })] }) }, item.key ?? '');
65
+ }) }));
66
+ };
67
+ export default TMCounterContainer;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { IColumnProps, IDataGridOptions } from 'devextreme-react/data-grid';
3
+ import dxDataGrid from 'devextreme/ui/data_grid';
4
+ import { ITMCounterContainerProps } from './TMCounterContainer';
5
+ export interface TMDataGridContextMenuItem {
6
+ text: string;
7
+ icon: string;
8
+ onClick?: (param?: any) => void;
9
+ operationType?: 'singleRow' | 'multiRow';
10
+ disabled?: boolean;
11
+ id?: string;
12
+ items?: Array<TMDataGridContextMenuItem>;
13
+ beginGroup?: boolean;
14
+ }
15
+ export declare enum TMDataGridPageSize {
16
+ Small = 30,
17
+ Medium = 50,
18
+ Large = 100
19
+ }
20
+ export interface TMDataGridProps<T> extends IDataGridOptions {
21
+ dataColumns: Array<IColumnProps>;
22
+ focusedRowKey: number | undefined;
23
+ selectedRowKeys?: Array<number>;
24
+ pageSize?: TMDataGridPageSize;
25
+ searchPanelToolbarPosition?: 'before' | 'default';
26
+ showHeaderFilter?: boolean;
27
+ showFilterPanel?: boolean;
28
+ showLoadPanel?: boolean;
29
+ showColumnChooser?: boolean;
30
+ showSearchPanel?: boolean;
31
+ showGroupPanel?: boolean;
32
+ counterConfig?: ITMCounterContainerProps;
33
+ }
34
+ declare const TMDataGrid: React.ForwardRefExoticComponent<TMDataGridProps<unknown> & React.RefAttributes<dxDataGrid<any, any>>>;
35
+ export default TMDataGrid;
@@ -0,0 +1,176 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
3
+ import DataGrid, { Column, HeaderFilter, Selection, Scrolling, LoadPanel, SearchPanel, Pager, Sorting, Paging, FilterPanel, ColumnChooser, Grouping, GroupPanel, Summary, Editing, FilterRow, StateStoring, RowDragging } from 'devextreme-react/data-grid';
4
+ import DataSource from 'devextreme/data/data_source';
5
+ import { IconSelected, IconVisible, SDKUI_Globals, SDKUI_Localizator } from '../../helper';
6
+ import TMCounterContainer, { CounterItemKey } from './TMCounterContainer';
7
+ ;
8
+ export var TMDataGridPageSize;
9
+ (function (TMDataGridPageSize) {
10
+ TMDataGridPageSize[TMDataGridPageSize["Small"] = 30] = "Small";
11
+ TMDataGridPageSize[TMDataGridPageSize["Medium"] = 50] = "Medium";
12
+ TMDataGridPageSize[TMDataGridPageSize["Large"] = 100] = "Large";
13
+ })(TMDataGridPageSize || (TMDataGridPageSize = {}));
14
+ const TMDataGrid = React.forwardRef((props, ref) => {
15
+ const {
16
+ // main properties
17
+ keyExpr = 'id', dataSource, focusedRowEnabled = true, hoverStateEnabled = true, focusedRowKey, selectedRowKeys = [],
18
+ // custom options
19
+ dataColumns = [], pageSize = TMDataGridPageSize.Large, showHeaderFilter = true, showFilterPanel = false, showLoadPanel = true, showSearchPanel = true, searchPanelToolbarPosition = 'before', counterConfig = {
20
+ show: false,
21
+ items: new Map()
22
+ },
23
+ // events and callbacks
24
+ onSelectionChanged, onFocusedRowChanged, onRowDblClick, onRowClick, onCellClick, onOptionChanged, onContentReady, onContextMenuPreparing, onInitialized, onEditorPreparing, onCellPrepared, onRowPrepared, onRowUpdating, onRowExpanded, onRowCollapsed, onRowUpdated, onSaved, onEditCanceled, onEditingStart, onEditingChange, customizeColumns, scrolling = { mode: 'standard', useNative: SDKUI_Globals.dataGridUseNativeScrollbar }, paging = { enabled: true, pageSize: pageSize }, pager = { visible: true, showInfo: true, showNavigationButtons: true }, selection = { mode: 'multiple', showCheckBoxesMode: "always", selectAllMode: "allPages" }, sorting, summary, stateStoring, columnChooser, grouping, groupPanel, filterRow, headerFilter, editing, rowDragging,
25
+ // other properties
26
+ disabled = false, autoNavigateToFocusedRow = true, columnResizingMode = 'widget', columnHidingEnabled = true, columnAutoWidth = true, allowColumnResizing = true, allowColumnReordering = true, showBorders = true, showRowLines = true, showColumnLines = false, showColumnHeaders = true, rowAlternationEnabled = false, wordWrapEnabled = false,
27
+ // styles
28
+ width = '100%', height = '100%', } = props;
29
+ const [counterValues, setCounterValues] = useState(new Map());
30
+ const [recordCount, setRecordCount] = useState(0);
31
+ useEffect(() => {
32
+ const count = getRecordCount(dataSource);
33
+ setRecordCount(count);
34
+ }, [dataSource]);
35
+ // Creating a ref to store the timestamp of the last selection change
36
+ const lastSelectionChangeTime = useRef(Date.now());
37
+ useEffect(() => {
38
+ if (counterConfig.show) {
39
+ const defaultCounterItems = new Map([
40
+ [
41
+ CounterItemKey.visibleItems,
42
+ { key: CounterItemKey.visibleItems, show: true, caption: SDKUI_Localizator.VisibleItems, value: recordCount, icon: _jsx(IconVisible, {}), order: 0 }
43
+ ],
44
+ [
45
+ CounterItemKey.selectedItems,
46
+ { key: CounterItemKey.selectedItems, show: true, caption: SDKUI_Localizator.SelectedItems, value: selectedRowKeys.length, icon: _jsx(IconSelected, {}), order: 1 }
47
+ ]
48
+ ]);
49
+ const mergedCounterItems = new Map(defaultCounterItems);
50
+ counterConfig.items?.forEach((value, key) => { mergedCounterItems.set(key.toString(), value); });
51
+ // Convert map to array and sort by order, then caption alphabetically
52
+ const sortedCounterItems = new Map([...mergedCounterItems.entries()]
53
+ .sort((a, b) => {
54
+ const aValue = a[1]; // Extract value
55
+ const bValue = b[1];
56
+ if ((aValue.order ?? 0) === (bValue.order ?? 0)) {
57
+ return (aValue.caption ?? '').localeCompare(bValue.caption ?? '');
58
+ }
59
+ return (aValue.order ?? 0) - (bValue.order ?? 0);
60
+ }));
61
+ setCounterValues(sortedCounterItems);
62
+ }
63
+ }, [counterConfig, recordCount, selectedRowKeys]);
64
+ // Handle selection changes and invoke callback if provided
65
+ const onSelectionChangedCallback = useCallback((e) => {
66
+ lastSelectionChangeTime.current = Date.now(); // Store current time of selection change
67
+ if (onSelectionChanged)
68
+ onSelectionChanged(e);
69
+ }, [onSelectionChanged]);
70
+ // Handle row double-click event
71
+ const onRowDblClickCallback = useCallback((e) => {
72
+ if (Date.now() - lastSelectionChangeTime.current < 300) {
73
+ // Skip the double-click if selection has changed recently
74
+ return;
75
+ }
76
+ if (onRowDblClick)
77
+ onRowDblClick(e);
78
+ }, [onRowDblClick]);
79
+ // Update context menu items based on operation type (single row or multi row)
80
+ const updateContextMenuItems = useCallback((items, rowID) => {
81
+ return items.map(item => {
82
+ // Determine if item is explicitly disabled; default to `false` if not provided
83
+ let disabled = item.disabled ?? false;
84
+ // Variable to determine if the item should be disabled based on row selection
85
+ let disabledCalculation = false;
86
+ // Get the active row ID, prioritizing `focusedRowKey` if `focusedRowEnabled` is true
87
+ const id = focusedRowEnabled ? focusedRowKey : rowID;
88
+ // Disable items based on their operation type and selection state
89
+ if (item.operationType === 'singleRow') {
90
+ // A single-row operation requires exactly one row to be selected
91
+ disabledCalculation = selectedRowKeys.length > 1 || id === undefined;
92
+ }
93
+ if (item.operationType === 'multiRow') {
94
+ // A multi-row operation requires at least one selected row
95
+ disabledCalculation = selectedRowKeys.length === 0 && id === undefined;
96
+ }
97
+ return {
98
+ ...item,
99
+ disabled: disabled || disabledCalculation, // An item is disabled if it's explicitly set to `true` or if the calculation above determines so
100
+ // Define the behavior when the menu item is clicked
101
+ onClick: () => {
102
+ // If there is no click handler defined, exit early
103
+ if (!item.onClick)
104
+ return;
105
+ if (item.operationType === 'singleRow' && id !== undefined) {
106
+ // For single-row operations, call onItemClick with the row ID
107
+ item.onClick(id);
108
+ }
109
+ else if (item.operationType === 'multiRow' && id !== undefined) {
110
+ // For multi-row operations, determine the appropriate argument
111
+ if (selectedRowKeys.length > 0) {
112
+ // If multiple rows are selected, pass all selected row IDs
113
+ item.onClick(selectedRowKeys);
114
+ }
115
+ else if (id !== undefined) {
116
+ // If no rows are selected but `id` exists, pass it as an array
117
+ item.onClick([id]);
118
+ }
119
+ }
120
+ else {
121
+ // For general operations without a specific row selection
122
+ item.onClick();
123
+ }
124
+ },
125
+ // Recursively update nested menu items, if present
126
+ items: item.items ? updateContextMenuItems(item.items, id) : undefined,
127
+ };
128
+ });
129
+ }, [focusedRowEnabled, focusedRowKey, selectedRowKeys]);
130
+ // Handle context menu preparation
131
+ const onContextMenuPreparingCallback = useCallback((e) => {
132
+ if (e === undefined)
133
+ return;
134
+ if (onContextMenuPreparing)
135
+ onContextMenuPreparing(e);
136
+ if (e.target === 'content') {
137
+ e.items = e.items || [];
138
+ if (e.items.length > 0) {
139
+ const rowId = e.row?.key;
140
+ const updatedContextMenuItems = updateContextMenuItems(e.items, rowId);
141
+ e.items = [...updatedContextMenuItems];
142
+ }
143
+ }
144
+ }, [updateContextMenuItems, onContextMenuPreparing]);
145
+ // Handle toolbar preparation, especially for the search panel
146
+ const onToolbarPreparingCallback = useCallback((e) => {
147
+ if (e === undefined || e.toolbarOptions === undefined || e.toolbarOptions.items === undefined)
148
+ return;
149
+ if (showSearchPanel && searchPanelToolbarPosition === 'before') {
150
+ e.toolbarOptions.items.forEach((item) => {
151
+ if (item.name === "searchPanel") {
152
+ item.location = "before";
153
+ }
154
+ });
155
+ }
156
+ }, []);
157
+ return _jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsx("div", { style: { width: "100%", height: counterConfig.show ? "calc(100% - 25px)" : "100%" }, children: _jsxs(DataGrid, { ref: ref, className: 'tm-datagrid',
158
+ // main properties
159
+ keyExpr: keyExpr, dataSource: dataSource, selectedRowKeys: selectedRowKeys, focusedRowEnabled: focusedRowEnabled, hoverStateEnabled: hoverStateEnabled,
160
+ // events and callbacks
161
+ onSelectionChanged: onSelectionChangedCallback, onRowDblClick: onRowDblClickCallback, onRowPrepared: onRowPrepared, onContextMenuPreparing: onContextMenuPreparingCallback, onToolbarPreparing: onToolbarPreparingCallback, onFocusedRowChanged: onFocusedRowChanged, onRowClick: onRowClick, onCellClick: onCellClick, onOptionChanged: onOptionChanged, onContentReady: onContentReady, onInitialized: onInitialized, customizeColumns: customizeColumns, onEditorPreparing: onEditorPreparing, onCellPrepared: onCellPrepared, onRowUpdating: onRowUpdating, onRowExpanded: onRowExpanded, onRowCollapsed: onRowCollapsed, onRowUpdated: onRowUpdated, onSaved: onSaved, onEditCanceled: onEditCanceled, onEditingStart: onEditingStart, onEditingChange: onEditingChange,
162
+ // other properties
163
+ disabled: disabled, autoNavigateToFocusedRow: autoNavigateToFocusedRow, focusedRowKey: focusedRowKey, columnHidingEnabled: columnHidingEnabled, columnResizingMode: columnResizingMode, columnAutoWidth: columnAutoWidth, allowColumnResizing: allowColumnResizing, allowColumnReordering: allowColumnReordering, showBorders: showBorders, showRowLines: showRowLines, showColumnLines: showColumnLines, showColumnHeaders: showColumnHeaders, rowAlternationEnabled: rowAlternationEnabled, wordWrapEnabled: wordWrapEnabled,
164
+ // styles
165
+ width: width, height: height, style: { userSelect: 'none' }, children: [dataColumns.map((column, index) => (_jsx(Column, { ...column }, column.caption + index.toString()))), sorting && _jsx(Sorting, { ...sorting }), selection && _jsx(Selection, { ...selection }), scrolling && _jsx(Scrolling, { ...scrolling }), summary && _jsx(Summary, { ...summary }), showHeaderFilter && _jsx(HeaderFilter, { visible: true, ...headerFilter }), rowDragging && _jsx(RowDragging, { ...rowDragging }), filterRow && _jsx(FilterRow, { ...filterRow }), showFilterPanel && _jsx(FilterPanel, { visible: true }), columnChooser && _jsx(ColumnChooser, { ...columnChooser }), stateStoring && _jsx(StateStoring, { ...stateStoring }), groupPanel && _jsx(GroupPanel, { ...groupPanel }), _jsx(Grouping, { contextMenuEnabled: true, ...grouping }), _jsx(LoadPanel, { enabled: showLoadPanel }), _jsx(SearchPanel, { visible: showSearchPanel }), editing && _jsx(Editing, { ...editing }), paging && _jsx(Paging, { ...paging }), pager && _jsx(Pager, { ...pager, visible: recordCount > pageSize })] }) }), counterConfig.show && _jsx("div", { style: { width: "100%", height: "25px", display: "flex", alignItems: "center", gap: "15px", backgroundColor: "#e0e0e0" }, children: _jsx(TMCounterContainer, { items: counterValues, bgColorContainer: counterConfig.bgColorContainer, bgColorItem: counterConfig.bgColorItem, hoverColorItem: counterConfig.hoverColorItem, textColorItem: counterConfig.textColorItem }) })] });
166
+ });
167
+ export default TMDataGrid;
168
+ const getRecordCount = (dataSource) => {
169
+ if (Array.isArray(dataSource)) {
170
+ return dataSource.length; // For array
171
+ }
172
+ if (dataSource instanceof DataSource) {
173
+ return dataSource.totalCount(); // For DataSource instance
174
+ }
175
+ return 0; // Default case when neither condition is met
176
+ };
@@ -54,4 +54,5 @@ export * from "./viewers/TMTidViewer";
54
54
  export * from "./viewers/TMMidViewer";
55
55
  export * from "./viewers/TMDataListItemViewer";
56
56
  export * from "./base/TMDeviceProvider";
57
+ export { default as TMDataGrid } from "./base/TMDataGrid";
57
58
  export { default as TMAreaManager } from "./base/TMAreaManager";
@@ -66,4 +66,5 @@ export * from "./viewers/TMMidViewer";
66
66
  export * from "./viewers/TMDataListItemViewer";
67
67
  //TMDeviceProvider
68
68
  export * from "./base/TMDeviceProvider";
69
+ export { default as TMDataGrid } from "./base/TMDataGrid";
69
70
  export { default as TMAreaManager } from "./base/TMAreaManager";
@@ -305,6 +305,7 @@ export declare class SDKUI_Localizator {
305
305
  static get View_Metadato(): "Anzeige (Methadaten)" | "Visualization (metadata)" | "Visualización (metadato)" | "Visualisation (métadonnée)" | "Display (metadados)" | "Visualizzazione (metadato)";
306
306
  static get ViewWithCheckOption(): "Kontrolle über Archivierung und Bearbeitung" | "Check on archive and update" | "Control en almacenamiento y modificación" | "Contrôle de l'archivage et la modifie" | "Controle de arquivamento e edição" | "Controllo su archiviazione e modifica";
307
307
  static get Visible(): "Sichtbar" | "Visible" | "Visibles" | "Visibiles" | "Visíveis" | "Visibili";
308
+ static get VisibleItems(): "sichtbare Elemente" | "Visible items" | "elementos visibles" | "éléments visibles" | "itens visíveis" | "Elementi visibili";
308
309
  static get WelcomeTo(): "Willkommen bei {{0}}" | "Welcome to {{0}}" | "Bienvenido a {{0}}" | "Bienvenue sur {{0}}" | "Bem-vindo à {{0}}" | "Benvenuto su {{0}}";
309
310
  static get WorkflowApproval(): "Workflow-Genehmigung" | "Workflow approval" | "Aprobación de flujo de trabajo" | "Approbation de workflow" | "Aprovação de fluxo de trabalho" | "Approvazione workflow";
310
311
  static get Yes(): "Ja" | "Yes" | "Sí" | "Oui" | "Sim" | "Sì";
@@ -3008,6 +3008,16 @@ export class SDKUI_Localizator {
3008
3008
  default: return "Visibili";
3009
3009
  }
3010
3010
  }
3011
+ static get VisibleItems() {
3012
+ switch (this._cultureID) {
3013
+ case CultureIDs.De_DE: return "sichtbare Elemente";
3014
+ case CultureIDs.En_US: return "Visible items";
3015
+ case CultureIDs.Es_ES: return "elementos visibles";
3016
+ case CultureIDs.Fr_FR: return "éléments visibles";
3017
+ case CultureIDs.Pt_PT: return "itens visíveis";
3018
+ default: return "Elementi visibili";
3019
+ }
3020
+ }
3011
3021
  static get WelcomeTo() {
3012
3022
  switch (this._cultureID) {
3013
3023
  case CultureIDs.De_DE: return "Willkommen bei {{0}}";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.10.13",
3
+ "version": "6.10.15",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",