Add System component with table display for custom and all beans
This commit is contained in:
@@ -106,6 +106,8 @@ To run the application in Docker, follow these steps:
|
||||
```bash
|
||||
docker-compose -f src/Docker/docker-compose.yml up -d
|
||||
```
|
||||
- For connection from pgadmin use
|
||||
hostename: **host.docker.internal**
|
||||
### Reference Documentation
|
||||
For further reference, please consider the following sections:
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
com.jambotronGroup.jambotron: DEBUG
|
||||
org.springframework: WARN
|
||||
pattern:
|
||||
console: "%d{yyyy-MM-dd HH:mm:ss} %-5level - %msg%n"
|
||||
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
|
||||
file:
|
||||
name: logs/application.log
|
||||
max-size: 10MB
|
||||
max-history: 30
|
||||
@@ -35,8 +35,25 @@ dependencies {
|
||||
implementation 'org.flywaydb:flyway-core'
|
||||
implementation("org.flywaydb:flyway-database-postgresql:10.4.1")
|
||||
|
||||
//implementation 'org.springframework.ai:spring-ai-starter-model-zhipuai'
|
||||
//implementation 'org.springframework.ai:spring-ai-zhipuai-spring-boot-starter'
|
||||
//implementation platform("org.springframework.ai:spring-ai-bom:1.0.0-SNAPSHOT")
|
||||
// Replace the following with the starter dependencies of specific modules you wish to use
|
||||
//implementation 'org.springframework.ai:spring-ai-zhipuai'
|
||||
//implementation 'org.springframework.boot:spring-boot-starter-webflux'
|
||||
//implementation("org.springframework.ai:spring-ai-spring-boot-autoconfigure:1.0.0-M6")
|
||||
// https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-retry
|
||||
//implementation("org.springframework.ai:spring-ai-retry:1.0.0")
|
||||
//implementation group: 'org.springframework.ai', name: 'spring-ai-spring-boot-autoconfigure', version: '1.0.0-M6'
|
||||
}
|
||||
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom ("org.springframework.ai:spring-ai-retry:1.0.0")
|
||||
}
|
||||
}
|
||||
|
||||
// copyResouces( type:Copy
|
||||
|
||||
//tasks copyResouces( type:Copy){
|
||||
|
||||
@@ -10,6 +10,8 @@ import { ProfileComponent } from './components/profile/profile.component';
|
||||
import { RegisterComponent } from './components/register/register.component';
|
||||
import { LoginComponent } from './components/login/login.component';
|
||||
import { HomeComponent } from './components/home/home.component';
|
||||
import {SystemComponent} from './components/system.component/system.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: 'home', component: HomeComponent },
|
||||
@@ -22,11 +24,12 @@ const routes: Routes = [
|
||||
{ path: '', redirectTo: 'home', pathMatch: 'full' },
|
||||
{ path: 'tutorials', component: TutorialsListComponent },
|
||||
{ path: 'tutorials/:id', component: TutorialDetailsComponent },
|
||||
{ path: 'add', component: AddTutorialComponent }
|
||||
{ path: 'add', component: AddTutorialComponent },
|
||||
{ path: 'system', component: SystemComponent}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, {useHash: true})],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
export class AppRoutingModule { }
|
||||
|
||||
@@ -1,52 +1,3 @@
|
||||
<div>
|
||||
<!-- <nav class="navbar navbar-expand navbar-dark bg-dark">
|
||||
<a href="#" class="navbar-brand">Spring-AngularTS</a>
|
||||
|
||||
<ul class="navbar-nav mr-auto" routerLinkActive="active">
|
||||
|
||||
<li class="nav-item">
|
||||
<a routerLink="tutorials" class="nav-link">Tutorials</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a routerLink="add" class="nav-link">Add</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" *ngIf="showAdminBoard">
|
||||
<a href="/admin" class="nav-link" routerLink="admin">Admin Board</a>
|
||||
</li>
|
||||
<li class="nav-item" *ngIf="showModeratorBoard">
|
||||
<a href="/mod" class="nav-link" routerLink="mod">Moderator Board</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/user" class="nav-link" *ngIf="isLoggedIn" routerLink="user">User</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav ml-auto" *ngIf="!isLoggedIn">
|
||||
<li class="nav-item">
|
||||
<a href="/register" class="nav-link" routerLink="register">Sign Up</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/login" class="nav-link" routerLink="login">Login</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav ml-auto" *ngIf="isLoggedIn">
|
||||
<li class="nav-item">
|
||||
<a href="/profile" class="nav-link" routerLink="profile">{{ username }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href class="nav-link" (click)="logout()">LogOut</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</nav>-->
|
||||
|
||||
<div class="card flex justify-center">
|
||||
<p-button label="Check" />
|
||||
</div>
|
||||
|
||||
|
||||
<mat-toolbar class="fixed-top">
|
||||
<button mat-raised-button routerLink="/" href="#">
|
||||
@@ -67,6 +18,13 @@
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (showAdminBoard) {
|
||||
<button mat-raised-button routerLink="system" >
|
||||
<mat-icon>settings_applications</mat-icon>
|
||||
System
|
||||
</button>
|
||||
}
|
||||
|
||||
<span class="example-spacer"></span>
|
||||
<button mat-raised-button routerLink="register" *ngIf="!isLoggedIn">
|
||||
<mat-icon>app_registration</mat-icon>
|
||||
@@ -94,4 +52,4 @@
|
||||
<div class="router_outlet_padding">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
|
||||
<mat-card>
|
||||
<mat-card-header>
|
||||
<mat-card-title>System</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Custom beans">
|
||||
Content 1
|
||||
<table mat-table
|
||||
[dataSource]="customBeans" multiTemplateDataRows="true" class="mat-elevation-z8">
|
||||
@for (column of displayedColumns; track column) {
|
||||
<ng-container matColumnDef="{{column}}">
|
||||
<th mat-header-cell *matHeaderCellDef>{{column}}</th>
|
||||
<td mat-cell *matCellDef="let element ; let k = dataIndex;">{{element[column]}}</td>
|
||||
</ng-container>
|
||||
}
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions"> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button
|
||||
matIconButton
|
||||
aria-label="expand row"
|
||||
(click)="toggle(element); $event.stopPropagation()"
|
||||
class="example-toggle-button"
|
||||
[class.example-toggle-button-expanded]="isExpanded(element)">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail-wrapper"
|
||||
[class.example-element-detail-wrapper-expanded]="isExpanded(element)">
|
||||
<div class="example-element-detail">
|
||||
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">Name: {{element.name}}</mat-list-item>
|
||||
<mat-list-item role="listitem">Type: {{element.type}}</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="isExpanded(element)"
|
||||
(click)="toggle(element)">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
|
||||
</mat-tab>
|
||||
<mat-tab label="All beans">
|
||||
Content 2
|
||||
<table mat-table
|
||||
[dataSource]="allBeans" multiTemplateDataRows="true" class="mat-elevation-z8">
|
||||
@for (column of displayedColumns; track column) {
|
||||
<ng-container matColumnDef="{{column}}">
|
||||
<th mat-header-cell *matHeaderCellDef>{{column}}</th>
|
||||
<td mat-cell *matCellDef="let element ; let k = dataIndex;">{{element[column]}}</td>
|
||||
</ng-container>
|
||||
}
|
||||
<ng-container matColumnDef="expand">
|
||||
<th mat-header-cell *matHeaderCellDef aria-label="row actions"> </th>
|
||||
<td mat-cell *matCellDef="let element">
|
||||
<button
|
||||
matIconButton
|
||||
aria-label="expand row"
|
||||
(click)="toggle(element); $event.stopPropagation()"
|
||||
class="example-toggle-button"
|
||||
[class.example-toggle-button-expanded]="isExpanded(element)">
|
||||
<mat-icon>keyboard_arrow_down</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
|
||||
<ng-container matColumnDef="expandedDetail">
|
||||
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
|
||||
<div class="example-element-detail-wrapper"
|
||||
[class.example-element-detail-wrapper-expanded]="isExpanded(element)">
|
||||
<div class="example-element-detail">
|
||||
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">Name: {{element.name}}</mat-list-item>
|
||||
<mat-list-item role="listitem">Type: {{element.type}}</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
|
||||
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;"
|
||||
class="example-element-row"
|
||||
[class.example-expanded-row]="isExpanded(element)"
|
||||
(click)="toggle(element)">
|
||||
</tr>
|
||||
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
|
||||
</table>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,113 @@
|
||||
mat-card{
|
||||
margin: 20px;
|
||||
background-color: rgba(240, 248, 255, 0.7);
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
|
||||
mat-card-title{
|
||||
color: cyan;
|
||||
}
|
||||
|
||||
mat-card-subtitle{
|
||||
color: #009dff;
|
||||
}
|
||||
|
||||
mat-tab{
|
||||
color:black;
|
||||
}
|
||||
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
color:lightgrey;
|
||||
}
|
||||
|
||||
|
||||
mat-list{
|
||||
//background-color: #1389d3;
|
||||
color:black;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
mat-list-item{
|
||||
margin: 10px 10px 10px 10px;
|
||||
background-color: #447694;
|
||||
|
||||
color: #009dff;
|
||||
}
|
||||
|
||||
tr.example-detail-row {
|
||||
height: 0;
|
||||
background: #fffdfd;
|
||||
}
|
||||
|
||||
tr.example-element-row {
|
||||
cursor: pointer;
|
||||
color: #1389d3;
|
||||
background: #fffdfd;
|
||||
}
|
||||
|
||||
tr.example-element-row:not(.example-expanded-row):hover {
|
||||
background: whitesmoke;
|
||||
}
|
||||
|
||||
tr.example-element-row:not(.example-expanded-row):active {
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
.example-element-row td {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.example-element-detail-wrapper {
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-rows: 0fr;
|
||||
grid-template-columns: 100%;
|
||||
transition: grid-template-rows 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.example-element-detail-wrapper-expanded {
|
||||
grid-template-rows: 1fr;
|
||||
|
||||
}
|
||||
|
||||
.example-element-detail {
|
||||
display: flex;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.example-element-diagram {
|
||||
min-width: 80px;
|
||||
border: 2px solid black;
|
||||
padding: 8px;
|
||||
font-weight: lighter;
|
||||
margin: 8px 0;
|
||||
height: 104px;
|
||||
}
|
||||
|
||||
.example-element-symbol {
|
||||
font-weight: bold;
|
||||
font-size: 40px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.example-element-description {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.example-element-description-attribution {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.example-toggle-button {
|
||||
transition: transform 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.example-toggle-button-expanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SystemComponent } from './system.component';
|
||||
|
||||
describe('SystemComponent', () => {
|
||||
let component: SystemComponent;
|
||||
let fixture: ComponentFixture<SystemComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [SystemComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(SystemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Bean} from '../../models/Bean';
|
||||
import {SystemService} from '../../services/system.service';
|
||||
import {
|
||||
MatCard,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatCardSubtitle,
|
||||
MatCardTitle,
|
||||
MatCardTitleGroup
|
||||
} from '@angular/material/card';
|
||||
import {MatDivider} from '@angular/material/divider';
|
||||
import {
|
||||
MatCell,
|
||||
MatCellDef,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef, MatHeaderRow,
|
||||
MatHeaderRowDef, MatRow, MatRowDef,
|
||||
MatTable
|
||||
} from '@angular/material/table';
|
||||
import {MatIconButton} from '@angular/material/button';
|
||||
import {MatIcon} from '@angular/material/icon';
|
||||
import {MatList, MatListItem} from '@angular/material/list';
|
||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-system.component',
|
||||
imports: [
|
||||
MatCard,
|
||||
MatCardSubtitle,
|
||||
MatCardContent,
|
||||
MatCardHeader,
|
||||
MatCardTitle,
|
||||
MatDivider,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatCell,
|
||||
MatIconButton,
|
||||
MatIcon,
|
||||
MatHeaderCellDef,
|
||||
MatCellDef,
|
||||
MatHeaderRowDef,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatHeaderRow,
|
||||
MatList,
|
||||
MatListItem,
|
||||
MatTabGroup,
|
||||
MatTab
|
||||
],
|
||||
templateUrl: './system.component.html',
|
||||
styleUrl: './system.component.scss'
|
||||
})
|
||||
export class SystemComponent {
|
||||
|
||||
// @ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
// @ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
customBeans:Bean[] = [] ;
|
||||
allBeans:Bean[] = [] ;
|
||||
displayedColumns: string[] = ['shortName', 'typeShortName', 'scope'];
|
||||
|
||||
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
|
||||
|
||||
expandedElement: Bean | null = null;
|
||||
|
||||
resultsLength = 0;
|
||||
isLoadingResults = true;
|
||||
isRateLimitReached = false;
|
||||
|
||||
constructor(private systemService: SystemService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.retrieveBeans();
|
||||
}
|
||||
|
||||
retrieveBeans(): void {
|
||||
this.systemService.getCustomBeans()
|
||||
.subscribe(
|
||||
(data: Bean[]) => {
|
||||
this.customBeans = data;
|
||||
console.log(data);
|
||||
},
|
||||
(error: any) => {
|
||||
console.log(error);
|
||||
});
|
||||
this.systemService.getAllBeans()
|
||||
.subscribe(
|
||||
(data: Bean[]) => {
|
||||
this.allBeans = data;
|
||||
console.log(data);
|
||||
},
|
||||
(error: any) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
/** Checks whether an element is expanded. */
|
||||
isExpanded(element: Bean) {
|
||||
return this.expandedElement === element;
|
||||
}
|
||||
|
||||
/** Toggles the expanded state of an element. */
|
||||
toggle(element: Bean) {
|
||||
this.expandedElement = this.isExpanded(element) ? null : element;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ngAfterViewInit() {
|
||||
//this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
|
||||
|
||||
// If the user changes the sort order, reset back to the first page.
|
||||
/* this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0));
|
||||
|
||||
merge(this.sort.sortChange, this.paginator.page)
|
||||
.pipe(
|
||||
startWith({}),
|
||||
switchMap(() => {
|
||||
this.isLoadingResults = true;
|
||||
return this.exampleDatabase!.getRepoIssues(
|
||||
this.sort.active,
|
||||
this.sort.direction,
|
||||
this.paginator.pageIndex,
|
||||
).pipe(catchError(() => observableOf(null)));
|
||||
}),
|
||||
map(data => {
|
||||
// Flip flag to show that loading has finished.
|
||||
this.isLoadingResults = false;
|
||||
this.isRateLimitReached = data === null;
|
||||
|
||||
if (data === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Only refresh the result length if there is new data. In case of rate
|
||||
// limit errors, we do not want to reset the paginator to zero, as that
|
||||
// would prevent users from re-triggering requests.
|
||||
this.resultsLength = data.total_count;
|
||||
return data.items;
|
||||
}),
|
||||
)
|
||||
.subscribe(data => (this.data = data));*/
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ColumnResizeDirective } from './column-resize.directive';
|
||||
|
||||
describe('ColumnResizeDirective', () => {
|
||||
it('should create an instance', () => {
|
||||
const directive = new ColumnResizeDirective();
|
||||
expect(directive).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Renderer2,
|
||||
NgZone,
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
import { Subject, fromEvent, takeUntil } from 'rxjs';
|
||||
|
||||
@Directive({
|
||||
selector: '[appColumnResize]',
|
||||
})
|
||||
export class ColumnResizeDirective implements OnInit, OnDestroy {
|
||||
@Input() resizableTable: HTMLElement | null = null;
|
||||
|
||||
private isResizing = false;
|
||||
private startX!: number;
|
||||
private startWidth!: number;
|
||||
private column: HTMLElement;
|
||||
private table: HTMLElement | null = null;
|
||||
private resizer!: HTMLElement;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
private renderer: Renderer2,
|
||||
private zone: NgZone
|
||||
) {
|
||||
this.column = this.el.nativeElement;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.table = this.resizableTable || this.findParentTable(this.column);
|
||||
|
||||
if (!this.table) {
|
||||
console.error(
|
||||
'Parent table not found. Make sure the directive is applied to a th element within a table.'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.createResizer();
|
||||
this.initializeResizeListener();
|
||||
}
|
||||
|
||||
private createResizer() {
|
||||
this.resizer = this.renderer.createElement('div');
|
||||
this.renderer.addClass(this.resizer, 'column-resizer');
|
||||
this.renderer.setStyle(this.resizer, 'position', 'absolute');
|
||||
this.renderer.setStyle(this.resizer, 'right', '0');
|
||||
this.renderer.setStyle(this.resizer, 'top', '0');
|
||||
this.renderer.setStyle(this.resizer, 'height', '100%');
|
||||
this.renderer.setStyle(this.resizer, 'width', '5px');
|
||||
this.renderer.setStyle(this.resizer, 'cursor', 'col-resize');
|
||||
this.renderer.appendChild(this.column, this.resizer);
|
||||
}
|
||||
|
||||
private initializeResizeListener() {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
fromEvent(this.resizer, 'mousedown')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((e: Event) => this.onMouseDown(e as MouseEvent));
|
||||
|
||||
fromEvent(document, 'mousemove')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((e: Event) => this.onMouseMove(e as MouseEvent));
|
||||
|
||||
fromEvent(document, 'mouseup')
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(() => this.onMouseUp());
|
||||
});
|
||||
}
|
||||
|
||||
private onMouseDown(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
this.isResizing = true;
|
||||
this.startX = e.pageX;
|
||||
this.startWidth = this.column.offsetWidth;
|
||||
this.renderer.addClass(this.column, 'resizing');
|
||||
if (this.table) {
|
||||
this.renderer.addClass(this.table, 'resizing');
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseMove(e: MouseEvent) {
|
||||
if (!this.isResizing) return;
|
||||
const width = this.startWidth + (e.pageX - this.startX);
|
||||
this.renderer.setStyle(this.column, 'width', `${width}px`);
|
||||
}
|
||||
|
||||
private onMouseUp() {
|
||||
if (!this.isResizing) return;
|
||||
this.isResizing = false;
|
||||
this.renderer.removeClass(this.column, 'resizing');
|
||||
if (this.table) {
|
||||
this.renderer.removeClass(this.table, 'resizing');
|
||||
}
|
||||
}
|
||||
|
||||
private findParentTable(element: HTMLElement): HTMLElement | null {
|
||||
while (element && element.tagName !== 'TABLE') {
|
||||
element = element.parentElement as HTMLElement;
|
||||
if (!element) return null;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export class Bean {
|
||||
name?:string;
|
||||
shortName?:string;
|
||||
type?:string;
|
||||
typeShortName?:string;
|
||||
scope?:string;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SystemService } from './system.service';
|
||||
|
||||
describe('SystemService', () => {
|
||||
let service: SystemService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(SystemService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {Observable} from 'rxjs';
|
||||
import {Tutorial} from '../models/tutorial.model';
|
||||
import {Bean} from '../models/Bean';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SystemService {
|
||||
|
||||
baseUrl : string = 'http://localhost:8080/api/system';
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getAllBeans(): Observable<Bean[]> {
|
||||
return this.http.get<Bean[]>(this.baseUrl+"/beans");
|
||||
}
|
||||
|
||||
getCustomBeans(): Observable<Bean[]> {
|
||||
return this.http.get<Bean[]>(this.baseUrl+"/beans/custom");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,27 @@
|
||||
package com.jambotronGroup.jambotron;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.event.Level;
|
||||
import org.slf4j.helpers.BasicMarker;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
@SpringBootApplication
|
||||
public class JambotronApplication {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JambotronApplication.class);
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(JambotronApplication.class, args);
|
||||
|
||||
|
||||
logger.error("Application Run.");
|
||||
logger.debug("Application Run.");
|
||||
logger.info("Application Run.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.jambotronGroup.jambotron.ZhiPuAi;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
//import org.springframework.web.reactive.function.client.WebClient;
|
||||
//
|
||||
//@Service
|
||||
//public class ZhiPuAiImageService {
|
||||
//
|
||||
// @Value("${spring.ai.zhipuai.base-url}")
|
||||
// private String baseUrl;
|
||||
//
|
||||
// @Value("${spring.ai.zhipuai.api-key}")
|
||||
// private String apiKey;
|
||||
//
|
||||
// private final WebClient webClient;
|
||||
//
|
||||
// public ZhiPuAiImageService(WebClient.Builder webClientBuilder) {
|
||||
// this.webClient = webClientBuilder.baseUrl(baseUrl).build();
|
||||
// }
|
||||
//
|
||||
// public String generateImage(String prompt) {
|
||||
// return webClient.post()
|
||||
// .uri("/image/generate")
|
||||
// .header("Authorization", "Bearer " + apiKey)
|
||||
// .bodyValue(new ImageRequest(prompt))
|
||||
// .retrieve()
|
||||
// .bodyToMono(String.class)
|
||||
// .block();
|
||||
// }
|
||||
//
|
||||
// private static class ImageRequest {
|
||||
// private final String prompt;
|
||||
//
|
||||
// public ImageRequest(String prompt) {
|
||||
// this.prompt = prompt;
|
||||
// }
|
||||
//
|
||||
// public String getPrompt() {
|
||||
// return prompt;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.jambotronGroup.jambotron.controllers;
|
||||
|
||||
import com.jambotronGroup.jambotron.model.Bean;
|
||||
import com.jambotronGroup.jambotron.model.Setting;
|
||||
import com.jambotronGroup.jambotron.system.SystemService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600, allowCredentials="true")
|
||||
@RestController
|
||||
@RequestMapping("/api/system")
|
||||
public class SystemController {
|
||||
|
||||
@Autowired
|
||||
SystemService systemService;
|
||||
|
||||
|
||||
|
||||
@GetMapping("/beans")
|
||||
public ResponseEntity<List<Bean>> getLoadedBeans(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Bean> beans = systemService.getLodedBeans();
|
||||
//userRepository.findAll().forEach(users::add);
|
||||
|
||||
|
||||
if (beans.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(beans, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
@GetMapping("/beans/custom")
|
||||
public ResponseEntity<List<Bean>> getLoadedCustomBeans(@RequestParam(required = false) String title) {
|
||||
try {
|
||||
List<Bean> beans = systemService.getLodedCustomBeans();
|
||||
//userRepository.findAll().forEach(users::add);
|
||||
|
||||
|
||||
if (beans.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(beans, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.jambotronGroup.jambotron.controllers;
|
||||
|
||||
public class ZhiPuAiController {
|
||||
|
||||
// This class is a placeholder for the ZhiPuAiController.
|
||||
// You can implement methods to handle requests related to ZhiPuAi functionality.
|
||||
// For example, you might want to add methods for generating images or processing text.
|
||||
|
||||
// Example method (to be implemented):
|
||||
// @GetMapping("/generate-image")
|
||||
// public ResponseEntity<String> generateImage(@RequestParam String prompt) {
|
||||
// String imageUrl = zhiPuAiService.generateImage(prompt);
|
||||
// return new ResponseEntity<>(imageUrl, HttpStatus.OK);
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.jambotronGroup.jambotron.model;
|
||||
|
||||
import jakarta.persistence.EmbeddedId;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import lombok.ToString;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
|
||||
@Entity
|
||||
public class Bean {
|
||||
|
||||
|
||||
private String name;
|
||||
@Id
|
||||
private String shortName;
|
||||
private String type;
|
||||
private String typeShortName;
|
||||
private String scope;
|
||||
|
||||
public Bean(String name, String type, String scope) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.scope = scope;
|
||||
|
||||
this.shortName = getAfterLastDot(name);
|
||||
this.typeShortName = getAfterLastDot(type);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("name = %s type= %s", this.shortName, this.typeShortName);
|
||||
}
|
||||
|
||||
public String getAfterLastDot(String input) {
|
||||
if (input == null || !input.contains(".")) {
|
||||
return input; // Return the input if it's null or doesn't contain a dot
|
||||
}
|
||||
return input.substring(input.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public void setShortName(String shortName) {
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public String getTypeShortName() {
|
||||
return typeShortName;
|
||||
}
|
||||
|
||||
public void setTypeShortName(String typeShortName) {
|
||||
this.typeShortName = typeShortName;
|
||||
}
|
||||
}
|
||||
@@ -110,13 +110,16 @@ public class WebSecurityConfig {// extends WebSecurityConfigurerAdapter {
|
||||
.requestMatchers("/api/test/**").permitAll()
|
||||
.requestMatchers("/api/tutorials").permitAll()
|
||||
|
||||
.requestMatchers("api/users").permitAll()
|
||||
.requestMatchers("api/users/**").permitAll()
|
||||
.requestMatchers("/api/users").permitAll()
|
||||
.requestMatchers("/api/users/**").permitAll()
|
||||
|
||||
.requestMatchers("api/roles").permitAll()
|
||||
.requestMatchers("api/roles/**").permitAll()
|
||||
.requestMatchers("/api/roles").permitAll()
|
||||
.requestMatchers("/api/roles/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/tutorials/**").permitAll()
|
||||
|
||||
.requestMatchers("/api/settings").permitAll()
|
||||
.requestMatchers("/api/system/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.jambotronGroup.jambotron.system;
|
||||
|
||||
import com.jambotronGroup.jambotron.model.Bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SystemService {
|
||||
List<Bean> getLodedBeans();
|
||||
|
||||
List<Bean> getLodedCustomBeans();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.jambotronGroup.jambotron.system;
|
||||
|
||||
import com.jambotronGroup.jambotron.JambotronApplication;
|
||||
import com.jambotronGroup.jambotron.model.Bean;
|
||||
import com.jambotronGroup.jambotron.utils.EntityLoggingConsumer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class SystemServiceImpl implements SystemService {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SystemServiceImpl.class);
|
||||
|
||||
|
||||
@Override
|
||||
public List<Bean> getLodedBeans() {
|
||||
// Get all bean names from the application context and map them to Bean objects
|
||||
List<Bean> beans = Arrays.stream(applicationContext.getBeanDefinitionNames()).map(
|
||||
name -> new Bean(name, applicationContext.getType(name).getName(),applicationContext.getApplicationName()))
|
||||
|
||||
.toList();
|
||||
beans.forEach(new EntityLoggingConsumer(logger));
|
||||
return beans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Bean> getLodedCustomBeans() {
|
||||
List<Bean> beans = getLodedBeans();
|
||||
|
||||
beans = beans.stream()
|
||||
.filter(bean -> bean.getName() != null &&
|
||||
bean.getType().contains(
|
||||
environment.getRequiredProperty("spring.application.name")
|
||||
)
|
||||
)
|
||||
.sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return beans;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.jambotronGroup.jambotron.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
|
||||
public class EntityLoggingConsumer implements Consumer {
|
||||
|
||||
private Logger _logger;
|
||||
public EntityLoggingConsumer(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void accept(Object o) {
|
||||
_logger.info(o.toString());
|
||||
}
|
||||
}
|
||||
@@ -41,4 +41,8 @@ spring.flyway.validate-on-migrate=true
|
||||
|
||||
spring.flyway.user=admin
|
||||
spring.flyway.password=postgrespw
|
||||
spring.flyway.url=jdbc:postgresql://localhost:5432/jambotronDB
|
||||
spring.flyway.url=jdbc:postgresql://localhost:5432/jambotronDB
|
||||
|
||||
|
||||
spring.ai.zhipuai.base-url=https://open.bigmodel.cn/api/paas/v3
|
||||
spring.ai.zhipuai.api-key = 628447c8c65845a48a7226391464a2ea.Dw8ci6TiW0BRF5LI
|
||||
Reference in New Issue
Block a user