Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
36f5bf3
Add model code for saving the database data properly. New schema-disc…
romanost03 Apr 2, 2025
6bbb47d
Change code for table-selection-dialog such that it opens a new windo…
romanost03 Apr 2, 2025
67ec616
Code change such that a small preview is given in the table-selection…
romanost03 Apr 13, 2025
ded1f8d
Added code snippets for a dataPreview-Request already with functional…
romanost03 Apr 18, 2025
ca1d054
Hardcoded PostgreSQL entity request for schema discovery
romanost03 Apr 23, 2025
920de41
Hardcoded PostgreSQL entity request is now processed properly and cor…
romanost03 Apr 25, 2025
acbb8c8
Selected metadata sends back to the Backend now
romanost03 Apr 30, 2025
1541600
Adapter deployment and entity request is not hardcodet anymore, so th…
romanost03 May 4, 2025
fbd79dc
Preview of data is shown on the right half of the window.
romanost03 May 9, 2025
29fe5b8
table-selection-dialog.component.html shows all previews instead of o…
romanost03 May 9, 2025
17ecf21
New added preview request such that form-data is nwo send with (for e…
romanost03 May 18, 2025
8b47a09
Newly created UI for preview request with new receiving model in prev…
romanost03 Jun 2, 2025
05e6a1c
Moving preview-selection component into UI-framework and add new http…
romanost03 Jun 13, 2025
4c1575e
Add new context for metadata change instead of deploying
romanost03 Jun 14, 2025
4af9cf3
Sending changed metadata (ack) correct to backend.
romanost03 Jun 15, 2025
6b73826
Add code for manually reconfigure metadata of a source.
romanost03 Jun 16, 2025
19b7c56
Code for collecting aliases when deploying new source.
romanost03 Jun 16, 2025
8076948
Collecting metadata automatically when it is ghost-node.
romanost03 Jun 20, 2025
0d9131c
Adding and removing metadata are now treated separately.
romanost03 Jun 21, 2025
77aaeff
Metadata for reconfiguration are collected and sent.
romanost03 Jun 21, 2025
4da1f1e
Differ between critical metadata changes and warnings of change
romanost03 Jun 23, 2025
8a2598f
Add code for preview document source and adding logs for every source.
romanost03 Jun 30, 2025
21cb891
Change logs are displayed only once.
romanost03 Jun 30, 2025
7390000
Change routing when deploying new source. Bugfix for metadata logs: N…
romanost03 Jul 1, 2025
c02b70a
Minor UI improvements.
romanost03 Jul 16, 2025
d330261
Change save button for reconfigure an adapter.
romanost03 Jul 30, 2025
e158f44
UI improvements and functionality for changing adapter credentials.
romanost03 Aug 5, 2025
b3a95e6
Send correct request for building ephemeral adapter on backend-side.
romanost03 Aug 6, 2025
bf635d2
Configuration button does not work during a CRITICAL change.
romanost03 Aug 11, 2025
80bd497
Minor UI improvements and code cleaning.
romanost03 Aug 11, 2025
be1d8de
Functionality to add multiple metadata with one click.
romanost03 Aug 11, 2025
450be9e
Bugfix: Removed metadata cannot be selected.
romanost03 Aug 12, 2025
43eae63
Code cleaning and minor improvements.
romanost03 Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,168 changes: 1,168 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

29 changes: 15 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@angular/core": "^17.2.3",
"@angular/elements": "^17.2.3",
"@angular/forms": "^17.2.3",
"@angular/material": "^17.2.1",
"@angular/platform-browser": "^17.2.3",
"@angular/platform-browser-dynamic": "^17.2.3",
"@angular/router": "^17.2.3",
Expand Down Expand Up @@ -59,6 +60,16 @@
"ngx-markdown": "^17.1.1",
"ngx-plyr": "^4.0.1",
"prismjs": "1.29.0",
"rete": "^2.0.3",
"rete-angular-plugin": "^2.1.1",
"rete-area-plugin": "^2.0.4",
"rete-auto-arrange-plugin": "^2.0.1",
"rete-connection-path-plugin": "^2.0.3",
"rete-connection-plugin": "^2.0.1",
"rete-context-menu-plugin": "^2.0.3",
"rete-engine": "^2.0.1",
"rete-readonly-plugin": "^2.0.1",
"rete-render-utils": "^2.0.2",
"rxjs": "^7.8.1",
"rxjs-compat": "^6.5.5",
"sass": "^1.26.3",
Expand All @@ -67,17 +78,7 @@
"ts-helpers": "^1.1.2",
"ts-md5": "^1.2.7",
"uuid": "^9.0.0",
"zone.js": "~0.14.4",
"rete": "^2.0.3",
"rete-angular-plugin": "^2.1.1",
"rete-connection-plugin": "^2.0.1",
"rete-auto-arrange-plugin": "^2.0.1",
"rete-area-plugin": "^2.0.4",
"rete-render-utils": "^2.0.2",
"rete-readonly-plugin": "^2.0.1",
"rete-connection-path-plugin": "^2.0.3",
"rete-context-menu-plugin": "^2.0.3",
"rete-engine": "^2.0.1"
"zone.js": "~0.14.4"
},
"devDependencies": {
"@angular-builders/custom-webpack": "^17.0.1",
Expand All @@ -86,6 +87,7 @@
"@angular/compiler-cli": "^17.2.3",
"@angular/language-service": "^17.2.3",
"@ngtools/webpack": "^17.2.2",
"@types/d3-shape": "^3.1.6",
"@types/hammerjs": "^2.0.36",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "^2.0.8",
Expand All @@ -108,11 +110,10 @@
"tslint": "~6.1.0",
"typescript": "^5.3.3",
"webpack": "^5.54.0",
"webpack-bundle-analyzer": "^4.9.0",
"@types/d3-shape": "^3.1.6"
"webpack-bundle-analyzer": "^4.9.0"
},
"engines": {
"node": ">= 16.3.0",
"npm": ">= 5.6.0"
}
}
}
8 changes: 8 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {DefaultLayoutComponent} from './containers/default-layout';
import {P404Component} from './views/error/404.component';
import {P500Component} from './views/error/500.component';
import {LoginComponent} from './views/login/login.component';
import {TableSelectionDialogComponent} from './components/table-selection-dialog/table-selection-dialog.component';


