Add System component with table display for custom and all beans

This commit is contained in:
liosha84
2025-06-19 18:36:09 +03:00
parent 4e7af10940
commit ab36ee35b4
24 changed files with 919 additions and 57 deletions
+2
View File
@@ -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:
+12
View File
@@ -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
+17
View File
@@ -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){
+5 -2
View File
@@ -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 { }
+8 -50
View File
@@ -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">&nbsp;</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">&nbsp;</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();
}
}
+7
View File
@@ -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());
}
}
+5 -1
View File
@@ -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