Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: delete resource templates #826

Merged
merged 22 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
82b9f94
feat: endpoints for resource and resource type templates
llorentelemmc Jan 3, 2025
fc51594
feat: create resource templates model and service
llorentelemmc Jan 3, 2025
6245596
refactor: prettier
llorentelemmc Jan 6, 2025
e41c84f
feat: templates-list component to list resource instance templates
llorentelemmc Jan 6, 2025
8cdb3cf
feat: adjust resource template endpoint to include inherited resource…
llorentelemmc Jan 6, 2025
9d5a69e
feat: adjust data structure to define template origin
llorentelemmc Jan 6, 2025
1a91556
feat: adjust endpoint to define template origin
llorentelemmc Jan 6, 2025
caaca1f
chore: styling
llorentelemmc Jan 6, 2025
d679398
feat: templates-list component to list resource templates
llorentelemmc Jan 6, 2025
edd31e8
feat: add resource type templates signal
llorentelemmc Jan 9, 2025
cb15089
feat: templates-list component to list resource type templates
llorentelemmc Jan 9, 2025
4ac5e6a
fix: description
llorentelemmc Jan 9, 2025
885c19a
Merge branch 'development' into list-templates
llorentelemmc Jan 9, 2025
a5c46e2
chore: adjust naming
llorentelemmc Jan 9, 2025
c2b0190
chore: unit test for component
llorentelemmc Jan 9, 2025
4b69eab
feat: delete template endpoint
llorentelemmc Jan 11, 2025
a150c0f
feat: resource template-delete component
llorentelemmc Jan 11, 2025
a4734e4
chore: remove repetition
llorentelemmc Jan 11, 2025
32ed072
feat: delete functionality in resource templates-list component
llorentelemmc Jan 11, 2025
7e8dc06
feat: delete functionality in resource type templates-list component
llorentelemmc Jan 11, 2025
5a8fef3
Merge branch 'development' into delete-templates
llorentelemmc Jan 14, 2025
d6f5dcc
refactor: create error mapper for TemplateNotDeletableException
llorentelemmc Jan 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create a mapper for a more meaningful error message for TemplateNotDeletableException and add it to RESTApplication.

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
Loading