export const routes: Routes = [
Expand All @@ -28,6 +29,13 @@ export const routes: Routes = [
title: 'Login Page'
}
},
{
path: 'table-selection',
component: TableSelectionDialogComponent,
data: {
title: 'Table Selection'
}
},
{
path: '',
pathMatch: 'full',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<button cButton size="sm" class="bg-transparent border-0">
<!--<button cButton size="sm" class="bg-transparent border-0">
<i id="delete" (click)="onClick()" (mouseleave)="confirm = false" class="text-danger"
[ngClass]="{ 'cil-trash': !confirm, 'fa fa-warning': confirm }"></i>
</button>
</button>-->
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<div style="display: flex; height: 80vh">
<div style="flex: 1; overflow-y: auto; padding: 1rem; border-right: 1px solid #ccc">
<h2>Tabellen auswählen</h2>

<div *ngFor="let db of data">
<h3>📦 {{ db.name }}</h3>
<div *ngFor="let schema of db.schemas">
<h4>📁 {{ schema.name }}</h4>
<ul>
<li *ngFor="let table of schema.tables">
<label>
📄 {{ db.name }}.{{ schema.name }}.{{ table.name }}
</label>
<ul>
<li *ngFor="let attr of table.attributes">
<label>
<input type="checkbox" [(ngModel)]="attr.selected"/>
🔹 {{ attr.name }} : {{ attr.type }}
</label>
</li>
</ul>
</li>
</ul>
</div>
</div>

<div style="margin-top: 1rem">
<button (click)="close()">Schließen</button>
<button (click)="showSelectedMetadata()">Ausgewählte anzeigen</button>
<button (click)="sendMetadataInfos()">Sende Metadaten</button>
</div>
</div>

<div style="flex: 2.5; padding: 1rem; overflow-x: auto; display: flex; gap: 2rem; border-left: 1px solid #ccc">

<div *ngFor="let name of getTableNames()">
<div *ngIf="tablePreviewAll[name]?.length">
<h3>{{ name }}</h3>

<table border="1" cellpadding="5" cellspacing="0">
<thead>
<tr>
<th *ngFor="let key of getKeys(tablePreviewAll[name])">{{ key }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tablePreviewAll[name]">
<td *ngFor="let key of getKeys(tablePreviewAll[name])">
{{ row[key] }}
</td>
</tr>
</tbody>
</table>
</div>
</div>

</div>

</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TableSelectionDialogComponent } from './table-selection-dialog.component';

// @ts-ignore
describe('TableSelectionDialogComponent', () => {
let component: TableSelectionDialogComponent;
let fixture: ComponentFixture<TableSelectionDialogComponent>;

// @ts-ignore
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TableSelectionDialogComponent]
})
.compileComponents();

