Skip to content

Commit

Permalink
feature: delete resource templates (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
llorentelemmc authored Jan 14, 2025
1 parent 5e7e672 commit 290d496
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 14 deletions.
8 changes: 8 additions & 0 deletions AMW_angular/io/src/app/resource/resource-templates.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@ export class ResourceTemplatesService extends BaseService {
})
.pipe(catchError(this.handleError));
}

deleteTemplate(id: number): Observable<void> {
return this.http
.delete<void>(`${this.getBaseUrl()}/resources/templates/${id}`, {
headers: this.getHeaders(),
})
.pipe(catchError(this.handleError));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ import { ButtonComponent } from '../../../shared/button/button.component';
selector: 'app-resource-function-delete',
standalone: true,
templateUrl: './resource-function-delete.component.html',
imports: [
ModalHeaderComponent,
ButtonComponent,
ModalHeaderComponent,
ButtonComponent,
ModalHeaderComponent,
ButtonComponent,
],
imports: [ModalHeaderComponent, ButtonComponent],
})
export class ResourceFunctionDeleteComponent {
activeModal = inject(NgbActiveModal);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="container">
<app-modal-header [title]="'Delete Template'" (cancel)="cancel()"></app-modal-header>
<div class="modal-body">
<div class="form-horizontal mx-2">
<div class="mb-3">
<div class="text-body">Do you really want to delete the selected template?</div>
</div>
</div>
</div>
<div class="modal-footer">
<app-button [variant]="'light'" (click)="cancel()">Cancel</app-button>
<app-button [variant]="'primary'" (click)="delete()">Delete</app-button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ResourceTemplateDeleteComponent } from './resource-template-delete.component';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

describe('ResourceTemplateDeleteComponent', () => {
let component: ResourceTemplateDeleteComponent;
let fixture: ComponentFixture<ResourceTemplateDeleteComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ResourceTemplateDeleteComponent],
providers: [NgbActiveModal],
}).compileComponents();

