Skip to content

Commit e59bc0b

Browse files
feat: add import modal for additional entities and update authentication handling
1 parent 6f99cf8 commit e59bc0b

5 files changed

Lines changed: 197 additions & 20 deletions

File tree

src/app/models/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export type DatabaseType =
5555
* Authentication providers supported by DAB
5656
*/
5757
export type AuthProvider =
58+
| 'None'
5859
| 'StaticWebApps'
5960
| 'EntraID'
6061
| 'Simulator'

src/app/pages/config-wizard/tabs/entities-tab/entities-tab.component.ts

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,139 @@ import { SchemaImporterService } from '../../../../services/schema-importer.serv
401401
</div>
402402
</div>
403403
}
404+
405+
<!-- Import Modal -->
406+
@if (showImportModal()) {
407+
<div class="modal d-block" tabindex="-1" role="dialog" (click)="showImportModal.set(false)">
408+
<div class="modal-dialog modal-lg" role="document" (click)="$event.stopPropagation()">
409+
<div class="modal-content">
410+
<div class="modal-header">
411+
<h5 class="modal-title">
412+
<i class="bi bi-file-earmark-arrow-up me-2"></i>
413+
Import Additional Entities
414+
</h5>
415+
<button
416+
type="button"
417+
class="btn-close"
418+
(click)="showImportModal.set(false)"
419+
aria-label="Close"
420+
></button>
421+
</div>
422+
<div class="modal-body">
423+
<p class="text-muted mb-4">
424+
Import your database schema to automatically generate entity configurations. All
425+
discovered tables will be added to your existing entities.
426+
</p>
427+
428+
<div class="row g-3">
429+
<!-- JSON Import -->
430+
<div class="col-md-4">
431+
<div
432+
class="import-option p-4 border rounded text-center h-100"
433+
[class.active]="importMode() === 'json'"
434+
(click)="selectImportMode('json')"
435+
>
436+
<i class="bi bi-filetype-json display-4 text-primary mb-3 d-block"></i>
437+
<h6>Import JSON File</h6>
438+
<p class="text-muted small mb-0">Upload a JSON file with table definitions</p>
439+
</div>
440+
</div>
441+
442+
<!-- SQL Import -->
443+
<div class="col-md-4">
444+
<div
445+
class="import-option p-4 border rounded text-center h-100"
446+
[class.active]="importMode() === 'sql'"
447+
(click)="selectImportMode('sql')"
448+
>
449+
<i class="bi bi-file-earmark-code display-4 text-success mb-3 d-block"></i>
450+
<h6>Paste SQL</h6>
451+
<p class="text-muted small mb-0">Paste CREATE TABLE statements</p>
452+
</div>
453+
</div>
454+
455+
<!-- Manual Entry -->
456+
<div class="col-md-4">
457+
<div
458+
class="import-option p-4 border rounded text-center h-100"
459+
[class.active]="importMode() === 'manual'"
460+
(click)="selectImportMode('manual')"
461+
>
462+
<i class="bi bi-pencil-square display-4 text-warning mb-3 d-block"></i>
463+
<h6>Manual Entry</h6>
464+
<p class="text-muted small mb-0">Add entities manually one by one</p>
465+
</div>
466+
</div>
467+
</div>
468+
469+
<!-- JSON File Upload -->
470+
@if (importMode() === 'json') {
471+
<div class="mt-4">
472+
<label for="jsonFileModal" class="form-label">Select JSON Schema File</label>
473+
<input
474+
type="file"
475+
id="jsonFileModal"
476+
class="form-control"
477+
accept=".json"
478+
(change)="onFileSelected($event)"
479+
/>
480+
<small class="form-text text-muted">
481+
Expected format: &#123; "tables": [&#123; "name": "...", "schema": "...",
482+
"columns": [...] &#125;] &#125;
483+
</small>
484+
</div>
485+
}
486+
487+
<!-- SQL Paste -->
488+
@if (importMode() === 'sql') {
489+
<div class="mt-4">
490+
<label for="sqlInputModal" class="form-label">
491+
Paste CREATE TABLE Statements
492+
</label>
493+
<textarea
494+
id="sqlInputModal"
495+
class="form-control font-monospace"
496+
rows="10"
497+
placeholder="CREATE TABLE dbo.Users (
498+
Id INT PRIMARY KEY,
499+
Name NVARCHAR(100) NOT NULL,
500+
Email NVARCHAR(255) NOT NULL,
501+
CreatedAt DATETIME2
502+
);"
503+
[(ngModel)]="sqlInput"
504+
></textarea>
505+
<button
506+
type="button"
507+
class="btn btn-primary mt-3"
508+
[disabled]="!sqlInput()"
509+
(click)="importSql()"
510+
>
511+
<i class="bi bi-upload me-1"></i>
512+
Parse and Import
513+
</button>
514+
</div>
515+
}
516+
517+
<!-- Manual Entry -->
518+
@if (importMode() === 'manual') {
519+
<div class="mt-4 text-center">
520+
<button type="button" class="btn btn-primary" (click)="addEntityFromModal()">
521+
<i class="bi bi-plus-lg me-1"></i>
522+
Add Entity Manually
523+
</button>
524+
</div>
525+
}
526+
</div>
527+
<div class="modal-footer">
528+
<button type="button" class="btn btn-secondary" (click)="closeImportModal()">
529+
Close
530+
</button>
531+
</div>
532+
</div>
533+
</div>
534+
</div>
535+
<div class="modal-backdrop show"></div>
536+
}
404537
</div>
405538
`,
406539
styles: `
@@ -504,8 +637,13 @@ export class EntitiesTabComponent {
504637
const entities = await this.schemaImporter.importAndGenerate(file);
505638
this.notifications.success(`Imported ${entities.length} entities`);
506639
this.importMode.set(null);
640+
this.showImportModal.set(false);
641+
// Reset the file input
642+
input.value = '';
507643
} catch (error) {
508644
this.notifications.error(error instanceof Error ? error.message : 'Failed to import schema');
645+
// Reset the file input even on error
646+
input.value = '';
509647
}
510648
}
511649

