From 5711450606a63b0a498c0a6a9069927e5320ecf5 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Mon, 1 Jun 2026 00:00:38 +0200
Subject: [PATCH] fix: UDB compact layout, mobile table view, DataSource ID
attach
Co-authored-by: Cursor
---
.../FormGeneratorControls.module.css | 37 +++++++++--------
.../FormGeneratorTable.module.css | 41 +++++++++++++------
.../FormGeneratorTree.module.css | 31 ++++++++++++--
.../FormGeneratorTree/FormGeneratorTree.tsx | 2 +-
src/components/UnifiedDataBar/SourcesTab.tsx | 26 +++++++-----
.../UnifiedDataBar/UdbSourcesProvider.tsx | 6 +++
6 files changed, 101 insertions(+), 42 deletions(-)
diff --git a/src/components/FormGenerator/FormGeneratorControls/FormGeneratorControls.module.css b/src/components/FormGenerator/FormGeneratorControls/FormGeneratorControls.module.css
index 329e7a3..9b09fac 100644
--- a/src/components/FormGenerator/FormGeneratorControls/FormGeneratorControls.module.css
+++ b/src/components/FormGenerator/FormGeneratorControls/FormGeneratorControls.module.css
@@ -300,40 +300,45 @@
/* Responsive Design */
@media (max-width: 768px) {
.deleteControlsIntegrated {
- flex-direction: column;
- align-items: stretch;
- gap: 10px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 6px;
width: 100%;
}
.controls {
- flex-direction: column;
- align-items: stretch;
- gap: 15px;
- padding: 10px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 6px;
+ padding: 6px 8px;
}
.filtersContainer {
- flex-direction: column;
- align-items: stretch;
- gap: 10px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 6px;
}
.filterGroup {
- flex-direction: column;
- align-items: flex-start;
+ flex-direction: row;
+ align-items: center;
gap: 4px;
}
.filterInput,
.filterSelect {
- width: 100%;
- min-width: auto;
+ width: auto;
+ min-width: 100px;
+ max-width: 160px;
+ font-size: 12px;
}
.floatingLabelInput {
- max-width: none;
- width: 100%;
+ max-width: 160px;
+ width: auto;
}
.filterGroup .floatingLabelInput {
diff --git a/src/components/FormGenerator/FormGeneratorTable/FormGeneratorTable.module.css b/src/components/FormGenerator/FormGeneratorTable/FormGeneratorTable.module.css
index db2673e..a2344d8 100644
--- a/src/components/FormGenerator/FormGeneratorTable/FormGeneratorTable.module.css
+++ b/src/components/FormGenerator/FormGeneratorTable/FormGeneratorTable.module.css
@@ -962,10 +962,24 @@ tbody .actionsColumn {
/* Responsive */
@media (max-width: 768px) {
+ .formGeneratorTable {
+ gap: 4px;
+ }
+
+ .title {
+ font-size: 1.1rem;
+ margin-bottom: 4px;
+ }
+
+ .tableWrapper {
+ border-radius: 4px;
+ }
+
.tableContainer {
flex: 1;
min-height: 0;
max-height: 100%;
+ -webkit-overflow-scrolling: touch;
}
.emptyTable {
@@ -974,31 +988,34 @@ tbody .actionsColumn {
}
.th {
- padding: 6px 8px;
+ padding: 4px 6px;
font-size: 10px;
+ letter-spacing: 0;
}
.td {
- padding: 6px 8px;
+ padding: 4px 6px;
font-size: 12px;
}
.actionButtons {
- flex-direction: column;
+ flex-direction: row;
gap: 2px;
}
.actionButton {
- padding: 4px;
+ padding: 3px;
font-size: 10px;
- min-width: 22px;
- min-height: 22px;
+ min-width: 20px;
+ min-height: 20px;
}
.pagination {
- flex-direction: column;
- gap: 10px;
- padding: 10px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 6px;
+ padding: 6px 8px;
}
.pageSizeSelector {
@@ -1009,7 +1026,7 @@ tbody .actionsColumn {
.paginationInfo {
text-align: center;
margin: 0;
- font-size: 12px;
+ font-size: 11px;
}
.pageNumbers {
@@ -1018,8 +1035,8 @@ tbody .actionsColumn {
}
.pageNumber {
- min-width: 24px;
- height: 24px;
+ min-width: 22px;
+ height: 22px;
font-size: 11px;
}
}
diff --git a/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.module.css b/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.module.css
index 088de25..3269993 100644
--- a/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.module.css
+++ b/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.module.css
@@ -252,7 +252,7 @@
}
.nodeRowCompact {
- height: 32px;
+ height: 28px;
}
.nodeRow:hover {
@@ -561,7 +561,7 @@
/* Compact mode */
.compactMode .sectionHeader {
- padding: 6px 8px;
+ padding: 4px 6px;
}
.compactMode .sectionTitle {
@@ -574,13 +574,38 @@
}
.compactMode .nodeRow {
- padding: 0 6px;
+ padding: 0 4px;
+ gap: 3px;
}
.compactMode .nodeName {
font-size: 12px;
}
+.compactMode .expandChevron,
+.compactMode .expandChevronPlaceholder {
+ width: 14px;
+ height: 14px;
+ font-size: 9px;
+}
+
+.compactMode .nodeIcon {
+ width: 14px;
+ font-size: 13px;
+}
+
+.compactMode .emojiBtn {
+ width: 18px;
+ font-size: 11px;
+ padding: 0 1px;
+}
+
+.compactMode .nodeActionBtn {
+ width: 18px;
+ height: 18px;
+ font-size: 12px;
+}
+
/* Dark theme */
@media (prefers-color-scheme: dark) {
.sectionHeader {
diff --git a/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.tsx b/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.tsx
index cee9833..8ec8f0e 100644
--- a/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.tsx
+++ b/src/components/FormGenerator/FormGeneratorTree/FormGeneratorTree.tsx
@@ -19,7 +19,7 @@ import { useConfirm } from '../../../hooks/useConfirm';
import { useLanguage } from '../../../providers/language/LanguageContext';
import styles from './FormGeneratorTree.module.css';
-const INDENT_PX = 24;
+const INDENT_PX = 16;
const DRAG_MIME = 'application/x-poweron-tree-items';
const SCOPE_ORDER: ScopeValue[] = ['personal', 'featureInstance', 'mandate', 'global'];
diff --git a/src/components/UnifiedDataBar/SourcesTab.tsx b/src/components/UnifiedDataBar/SourcesTab.tsx
index 5c241e6..703cfb2 100644
--- a/src/components/UnifiedDataBar/SourcesTab.tsx
+++ b/src/components/UnifiedDataBar/SourcesTab.tsx
@@ -48,7 +48,14 @@ const SourcesTab: React.FC = ({
setSettingsModal({ dataSourceId, title: label });
}, []);
- const _handleSendToChat = useCallback((node: TreeNode) => {
+ const provider = useMemo(
+ () => instanceId
+ ? createUdbSourcesProvider(instanceId, _handleOpenSettings)
+ : null,
+ [instanceId, _handleOpenSettings],
+ );
+
+ const _handleSendToChat = useCallback(async (node: TreeNode) => {
const data = node.data;
if (!data) return;
@@ -65,16 +72,15 @@ const SourcesTab: React.FC = ({
});
} else if (data.kind === 'connection' || data.kind === 'service'
|| data.kind === 'folder' || data.kind === 'file') {
- onAttachDataSource?.(data.connectionId || data.key);
+ if (!provider) return;
+ const dsId = await provider.ensureDataSourceId(data);
+ if (dsId) {
+ onAttachDataSource?.(dsId);
+ } else {
+ console.warn('[SourcesTab] Could not resolve DataSource ID for', data.key);
+ }
}
- }, [onSendToChat_FeatureSource, onAttachDataSource]);
-
- const provider = useMemo(
- () => instanceId
- ? createUdbSourcesProvider(instanceId, _handleOpenSettings)
- : null,
- [instanceId, _handleOpenSettings],
- );
+ }, [onSendToChat_FeatureSource, onAttachDataSource, provider]);
if (!instanceId || !provider) {
return (
diff --git a/src/components/UnifiedDataBar/UdbSourcesProvider.tsx b/src/components/UnifiedDataBar/UdbSourcesProvider.tsx
index 86e399d..96ffedd 100644
--- a/src/components/UnifiedDataBar/UdbSourcesProvider.tsx
+++ b/src/components/UnifiedDataBar/UdbSourcesProvider.tsx
@@ -212,6 +212,8 @@ function _mapBackendNode(
// ---------------------------------------------------------------------------
export interface UdbSourcesProviderHandle extends TreeNodeProvider {
+ /** Resolve the DataSource UUID for a node, creating a record if needed. */
+ ensureDataSourceId(node: UdbBackendNode): Promise;
/** Test/diagnostic hook only -- exposes the latest cached backend payloads
* so consumers can inspect data flow without round-tripping through the
* network. Not part of the contract used at runtime. */
@@ -375,6 +377,10 @@ export function createUdbSourcesProvider(
}
},
+ async ensureDataSourceId(node: UdbBackendNode): Promise {
+ return _ensureRecordForSettings(node);
+ },
+
_diagnosticGetCacheSize() {
return nodeCache.size;
},