@@ -18,70 +18,105 @@ A custom [OpenAPI Generator](https://openapi-generator.tech/) for generating mod
1818
1919### Models
2020``` typescript
21- export interface User {
21+ export interface Course {
2222 readonly id: number ;
23- readonly login: string ;
24- readonly email? : string ;
25- readonly firstName? : string ;
26- readonly lastName? : string ;
23+ readonly title: string ;
24+ readonly shortName: string ;
25+ readonly description? : string ;
26+ readonly startDate? : string ;
27+ readonly endDate? : string ;
28+ readonly semester? : string ;
29+ readonly testCourse? : boolean ;
30+ readonly onlineCourse? : boolean ;
31+ readonly maxComplaints? : number ;
32+ readonly maxTeamComplaints? : number ;
33+ readonly maxComplaintTimeDays? : number ;
34+ readonly studentGroupName? : string ;
35+ readonly teachingAssistantGroupName? : string ;
36+ readonly editorGroupName? : string ;
37+ readonly instructorGroupName? : string ;
38+ readonly color? : string ;
39+ readonly courseIcon? : string ;
2740}
2841
29- export interface UserCreate {
30- login: string ;
31- email: string ;
32- firstName? : string ;
33- lastName? : string ;
42+ export interface CourseCreate {
43+ title: string ;
44+ shortName: string ;
45+ description? : string ;
46+ startDate? : string ;
47+ endDate? : string ;
48+ semester? : string ;
49+ testCourse? : boolean ;
50+ onlineCourse? : boolean ;
51+ color? : string ;
52+ }
53+
54+ export interface CourseUpdate {
55+ title? : string ;
56+ description? : string ;
57+ startDate? : string ;
58+ endDate? : string ;
59+ semester? : string ;
60+ color? : string ;
3461}
3562```
3663
3764### API Service (Mutations)
3865``` typescript
3966@Injectable ({ providedIn: ' root' })
40- export class UserApi {
67+ export class CourseApi {
4168 private readonly http = inject (HttpClient );
69+ private readonly basePath = ' /api' ;
4270
43- createUser(body : UserCreate ): Observable <User > {
44- return this .http .post <User >(` /api/users ` , body );
71+ createCourse(courseCreate : CourseCreate ): Observable <Course > {
72+ const url = ` ${this .basePath }/courses ` ;
73+ return this .http .post <Course >(url , courseCreate );
4574 }
4675
47- updateUser(userId : number , body : UserUpdate ): Observable <User > {
48- return this .http .put <User >(` /api/users/${userId } ` , body );
76+ deleteCourse(courseId : number ): Observable <void > {
77+ const url = ` ${this .basePath }/courses/$${courseId } ` ;
78+ return this .http .delete (url );
4979 }
5080
51- deleteUser(userId : number ): Observable <void > {
52- return this .http .delete <void >(` /api/users/${userId } ` );
81+ updateCourse(courseId : number , courseUpdate : CourseUpdate ): Observable <Course > {
82+ const url = ` ${this .basePath }/courses/$${courseId } ` ;
83+ return this .http .put <Course >(url , courseUpdate );
5384 }
5485}
5586```
5687
5788### Resources (GET with httpResource)
5889``` typescript
59- export interface GetAllUsersParams {
60- search? : string ;
90+ const BASE_PATH = ' /api' ;
91+
92+ export interface GetAllCoursesParams {
93+ onlyActive? : boolean ;
6194 page? : number ;
6295 size? : number ;
6396}
6497
65- export function getAllUsersResource(
66- params ? : Signal <GetAllUsersParams >
67- ): HttpResourceRef <User [] | undefined > {
68- return httpResource <User []>(() => {
69- const p = params ?.() ?? {};
98+ export function getAllCoursesResource(params ? : Signal <GetAllCoursesParams >): HttpResourceRef <Array <Course > | undefined > {
99+ return httpResource <Array <Course >>(() => {
100+ const queryParams = params ?.() ?? {};
70101 const searchParams = new URLSearchParams ();
71- if (p .search ) searchParams .set (' search' , p .search );
72- if (p .page !== undefined ) searchParams .set (' page' , String (p .page ));
73- if (p .size !== undefined ) searchParams .set (' size' , String (p .size ));
102+ if (queryParams .onlyActive !== undefined ) {
103+ searchParams .set (' onlyActive' , String (queryParams .onlyActive ));
104+ }
105+ if (queryParams .page !== undefined && queryParams .page !== null ) {
106+ searchParams .set (' page' , String (queryParams .page ));
107+ }
108+ if (queryParams .size !== undefined && queryParams .size !== null ) {
109+ searchParams .set (' size' , String (queryParams .size ));
110+ }
74111 const query = searchParams .toString ();
75- return ` /api/users ${query ? ` ?${query } ` : ' ' }` ;
112+ return ` ${ BASE_PATH }/courses ${query ? ` ?${query } ` : ' ' }` ;
76113 });
77114}
78115
79- export function getUserResource(
80- userId : Signal <number > | number
81- ): HttpResourceRef <User | undefined > {
82- return httpResource <User >(() => {
83- const userIdValue = typeof userId === ' function' ? userId () : userId ;
84- return ` /api/users/${userIdValue } ` ;
116+ export function getCourseResource(courseId : Signal <number > | number ): HttpResourceRef <Course | undefined > {
117+ return httpResource <Course >(() => {
118+ const courseIdValue = typeof courseId === ' function' ? courseId () : courseId ;
119+ return ` ${BASE_PATH }/courses/${courseIdValue } ` ;
85120 });
86121}
87122```
@@ -147,7 +182,7 @@ openApiGenerate {
147182<plugin >
148183 <groupId >org.openapitools</groupId >
149184 <artifactId >openapi-generator-maven-plugin</artifactId >
150- <version >7.10 .0</version >
185+ <version >7.18 .0</version >
151186 <executions >
152187 <execution >
153188 <goals >
@@ -183,7 +218,7 @@ openApiGenerate {
183218wget https://github.com/ls1intum/openapi-generator-angular21/releases/download/v1.0.0/openapi-generator-angular21-1.0.0.jar
184219
185220# Generate code
186- java -cp openapi-generator-angular21-1.0.0.jar:openapi-generator-cli-7.10 .0.jar \
221+ java -cp openapi-generator-angular21-1.0.0.jar:openapi-generator-cli-7.18 .0.jar \
187222 org.openapitools.codegen.OpenAPIGenerator generate \
188223 -g angular21 \
189224 -i openapi.yaml \
@@ -192,73 +227,85 @@ java -cp openapi-generator-angular21-1.0.0.jar:openapi-generator-cli-7.10.0.jar
192227
193228## Configuration Options
194229
195- | Option | Default | Description |
196- | --------| ---------| -------------|
197- | ` useHttpResource ` | ` true ` | Use ` httpResource ` for GET requests instead of ` HttpClient ` |
198- | ` useInjectFunction ` | ` true ` | Use ` inject() ` function instead of constructor injection |
199- | ` separateResources ` | ` true ` | Generate separate ` *-resources.ts ` files for GET operations |
200- | ` readonlyModels ` | ` true ` | Add ` readonly ` modifier to response model properties |
230+ | Option | Default | Description |
231+ | --------------------- | ---------| ------------------------------------------------ -------------|
232+ | ` useHttpResource ` | ` true ` | Use ` httpResource ` for GET requests instead of ` HttpClient ` |
233+ | ` useInjectFunction ` | ` true ` | Use ` inject() ` function instead of constructor injection |
234+ | ` separateResources ` | ` true ` | Generate separate ` *-resources.ts ` files for GET operations |
235+ | ` readonlyModels ` | ` true ` | Add ` readonly ` modifier to response model properties |
201236
202237## Usage in Components
203238
204239``` typescript
205240import { Component , computed , signal , inject } from ' @angular/core' ;
206241import { firstValueFrom } from ' rxjs' ;
207242import {
208- UserApi ,
209- getUserResource ,
210- getAllUsersResource ,
211- User ,
212- UserCreate
243+ CourseApi ,
244+ getCourseResource ,
245+ getAllCoursesResource ,
246+ Course ,
247+ CourseCreate ,
248+ CourseUpdate
213249} from ' ./generated' ;
214250
215251@Component ({
216- selector: ' app-user -list' ,
252+ selector: ' app-course -list' ,
217253 standalone: true ,
218254 template: `
219- @if (users .isLoading()) {
255+ @if (courses .isLoading()) {
220256 <div class="spinner">Loading...</div>
221257 }
222258
223- @if (users .hasValue()) {
224- @for (user of users .value(); track user .id) {
225- <div (click)="selectUser(user .id)">
226- {{ user.firstName }} {{ user.lastName }}
259+ @if (courses .hasValue()) {
260+ @for (course of courses .value() ?? [] ; track course .id) {
261+ <div (click)="selectCourse(course .id)">
262+ {{ course.title }}
227263 </div>
228264 }
229265 }
230266
231- @if (selectedUser .hasValue()) {
267+ @if (selectedCourse .hasValue()) {
232268 <div class="details">
233- Selected: {{ selectedUser .value()?.email }}
269+ Selected: {{ selectedCourse .value()?.shortName }}
234270 </div>
235271 }
236272 `
237273})
238- export class UserListComponent {
239- private readonly userApi = inject (UserApi );
274+ export class CourseListComponent {
275+ private readonly courseApi = inject (CourseApi );
240276
241277 // Reactive state
242278 protected readonly page = signal (0 );
243- protected readonly selectedUserId = signal <number | undefined >(undefined );
279+ protected readonly selectedCourseId = signal <number | undefined >(undefined );
244280
245281 // Resources - automatically refetch when signals change
246- protected readonly users = getAllUsersResource (
247- computed (() => ({ page: this .page (), size: 20 }))
282+ protected readonly courses = getAllCoursesResource (
283+ computed (() => ({ page: this .page (), size: 20 , onlyActive: true }))
248284 );
249285
250- protected readonly selectedUser = getUserResource (
251- computed (() => this .selectedUserId () ?? - 1 )
286+ protected readonly selectedCourse = getCourseResource (
287+ computed (() => this .selectedCourseId () ?? - 1 )
252288 );
253289
254- selectUser (id : number ): void {
255- this .selectedUserId .set (id );
290+ selectCourse (id : number ): void {
291+ this .selectedCourseId .set (id );
256292 }
257293
258- async createUser (data : UserCreate ): Promise <void > {
259- const created = await firstValueFrom (this .userApi . createUser (data ));
294+ async createCourse (data : CourseCreate ): Promise <void > {
295+ const created = await firstValueFrom (this .courseApi . createCourse (data ));
260296 console .log (' Created:' , created );
261- this .users .reload (); // Refresh the list
297+ this .courses .reload (); // Refresh the list
298+ }
299+
300+ async updateCourse(courseId : number , data : CourseUpdate ): Promise <void > {
301+ const updated = await firstValueFrom (this .courseApi .updateCourse (courseId , data ));
302+ console .log (' Updated:' , updated );
303+ this .courses .reload (); // Refresh the list
304+ }
305+
306+ async deleteCourse(courseId : number ): Promise <void > {
307+ await firstValueFrom (this .courseApi .deleteCourse (courseId ));
308+ this .courses .reload (); // Refresh the list
262309 }
263310}
264311```
0 commit comments