fixture = TestBed.createComponent(TableSelectionDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

// @ts-ignore
it('should create', () => {
// @ts-ignore
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import {Component, inject} from '@angular/core';
import {DatabaseInfo, SchemaInfo, TableInfo} from '../../models/databaseInfo.model';
import {FormsModule} from '@angular/forms';
import {NgForOf, NgIf} from '@angular/common';
import {CrudService} from '../../services/crud.service';
import {AdapterModel, AdapterType, PolyMap} from '../../views/adapters/adapter.model';
import {DeployMode} from '../../models/catalog.model';

@Component({
selector: 'app-table-selection-dialog',
imports: [
FormsModule,
NgForOf,
NgIf
],
templateUrl: './table-selection-dialog.component.html',
standalone: true,
styleUrl: './table-selection-dialog.component.scss'
})
export class TableSelectionDialogComponent {

private readonly _crud = inject(CrudService);

data: DatabaseInfo[] = [];
selectedMetadata: string[] = [];
adapter: AdapterModel;

tablePreviewName = '';
tablePreview: any[] = [];
previewKeys: string[] = [];

tablePreviewAll: { [tableName: string]: any[] } = {};


close(): void {
window.close();
}

ngOnInit(): void {
const rawSettings = localStorage.getItem('adapterSettings');
const metaRaw = localStorage.getItem('metaRoot');
const previewRaw = localStorage.getItem('preview');
console.log(metaRaw);
console.log(previewRaw);

const settingsObj = rawSettings ? JSON.parse(rawSettings) as Record<string, string> : {};
const adapterSettings = new PolyMap<string, string>();
for (const [k, v] of Object.entries(settingsObj)) {
adapterSettings.set(k, v as string);
}

if (!metaRaw || !previewRaw) {
console.error('No meta or preview data found');
return;
}

let rootNode: any = JSON.parse(metaRaw);
if (typeof rootNode === 'string') {
rootNode = JSON.parse(rootNode);
}

let preview: any = JSON.parse(previewRaw);
if (typeof preview === 'string') {
preview = JSON.parse(preview);
}

this.tablePreviewAll = preview;
const [name, rawRows] = Object.entries(preview)[0];
const rows = rawRows as any[];

this.tablePreviewName = name;
this.tablePreview = rows;
this.previewKeys = rows.length > 0 ? Object.keys(rows[0]) : [];


this.data = this.buildDatabaseInfo(rootNode, preview);

const infoRaw = localStorage.getItem('adapterInfo');
const info = infoRaw ? JSON.parse(infoRaw) as Partial<{
uniqueName: string;
adapterName: string;
type: AdapterType;
mode: DeployMode;
persistent: boolean;
}> : {};

this.adapter = new AdapterModel(
info.uniqueName ?? adapterSettings.get('uniqueName') ?? 'adapter_' + Date.now(),
info.adapterName ?? 'UNKNOWN',
adapterSettings,
info.persistent ?? true,
info.type ?? AdapterType.SOURCE,
info.mode ?? DeployMode.REMOTE
);
}

private buildDatabaseInfo(root: any, preview: any): DatabaseInfo[] {
const db: DatabaseInfo = {name: root.name, schemas: []};
for (const schemaNode of root.children ?? []) {

const schema: SchemaInfo = {name: schemaNode.name, tables: []};

for (const tableNode of schemaNode.children ?? []) {

const tableKey = `${schemaNode.name}.${tableNode.name}`;
const sampleRows = preview[tableKey] ?? [];

const table: TableInfo = {name: tableNode.name, attributes: []};

for (const colNode of tableNode.children ?? []) {
const colName = colNode.name;

table.attributes.push({
name: colName,
type: colNode.properties?.type ?? '',
selected: false,
sampleValues: sampleRows.slice(0, 5).map((r: any) => r[colName])
});
}
schema.tables.push(table);
}
db.schemas.push(schema);
}
this.data = [db];
return [db];
}

getSelectedAttributeMetadata(): string[] {
const selected: string[] = [];

for (const db of this.data) {
for (const schema of db.schemas) {
for (const table of schema.tables) {
for (const attr of table.attributes) {
if (attr.selected) {
selected.push(
`${db.name}.${schema.name}.${table.name}.${attr.name} : ${attr.type}`
);
}
}
}
}
}

return selected;
}

showSelectedMetadata(): void {
this.selectedMetadata = this.getSelectedAttributeMetadata();
console.log(this.selectedMetadata);
}

getKeys(rows: any[]): string[] {
return rows.length > 0 ? Object.keys(rows[0]) : [];
}

getTableNames(): string[] {
return Object.keys(this.tablePreviewAll);
}


sendMetadataInfos(): void {


(this.adapter as any).metadata = this.selectedMetadata;

const formdata = new FormData();
formdata.set('body', JSON.stringify(this.adapter));

formdata.forEach((value, key) => {
console.log(`${key}: ${value}`);
});

this._crud.createAdapter(this.adapter, formdata).subscribe({
next: (res) => {
console.log('Adapter + Metadaten erfolgreich gesendet', res);
alert('Daten erfolgreich gesendet.');
},
error: (err) => {
console.error(err);
alert('Fehler beim Senden!');
}
});
}


}

21 changes: 21 additions & 0 deletions src/app/models/databaseInfo.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface DatabaseInfo {
name: string;
schemas: SchemaInfo[];
}

export interface TableInfo {
name: string;
attributes: AttributeInfo[];
}

export interface SchemaInfo {
name: string;
tables: TableInfo[];
}

export interface AttributeInfo {
name: String;
type: String;
sampleValues?: string[];
selected?: boolean;
}
Loading