diff --git a/build/libs/jambotron-0.0.1-SNAPSHOT.jar b/build/libs/jambotron-0.0.1-SNAPSHOT.jar index 82b88c5..e52fd4e 100644 Binary files a/build/libs/jambotron-0.0.1-SNAPSHOT.jar and b/build/libs/jambotron-0.0.1-SNAPSHOT.jar differ diff --git a/jambotron-ui/src/app/models/tutorial.model.ts b/jambotron-ui/src/app/models/tutorial.model.ts index 66c6ce3..6e356d8 100644 --- a/jambotron-ui/src/app/models/tutorial.model.ts +++ b/jambotron-ui/src/app/models/tutorial.model.ts @@ -1,6 +1,47 @@ export class Tutorial { + isSelected?: boolean; id?: any; title?: string; description?: string; published?: boolean; + created?: Date; + modified?: Date; + isEdit?: boolean; } + +export const TutorialColumns = [ + { + key: 'isSelected', + type: 'isSelected', + label: '', + }, + { + key: 'title', + type: 'text', + label: 'Title', + required: true, + }, + { + key: 'published', + type: 'boolean', + label: 'Is Published', + }, + { + key: 'created', + type: 'datetime', + label: 'Created Date', + required: true, + + }, + { + key: 'modified', + type: 'datetime', + label: 'Modified Date', + required: true + }, + { + key: 'isEdit', + type: 'isEdit', + label: '', + } +]; diff --git a/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.html b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.html new file mode 100644 index 0000000..9a3eefd --- /dev/null +++ b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.html @@ -0,0 +1,41 @@ + + + Edit tutorial + + + + Title + + + + + + + + + + + + + + + + + + + + @if (hasError){ + + {{errorMessage}} + + } + @if(submitted) { +

Tutorial was submitted successfully!

+ + + } + +
+
+ diff --git a/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.scss b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.scss new file mode 100644 index 0000000..bd7c2c2 --- /dev/null +++ b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.scss @@ -0,0 +1,52 @@ +.submit-form { + max-width: 400px; + margin: auto; +} + +mat-card{ + margin: 20px; +} +mat-card-title{ + color: cyan; +} + +.example-form { + min-width: 150px; + max-width: 500px; + width: 100%; +} + + +.example-full-width { + width: 100%; +} + + +.variable-binding, +.variable-textarea { + width: 49%; +} + +.variable-textarea { + border-radius: 5px; + box-shadow: 0 1px 2px rgba(0,0,0,.07); + min-height: 420px; + padding: 8px; + transition: all 300ms ease-out; +} + +.variable-textarea:hover { + box-shadow: 0 6px 12px 3px rgba(0,0,0,.09), + 0 2px 3px 1px rgba(0,0,0,.06); +} + +.variable-binding { + display: block; + float: right; +} + +.preview { + /* display: block; + float: right;*/ +} + diff --git a/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.spec.ts b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.spec.ts new file mode 100644 index 0000000..e480036 --- /dev/null +++ b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TutorialEditComponent } from './tutorial-edit.component'; + +describe('TutorialEditComponent', () => { + let component: TutorialEditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [TutorialEditComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(TutorialEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.ts b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.ts new file mode 100644 index 0000000..301c9db --- /dev/null +++ b/jambotron-ui/src/app/user-module/tutorial-edit.component/tutorial-edit.component.ts @@ -0,0 +1,91 @@ +import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core'; +import {MarkdownComponent} from 'ngx-markdown'; +import {MatButton} from '@angular/material/button'; +import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card'; +import {MatError, MatFormField, MatInput, MatLabel} from '@angular/material/input'; +import {MatTab, MatTabGroup} from '@angular/material/tabs'; +import {NgIf} from '@angular/common'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; +import {Tutorial} from '../../models/tutorial.model'; +import {UserApiService} from '../user-api.service'; +import {ActivatedRoute, Router, RouterLink} from '@angular/router'; + +@Component({ + selector: 'app-tutorial-edit.component', + imports: [ + MarkdownComponent, + MatButton, + MatCard, + MatCardActions, + MatCardContent, + MatCardHeader, + MatFormField, + MatInput, + MatLabel, + MatTab, + MatTabGroup, + ReactiveFormsModule, + FormsModule, + MatFormField, + RouterLink, + MatError + ], + templateUrl: './tutorial-edit.component.html', + styleUrl: './tutorial-edit.component.scss', + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class TutorialEditComponent { + tutorial: Tutorial = new Tutorial(); + submitted = false; + hasError = false; + errorMessage = ''; + markdown = `## Markdown __rulez__! +--- + +### Syntax highlight +\`\`\`typescript +const language = 'typescript'; +\`\`\` + +### Lists +1. Ordered list +2. Another bullet point + - Unordered list + - Another unordered bullet + +### Blockquote +> Blockquote to the max`; + private id: string | null | undefined; + + constructor(private userApiService: UserApiService, private route: ActivatedRoute) { + + this.route.queryParams + .subscribe(params => { + console.log(params); + this.id = params['id']; + console.log(this.id); + }); + + this.userApiService.getTutorial(this.id).subscribe( + data=>{ + this.tutorial = data; + } + ); + } + updateTutorial(): void { + this.userApiService.update(this.id, this.tutorial) + .subscribe( + response => { + console.log(response); + this.submitted = true; + this.hasError = false; + }, + error => { + console.log(error); + + this.errorMessage = error.error.message; + + this.hasError = true; + }); + } +} diff --git a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.html b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.html index 4e5588a..dd683bf 100644 --- a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.html +++ b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.html @@ -1,29 +1,148 @@ -

tutorials-list.component works!

+
+ + + - +
+ + @for (column of columnsSchema; track column){ + + + + - - - - - --> - -
- {{tutorial.title}} - - X -
-
} + + + + + + +
+ @switch (column.key) { + @case ('isSelected') { + + } + @default { + {{ column.label }} + } + } + + + @switch (column.type) { + @case ('isSelected') { + + } + @case('isEdit') { +
+ + +
+ } + @case ('boolean') { + - - @for (tutorial of tutorials; track tutorial) { - +
+ - diff --git a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.scss b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.scss index d37713e..e4d8bda 100644 --- a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.scss +++ b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.scss @@ -1,3 +1,14 @@ +.table-header { + width: 90%; + margin: auto; + text-align: right; + margin-bottom: 10px; + padding-top: 10px; + display: flex; + align-items: center; + justify-content: space-between; +} + .spacer{ flex: 1 1 auto; } diff --git a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.ts b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.ts index 88f5b2d..ba637d4 100644 --- a/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.ts +++ b/jambotron-ui/src/app/user-module/tutorials-list.component/tutorials-list.component.ts @@ -1,6 +1,6 @@ import {Component, CUSTOM_ELEMENTS_SCHEMA, OnInit} from '@angular/core'; import {MatList, MatListItem} from '@angular/material/list'; -import {Tutorial} from '../../models/tutorial.model'; +import {Tutorial, TutorialColumns} from '../../models/tutorial.model'; import {TutorialService} from '../../services/tutorial.service'; import {UserApiService} from '../user-api.service'; import {MatButton} from '@angular/material/button'; @@ -11,29 +11,80 @@ import {EventBusService} from '../../_shared/event-bus.service'; import {EventData} from '../../_shared/event.class'; import {Router, RouterLink} from '@angular/router'; import {AuthService} from '../../services/auth.service'; +import {FormGroup, FormsModule, ReactiveFormsModule} from '@angular/forms'; +import { + MatCell, + MatCellDef, + MatColumnDef, MatHeaderCell, MatHeaderCellDef, + MatHeaderRow, + MatHeaderRowDef, + MatRow, + MatRowDef, + MatTable, + MatTableDataSource +} from '@angular/material/table'; +import {MatFormField, MatInput} from '@angular/material/input'; +import {DatePipe, NgForOf, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common'; +import {MatCheckbox} from '@angular/material/checkbox'; +import {MatDatepicker, MatDatepickerInput, MatDatepickerToggle} from '@angular/material/datepicker'; +import {MatSlideToggle} from '@angular/material/slide-toggle'; -@Component({ - selector: 'app-tutorials-list.component', - imports: [ - MatList, - MatListItem, - MatLine, - MatButton, - MatIcon, - MatOption, - RouterLink - ], - schemas:[CUSTOM_ELEMENTS_SCHEMA], - templateUrl: './tutorials-list.component.html', - styleUrl: './tutorials-list.component.scss' -}) -export class TutorialsListComponent implements OnInit { - tutorials?: Tutorial[]; + + @Component({ + selector: 'app-tutorials-list.component', + imports: [ + MatList, + MatListItem, + MatLine, + MatButton, + MatIcon, + MatOption, + RouterLink, + ReactiveFormsModule, + MatTable, + MatHeaderRowDef, + MatHeaderRow, + MatRowDef, + MatRow, + FormsModule, + MatInput, + MatFormField, + MatColumnDef, + MatHeaderCell, + MatHeaderCellDef, + NgSwitch, + NgSwitchCase, + NgSwitchDefault, + MatCellDef, + MatCheckbox, + MatDatepickerInput, + MatDatepickerToggle, + MatDatepicker, + DatePipe, + NgIf, + NgForOf, + MatCell, + MatSlideToggle + ], + schemas:[CUSTOM_ELEMENTS_SCHEMA], + templateUrl: './tutorials-list.component.html', + styleUrl: './tutorials-list.component.scss' + }) + export class TutorialsListComponent implements OnInit { + //tutorials?: Tutorial[]; + + displayedColumns: string[] = TutorialColumns.map((col) => col.key) + columnsSchema: any = TutorialColumns + dataSource = new MatTableDataSource() + valid: any = {} constructor(private userApiService: UserApiService, private storageService: TokenStorageService, private eventBusService: EventBusService, - private router: Router, private authService: AuthService) { + private router: Router, + private authService: AuthService + + ) { } @@ -41,14 +92,13 @@ export class TutorialsListComponent implements OnInit { this.eventBusService.on('logout', () => { this.logout(); }) - this.retrieveTutorials(); + this.getTutorials(); } - retrieveTutorials(): void { + getTutorials(): void { this.userApiService.getUserAllTutorials() - .subscribe( - data => { - this.tutorials = data; + .subscribe(( data:Tutorial[] ) => { + this.dataSource.data = data; console.log(data); }, error => { @@ -65,9 +115,63 @@ export class TutorialsListComponent implements OnInit { }); } - deleteOption($event: MouseEvent, option: any) { + selectAll(event: any) { + this.dataSource.data = this.dataSource.data.map((item) => ({ + ...item, + isSelected: event.checked + })); + } + + isAllSelected() { + return this.dataSource.data.every((item) => item.isSelected) + } + + isAnySelected() { + return this.dataSource.data.some((item) => item.isSelected) + } + + removeSelectedRows() { + const selectedTutorials = this.dataSource.data.filter((u: Tutorial) => u.isSelected) + /*this.dialog + .open(ConfirmDialogComponent) + .afterClosed() + .subscribe((confirm) => {*/ + // if (confirm) { + this.userApiService.deleteTutorials(selectedTutorials).subscribe(() => { + this.dataSource.data = this.dataSource.data.filter( + (u: Tutorial) => !u.isSelected + ) + }) + // } + // }) + } + + removeRow(id: number) { + this.userApiService.deleteTutorial(id).subscribe(() => { + this.dataSource.data = this.dataSource.data.filter( + (u: Tutorial) => u.id !== id, + ) + }) + } + + editRow(row: Tutorial) { + /*if (row.id === 0) { + this.userService.addUser(row).subscribe((newUser: User) => { + row.id = newUser.id + row.isEdit = false + }) + } else { + this.userService.updateUser(row).subscribe(() => (row.isEdit = false)) + }*/ + } + + disableSubmit(id: number) { + if (this.valid[id]) { + return Object.values(this.valid[id]).some((item) => item === false) + } + return false + } - } logout(): void { this.authService.logout().subscribe({ next: res => { diff --git a/jambotron-ui/src/app/user-module/user-api.service.ts b/jambotron-ui/src/app/user-module/user-api.service.ts index 0ae9fc4..a26176c 100644 --- a/jambotron-ui/src/app/user-module/user-api.service.ts +++ b/jambotron-ui/src/app/user-module/user-api.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import {Observable} from 'rxjs'; +import {forkJoin, Observable} from 'rxjs'; import {Tutorial} from '../models/tutorial.model'; import {HttpClient, HttpHeaders} from '@angular/common/http'; @@ -21,7 +21,28 @@ export class UserApiService { return this.http.get(`${this.baseUrl}/tutorials`, this.httpOptions); } + getTutorial(id: string | null | undefined): Observable { + return this.http.get(`${this.baseUrl}/tutorial-get/${id}`); + } + create(data: any): Observable { return this.http.post(`${this.baseUrl}/tutorial-add`, data); } + + update(id: any,data: any): Observable { + return this.http.put(`${this.baseUrl}/tutorial-update/${id}`, data); + } + + deleteTutorials(tutorials: Tutorial[]): Observable { + return forkJoin( + tutorials.map((tutorial) => + this.http.delete(`${this.baseUrl}/tutorials/${tutorial.id}`) + ) + ); + } + + deleteTutorial(id: number): Observable { + return this.http.delete(`${this.baseUrl}/tutorials/${id}`); + } + } diff --git a/jambotron-ui/src/app/user-module/user.component/user.component.scss b/jambotron-ui/src/app/user-module/user.component/user.component.scss index 070126d..0a94558 100644 --- a/jambotron-ui/src/app/user-module/user.component/user.component.scss +++ b/jambotron-ui/src/app/user-module/user.component/user.component.scss @@ -47,4 +47,6 @@ mat-sidenav-content{ } .pc-container{ top: 0px; + padding-left: 5px; + padding-right: 5px; } diff --git a/jambotron-ui/src/app/user-module/user.routing.ts b/jambotron-ui/src/app/user-module/user.routing.ts index cb542bb..728a19d 100644 --- a/jambotron-ui/src/app/user-module/user.routing.ts +++ b/jambotron-ui/src/app/user-module/user.routing.ts @@ -20,6 +20,10 @@ const USER_ROUTES: Routes = [ path: 'tutorial-add', loadComponent: () => import('../user-module/tutorial-add.component/tutorial-add.component').then((c) => c.TutorialAddComponent) }, + { + path: 'tutorial-edit', + loadComponent: () => import('../user-module/tutorial-edit.component/tutorial-edit.component').then((c) => c.TutorialEditComponent) + }, { path: 'ai-models', loadComponent: () => import('../user-module/ai-models.component/ai-models.component').then((c) => c.AiModelsComponent) diff --git a/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyAIImageModel.java b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyAIImageModel.java new file mode 100644 index 0000000..192492d --- /dev/null +++ b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyAIImageModel.java @@ -0,0 +1,109 @@ +package com.jambotronGroup.jambotron.ZhiPuAi; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.ai.image.*; +import org.springframework.ai.model.ModelOptionsUtils; +import org.springframework.ai.retry.RetryUtils; +import org.springframework.ai.zhipuai.ZhiPuAiImageModel; +import org.springframework.ai.zhipuai.ZhiPuAiImageOptions; +import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; +import org.springframework.http.ResponseEntity; +import org.springframework.retry.support.RetryTemplate; +import org.springframework.util.Assert; + +import java.util.List; + +public class MyAIImageModel implements ImageModel { + + private static final Logger logger = LoggerFactory.getLogger(ZhiPuAiImageModel.class); + + public final RetryTemplate retryTemplate; + + private final MyImageOptions defaultOptions; + + private final ZhiPuAiImageApi zhiPuAiImageApi; + + public MyAIImageModel(ZhiPuAiImageApi zhiPuAiImageApi) { + this(zhiPuAiImageApi, MyImageOptions.builder().build(), RetryUtils.DEFAULT_RETRY_TEMPLATE); + } + + public MyAIImageModel(ZhiPuAiImageApi zhiPuAiImageApi, MyImageOptions defaultOptions, + RetryTemplate retryTemplate) { + Assert.notNull(zhiPuAiImageApi, "ZhiPuAiImageApi must not be null"); + Assert.notNull(defaultOptions, "defaultOptions must not be null"); + Assert.notNull(retryTemplate, "retryTemplate must not be null"); + this.zhiPuAiImageApi = zhiPuAiImageApi; + this.defaultOptions = defaultOptions; + this.retryTemplate = retryTemplate; + } + + public MyImageOptions getDefaultOptions() { + return this.defaultOptions; + } + + @Override + public ImageResponse call(ImagePrompt imagePrompt) { + return this.retryTemplate.execute(ctx -> { + + String instructions = imagePrompt.getInstructions().get(0).getText(); + + ZhiPuAiImageApi.ZhiPuAiImageRequest imageRequest = new ZhiPuAiImageApi.ZhiPuAiImageRequest(instructions, + ZhiPuAiImageApi.DEFAULT_IMAGE_MODEL); + + if (this.defaultOptions != null) { + imageRequest = ModelOptionsUtils.merge(this.defaultOptions, imageRequest, + ZhiPuAiImageApi.ZhiPuAiImageRequest.class); + } + + if (imagePrompt.getOptions() != null) { + imageRequest = ModelOptionsUtils.merge(toZhiPuAiImageOptions(imagePrompt.getOptions()), imageRequest, + ZhiPuAiImageApi.ZhiPuAiImageRequest.class); + } + + // Make the request + ResponseEntity imageResponseEntity = this.zhiPuAiImageApi + .createImage(imageRequest); + + // Convert to org.springframework.ai.model derived ImageResponse data type + return convertResponse(imageResponseEntity, imageRequest); + }); + } + + private ImageResponse convertResponse(ResponseEntity imageResponseEntity, + ZhiPuAiImageApi.ZhiPuAiImageRequest zhiPuAiImageRequest) { + ZhiPuAiImageApi.ZhiPuAiImageResponse imageApiResponse = imageResponseEntity.getBody(); + if (imageApiResponse == null) { + logger.warn("No image response returned for request: {}", zhiPuAiImageRequest); + return new ImageResponse(List.of()); + } + + List imageGenerationList = imageApiResponse.data() + .stream() + .map(entry -> new ImageGeneration(new Image(entry.url(), null))) + .toList(); + + return new ImageResponse(imageGenerationList); + } + + /** + * Convert the {@link ImageOptions} into {@link ZhiPuAiImageOptions}. + * @param runtimeImageOptions the image options to use. + * @return the converted {@link ZhiPuAiImageOptions}. + */ + private MyImageOptions toZhiPuAiImageOptions(ImageOptions runtimeImageOptions) { + MyImageOptions.Builder myImageOptionsBuilder = MyImageOptions.builder(); + if (runtimeImageOptions != null) { + if (runtimeImageOptions.getModel() != null) { + myImageOptionsBuilder.model(runtimeImageOptions.getModel()); + } + if (runtimeImageOptions instanceof MyImageOptions myImageOptions) { + if (myImageOptions.getUser() != null) { + myImageOptionsBuilder.user(myImageOptions.getUser()); + } + } + } + return myImageOptionsBuilder.build(); + } + +} diff --git a/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyImageOptions.java b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyImageOptions.java new file mode 100644 index 0000000..ebffdb1 --- /dev/null +++ b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/MyImageOptions.java @@ -0,0 +1,128 @@ +package com.jambotronGroup.jambotron.ZhiPuAi; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.ai.image.ImageOptions; +import org.springframework.ai.zhipuai.ZhiPuAiImageOptions; +import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; + +import java.util.Objects; + +public class MyImageOptions implements ImageOptions { + /** + * The model to use for image generation. + */ + @JsonProperty("model") + private String model = ZhiPuAiImageApi.DEFAULT_IMAGE_MODEL; + + /** + * A unique identifier representing your end-user, which can help ZhiPuAI to monitor + * and detect abuse. User ID length requirement: minimum of 6 characters, maximum of + * 128 characters + */ + @JsonProperty("user_id") + private String user; + + public static MyImageOptions.Builder builder() { + + return new MyImageOptions.Builder(); + } + + @Override + @JsonIgnore + public Integer getN() { + return null; + } + + @Override + public String getModel() { + return this.model; + } + + public void setModel(String model) { + this.model = model; + } + + @Override + @JsonIgnore + public Integer getWidth() { + return 300; + } + + @Override + @JsonIgnore + public Integer getHeight() { + + return 200; + } + + @Override + @JsonIgnore + public String getResponseFormat() { + return null; + } + + @Override + @JsonIgnore + public String getStyle() { + return null; + } + + public String getUser() { + return this.user; + } + + public void setUser(String user) { + this.user = user; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + else { + return false; + } +// if (!(o instanceof ZhiPuAiImageOptions that)) { +// return false; +// } +// return Objects.equals(this.model, that.model) && Objects.equals(this.user, that.user); + } + + @Override + public int hashCode() { + return Objects.hash(this.model, this.user); + } + + @Override + public String toString() { + return "ZhiPuAiImageOptions{model='" + this.model + '\'' + ", user='" + this.user + '\'' + '}'; + } + + public static final class Builder { + + private final MyImageOptions options; + + Builder() { + this.options = new MyImageOptions(); + } + + public MyImageOptions.Builder model(String model) { + this.options.setModel(model); + return this; + } + + public MyImageOptions.Builder user(String user) { + this.options.setUser(user); + return this; + } + + public MyImageOptions build() { + + return this.options; + } + + } + +} diff --git a/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/ZhiPuAiImageService.java b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/ZhiPuAiImageService.java index 59f5b96..2fc88ad 100644 --- a/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/ZhiPuAiImageService.java +++ b/src/main/java/com/jambotronGroup/jambotron/ZhiPuAi/ZhiPuAiImageService.java @@ -1,9 +1,13 @@ package com.jambotronGroup.jambotron.ZhiPuAi; +import org.springframework.ai.image.ImageOptions; +import org.springframework.ai.image.ImageOptionsBuilder; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; +import org.springframework.ai.retry.RetryUtils; import org.springframework.ai.zhipuai.ZhiPuAiImageModel; +import org.springframework.ai.zhipuai.ZhiPuAiImageOptions; import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -21,18 +25,48 @@ public class ZhiPuAiImageService { private ZhiPuAiImageApi _zhiPuAiImageApi; + private MyAIImageModel _myAIImageModel; + private ZhiPuAiImageModel _zhiPuAiImageModel; + private MyImageOptions _myImageOptions; + public ZhiPuAiImageService() { _zhiPuAiImageApi = new ZhiPuAiImageApi("628447c8c65845a48a7226391464a2ea.Dw8ci6TiW0BRF5LI"); + ImageOptionsBuilder imageOptionsBuilder = ImageOptionsBuilder.builder(); + + ImageOptions imageOptions = imageOptionsBuilder.model("Cogview-3-Flash")//ZhiPuAiImageApi.DEFAULT_IMAGE_MODEL) + .height(100) + .width(200) + + .build(); +// _myImageOptions = new MyImageOptions.Builder() +// .model(ZhiPuAiImageApi.DEFAULT_IMAGE_MODEL) +// .user("jambotron") +// +// .build(); + + _zhiPuAiImageModel = new ZhiPuAiImageModel(_zhiPuAiImageApi); + _myAIImageModel = new MyAIImageModel(_zhiPuAiImageApi); + } public ImageResponse generateImage(String prompt) { + ImageOptionsBuilder imageOptionsBuilder = ImageOptionsBuilder.builder(); + ImageOptions imageOptions = imageOptionsBuilder.model("Cogview-3-Flash")//ZhiPuAiImageApi.DEFAULT_IMAGE_MODEL) + .height(1440) + .width(720) + + .build(); // Create an ImagePrompt object with the desired prompt - ImagePrompt imagePrompt = new ImagePrompt(prompt); + ImagePrompt imagePrompt = new ImagePrompt(prompt,imageOptions); + + /*// Call the generate method to get the image response + ImageResponse imageResponse = _myAIImageModel.call(imagePrompt); +*/ // Call the generate method to get the image response ImageResponse imageResponse = _zhiPuAiImageModel.call(imagePrompt); diff --git a/src/main/java/com/jambotronGroup/jambotron/controllers/TutorialController.java b/src/main/java/com/jambotronGroup/jambotron/controllers/TutorialController.java index 9f9e334..b897497 100644 --- a/src/main/java/com/jambotronGroup/jambotron/controllers/TutorialController.java +++ b/src/main/java/com/jambotronGroup/jambotron/controllers/TutorialController.java @@ -7,21 +7,17 @@ import com.jambotronGroup.jambotron.repository.TutorialRepository; import com.jambotronGroup.jambotron.repository.UserRepository; import com.jambotronGroup.jambotron.security.AuthenticationFacade; import com.jambotronGroup.jambotron.security.services.UserDetailsImpl; -import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; -import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.util.*; //@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600, allowCredentials="true") @@ -106,18 +102,7 @@ public class TutorialController { } } - @GetMapping("/tutorials/{id}") - public ResponseEntity getTutorialById(@PathVariable("id") long id) { - Optional tutorialData = tutorialRepository.findById(id); - - if (tutorialData.isPresent()) { - return new ResponseEntity<>(tutorialData.get(), HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - } - - @PostMapping("user/tutorial-add") + @PostMapping("user/tutorial-add") public ResponseEntity createTutorial(@RequestBody Tutorial tutorial) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); @@ -127,29 +112,49 @@ public class TutorialController { try { Tutorial _tutorial = tutorialRepository - .save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false, user)); + .save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false, user, Timestamp.valueOf(LocalDateTime.now()), Timestamp.valueOf(LocalDateTime.now()))); return new ResponseEntity<>(_tutorial, HttpStatus.CREATED); } catch (Exception e) { return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); } } - @PutMapping("/tutorials/{id}") - public ResponseEntity updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) { + @GetMapping("user/tutorial-get/{id}") + public ResponseEntity getTutorial(@PathVariable("id") long id) { Optional tutorialData = tutorialRepository.findById(id); if (tutorialData.isPresent()) { - Tutorial _tutorial = tutorialData.get(); - _tutorial.setTitle(tutorial.getTitle()); - _tutorial.setDescription(tutorial.getDescription()); - _tutorial.setPublished(tutorial.isPublished()); - return new ResponseEntity<>(tutorialRepository.save(_tutorial), HttpStatus.OK); + + return new ResponseEntity(tutorialData.get(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } - @DeleteMapping("/tutorials/{id}") + @PutMapping("user/tutorial-update/{id}") + public ResponseEntity updateTutorial(@PathVariable("id") long id, @RequestBody Tutorial tutorial) { + Optional tutorialData = tutorialRepository.findById(id); + Map map = new LinkedHashMap(); + if (tutorialData.isPresent()) { + Tutorial servTutorial = tutorialData.get(); + servTutorial.setTitle(tutorial.getTitle()); + servTutorial.setDescription(tutorial.getDescription()); + servTutorial.setPublished(tutorial.isPublished()); + try { + servTutorial = tutorialRepository.save(servTutorial); + } catch (Exception e) { + + map.put("status", 0); + map.put("message", e.getMessage()); + return new ResponseEntity<>(map,HttpStatus.INTERNAL_SERVER_ERROR); + } + return new ResponseEntity<>(servTutorial, HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + + @DeleteMapping("user/tutorials/{id}") public ResponseEntity deleteTutorial(@PathVariable("id") long id) { try { tutorialRepository.deleteById(id); diff --git a/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java b/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java index 1a773c3..3f41dde 100644 --- a/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java +++ b/src/main/java/com/jambotronGroup/jambotron/model/Tutorial.java @@ -25,15 +25,25 @@ public class Tutorial { @JoinColumn(name = "userID", nullable = false) private User user; + @Column(name = "created") + private java.sql.Timestamp created; + + @Column(name = "modified") + private java.sql.Timestamp modified; + + + public Tutorial() { } - public Tutorial(String title, String description, boolean published, User user) { + public Tutorial(String title, String description, boolean published, User user, java.sql.Timestamp created, java.sql.Timestamp modified) { this.title = title; this.description = description; this.published = published; this.user = user; + this.created = created; + this.modified = modified; } public long getId() { @@ -64,6 +74,22 @@ public class Tutorial { this.published = isPublished; } + public void setCreated(java.sql.Timestamp created) { + this.created = created; + } + + public java.sql.Timestamp getCreated() { + return created; + } + + public void setModified(java.sql.Timestamp modified) { + this.modified = modified; + } + + public java.sql.Timestamp getModified() { + return modified; + } + @Override public String toString() { return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]"; diff --git a/src/main/java/com/jambotronGroup/jambotron/utils/DateTimeHelper.java b/src/main/java/com/jambotronGroup/jambotron/utils/DateTimeHelper.java new file mode 100644 index 0000000..930bc47 --- /dev/null +++ b/src/main/java/com/jambotronGroup/jambotron/utils/DateTimeHelper.java @@ -0,0 +1,18 @@ +package com.jambotronGroup.jambotron.utils; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +public class DateTimeHelper { + + public static SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public static java.sql.Timestamp parseTimestamp(String timestamp) { + try { + return new Timestamp(DATE_TIME_FORMAT.parse(timestamp).getTime()); + } catch (ParseException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 290a27a..c8429f1 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,32 +2,32 @@ spring.application.name=jambotron #============Localhost Configurations======================== -#spring.datasource.url= jdbc:postgresql://localhost:5432/jambotronDB -#spring.datasource.username= admin -#spring.datasource.password= postgrespw - -#spring.flyway.baseline-on-migrate=true -#spring.flyway.validate-on-migrate=true -# -#spring.flyway.url=jdbc:postgresql://localhost:5432/jambotronDB -#spring.flyway.user=admin -#spring.flyway.password=postgrespw - - -#============Koyeb Configurations======================== - -spring.datasource.url= jdbc:postgresql://ep-red-breeze-a2cxhq5f.eu-central-1.pg.koyeb.app/jambotronDB -spring.datasource.username= koyeb-adm -spring.datasource.password= npg_HfFEUA7bay1i +spring.datasource.url= jdbc:postgresql://localhost:5432/jambotronDB +spring.datasource.username= admin +spring.datasource.password= postgrespw spring.flyway.baseline-on-migrate=true spring.flyway.validate-on-migrate=true -spring.flyway.url=jdbc:postgresql://ep-red-breeze-a2cxhq5f.eu-central-1.pg.koyeb.app/jambotronDB -spring.flyway.user=koyeb-adm -spring.flyway.password=npg_HfFEUA7bay1i +spring.flyway.url=jdbc:postgresql://localhost:5432/jambotronDB +spring.flyway.user=admin +spring.flyway.password=postgrespw +#============Koyeb Configurations======================== + +#spring.datasource.url= jdbc:postgresql://ep-red-breeze-a2cxhq5f.eu-central-1.pg.koyeb.app/jambotronDB +#spring.datasource.username= koyeb-adm +#spring.datasource.password= npg_HfFEUA7bay1i +# +#spring.flyway.baseline-on-migrate=true +#spring.flyway.validate-on-migrate=true +# +#spring.flyway.url=jdbc:postgresql://ep-red-breeze-a2cxhq5f.eu-central-1.pg.koyeb.app/jambotronDB +#spring.flyway.user=koyeb-adm +#spring.flyway.password=npg_HfFEUA7bay1i +# + #spring.datasource.url=${SPRING_DATASOURCE_URL} #spring.datasource.username=${SPRING_DATASOURCE_USERNAME} #spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}