Active Feature Sources
- {[...featureDataSources].sort((a, b) => (a.label || a.tableName || '').localeCompare(b.label || b.tableName || '')).map(fds => {
- const meta = _findFeatureInstanceMeta(featureTree, fds.featureInstanceId);
- const fdsConnLabel = meta?.instanceLabel || fds.tableName;
+ {(() => {
+ const sorted = [...featureDataSources].sort((a, b) => (a.label || a.tableName || '').localeCompare(b.label || b.tableName || ''));
+ const grouped: { key: string; label: string; items: UdbFeatureDataSource[] }[] = [];
+ const standalone: UdbFeatureDataSource[] = [];
+
+ for (const fds of sorted) {
+ if (fds.recordFilter && Object.keys(fds.recordFilter).length > 0) {
+ const filterKey = `${fds.featureInstanceId}|${JSON.stringify(fds.recordFilter)}`;
+ let group = grouped.find(g => g.key === filterKey);
+ if (!group) {
+ const parentLabel = fds.label.includes(':') ? fds.label.split(':')[1]?.trim() : fds.label;
+ const meta = _findFeatureInstanceMeta(featureTree, fds.featureInstanceId);
+ group = { key: filterKey, label: `${meta?.instanceLabel || fds.featureCode} – ${parentLabel}`, items: [] };
+ grouped.push(group);
+ }
+ group.items.push(fds);
+ } else {
+ standalone.push(fds);
+ }
+ }
+
return (
-
-
- {getPageIcon(`feature.${fds.featureCode}`) || '\uD83D\uDDC3\uFE0F'}
-
-
- {fdsConnLabel} – {fds.tableName}
-
-
-
-
-
+ <>
+ {grouped.map(group => (
+
+
+ {'\uD83D\uDCCB'}
+
+ {group.label}
+
+
+
+ {group.items.map(fds => {
+ const meta = _findFeatureInstanceMeta(featureTree, fds.featureInstanceId);
+ return (
+
+
+ {getPageIcon(`feature.${fds.featureCode}`) || '\uD83D\uDCC4'}
+
+
+ {fds.tableName}
+
+
+
+
+
+ );
+ })}
+
+ ))}
+ {standalone.map(fds => {
+ const meta = _findFeatureInstanceMeta(featureTree, fds.featureInstanceId);
+ const fdsConnLabel = meta?.instanceLabel || fds.tableName;
+ return (
+
+
+ {getPageIcon(`feature.${fds.featureCode}`) || '\uD83D\uDDC3\uFE0F'}
+
+
+ {fdsConnLabel} – {fds.tableName}
+
+
+
+
+
+ );
+ })}
+ >
);
- })}
+ })()}
)}
@@ -871,6 +1083,13 @@ const SourcesTab: React.FC