fixture = TestBed.createComponent(ResourceTemplateDeleteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { ModalHeaderComponent } from '../../../shared/modal-header/modal-header.component';
import { ButtonComponent } from '../../../shared/button/button.component';

@Component({
selector: 'app-resource-template-delete',
standalone: true,
templateUrl: './resource-template-delete.component.html',
imports: [ModalHeaderComponent, ButtonComponent],
})
export class ResourceTemplateDeleteComponent {
activeModal = inject(NgbActiveModal);
@Input() templateId: number;
@Output() deleteTemplateId: EventEmitter<number> = new EventEmitter<number>();

cancel() {
this.activeModal.close();
}

delete() {
this.deleteTemplateId.emit(this.templateId);
this.activeModal.close();
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Component, computed, inject, input, OnDestroy } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { NgbModal, NgbModalRef } 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 { BehaviorSubject, Subject } from 'rxjs';
import { ResourceTemplatesService } from '../../../resource/resource-templates.service';
import { ResourceTemplate } from '../../../resource/resource-template';
import { ResourceTemplateDeleteComponent } from './resource-template-delete.component';
import { takeUntil } from 'rxjs/operators';
import { ToastService } from '../../../shared/elements/toast/toast.service';

const RESOURCE_PERM = 'RESOURCE_TEMPLATE';
const RESOURCETYPE_PERM = 'RESOURCETYPE_TEMPLATE';
Expand All @@ -22,7 +25,9 @@ export class ResourceTemplatesListComponent implements OnDestroy {
private authService = inject(AuthService);
private modalService = inject(NgbModal);
private templatesService = inject(ResourceTemplatesService);
private toastService = inject(ToastService);
private destroy$ = new Subject<void>();
private error$ = new BehaviorSubject<string>('');

resource = input.required<Resource>();
contextId = input.required<number>();
Expand Down Expand Up @@ -123,6 +128,23 @@ export class ResourceTemplatesListComponent implements OnDestroy {
}

private deleteTemplate(id: number) {
this.modalService.open('This would open a modal to delete template with id: ' + id);
const modalRef: NgbModalRef = this.modalService.open(ResourceTemplateDeleteComponent);
modalRef.componentInstance.templateId = id;
modalRef.componentInstance.deleteTemplateId
.pipe(takeUntil(this.destroy$))
.subscribe((id: number) => this.removeTemplate(id));
}

private removeTemplate(id: number) {
this.templatesService
.deleteTemplate(id)
.pipe(takeUntil(this.destroy$))
.subscribe({
next: () => this.toastService.success('Template deleted successfully.'),
error: (e) => this.error$.next(e.toString()),
complete: () => {
this.templatesService.setIdForResourceTemplateList(this.resource().id);
},
});
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Component, computed, inject, input, OnDestroy } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { NgbModal, NgbModalRef } 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 { BehaviorSubject, Subject } from 'rxjs';
import { ResourceTemplatesService } from '../../../resource/resource-templates.service';
import { ResourceTemplate } from '../../../resource/resource-template';
import { ResourceType } from '../../../resource/resource-type';
import { takeUntil } from 'rxjs/operators';
import { ToastService } from '../../../shared/elements/toast/toast.service';
import { ResourceTemplateDeleteComponent } from '../../resource-edit/resource-templates/resource-template-delete.component';

const RESOURCETYPE_PERM = 'RESOURCETYPE_TEMPLATE';

Expand All @@ -21,7 +24,9 @@ export class ResourceTypeTemplatesListComponent implements OnDestroy {
private authService = inject(AuthService);
private modalService = inject(NgbModal);
private templatesService = inject(ResourceTemplatesService);
private toastService = inject(ToastService);
private destroy$ = new Subject<void>();
private error$ = new BehaviorSubject<string>('');

resourceType = input.required<ResourceType>();
contextId = input.required<number>();
Expand Down Expand Up @@ -106,6 +111,23 @@ export class ResourceTypeTemplatesListComponent implements OnDestroy {
}

private deleteTemplate(id: number) {
this.modalService.open('This would open a modal to delete template with id: ' + id);
const modalRef: NgbModalRef = this.modalService.open(ResourceTemplateDeleteComponent);
modalRef.componentInstance.templateId = id;
modalRef.componentInstance.deleteTemplateId
.pipe(takeUntil(this.destroy$))
.subscribe((id: number) => this.removeTemplate(id));
}

private removeTemplate(id: number) {
this.templatesService
.deleteTemplate(id)
.pipe(takeUntil(this.destroy$))
.subscribe({
next: () => this.toastService.success('Template deleted successfully.'),
error: (e) => this.error$.next(e.toString()),
complete: () => {
this.templatesService.setIdForResourceTypeTemplateList(this.resourceType().id);
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(ConstraintViolationExceptionMapper.class);
resources.add(ConcurrentModificationExceptionMapper.class);
resources.add(ElementAlreadyExistsExceptionMapper.class);
resources.add(TemplateNotDeletableExceptionMapper.class);

// health
resources.add(HealthCheck.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* AMW - Automated Middleware allows you to manage the configurations of
* your Java EE applications on an unlimited number of different environments
* with various versions, including the automated deployment of those apps.
* Copyright (C) 2013-2016 by Puzzle ITC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package ch.mobi.itc.mobiliar.rest.exceptions;

import ch.puzzle.itc.mobiliar.common.exception.TemplateNotDeletableException;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class TemplateNotDeletableExceptionMapper implements ExceptionMapper<TemplateNotDeletableException> {
@Override
public Response toResponse(TemplateNotDeletableException exception) {
return Response.status(Response.Status.BAD_REQUEST).entity(new ExceptionDto(exception)).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ public Response deleteResourceTemplate(@PathParam("resourceGroupName") String re
return Response.status(Response.Status.OK).build();
}

@DELETE
@Path("/{id : \\d+}")
@ApiOperation(value = "Remove a template")
public Response deleteTemplate(@PathParam("id") Integer id) throws TemplateNotDeletableException {
templateEditor.removeTemplate(id);
return Response.status(Response.Status.NO_CONTENT).build();
}

@POST
@Path("/{resourceGroupName}/{releaseName}")
@ApiOperation(value = "Create a template for a resource in a specific release")
Expand Down

0 comments on commit 290d496

Please sign in to comment.