@industream/flowmaker-flowbox-ui-components 0.0.1
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.
- package/README.md +179 -0
- package/dist/DCSourceConnection.svelte +141 -0
- package/dist/DCSourceConnection.svelte.d.ts +21 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/package.json +44 -0
- package/src/DCSourceConnection.svelte +141 -0
- package/src/index.ts +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @industream/flowmaker-flowbox-ui-components
|
|
2
|
+
|
|
3
|
+
Reusable Svelte 5 components for FlowMaker FlowBox configuration UIs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @industream/flowmaker-flowbox-ui-components
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Peer dependencies:**
|
|
12
|
+
- `svelte@^5.0.0`
|
|
13
|
+
- `@industream/datacatalog-client@^1.0.0-preview.1`
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Components
|
|
18
|
+
|
|
19
|
+
### DataCatalog Integration
|
|
20
|
+
|
|
21
|
+
#### DCSourceConnection
|
|
22
|
+
|
|
23
|
+
A dropdown component that fetches and displays source connections from the DataCatalog API, allowing users to select a data source for their FlowBox configuration.
|
|
24
|
+
|
|
25
|
+
##### Import
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { DCSourceConnection, type SourceConnection } from '@industream/flowmaker-flowbox-ui-components';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
##### Props
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Default | Description |
|
|
34
|
+
|------|------|---------|-------------|
|
|
35
|
+
| `dcapiurl` | `string` | `''` | Base URL of the DataCatalog API |
|
|
36
|
+
| `sourcetypefilter` | `string \| string[] \| null` | `null` | Filter connections by source type(s) |
|
|
37
|
+
| `onsourceselect` | `(connection: SourceConnection) => void` | `null` | Callback when a connection is selected |
|
|
38
|
+
| `onitemsloaded` | `(connections: SourceConnection[]) => void` | `null` | Callback when connections are loaded |
|
|
39
|
+
|
|
40
|
+
##### Exported Methods
|
|
41
|
+
|
|
42
|
+
| Method | Signature | Description |
|
|
43
|
+
|--------|-----------|-------------|
|
|
44
|
+
| `select` | `(idOrConnection: string \| SourceConnection) => void` | Programmatically select a connection |
|
|
45
|
+
| `getSelection` | `() => SourceConnection \| null` | Get the currently selected connection |
|
|
46
|
+
| `getConnections` | `() => SourceConnection[]` | Get all loaded connections |
|
|
47
|
+
|
|
48
|
+
##### Types
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
interface SourceConnection {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
sourceType?: { name: string };
|
|
55
|
+
[key: string]: any;
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
##### Example: FlowBox Config Form
|
|
60
|
+
|
|
61
|
+
This example shows how to integrate `DCSourceConnection` into a FlowBox configuration form using `@industream/flowmaker-flowbox-ui`.
|
|
62
|
+
|
|
63
|
+
```svelte
|
|
64
|
+
<script lang="ts">
|
|
65
|
+
import { flowMakerBridge } from '@industream/flowmaker-flowbox-ui';
|
|
66
|
+
import { DCSourceConnection, type SourceConnection } from '@industream/flowmaker-flowbox-ui-components';
|
|
67
|
+
|
|
68
|
+
const props = $props();
|
|
69
|
+
const { context, values, validity, emit } = flowMakerBridge(props);
|
|
70
|
+
|
|
71
|
+
// Get DC API URL from context (passed by FlowMaker)
|
|
72
|
+
const dcApiUrl = $derived($context?.dcApiUrl || 'http://localhost:8002');
|
|
73
|
+
|
|
74
|
+
// Optional: filter by source type
|
|
75
|
+
const sourceTypeFilter = $derived($context?.sourceTypeFilter || null);
|
|
76
|
+
|
|
77
|
+
// Reference to component for programmatic access
|
|
78
|
+
let dcSourceConnection: ReturnType<typeof DCSourceConnection>;
|
|
79
|
+
|
|
80
|
+
function handleSourceSelect(connection: SourceConnection) {
|
|
81
|
+
// Store selected connection ID in values
|
|
82
|
+
$values.sourceConnectionId = connection.id;
|
|
83
|
+
|
|
84
|
+
// Optionally store more details
|
|
85
|
+
$values.sourceConnectionName = connection.name;
|
|
86
|
+
$values.sourceType = connection.sourceType?.name;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function handleItemsLoaded(connections: SourceConnection[]) {
|
|
90
|
+
// Restore previous selection if exists
|
|
91
|
+
if ($values.sourceConnectionId) {
|
|
92
|
+
dcSourceConnection.select($values.sourceConnectionId);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<div class="config-form">
|
|
98
|
+
<h4>Select Source Connection</h4>
|
|
99
|
+
|
|
100
|
+
<DCSourceConnection
|
|
101
|
+
dcapiurl={dcApiUrl}
|
|
102
|
+
sourcetypefilter={sourceTypeFilter}
|
|
103
|
+
onsourceselect={handleSourceSelect}
|
|
104
|
+
onitemsloaded={handleItemsLoaded}
|
|
105
|
+
bind:this={dcSourceConnection}
|
|
106
|
+
/>
|
|
107
|
+
|
|
108
|
+
{#if $values.sourceConnectionId}
|
|
109
|
+
<div class="selection-info">
|
|
110
|
+
<p><strong>Selected:</strong> {$values.sourceConnectionName}</p>
|
|
111
|
+
<p><strong>Type:</strong> {$values.sourceType}</p>
|
|
112
|
+
</div>
|
|
113
|
+
{/if}
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<style>
|
|
117
|
+
.config-form {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
gap: 1rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.selection-info {
|
|
124
|
+
padding: 1rem;
|
|
125
|
+
background: var(--cds-layer-01, #393939);
|
|
126
|
+
border-radius: 4px;
|
|
127
|
+
}
|
|
128
|
+
</style>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
##### Context Configuration
|
|
132
|
+
|
|
133
|
+
When registering your FlowBox, pass the DataCatalog API URL via context:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"context": {
|
|
138
|
+
"dcApiUrl": "https://datacatalog.example.com/api",
|
|
139
|
+
"sourceTypeFilter": ["Mqtt", "DataBridge"]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
##### Filtering by Source Type
|
|
145
|
+
|
|
146
|
+
Filter to show only specific source types:
|
|
147
|
+
|
|
148
|
+
```svelte
|
|
149
|
+
<!-- Single type -->
|
|
150
|
+
<DCSourceConnection
|
|
151
|
+
dcapiurl={dcApiUrl}
|
|
152
|
+
sourcetypefilter="DataBridge"
|
|
153
|
+
onsourceselect={handleSelect}
|
|
154
|
+
/>
|
|
155
|
+
|
|
156
|
+
<!-- Multiple types -->
|
|
157
|
+
<DCSourceConnection
|
|
158
|
+
dcapiurl={dcApiUrl}
|
|
159
|
+
sourcetypefilter={["Relational", "DataBridge", "Mqtt"]}
|
|
160
|
+
onsourceselect={handleSelect}
|
|
161
|
+
/>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
##### Programmatic Selection
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Select by ID
|
|
168
|
+
dcSourceConnection.select('xxxx-guid-1234-4567');
|
|
169
|
+
|
|
170
|
+
// Select by connection object
|
|
171
|
+
dcSourceConnection.select(connectionObject);
|
|
172
|
+
|
|
173
|
+
// Get current selection
|
|
174
|
+
const selected = dcSourceConnection.getSelection();
|
|
175
|
+
|
|
176
|
+
// Get all loaded connections
|
|
177
|
+
const all = dcSourceConnection.getConnections();
|
|
178
|
+
```
|
|
179
|
+
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DataCatalogClient } from '@industream/datacatalog-client';
|
|
3
|
+
|
|
4
|
+
export interface SourceConnection {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
sourceType?: { name: string };
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
dcapiurl?: string;
|
|
13
|
+
sourcetypefilter?: string | string[] | null;
|
|
14
|
+
onsourceselect?: (connection: SourceConnection) => void;
|
|
15
|
+
onitemsloaded?: (connections: SourceConnection[]) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
dcapiurl = '',
|
|
20
|
+
sourcetypefilter = null,
|
|
21
|
+
onsourceselect = null,
|
|
22
|
+
onitemsloaded = null
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
|
|
25
|
+
let sourceConnections = $state<SourceConnection[]>([]);
|
|
26
|
+
let selectedValue = $state('');
|
|
27
|
+
let loading = $state(true);
|
|
28
|
+
let error = $state<string | null>(null);
|
|
29
|
+
let dropdownRef = $state<HTMLElement | null>(null);
|
|
30
|
+
|
|
31
|
+
// Load source connections when component mounts or dcapiurl changes
|
|
32
|
+
$effect(() => {
|
|
33
|
+
if (dcapiurl && sourcetypefilter !== null) {
|
|
34
|
+
loadSourceConnections();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Add event listener for Carbon's custom event
|
|
39
|
+
$effect(() => {
|
|
40
|
+
if (dropdownRef) {
|
|
41
|
+
dropdownRef.addEventListener('cds-dropdown-selected', handleSelect);
|
|
42
|
+
return () => {
|
|
43
|
+
dropdownRef.removeEventListener('cds-dropdown-selected', handleSelect);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
async function loadSourceConnections() {
|
|
49
|
+
loading = true;
|
|
50
|
+
error = null;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const client = new DataCatalogClient({ baseUrl: dcapiurl });
|
|
54
|
+
const filters = {};
|
|
55
|
+
|
|
56
|
+
if (sourcetypefilter && sourcetypefilter.length > 0) {
|
|
57
|
+
filters.sourceTypes = Array.isArray(sourcetypefilter)
|
|
58
|
+
? sourcetypefilter
|
|
59
|
+
: [sourcetypefilter];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const result = await client.sourceConnections.get(filters);
|
|
63
|
+
sourceConnections = result.items || [];
|
|
64
|
+
console.log('Loaded source connections:', sourceConnections);
|
|
65
|
+
onitemsloaded?.(sourceConnections);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
console.error('Failed to load source connections:', e);
|
|
68
|
+
error = e.message || 'Failed to load source connections';
|
|
69
|
+
sourceConnections = [];
|
|
70
|
+
} finally {
|
|
71
|
+
loading = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function handleSelect(e: CustomEvent) {
|
|
76
|
+
const selectedId = e.detail?.item?.value || e.target?.value;
|
|
77
|
+
console.log('Dropdown selected event:', e, 'selectedId:', selectedId);
|
|
78
|
+
selectedValue = selectedId;
|
|
79
|
+
|
|
80
|
+
if (selectedId && onsourceselect) {
|
|
81
|
+
const selected = sourceConnections.find(sc => sc.id === selectedId);
|
|
82
|
+
console.log('Found selected:', selected);
|
|
83
|
+
if (selected) {
|
|
84
|
+
onsourceselect(selected);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Exposed method to programmatically select a source connection
|
|
90
|
+
export function select(idOrConnection: string | SourceConnection) {
|
|
91
|
+
const id = typeof idOrConnection === 'string' ? idOrConnection : idOrConnection?.id;
|
|
92
|
+
if (!id) return;
|
|
93
|
+
|
|
94
|
+
const connection = sourceConnections.find(sc => sc.id === id);
|
|
95
|
+
if (connection) {
|
|
96
|
+
selectedValue = id;
|
|
97
|
+
if (dropdownRef) {
|
|
98
|
+
dropdownRef.value = id;
|
|
99
|
+
}
|
|
100
|
+
if (onsourceselect) {
|
|
101
|
+
onsourceselect(connection);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Exposed method to get current selection
|
|
107
|
+
export function getSelection(): SourceConnection | null {
|
|
108
|
+
return sourceConnections.find(sc => sc.id === selectedValue) || null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Exposed method to get all loaded connections
|
|
112
|
+
export function getConnections(): SourceConnection[] {
|
|
113
|
+
return sourceConnections;
|
|
114
|
+
}
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
{#if loading}
|
|
118
|
+
<cds-dropdown label="Source Connection" disabled>
|
|
119
|
+
<cds-dropdown-item value="">Loading...</cds-dropdown-item>
|
|
120
|
+
</cds-dropdown>
|
|
121
|
+
{:else if error}
|
|
122
|
+
<cds-dropdown label="Source Connection" invalid invalid-text={error}>
|
|
123
|
+
<cds-dropdown-item value="">Error loading connections</cds-dropdown-item>
|
|
124
|
+
</cds-dropdown>
|
|
125
|
+
{:else}
|
|
126
|
+
<cds-dropdown
|
|
127
|
+
bind:this={dropdownRef}
|
|
128
|
+
label="Select a source connection"
|
|
129
|
+
value={selectedValue}
|
|
130
|
+
>
|
|
131
|
+
{#each sourceConnections as conn}
|
|
132
|
+
<cds-dropdown-item value={conn.id}>
|
|
133
|
+
{conn.name} [{conn.sourceType?.name || 'Unknown'}]
|
|
134
|
+
</cds-dropdown-item>
|
|
135
|
+
{/each}
|
|
136
|
+
</cds-dropdown>
|
|
137
|
+
{/if}
|
|
138
|
+
|
|
139
|
+
<style>
|
|
140
|
+
/* Component styles */
|
|
141
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface SourceConnection {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
sourceType?: {
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
interface Props {
|
|
10
|
+
dcapiurl?: string;
|
|
11
|
+
sourcetypefilter?: string | string[] | null;
|
|
12
|
+
onsourceselect?: (connection: SourceConnection) => void;
|
|
13
|
+
onitemsloaded?: (connections: SourceConnection[]) => void;
|
|
14
|
+
}
|
|
15
|
+
declare const DCSourceConnection: import("svelte").Component<Props, {
|
|
16
|
+
select: (idOrConnection: string | SourceConnection) => void;
|
|
17
|
+
getSelection: () => SourceConnection | null;
|
|
18
|
+
getConnections: () => SourceConnection[];
|
|
19
|
+
}, "">;
|
|
20
|
+
type DCSourceConnection = ReturnType<typeof DCSourceConnection>;
|
|
21
|
+
export default DCSourceConnection;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as DCSourceConnection } from './DCSourceConnection.svelte';
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@industream/flowmaker-flowbox-ui-components",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Reusable Svelte components for FlowMaker FlowBox UI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"svelte": "./dist/index.js",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"svelte": "./dist/index.js",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./DCSourceConnection.svelte": {
|
|
17
|
+
"types": "./dist/DCSourceConnection.svelte.d.ts",
|
|
18
|
+
"svelte": "./dist/DCSourceConnection.svelte",
|
|
19
|
+
"import": "./dist/DCSourceConnection.svelte"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src",
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "svelte-package --input src"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"svelte": "^5.0.0",
|
|
32
|
+
"@industream/datacatalog-client": "^1.0.0-preview.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"svelte": "^5.0.0",
|
|
36
|
+
"vite": "^6.0.0",
|
|
37
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
|
38
|
+
"@sveltejs/package": "^2.0.0",
|
|
39
|
+
"typescript": "^5.0.0"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { DataCatalogClient } from '@industream/datacatalog-client';
|
|
3
|
+
|
|
4
|
+
export interface SourceConnection {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
sourceType?: { name: string };
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
dcapiurl?: string;
|
|
13
|
+
sourcetypefilter?: string | string[] | null;
|
|
14
|
+
onsourceselect?: (connection: SourceConnection) => void;
|
|
15
|
+
onitemsloaded?: (connections: SourceConnection[]) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
dcapiurl = '',
|
|
20
|
+
sourcetypefilter = null,
|
|
21
|
+
onsourceselect = null,
|
|
22
|
+
onitemsloaded = null
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
|
|
25
|
+
let sourceConnections = $state<SourceConnection[]>([]);
|
|
26
|
+
let selectedValue = $state('');
|
|
27
|
+
let loading = $state(true);
|
|
28
|
+
let error = $state<string | null>(null);
|
|
29
|
+
let dropdownRef = $state<HTMLElement | null>(null);
|
|
30
|
+
|
|
31
|
+
// Load source connections when component mounts or dcapiurl changes
|
|
32
|
+
$effect(() => {
|
|
33
|
+
if (dcapiurl && sourcetypefilter !== null) {
|
|
34
|
+
loadSourceConnections();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Add event listener for Carbon's custom event
|
|
39
|
+
$effect(() => {
|
|
40
|
+
if (dropdownRef) {
|
|
41
|
+
dropdownRef.addEventListener('cds-dropdown-selected', handleSelect);
|
|
42
|
+
return () => {
|
|
43
|
+
dropdownRef.removeEventListener('cds-dropdown-selected', handleSelect);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
async function loadSourceConnections() {
|
|
49
|
+
loading = true;
|
|
50
|
+
error = null;
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const client = new DataCatalogClient({ baseUrl: dcapiurl });
|
|
54
|
+
const filters = {};
|
|
55
|
+
|
|
56
|
+
if (sourcetypefilter && sourcetypefilter.length > 0) {
|
|
57
|
+
filters.sourceTypes = Array.isArray(sourcetypefilter)
|
|
58
|
+
? sourcetypefilter
|
|
59
|
+
: [sourcetypefilter];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const result = await client.sourceConnections.get(filters);
|
|
63
|
+
sourceConnections = result.items || [];
|
|
64
|
+
console.log('Loaded source connections:', sourceConnections);
|
|
65
|
+
onitemsloaded?.(sourceConnections);
|
|
66
|
+
} catch (e) {
|
|
67
|
+
console.error('Failed to load source connections:', e);
|
|
68
|
+
error = e.message || 'Failed to load source connections';
|
|
69
|
+
sourceConnections = [];
|
|
70
|
+
} finally {
|
|
71
|
+
loading = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function handleSelect(e: CustomEvent) {
|
|
76
|
+
const selectedId = e.detail?.item?.value || e.target?.value;
|
|
77
|
+
console.log('Dropdown selected event:', e, 'selectedId:', selectedId);
|
|
78
|
+
selectedValue = selectedId;
|
|
79
|
+
|
|
80
|
+
if (selectedId && onsourceselect) {
|
|
81
|
+
const selected = sourceConnections.find(sc => sc.id === selectedId);
|
|
82
|
+
console.log('Found selected:', selected);
|
|
83
|
+
if (selected) {
|
|
84
|
+
onsourceselect(selected);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Exposed method to programmatically select a source connection
|
|
90
|
+
export function select(idOrConnection: string | SourceConnection) {
|
|
91
|
+
const id = typeof idOrConnection === 'string' ? idOrConnection : idOrConnection?.id;
|
|
92
|
+
if (!id) return;
|
|
93
|
+
|
|
94
|
+
const connection = sourceConnections.find(sc => sc.id === id);
|
|
95
|
+
if (connection) {
|
|
96
|
+
selectedValue = id;
|
|
97
|
+
if (dropdownRef) {
|
|
98
|
+
dropdownRef.value = id;
|
|
99
|
+
}
|
|
100
|
+
if (onsourceselect) {
|
|
101
|
+
onsourceselect(connection);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Exposed method to get current selection
|
|
107
|
+
export function getSelection(): SourceConnection | null {
|
|
108
|
+
return sourceConnections.find(sc => sc.id === selectedValue) || null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Exposed method to get all loaded connections
|
|
112
|
+
export function getConnections(): SourceConnection[] {
|
|
113
|
+
return sourceConnections;
|
|
114
|
+
}
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
{#if loading}
|
|
118
|
+
<cds-dropdown label="Source Connection" disabled>
|
|
119
|
+
<cds-dropdown-item value="">Loading...</cds-dropdown-item>
|
|
120
|
+
</cds-dropdown>
|
|
121
|
+
{:else if error}
|
|
122
|
+
<cds-dropdown label="Source Connection" invalid invalid-text={error}>
|
|
123
|
+
<cds-dropdown-item value="">Error loading connections</cds-dropdown-item>
|
|
124
|
+
</cds-dropdown>
|
|
125
|
+
{:else}
|
|
126
|
+
<cds-dropdown
|
|
127
|
+
bind:this={dropdownRef}
|
|
128
|
+
label="Select a source connection"
|
|
129
|
+
value={selectedValue}
|
|
130
|
+
>
|
|
131
|
+
{#each sourceConnections as conn}
|
|
132
|
+
<cds-dropdown-item value={conn.id}>
|
|
133
|
+
{conn.name} [{conn.sourceType?.name || 'Unknown'}]
|
|
134
|
+
</cds-dropdown-item>
|
|
135
|
+
{/each}
|
|
136
|
+
</cds-dropdown>
|
|
137
|
+
{/if}
|
|
138
|
+
|
|
139
|
+
<style>
|
|
140
|
+
/* Component styles */
|
|
141
|
+
</style>
|
package/src/index.ts
ADDED