fix: UDB compact layout, mobile table view, DataSource ID attach
All checks were successful
Deploy Nyla Frontend to Production / deploy (push) Successful in 48s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-06-01 00:00:38 +02:00
parent 7da7ad5041
commit 5711450606
6 changed files with 101 additions and 42 deletions

View file

@ -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 {

View file

@ -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;
}
}

View file

@ -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 {

View file

@ -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'];

View file

@ -48,7 +48,14 @@ const SourcesTab: React.FC<SourcesTabProps> = ({
setSettingsModal({ dataSourceId, title: label });
}, []);
const _handleSendToChat = useCallback((node: TreeNode<UdbBackendNode>) => {
const provider = useMemo(
() => instanceId
? createUdbSourcesProvider(instanceId, _handleOpenSettings)
: null,
[instanceId, _handleOpenSettings],
);
const _handleSendToChat = useCallback(async (node: TreeNode<UdbBackendNode>) => {
const data = node.data;
if (!data) return;
@ -65,16 +72,15 @@ const SourcesTab: React.FC<SourcesTabProps> = ({
});
} 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 (

View file

@ -212,6 +212,8 @@ function _mapBackendNode(
// ---------------------------------------------------------------------------
export interface UdbSourcesProviderHandle extends TreeNodeProvider<UdbBackendNode> {
/** Resolve the DataSource UUID for a node, creating a record if needed. */
ensureDataSourceId(node: UdbBackendNode): Promise<string | null>;
/** 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<string | null> {
return _ensureRecordForSettings(node);
},
_diagnosticGetCacheSize() {
return nodeCache.size;
},