@@ -522,6 +660,7 @@ export class EntitiesTabComponent {
522660
this.notifications.success(`Imported ${entities.length} entities`);
523661
this.sqlInput.set('');
524662
this.importMode.set(null);
663+
this.showImportModal.set(false);
525664
} catch (error) {
526665
this.notifications.error(error instanceof Error ? error.message : 'Failed to parse SQL');
527666
}
@@ -533,6 +672,16 @@ export class EntitiesTabComponent {
533672
this.selectedEntityId.set(entity.id);
534673
}
535674

675+
addEntityFromModal(): void {
676+
this.addEntity();
677+
this.closeImportModal();
678+
}
679+
680+
closeImportModal(): void {
681+
this.showImportModal.set(false);
682+
this.importMode.set(null);
683+
}
684+
536685
deleteEntity(id: string): void {
537686
if (confirm('Are you sure you want to delete this entity?')) {
538687
this.configBuilder.removeEntity(id);

src/app/pages/config-wizard/tabs/runtime-tab/runtime-tab.component.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ import { ConfigBuilderService } from '../../../../services/config-builder.servic
276276
<select
277277
id="authProvider"
278278
class="form-select"
279-
[ngModel]="configBuilder.hostConfig().authentication?.provider || 'AppService'"
279+
[ngModel]="configBuilder.hostConfig().authentication?.provider || 'None'"
280280
(ngModelChange)="setAuthProvider($event)"
281281
>
282282
@for (provider of authProviders; track provider.value) {
@@ -314,6 +314,11 @@ import { ConfigBuilderService } from '../../../../services/config-builder.servic
314314
<div class="alert alert-info mb-0 mt-2">
315315
<small>
316316
@switch (configBuilder.hostConfig().authentication?.provider) {
317+
@case ('None') {
318+
<strong>No Authentication:</strong> All requests will be allowed without
319+
authentication. Use only for development or when authentication is handled
320+
externally.
321+
}
317322
@case ('EntraID') {
318323
<strong>Microsoft Entra ID:</strong> Configure JWT audience and issuer from
319324
your app registration.
@@ -331,7 +336,9 @@ import { ConfigBuilderService } from '../../../../services/config-builder.servic
331336
authenticated requests.
332337
}
333338
@default {
334-
Select an authentication provider to see configuration guidance.
339+
<strong>No Authentication:</strong> All requests will be allowed without
340+
authentication. Use only for development or when authentication is handled
341+
externally.
335342
}
336343
}
337344
</small>
@@ -352,6 +359,7 @@ export class RuntimeTabComponent {
352359
protected readonly configBuilder = inject(ConfigBuilderService);
353360

354361
readonly authProviders: { value: AuthProvider; label: string }[] = [
362+
{ value: 'None', label: 'None (No Authentication)' },
355363
{ value: 'AppService', label: 'Azure App Service' },
356364
{ value: 'EntraID', label: 'Microsoft Entra ID' },
357365
{ value: 'StaticWebApps', label: 'Azure Static Web Apps' },
@@ -399,13 +407,20 @@ export class RuntimeTabComponent {
399407

400408
setAuthProvider(provider: AuthProvider): void {
401409
const current = this.configBuilder.hostConfig();
402-
this.configBuilder.setHostConfig({
403-
authentication: {
404-
...current.authentication,
405-
provider,
406-
jwt: this.requiresJwt() ? current.authentication?.jwt : undefined,
407-
},
408-
});
410+
if (provider === 'None') {
411+
// Remove authentication section entirely
412+
this.configBuilder.setHostConfig({
413+
authentication: undefined,
414+
});
415+
} else {
416+
this.configBuilder.setHostConfig({
417+
authentication: {
418+
...current.authentication,
419+
provider,
420+
jwt: this.requiresJwt() ? current.authentication?.jwt : undefined,
421+
},
422+
});
423+
}
409424
}
410425

411426
setJwtField(field: 'audience' | 'issuer', value: string): void {

src/app/services/config-builder.service.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,23 @@ export class ConfigBuilderService {
174174
entitiesConfig[entity.name] = this.buildEntityConfig(entity);
175175
}
176176

177+
// Build host config, excluding authentication if not configured or set to 'None'
178+
const hostConfig = this.hostConfig();
179+
const cleanedHostConfig: IHostConfig = {
180+
cors: hostConfig.cors,
181+
mode: hostConfig.mode,
182+
};
183+
184+
// Only include authentication if it exists and provider is not 'None'
185+
if (hostConfig.authentication && hostConfig.authentication.provider !== 'None') {
186+
cleanedHostConfig.authentication = hostConfig.authentication;
187+
}
188+
177189
const runtime: IRuntimeConfig = {
178190
rest: this.restConfig(),
179191
graphql: this.graphqlConfig(),
180192
mcp: this.mcpConfig(),
181-
host: this.hostConfig(),
193+
host: cleanedHostConfig,
182194
};
183195

184196
return {

src/index.html

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<!doctype html>
22
<html lang="en">
3-
<head>
4-
<meta charset="utf-8">
5-
<title>IntelliTectSqlMcpConfiguration</title>
6-
<base href="/">
7-
<meta name="viewport" content="width=device-width, initial-scale=1">
8-
<link rel="icon" type="image/x-icon" href="favicon.ico">
9-
</head>
10-
<body>
11-
<app-root></app-root>
12-
</body>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>SQL MCP Configuration</title>
6+
<base href="/" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1" />
8+
<link rel="icon" type="image/x-icon" href="favicon.ico" />
9+
</head>
10+
<body>
11+
<app-root></app-root>
12+
</body>
1313
</html>

0 commit comments

Comments
 (0)