From 82b9f947947527625674ff858ab4d0223187c3e7 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Fri, 3 Jan 2025 12:38:21 +0000 Subject: [PATCH 01/16] feat: endpoints for resource and resource type templates --- .../rest/resources/ResourceTemplatesRest.java | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java index ae53bc1d9..28efbc6d2 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java @@ -36,7 +36,9 @@ import ch.mobi.itc.mobiliar.rest.dtos.TemplateDTO; import ch.puzzle.itc.mobiliar.business.resourcegroup.boundary.ResourceGroupLocator; +import ch.puzzle.itc.mobiliar.business.resourcegroup.entity.ResourceEntity; import ch.puzzle.itc.mobiliar.business.resourcegroup.entity.ResourceGroupEntity; +import ch.puzzle.itc.mobiliar.business.resourcegroup.entity.ResourceTypeEntity; import ch.puzzle.itc.mobiliar.business.template.boundary.TemplateEditor; import ch.puzzle.itc.mobiliar.business.template.control.TemplatesScreenDomainService; import ch.puzzle.itc.mobiliar.business.template.entity.TemplateDescriptorEntity; @@ -46,14 +48,15 @@ import ch.puzzle.itc.mobiliar.common.exception.ValidationException; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import javax.persistence.EntityManager; /** - * Rest boundary for Resource-Templates + * Rest boundary for Resource and Resource Type Templates */ @RequestScoped -@Path("/resources/{resourceGroupName}/{releaseName}/templates") -@Api(value = "/resources/{resourceGroupName}/{releaseName}/templates", description = "Resource templates") -public class ResourceTemplatesRest {; +@Path("/resources/templates") +@Api(value = "/resources/templates") +public class ResourceTemplatesRest { @Inject ResourceGroupLocator resourceGroupLocator; @@ -64,7 +67,11 @@ public class ResourceTemplatesRest {; @Inject TemplateEditor templateEditor; + @Inject + private EntityManager entityManager; + @GET + @Path("/{resourceGroupName}/{releaseName}") @ApiOperation(value = "Get all templates for a resource in a specific release") public List getResourceTemplates(@PathParam("resourceGroupName") String resourceGroupName, @PathParam("releaseName") String releaseName) throws ValidationException { @@ -79,7 +86,40 @@ public List getResourceTemplates(@PathParam("resourceGroupName") St } @GET - @Path("/{templateName}") + @Path("/{resourceId}") + @ApiOperation(value = "Get all templates for a resource") + public List getResourceTemplatesByResourceId(@PathParam("resourceId") Integer resourceId) throws NotFoundException { + ResourceEntity resource = entityManager.find(ResourceEntity.class, resourceId); + if (resource == null) { + throw new NotFoundException("Resource not found"); + } + List templates = templateService.getGlobalTemplateDescriptorsForResource(resource); + List templateDTOs = new ArrayList<>(); + for (TemplateDescriptorEntity template : templates) { + templateDTOs.add(new TemplateDTO(template)); + } + return templateDTOs; + } + + @GET + @Path("/resourceType/{resourceTypeId}") + @ApiOperation(value = "Get all templates for a resource type") + public Response getResourceTypeTemplatesById(@PathParam("resourceTypeId") Integer resourceTypeId) throws NotFoundException { + + ResourceTypeEntity resourceType = entityManager.find(ResourceTypeEntity.class, resourceTypeId); + if (resourceType == null) { + throw new NotFoundException("Resource type not found"); + } + List templates = templateService.getGlobalTemplateDescriptorsForResourceType(resourceType); + List templateDTOs = new ArrayList<>(); + for (TemplateDescriptorEntity template : templates) { + templateDTOs.add(new TemplateDTO(template)); + } + return Response.status(Response.Status.OK).entity(templateDTOs).build(); + } + + @GET + @Path("/{resourceGroupName}/{releaseName}/{templateName}") @ApiOperation(value = "Get a template for a resource in a specific release") public TemplateDTO getResourceTemplate(@PathParam("resourceGroupName") String resourceGroupName, @PathParam("releaseName") String releaseName, @@ -92,7 +132,7 @@ public TemplateDTO getResourceTemplate(@PathParam("resourceGroupName") String re } @DELETE - @Path("/{templateName}") + @Path("/{resourceGroupName}/{releaseName}/{templateName}") @ApiOperation(value = "Delete a template for a resource in a specific release") public Response deleteResourceTemplate(@PathParam("resourceGroupName") String resourceGroupName, @PathParam("releaseName") String releaseName, @@ -106,6 +146,7 @@ public Response deleteResourceTemplate(@PathParam("resourceGroupName") String re } @POST + @Path("/{resourceGroupName}/{releaseName}") @ApiOperation(value = "Create a template for a resource in a specific release") public Response createResourceTemplates(@PathParam("resourceGroupName") String resourceGroupName, @PathParam("releaseName") String releaseName, @@ -119,7 +160,7 @@ public Response createResourceTemplates(@PathParam("resourceGroupName") String r } @PUT - @Path("/{templateName}") + @Path("/{resourceGroupName}/{releaseName}/{templateName}") @ApiOperation(value = "Update a template for a resource in a specific release") public Response updateResourceTemplates(@PathParam("resourceGroupName") String resourceGroupName, @PathParam("releaseName") String releaseName, From fc51594c68d12741ff5d9ffc0d7e107ada621eb1 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Fri, 3 Jan 2025 16:05:33 +0000 Subject: [PATCH 02/16] feat: create resource templates model and service --- .../io/src/app/resource/resource-template.ts | 8 +++++ .../resource/resource-templates.service.ts | 29 +++++++++++++++++++ .../rest/resources/ResourceTemplatesRest.java | 13 ++++----- 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 AMW_angular/io/src/app/resource/resource-template.ts create mode 100644 AMW_angular/io/src/app/resource/resource-templates.service.ts diff --git a/AMW_angular/io/src/app/resource/resource-template.ts b/AMW_angular/io/src/app/resource/resource-template.ts new file mode 100644 index 000000000..b88745c92 --- /dev/null +++ b/AMW_angular/io/src/app/resource/resource-template.ts @@ -0,0 +1,8 @@ +export interface ResourceTemplate { + id: number; + relatedResourceIdentifier: string; + name: string; + targetPath: string; + targetPlatforms: string[]; + fileContent: string; +} diff --git a/AMW_angular/io/src/app/resource/resource-templates.service.ts b/AMW_angular/io/src/app/resource/resource-templates.service.ts new file mode 100644 index 000000000..9b33ba505 --- /dev/null +++ b/AMW_angular/io/src/app/resource/resource-templates.service.ts @@ -0,0 +1,29 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { ResourceTemplate } from './resource-template'; +import { catchError } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { BaseService } from '../base/base.service'; + +@Injectable({ providedIn: 'root' }) +export class ResourceTemplatesService extends BaseService { + constructor(private http: HttpClient) { + super(); + } + + getResourceTemplates(id: number): Observable { + return this.http + .get(`${this.getBaseUrl()}/resources/templates/${id}`, { + headers: this.getHeaders(), + }) + .pipe(catchError(this.handleError)); + } + + getResourceTypeTemplates(id: number): Observable { + return this.http + .get(`${this.getBaseUrl()}/resources/templates/resourceType/${id}`, { + headers: this.getHeaders(), + }) + .pipe(catchError(this.handleError)); + } +} diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java index 28efbc6d2..5a272a7c8 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java @@ -26,12 +26,7 @@ import javax.enterprise.context.RequestScoped; import javax.inject.Inject; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; +import javax.ws.rs.*; import javax.ws.rs.core.Response; import ch.mobi.itc.mobiliar.rest.dtos.TemplateDTO; @@ -50,12 +45,16 @@ import io.swagger.annotations.ApiOperation; import javax.persistence.EntityManager; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; + /** * Rest boundary for Resource and Resource Type Templates */ @RequestScoped @Path("/resources/templates") @Api(value = "/resources/templates") +@Consumes(APPLICATION_JSON) +@Produces(APPLICATION_JSON) public class ResourceTemplatesRest { @Inject @@ -88,7 +87,7 @@ public List getResourceTemplates(@PathParam("resourceGroupName") St @GET @Path("/{resourceId}") @ApiOperation(value = "Get all templates for a resource") - public List getResourceTemplatesByResourceId(@PathParam("resourceId") Integer resourceId) throws NotFoundException { + public List getResourceTemplatesById(@PathParam("resourceId") Integer resourceId) throws NotFoundException { ResourceEntity resource = entityManager.find(ResourceEntity.class, resourceId); if (resource == null) { throw new NotFoundException("Resource not found"); From 6245596e6d9c3bdeab493d8a68d3bdc323379cfc Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 12:30:38 +0000 Subject: [PATCH 03/16] refactor: prettier --- AMW_angular/io/src/app/resource/resource-types.service.ts | 2 +- .../io/src/app/resources/resource-functions.service.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AMW_angular/io/src/app/resource/resource-types.service.ts b/AMW_angular/io/src/app/resource/resource-types.service.ts index b1908d3ff..28314b8cf 100644 --- a/AMW_angular/io/src/app/resource/resource-types.service.ts +++ b/AMW_angular/io/src/app/resource/resource-types.service.ts @@ -10,7 +10,7 @@ import { ResourceTypeRequest } from './resource-type-request'; @Injectable({ providedIn: 'root' }) export class ResourceTypesService extends BaseService { private reload$ = new Subject(); - private resourceTypeId$: Subject = new Subject(); + private resourceTypeId$: Subject = new Subject(); private predefinedResourceTypes$ = this.getPredefinedResourceTypes(); private rootResourceTypes$ = this.reload$.pipe( diff --git a/AMW_angular/io/src/app/resources/resource-functions.service.ts b/AMW_angular/io/src/app/resources/resource-functions.service.ts index 036b5acac..0f4ca0301 100644 --- a/AMW_angular/io/src/app/resources/resource-functions.service.ts +++ b/AMW_angular/io/src/app/resources/resource-functions.service.ts @@ -10,8 +10,8 @@ import { BaseService } from '../base/base.service'; @Injectable({ providedIn: 'root' }) export class ResourceFunctionsService extends BaseService { private path = `${this.getBaseUrl()}/resources/functions`; - private functions$: Subject = new Subject(); - private functionsForType$: Subject = new Subject(); + private functions$: Subject = new Subject(); + private functionsForType$: Subject = new Subject(); private functionById$: Observable = this.functions$.pipe( switchMap((id: number) => this.getResourceFunctions(id)), From e41c84f67d2440b827a6aa2b9c76adc6c2af4997 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 13:35:46 +0000 Subject: [PATCH 04/16] feat: templates-list component to list resource instance templates --- .../resource/resource-templates.service.ts | 18 ++- .../resource-edit.component.html | 14 +-- .../resource-edit/resource-edit.component.ts | 9 +- .../resource-templates-list.component.html | 9 ++ .../resource-templates-list.component.spec.ts | 27 +++++ .../resource-templates-list.component.ts | 111 ++++++++++++++++++ 6 files changed, 174 insertions(+), 14 deletions(-) create mode 100644 AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.html create mode 100644 AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.spec.ts create mode 100644 AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts diff --git a/AMW_angular/io/src/app/resource/resource-templates.service.ts b/AMW_angular/io/src/app/resource/resource-templates.service.ts index 9b33ba505..0871ebe6c 100644 --- a/AMW_angular/io/src/app/resource/resource-templates.service.ts +++ b/AMW_angular/io/src/app/resource/resource-templates.service.ts @@ -1,16 +1,30 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ResourceTemplate } from './resource-template'; -import { catchError } from 'rxjs/operators'; -import { Observable } from 'rxjs'; +import { catchError, shareReplay, switchMap } from 'rxjs/operators'; +import { Observable, Subject } from 'rxjs'; import { BaseService } from '../base/base.service'; +import { toSignal } from '@angular/core/rxjs-interop'; @Injectable({ providedIn: 'root' }) export class ResourceTemplatesService extends BaseService { + private templates$: Subject = new Subject(); + + private templateById$: Observable = this.templates$.pipe( + switchMap((id: number) => this.getResourceTemplates(id)), + shareReplay(1), + ); + + resourceTemplates = toSignal(this.templateById$, { initialValue: [] }); + constructor(private http: HttpClient) { super(); } + setIdForResourceTemplateList(id: number) { + this.templates$.next(id); + } + getResourceTemplates(id: number): Observable { return this.http .get(`${this.getBaseUrl()}/resources/templates/${id}`, { diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.html b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.html index 48bbb36a5..88d9df63a 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.html +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.html @@ -5,22 +5,14 @@
@if ((this.resource()?.name && !permissions().canEditResource)) {
- Not Authorized! You are not allowed to Edit-Resources. + Not Authorized! You are not allowed to edit resources.
} @else if (id() === 0) {
- Please provide a resource-id to edit a resource. + Please provide the resource id to edit a resource.
} @else { - + }
diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts index 5a3167cf5..6a5f76918 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts @@ -11,11 +11,18 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TileComponent } from '../../shared/tile/tile.component'; import { AuthService } from '../../auth/auth.service'; import { ResourceFunctionsListComponent } from './resource-functions/resource-functions-list.component'; +import { ResourceTemplatesListComponent } from './resource-templates/resource-templates-list.component'; @Component({ selector: 'app-resource-edit', standalone: true, - imports: [LoadingIndicatorComponent, PageComponent, TileComponent, ResourceFunctionsListComponent], + imports: [ + LoadingIndicatorComponent, + PageComponent, + TileComponent, + ResourceFunctionsListComponent, + ResourceTemplatesListComponent, + ], templateUrl: './resource-edit.component.html', }) export class ResourceEditComponent { diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.html b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.html new file mode 100644 index 000000000..dc38e2887 --- /dev/null +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.html @@ -0,0 +1,9 @@ + + diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.spec.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.spec.ts new file mode 100644 index 000000000..a0b92d7a0 --- /dev/null +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.spec.ts @@ -0,0 +1,27 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { InputSignal, signal } from '@angular/core'; +import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { ResourceTemplatesListComponent } from './resource-templates-list.component'; +import { Resource } from '../../../resource/resource'; + +describe('ResourceTemplatesComponent', () => { + let component: ResourceTemplatesListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ResourceTemplatesListComponent], + providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()], + }).compileComponents(); + + fixture = TestBed.createComponent(ResourceTemplatesListComponent); + component = fixture.componentInstance; + component.resource = signal(null) as unknown as InputSignal; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts new file mode 100644 index 000000000..bf27125ae --- /dev/null +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts @@ -0,0 +1,111 @@ +import { Component, computed, inject, input, OnDestroy } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LoadingIndicatorComponent } from '../../../shared/elements/loading-indicator.component'; +import { TileComponent } from '../../../shared/tile/tile.component'; +import { EntryAction, TileListEntryOutput } from '../../../shared/tile/tile-list/tile-list.component'; +import { Action, AuthService } from '../../../auth/auth.service'; +import { Resource } from '../../../resource/resource'; +import { Subject } from 'rxjs'; +import { ResourceTemplatesService } from '../../../resource/resource-templates.service'; +import { ResourceTemplate } from '../../../resource/resource-template'; + +const RESOURCE_PERM = 'RESOURCE_TEMPLATE'; + +@Component({ + selector: 'app-resource-templates-list', + standalone: true, + imports: [LoadingIndicatorComponent, TileComponent], + templateUrl: './resource-templates-list.component.html', +}) +export class ResourceTemplatesListComponent implements OnDestroy { + private authService = inject(AuthService); + private modalService = inject(NgbModal); + private templatesService = inject(ResourceTemplatesService); + private destroy$ = new Subject(); + + resource = input.required(); + contextId = input.required(); + templates = this.templatesService.resourceTemplates; + + isLoading = computed(() => { + if (this.resource() != null) { + this.templatesService.setIdForResourceTemplateList(this.resource().id); + return false; + } + }); + + permissions = computed(() => { + if (this.authService.restrictions().length > 0 && this.resource()) { + return { + canShowInstanceTemplates: this.authService.hasPermission(RESOURCE_PERM, Action.READ), + canAdd: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceGroupPermission(RESOURCE_PERM, Action.CREATE, this.resource().resourceGroupId), + canEdit: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceGroupPermission(RESOURCE_PERM, Action.UPDATE, this.resource().resourceGroupId), + canDelete: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceGroupPermission(RESOURCE_PERM, Action.DELETE, this.resource().resourceGroupId), + }; + } else { + return { + canShowInstanceTemplates: false, + canAdd: false, + canEdit: false, + canDelete: false, + }; + } + }); + + templatesData = computed(() => { + if (this.templates()?.length > 0) { + const instanceTemplates = this.mapListEntries(this.templates()); + const result = []; + if (this.permissions().canShowInstanceTemplates) { + result.push({ + title: 'Resource Instance Templates', + entries: instanceTemplates, + canEdit: this.permissions().canEdit, + canDelete: this.permissions().canDelete, + }); + } + return result; + } else return null; + }); + + ngOnDestroy(): void { + this.destroy$.next(undefined); + } + + doListAction($event: TileListEntryOutput) { + switch ($event.action) { + case EntryAction.edit: + this.editTemplate($event.id); + return; + case EntryAction.delete: + this.deleteTemplate($event.id); + return; + } + } + + mapListEntries(templates: ResourceTemplate[]) { + return templates.map((template) => ({ + name: template.name, + description: template.fileContent, + id: template.id, + })); + } + + addTemplate() { + this.modalService.open('This would open a modal to add a new instance template'); + } + + private editTemplate(id: number) { + this.modalService.open('This would open a modal to edit template with id: ' + id); + } + + private deleteTemplate(id: number) { + this.modalService.open('This would open a modal to delete template with id: ' + id); + } +} From 8cdb3cf73be54e66bf2f84219dbb0561260244c4 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 15:43:09 +0000 Subject: [PATCH 05/16] feat: adjust resource template endpoint to include inherited resource type templates --- .../rest/resources/ResourceTemplatesRest.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java index 5a272a7c8..ab6664f7a 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java @@ -23,6 +23,8 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; @@ -86,18 +88,19 @@ public List getResourceTemplates(@PathParam("resourceGroupName") St @GET @Path("/{resourceId}") - @ApiOperation(value = "Get all templates for a resource") + @ApiOperation(value = "Get all templates for a resource, including inherited resource type templates") public List getResourceTemplatesById(@PathParam("resourceId") Integer resourceId) throws NotFoundException { ResourceEntity resource = entityManager.find(ResourceEntity.class, resourceId); if (resource == null) { throw new NotFoundException("Resource not found"); } - List templates = templateService.getGlobalTemplateDescriptorsForResource(resource); - List templateDTOs = new ArrayList<>(); - for (TemplateDescriptorEntity template : templates) { - templateDTOs.add(new TemplateDTO(template)); - } - return templateDTOs; + List resourceTemplates = templateService.getGlobalTemplateDescriptorsForResource(resource); + List resourceTypeTemplates = templateService.getGlobalTemplateDescriptorsForResourceType(resource.getResourceType()); + List combinedTemplates = Stream.concat(resourceTemplates.stream(), resourceTypeTemplates.stream()) + .collect(Collectors.toList()); + return combinedTemplates.stream() + .map(TemplateDTO::new) + .collect(Collectors.toList()); } @GET From 9d5a69e6d2a9c9a75e96bedddd3c715bc2d413f0 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 17:17:45 +0000 Subject: [PATCH 06/16] feat: adjust data structure to define template origin --- AMW_angular/io/src/app/resource/resource-template.ts | 1 + .../template/entity/TemplateDescriptorEntity.java | 10 ++++++++++ .../ch/mobi/itc/mobiliar/rest/dtos/TemplateDTO.java | 2 ++ 3 files changed, 13 insertions(+) diff --git a/AMW_angular/io/src/app/resource/resource-template.ts b/AMW_angular/io/src/app/resource/resource-template.ts index b88745c92..9c8da0b71 100644 --- a/AMW_angular/io/src/app/resource/resource-template.ts +++ b/AMW_angular/io/src/app/resource/resource-template.ts @@ -5,4 +5,5 @@ export interface ResourceTemplate { targetPath: string; targetPlatforms: string[]; fileContent: string; + sourceType?: 'RESOURCE' | 'RESOURCE_TYPE'; } diff --git a/AMW_business/src/main/java/ch/puzzle/itc/mobiliar/business/template/entity/TemplateDescriptorEntity.java b/AMW_business/src/main/java/ch/puzzle/itc/mobiliar/business/template/entity/TemplateDescriptorEntity.java index 59b94a390..6d13b4cff 100644 --- a/AMW_business/src/main/java/ch/puzzle/itc/mobiliar/business/template/entity/TemplateDescriptorEntity.java +++ b/AMW_business/src/main/java/ch/puzzle/itc/mobiliar/business/template/entity/TemplateDescriptorEntity.java @@ -79,6 +79,16 @@ public class TemplateDescriptorEntity implements Identifiable, Serializable, Cop @Transient private boolean relationTemplate; + public enum TemplateSourceType { + RESOURCE, + RESOURCE_TYPE + } + + @Transient + @Getter + @Setter + private TemplateSourceType sourceType; + @Version private long v; diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/dtos/TemplateDTO.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/dtos/TemplateDTO.java index a826ebda5..75601644b 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/dtos/TemplateDTO.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/dtos/TemplateDTO.java @@ -44,6 +44,7 @@ public class TemplateDTO { private String targetPath; private Set targetPlatforms; private String fileContent; + private String sourceType; public TemplateDTO(TemplateDescriptorEntity template){ this.id = template.getId(); @@ -57,5 +58,6 @@ public TemplateDTO(TemplateDescriptorEntity template){ } } this.fileContent = template.getFileContent(); + this.sourceType = template.getSourceType() != null ? template.getSourceType().name() : null; } } From 1a915563cc4a65a537d56e95c12909d8d3cf2eff Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 17:34:19 +0000 Subject: [PATCH 07/16] feat: adjust endpoint to define template origin --- .../mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java index ab6664f7a..98fe497b7 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java @@ -95,7 +95,9 @@ public List getResourceTemplatesById(@PathParam("resourceId") Integ throw new NotFoundException("Resource not found"); } List resourceTemplates = templateService.getGlobalTemplateDescriptorsForResource(resource); + resourceTemplates.forEach(template -> template.setSourceType(TemplateDescriptorEntity.TemplateSourceType.RESOURCE)); List resourceTypeTemplates = templateService.getGlobalTemplateDescriptorsForResourceType(resource.getResourceType()); + resourceTypeTemplates.forEach(template -> template.setSourceType(TemplateDescriptorEntity.TemplateSourceType.RESOURCE_TYPE)); List combinedTemplates = Stream.concat(resourceTemplates.stream(), resourceTypeTemplates.stream()) .collect(Collectors.toList()); return combinedTemplates.stream() From caaca1ffecb2468f197390bb0d6aec5d9c1664d3 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 6 Jan 2025 17:35:48 +0000 Subject: [PATCH 08/16] chore: styling --- .../resource-functions/resource-functions-list.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-functions/resource-functions-list.component.html b/AMW_angular/io/src/app/resources/resource-edit/resource-functions/resource-functions-list.component.html index d440c8f9c..430eb4074 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-functions/resource-functions-list.component.html +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-functions/resource-functions-list.component.html @@ -1,7 +1,7 @@ Date: Mon, 6 Jan 2025 17:43:29 +0000 Subject: [PATCH 09/16] feat: templates-list component to list resource templates --- .../resource-edit/resource-edit.component.ts | 35 +------------------ .../resource-templates-list.component.ts | 19 +++++++++- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts index 6a5f76918..ad1646c4c 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts @@ -1,4 +1,4 @@ -import { Component, computed, inject, Signal, signal } from '@angular/core'; +import { Component, computed, inject, Signal } from '@angular/core'; import { LoadingIndicatorComponent } from '../../shared/elements/loading-indicator.component'; import { PageComponent } from '../../layout/page/page.component'; import { ActivatedRoute } from '@angular/router'; @@ -6,7 +6,6 @@ import { map } from 'rxjs/operators'; import { toSignal } from '@angular/core/rxjs-interop'; import { ResourceService } from '../../resource/resource.service'; import { Resource } from '../../resource/resource'; -import { EntryAction, TileListEntry, TileListEntryOutput } from '../../shared/tile/tile-list/tile-list.component'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TileComponent } from '../../shared/tile/tile.component'; import { AuthService } from '../../auth/auth.service'; @@ -52,41 +51,9 @@ export class ResourceEditComponent { } }); - templatesData = signal([ - { - title: 'Instance Templates', - entries: [ - { name: 'startJob_0.sh', description: 'startJob_0.sh', id: 0 }, - { name: 'startJob_1.sh', description: 'job 2 again', id: 1 }, - ] as TileListEntry[], - canEdit: true, - canDelete: true, - }, - { - title: 'Resource Type Templates', - entries: [{ name: 'seg', description: 'segmentation', id: 666 }] as TileListEntry[], - canOverwrite: false, - }, - ]); - add() { this.modalService.open('This would open a modal to add something'); } - - doListAction($event: TileListEntryOutput) { - switch ($event.action) { - case EntryAction.edit: - this.editFunction($event.id); - return; - case EntryAction.delete: - this.deleteFunction($event.id); - return; - case EntryAction.overwrite: - this.overwriteFunction($event.id); - return; - } - } - private editFunction(id: number) { this.modalService.open('This would open a modal to edit function with id:' + id); } diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts index bf27125ae..5de3fd197 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts @@ -10,6 +10,7 @@ import { ResourceTemplatesService } from '../../../resource/resource-templates.s import { ResourceTemplate } from '../../../resource/resource-template'; const RESOURCE_PERM = 'RESOURCE_TEMPLATE'; +const RESOURCETYPE_PERM = 'RESOURCETYPE_TEMPLATE'; @Component({ selector: 'app-resource-templates-list', @@ -38,6 +39,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { if (this.authService.restrictions().length > 0 && this.resource()) { return { canShowInstanceTemplates: this.authService.hasPermission(RESOURCE_PERM, Action.READ), + canShowSuperTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), canAdd: (this.contextId() === 1 || this.contextId === null) && this.authService.hasResourceGroupPermission(RESOURCE_PERM, Action.CREATE, this.resource().resourceGroupId), @@ -51,6 +53,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { } else { return { canShowInstanceTemplates: false, + canShowSuperTypeTemplates: false, canAdd: false, canEdit: false, canDelete: false, @@ -60,7 +63,13 @@ export class ResourceTemplatesListComponent implements OnDestroy { templatesData = computed(() => { if (this.templates()?.length > 0) { - const instanceTemplates = this.mapListEntries(this.templates()); + const instanceTemplates = this.mapListEntries( + this.templates().filter((template) => template.sourceType === 'RESOURCE'), + ); + const typeTemplates = this.mapListEntries( + this.templates().filter((template) => template.sourceType === 'RESOURCE_TYPE'), + ); + const result = []; if (this.permissions().canShowInstanceTemplates) { result.push({ @@ -70,6 +79,14 @@ export class ResourceTemplatesListComponent implements OnDestroy { canDelete: this.permissions().canDelete, }); } + if (this.permissions().canShowSuperTypeTemplates) { + result.push({ + title: 'Resource Type Templates', + entries: typeTemplates, + canEdit: false, + canDelete: false, + }); + } return result; } else return null; }); From edd31e8685e189c3bb31074c5be7e66ac9f039de Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Thu, 9 Jan 2025 11:41:55 +0100 Subject: [PATCH 10/16] feat: add resource type templates signal --- .../io/src/app/resource/resource-templates.service.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/AMW_angular/io/src/app/resource/resource-templates.service.ts b/AMW_angular/io/src/app/resource/resource-templates.service.ts index 0871ebe6c..80c6ab918 100644 --- a/AMW_angular/io/src/app/resource/resource-templates.service.ts +++ b/AMW_angular/io/src/app/resource/resource-templates.service.ts @@ -9,14 +9,22 @@ import { toSignal } from '@angular/core/rxjs-interop'; @Injectable({ providedIn: 'root' }) export class ResourceTemplatesService extends BaseService { private templates$: Subject = new Subject(); + private templatesForType$: Subject = new Subject(); private templateById$: Observable = this.templates$.pipe( switchMap((id: number) => this.getResourceTemplates(id)), shareReplay(1), ); + private templateByTypeId$: Observable = this.templatesForType$.pipe( + switchMap((id: number) => this.getResourceTypeTemplates(id)), + shareReplay(1), + ); + resourceTemplates = toSignal(this.templateById$, { initialValue: [] }); + resourceTypeTemplates = toSignal(this.templateByTypeId$, { initialValue: [] }); + constructor(private http: HttpClient) { super(); } From cb1508913fc4b1b54c9780c7bca89bf933669501 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Thu, 9 Jan 2025 13:04:26 +0100 Subject: [PATCH 11/16] feat: templates-list component to list resource type templates --- .../resource/resource-templates.service.ts | 4 + .../resource-type-edit.component.html | 13 +- .../resource-type-edit.component.ts | 44 ++----- ...esource-type-functions-list.component.html | 2 +- .../resource-type-functions-list.component.ts | 2 +- ...esource-type-templates-list.component.html | 9 ++ .../resource-type-templates-list.component.ts | 111 ++++++++++++++++++ 7 files changed, 139 insertions(+), 46 deletions(-) create mode 100644 AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.html create mode 100644 AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts diff --git a/AMW_angular/io/src/app/resource/resource-templates.service.ts b/AMW_angular/io/src/app/resource/resource-templates.service.ts index 80c6ab918..b5f94a570 100644 --- a/AMW_angular/io/src/app/resource/resource-templates.service.ts +++ b/AMW_angular/io/src/app/resource/resource-templates.service.ts @@ -33,6 +33,10 @@ export class ResourceTemplatesService extends BaseService { this.templates$.next(id); } + setIdForResourceTypeTemplateList(id: number) { + this.templatesForType$.next(id); + } + getResourceTemplates(id: number): Observable { return this.http .get(`${this.getBaseUrl()}/resources/templates/${id}`, { diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.html b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.html index 2ed86e3fa..bfbb2dc7d 100644 --- a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.html +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.html @@ -12,15 +12,10 @@ Please provide a resourceType-id to edit a resource. } @else { - + + diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts new file mode 100644 index 000000000..b545e12e4 --- /dev/null +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts @@ -0,0 +1,111 @@ +import { Component, computed, inject, input, OnDestroy } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { LoadingIndicatorComponent } from '../../../shared/elements/loading-indicator.component'; +import { TileComponent } from '../../../shared/tile/tile.component'; +import { EntryAction, TileListEntryOutput } from '../../../shared/tile/tile-list/tile-list.component'; +import { Action, AuthService } from '../../../auth/auth.service'; +import { Subject } from 'rxjs'; +import { ResourceTemplatesService } from '../../../resource/resource-templates.service'; +import { ResourceTemplate } from '../../../resource/resource-template'; +import { ResourceType } from '../../../resource/resource-type'; + +const RESOURCETYPE_PERM = 'RESOURCETYPE_TEMPLATE'; + +@Component({ + selector: 'app-resource-type-templates-list', + standalone: true, + imports: [LoadingIndicatorComponent, TileComponent], + templateUrl: './resource-type-templates-list.component.html', +}) +export class ResourceTypeTemplatesListComponent implements OnDestroy { + private authService = inject(AuthService); + private modalService = inject(NgbModal); + private templatesService = inject(ResourceTemplatesService); + private destroy$ = new Subject(); + + resourceType = input.required(); + contextId = input.required(); + templates = this.templatesService.resourceTypeTemplates; + + isLoading = computed(() => { + if (this.resourceType() != null) { + this.templatesService.setIdForResourceTypeTemplateList(this.resourceType().id); + return false; + } + }); + + permissions = computed(() => { + if (this.authService.restrictions().length > 0 && this.resourceType()) { + return { + canShowSuperTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), + canAdd: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceTypePermission(RESOURCETYPE_PERM, Action.CREATE, this.resourceType().name), + canEdit: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceTypePermission(RESOURCETYPE_PERM, Action.UPDATE, this.resourceType().name), + canDelete: + (this.contextId() === 1 || this.contextId === null) && + this.authService.hasResourceTypePermission(RESOURCETYPE_PERM, Action.DELETE, this.resourceType().name), + }; + } else { + return { + canShowSuperTypeTemplates: false, + canAdd: false, + canEdit: false, + canDelete: false, + }; + } + }); + + templatesData = computed(() => { + if (this.templates()?.length > 0) { + const typeTemplates = this.mapListEntries(this.templates()); + return [ + { + title: 'Resource Type Templates', + entries: typeTemplates, + canEdit: this.permissions().canEdit, + canDelete: this.permissions().canDelete, + }, + ]; + } else { + return null; + } + }); + + ngOnDestroy(): void { + this.destroy$.next(undefined); + } + + doListAction($event: TileListEntryOutput) { + switch ($event.action) { + case EntryAction.edit: + this.editTemplate($event.id); + return; + case EntryAction.delete: + this.deleteTemplate($event.id); + return; + } + } + + mapListEntries(templates: ResourceTemplate[]) { + return templates.map((template) => ({ + name: template.name, + description: template.fileContent, + id: template.id, + })); + } + + addTemplate() { + this.modalService.open('This would open a modal to add a new resource type template'); + } + + private editTemplate(id: number) { + this.modalService.open('This would open a modal to edit template with id: ' + id); + } + + private deleteTemplate(id: number) { + this.modalService.open('This would open a modal to delete template with id: ' + id); + } +} From 4ac5e6a5bf1ed7bff744d60e35cc67d7f3f5f85f Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Thu, 9 Jan 2025 13:20:01 +0100 Subject: [PATCH 12/16] fix: description --- .../resource-templates/resource-templates-list.component.ts | 2 +- .../resource-type-templates-list.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts index 5de3fd197..eaa003141 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts @@ -109,7 +109,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { mapListEntries(templates: ResourceTemplate[]) { return templates.map((template) => ({ name: template.name, - description: template.fileContent, + description: template.targetPath, id: template.id, })); } diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts index b545e12e4..e42e586b3 100644 --- a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts @@ -92,7 +92,7 @@ export class ResourceTypeTemplatesListComponent implements OnDestroy { mapListEntries(templates: ResourceTemplate[]) { return templates.map((template) => ({ name: template.name, - description: template.fileContent, + description: template.targetPath, id: template.id, })); } From a5c46e2757602f45059bad7aa2abb466e85401d3 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Thu, 9 Jan 2025 17:03:52 +0100 Subject: [PATCH 13/16] chore: adjust naming --- .../resource-type-functions-list.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-functions/resource-type-functions-list.component.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-functions/resource-type-functions-list.component.ts index 300365da9..65ab410ec 100644 --- a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-functions/resource-type-functions-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-functions/resource-type-functions-list.component.ts @@ -72,7 +72,7 @@ export class ResourceTypeFunctionsListComponent { const result = []; if (this.permissions().canShowInstanceFunctions) { result.push({ - title: 'Type Functions', + title: 'Resource Type Functions', entries: instance, canEdit: this.permissions().canEdit || this.permissions().canShowInstanceFunctions, canDelete: this.permissions().canDelete, From c2b0190115cc672d5003d02a7921bfac9dfd4bbd Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Thu, 9 Jan 2025 17:16:19 +0100 Subject: [PATCH 14/16] chore: unit test for component --- ...urce-type-templates-list.component.spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.spec.ts diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.spec.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.spec.ts new file mode 100644 index 000000000..41d1c968f --- /dev/null +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.spec.ts @@ -0,0 +1,27 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { InputSignal, signal } from '@angular/core'; +import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { ResourceTypeTemplatesListComponent } from './resource-type-templates-list.component'; +import { ResourceType } from '../../../resource/resource-type'; + +describe('ResourceTypeTemplatesListComponent', () => { + let component: ResourceTypeTemplatesListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ResourceTypeTemplatesListComponent], + providers: [provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()], + }).compileComponents(); + + fixture = TestBed.createComponent(ResourceTypeTemplatesListComponent); + component = fixture.componentInstance; + component.resourceType = signal(null) as unknown as InputSignal; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); From 7b4efba73e27185167163dfc60ac2b34fb310732 Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 13 Jan 2025 13:18:27 +0100 Subject: [PATCH 15/16] chore: delete unused methods and rename permissions --- .../resource-edit/resource-edit.component.ts | 17 ----------------- .../resource-templates-list.component.ts | 6 +++--- .../resource-type-edit.component.ts | 17 ----------------- .../resource-type-templates-list.component.ts | 4 ++-- 4 files changed, 5 insertions(+), 39 deletions(-) diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts index 2cda3fe20..f3558f428 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-edit.component.ts @@ -6,7 +6,6 @@ import { map } from 'rxjs/operators'; import { toSignal } from '@angular/core/rxjs-interop'; import { ResourceService } from '../../resource/resource.service'; import { Resource } from '../../resource/resource'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TileComponent } from '../../shared/tile/tile.component'; import { AuthService } from '../../auth/auth.service'; import { ResourceFunctionsListComponent } from './resource-functions/resource-functions-list.component'; @@ -26,7 +25,6 @@ import { ResourceTemplatesListComponent } from './resource-templates/resource-te }) export class ResourceEditComponent { private authService = inject(AuthService); - private modalService = inject(NgbModal); private resourceService = inject(ResourceService); private route = inject(ActivatedRoute); @@ -50,19 +48,4 @@ export class ResourceEditComponent { return { canEditResource: false }; } }); - - add() { - this.modalService.open('This would open a modal to add something'); - } - private edit(id: number) { - this.modalService.open('This would open a modal to edit with id:' + id); - } - - private delete(id: number) { - this.modalService.open('This would open a modal to delete with id:' + id); - } - - private overwrite(id: number) { - this.modalService.open('This would open a modal to overwrite with id:' + id); - } } diff --git a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts index eaa003141..e72e21065 100644 --- a/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-edit/resource-templates/resource-templates-list.component.ts @@ -39,7 +39,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { if (this.authService.restrictions().length > 0 && this.resource()) { return { canShowInstanceTemplates: this.authService.hasPermission(RESOURCE_PERM, Action.READ), - canShowSuperTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), + canShowTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), canAdd: (this.contextId() === 1 || this.contextId === null) && this.authService.hasResourceGroupPermission(RESOURCE_PERM, Action.CREATE, this.resource().resourceGroupId), @@ -53,7 +53,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { } else { return { canShowInstanceTemplates: false, - canShowSuperTypeTemplates: false, + canShowTypeTemplates: false, canAdd: false, canEdit: false, canDelete: false, @@ -79,7 +79,7 @@ export class ResourceTemplatesListComponent implements OnDestroy { canDelete: this.permissions().canDelete, }); } - if (this.permissions().canShowSuperTypeTemplates) { + if (this.permissions().canShowTypeTemplates) { result.push({ title: 'Resource Type Templates', entries: typeTemplates, diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.ts index cf2cbbe99..8875d3a91 100644 --- a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.ts +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-edit.component.ts @@ -4,7 +4,6 @@ import { PageComponent } from '../../layout/page/page.component'; import { ActivatedRoute } from '@angular/router'; import { map } from 'rxjs/operators'; import { toSignal } from '@angular/core/rxjs-interop'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; import { TileComponent } from '../../shared/tile/tile.component'; import { AuthService } from '../../auth/auth.service'; import { ResourceType } from '../../resource/resource-type'; @@ -26,7 +25,6 @@ import { ResourceTypeTemplatesListComponent } from './resource-type-templates/re }) export class ResourceTypeEditComponent { private authService = inject(AuthService); - private modalService = inject(NgbModal); private resourceTypeService = inject(ResourceTypesService); private route = inject(ActivatedRoute); @@ -50,19 +48,4 @@ export class ResourceTypeEditComponent { return { canEditResourceType: false }; } }); - - add() { - this.modalService.open('This would open a modal to add something'); - } - private edit(id: number) { - this.modalService.open('This would open a modal to edit with id:' + id); - } - - private delete(id: number) { - this.modalService.open('This would open a modal to delete with id:' + id); - } - - private overwrite(id: number) { - this.modalService.open('This would open a modal to overwrite with id:' + id); - } } diff --git a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts index e42e586b3..dff35b1c4 100644 --- a/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts +++ b/AMW_angular/io/src/app/resources/resource-type-edit/resource-type-templates/resource-type-templates-list.component.ts @@ -37,7 +37,7 @@ export class ResourceTypeTemplatesListComponent implements OnDestroy { permissions = computed(() => { if (this.authService.restrictions().length > 0 && this.resourceType()) { return { - canShowSuperTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), + canShowTypeTemplates: this.authService.hasPermission(RESOURCETYPE_PERM, Action.READ), canAdd: (this.contextId() === 1 || this.contextId === null) && this.authService.hasResourceTypePermission(RESOURCETYPE_PERM, Action.CREATE, this.resourceType().name), @@ -50,7 +50,7 @@ export class ResourceTypeTemplatesListComponent implements OnDestroy { }; } else { return { - canShowSuperTypeTemplates: false, + canShowTypeTemplates: false, canAdd: false, canEdit: false, canDelete: false, From 3494119b7194b9325e25145b5d4a847ca6a1984a Mon Sep 17 00:00:00 2001 From: llorentelemmc Date: Mon, 13 Jan 2025 13:55:17 +0100 Subject: [PATCH 16/16] refactor: add numeric validation to endpoints --- .../itc/mobiliar/rest/resources/ResourceTemplatesRest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java index 98fe497b7..7eb526cd9 100644 --- a/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java +++ b/AMW_rest/src/main/java/ch/mobi/itc/mobiliar/rest/resources/ResourceTemplatesRest.java @@ -87,7 +87,7 @@ public List getResourceTemplates(@PathParam("resourceGroupName") St } @GET - @Path("/{resourceId}") + @Path("/{resourceId: \\d+}") @ApiOperation(value = "Get all templates for a resource, including inherited resource type templates") public List getResourceTemplatesById(@PathParam("resourceId") Integer resourceId) throws NotFoundException { ResourceEntity resource = entityManager.find(ResourceEntity.class, resourceId); @@ -106,7 +106,7 @@ public List getResourceTemplatesById(@PathParam("resourceId") Integ } @GET - @Path("/resourceType/{resourceTypeId}") + @Path("/resourceType/{resourceTypeId: \\d+}") @ApiOperation(value = "Get all templates for a resource type") public Response getResourceTypeTemplatesById(@PathParam("resourceTypeId") Integer resourceTypeId) throws NotFoundException {