From ac746e204b0b0f049373332147bc15fa8e05b732 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 19 May 2026 12:30:51 -0400 Subject: [PATCH 1/6] feat: Add delete and restore log actions to admin control panel --- .../ClientApp/src/app/admin/admin.module.ts | 6 ++- .../expired-log-item.component.html | 30 ++++++++++- .../expired-log-item.component.scss | 3 +- .../expired-log-item.component.ts | 50 +++++++++++++++++-- .../modal-delete-log.component.html | 48 ++++++++++++++++++ .../modal-delete-log.component.scss | 15 ++++++ .../modal-delete-log.component.spec.ts | 23 +++++++++ .../modal-delete-log.component.ts | 44 ++++++++++++++++ .../modal-restore-log.component.html | 48 ++++++++++++++++++ .../modal-restore-log.component.scss | 15 ++++++ .../modal-restore-log.component.spec.ts | 23 +++++++++ .../modal-restore-log.component.ts | 43 ++++++++++++++++ .../project-logs/project-logs.component.html | 2 +- .../project-logs/project-logs.component.scss | 3 +- .../project-logs/project-logs.component.ts | 14 ------ 15 files changed, 343 insertions(+), 24 deletions(-) create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.html create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.scss create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.spec.ts create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.ts create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.html create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.scss create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.spec.ts create mode 100644 src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.ts diff --git a/src/Analysim.Web/ClientApp/src/app/admin/admin.module.ts b/src/Analysim.Web/ClientApp/src/app/admin/admin.module.ts index b226a48c..41245edc 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/admin.module.ts +++ b/src/Analysim.Web/ClientApp/src/app/admin/admin.module.ts @@ -21,6 +21,8 @@ import { ModalDeleteReportsComponent } from './components/comments/modal-delete- import { ModalIgnoreReportsComponent } from './components/comments/modal-ignore-reports/modal-ignore-reports.component'; import { ProjectLogsComponent } from './components/project-logs/project-logs.component'; import { ExpiredLogItemComponent } from './components/project-logs/expired-log-item/expired-log-item.component'; +import { ModalDeleteLogComponent } from './components/project-logs/modal-delete-log/modal-delete-log.component'; +import { ModalRestoreLogComponent } from './components/project-logs/modal-restore-log/modal-restore-log.component'; @NgModule({ declarations: [ @@ -41,7 +43,9 @@ import { ExpiredLogItemComponent } from './components/project-logs/expired-log-i ModalDeleteReportsComponent, ModalIgnoreReportsComponent, ProjectLogsComponent, - ExpiredLogItemComponent + ExpiredLogItemComponent, + ModalDeleteLogComponent, + ModalRestoreLogComponent ], imports: [ CommonModule, diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.html b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.html index a085c2a5..07c7685a 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.html +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.html @@ -30,6 +30,14 @@
+ +
- \ No newline at end of file + + + + + + + + + + + \ No newline at end of file diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.scss b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.scss index 905ff0dd..35b6e413 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.scss +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.scss @@ -4,7 +4,7 @@ .expired-log-row { display: grid; - grid-template-columns: 1.5fr .75fr .75fr .5fr .5fr .5fr .25fr; + grid-template-columns: 1.5fr .75fr .75fr .5fr .5fr .5fr .5fr; gap: var(--space-3); align-items: center; padding: var(--space-1) var(--space-3); @@ -63,6 +63,7 @@ .actions-col { display: flex; justify-content: flex-end; + gap: var(--space-2); } @media (max-width: 900px) { diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.ts index 93f7b29d..45c45084 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.ts +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/expired-log-item/expired-log-item.component.ts @@ -1,4 +1,5 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core'; +import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal'; import { ExpiredProjectLog } from 'src/app/interfaces/expired-project-log'; @Component({ @@ -8,15 +9,56 @@ import { ExpiredProjectLog } from 'src/app/interfaces/expired-project-log'; }) export class ExpiredLogItemComponent implements OnInit { @Input() log!: ExpiredProjectLog; - @Output() deleteLog = new EventEmitter(); + @Output() onReload = new EventEmitter(); - constructor() { } + // Modals + @ViewChild('restoreModal') restoreModal: TemplateRef; + @ViewChild('deleteModal') deleteModal: TemplateRef; + + // Modal Refs + restoreModalRef: BsModalRef; + deleteModalRef: BsModalRef; + + isDeleted: boolean; + isDeleting: boolean; + isRestoring: boolean; + + constructor(private modalService: BsModalService) {} ngOnInit(): void { } + // Delete + onDelete(): void { - this.deleteLog.emit(this.log.logID); + this.toggleModalDelete(); + this.isDeleting = true; + } + + onHandleSuccessfulDelete(): void { + this.isDeleted = true; + this.isDeleting = false; + this.onReload.emit(); + } + + toggleModalDelete() { + this.deleteModalRef = this.modalService.show(this.deleteModal) + } + + // Restore + + onRestore(): void { + this.toggleModalRestore(); + this.isRestoring = true; + } + + onHandleSuccessfulRestore(): void { + this.isRestoring = false; + this.onReload.emit(); + } + + toggleModalRestore() { + this.restoreModalRef = this.modalService.show(this.restoreModal) } } diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.html b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.html new file mode 100644 index 00000000..eecb8052 --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.html @@ -0,0 +1,48 @@ + diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.scss b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.scss new file mode 100644 index 00000000..e4caf7ff --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.scss @@ -0,0 +1,15 @@ +.modal-confirm{ + text-align: center; + font-weight: 700; + font-size: large; + padding: 0; + padding-bottom: 1rem; + margin: 0; +} + +.modal-warning{ + text-align: center; + font-size: small; + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.spec.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.spec.ts new file mode 100644 index 00000000..9d6c2a09 --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModalDeleteLogComponent } from './modal-delete-log.component'; + +describe('ModalDeleteLogComponent', () => { + let component: ModalDeleteLogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ModalDeleteLogComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ModalDeleteLogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.ts new file mode 100644 index 00000000..9eb76da3 --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-delete-log/modal-delete-log.component.ts @@ -0,0 +1,44 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { ProjectService } from 'src/app/services/project.service'; + +@Component({ + selector: 'app-modal-delete-log', + templateUrl: './modal-delete-log.component.html', + styleUrls: ['./modal-delete-log.component.scss'], +}) +export class ModalDeleteLogComponent implements OnInit { + @Input() deleteModalRef: BsModalRef; + @Input() logID: number; + + @Output() onSuccessfulDelete = new EventEmitter(); + @Output() onCancelDelete = new EventEmitter(); + + errorResult: String; + errorStatusAlert = false; + + constructor(private projectService: ProjectService) {} + + ngOnInit(): void {} + + onDelete(): void { + this.projectService.deleteExpiredProjectLog(this.logID).subscribe({ + next: (result) => { + console.log('Deleted log:', this.logID); + this.onSuccessfulDelete.emit(); + this.deleteModalRef.hide(); + }, + error: (error) => { + this.errorStatusAlert = true; + this.errorResult = + 'Error: unable to delete log, please contact developers for assistance'; + console.log(error); + }, + }); + } + + closeModal() { + this.onCancelDelete.emit(); + this.deleteModalRef.hide(); + } +} diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.html b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.html new file mode 100644 index 00000000..b072d17d --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.html @@ -0,0 +1,48 @@ + diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.scss b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.scss new file mode 100644 index 00000000..e4caf7ff --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.scss @@ -0,0 +1,15 @@ +.modal-confirm{ + text-align: center; + font-weight: 700; + font-size: large; + padding: 0; + padding-bottom: 1rem; + margin: 0; +} + +.modal-warning{ + text-align: center; + font-size: small; + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.spec.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.spec.ts new file mode 100644 index 00000000..dec869bb --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModalRestoreLogComponent } from './modal-restore-log.component'; + +describe('ModalRestoreLogComponent', () => { + let component: ModalRestoreLogComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ModalRestoreLogComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ModalRestoreLogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.ts new file mode 100644 index 00000000..7e4e21bd --- /dev/null +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/modal-restore-log/modal-restore-log.component.ts @@ -0,0 +1,43 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { BsModalRef } from 'ngx-bootstrap/modal'; +import { ProjectService } from 'src/app/services/project.service'; + +@Component({ + selector: 'app-modal-restore-log', + templateUrl: './modal-restore-log.component.html', + styleUrls: ['./modal-restore-log.component.scss'] +}) +export class ModalRestoreLogComponent implements OnInit { + @Input() restoreModalRef: BsModalRef + @Input() logID: number; + + @Output() onSuccessfulRestore = new EventEmitter(); + @Output() onCancelRestore = new EventEmitter(); + + errorResult: String; + errorStatusAlert = false; + + constructor(private projectService: ProjectService) { } + + ngOnInit(): void {} + + onRestore(): void { + this.projectService.repostProjectLog(this.logID).subscribe({ + next: (result) => { + console.log('Restored log', this.logID); + this.onSuccessfulRestore.emit(); + this.restoreModalRef.hide(); + }, + error: (error) => { + this.errorStatusAlert = true; + this.errorResult = "Error: unable to restore log, please contact developers for assistance"; + console.log(error); + }, + }); + } + + closeModal() { + this.onCancelRestore.emit(); + this.restoreModalRef.hide(); + } +} diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.html b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.html index bfd207d0..55c7ed95 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.html +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.html @@ -40,7 +40,7 @@

Expired Logs

diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.scss b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.scss index 92280443..0fc3044f 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.scss +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.scss @@ -11,7 +11,7 @@ .expired-log-header { display: grid; - grid-template-columns: 1.5fr .75fr .75fr .5fr .5fr .5fr .25fr; + grid-template-columns: 1.5fr .75fr .75fr .5fr .5fr .5fr .5fr; gap: var(--space-3); align-items: center; padding: var(--space-1) var(--space-3); @@ -24,7 +24,6 @@ .actions-col { display: flex; - justify-content: flex-end; } .empty-set{ diff --git a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.ts b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.ts index 044e0485..a9af5f1d 100644 --- a/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.ts +++ b/src/Analysim.Web/ClientApp/src/app/admin/components/project-logs/project-logs.component.ts @@ -34,18 +34,4 @@ export class ProjectLogsComponent implements OnInit { }, }); } - - deleteExpiredLog(logID: number){ - this.projectService.deleteExpiredProjectLog(logID).subscribe({ - next: (result) => { - console.log('Deleted project log', logID); - this.loadLogs(); - }, - error: (error) => { - this.errorStatusAlert = true; - this.errorResult = "Error: unable to delete project log, please try again later"; - console.log(error); - }, - }); - } } From a8b7f38ba0281ed52aaa34f76a10230f0eb51bf5 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 19 May 2026 12:37:31 -0400 Subject: [PATCH 2/6] style: Improve main project layout --- .../modal-member-list.component.html | 60 ++-- .../project-stat-counter.component.html | 51 +++ .../project-stat-counter.component.scss | 50 +++ .../project-stat-counter.component.spec.ts | 23 ++ .../project-stat-counter.component.ts | 28 ++ .../projects/project/project.component.html | 101 +----- .../projects/project/project.component.scss | 324 +++++++++++------- .../app/projects/project/project.component.ts | 7 - .../src/app/projects/projects.module.ts | 2 + .../styles/base/_bootstrap-overrides.scss | 15 +- .../src/assets/styles/base/_reset.scss | 8 + 11 files changed, 424 insertions(+), 245 deletions(-) create mode 100644 src/Analysim.Web/ClientApp/src/app/projects/project/project-stat-counter/project-stat-counter.component.html create mode 100644 src/Analysim.Web/ClientApp/src/app/projects/project/project-stat-counter/project-stat-counter.component.scss create mode 100644 src/Analysim.Web/ClientApp/src/app/projects/project/project-stat-counter/project-stat-counter.component.spec.ts create mode 100644 src/Analysim.Web/ClientApp/src/app/projects/project/project-stat-counter/project-stat-counter.component.ts diff --git a/src/Analysim.Web/ClientApp/src/app/projects/project/modal-member-list/modal-member-list.component.html b/src/Analysim.Web/ClientApp/src/app/projects/project/modal-member-list/modal-member-list.component.html index acdd280c..d6f25368 100644 --- a/src/Analysim.Web/ClientApp/src/app/projects/project/modal-member-list/modal-member-list.component.html +++ b/src/Analysim.Web/ClientApp/src/app/projects/project/modal-member-list/modal-member-list.component.html @@ -1,31 +1,39 @@