Skip to content

Commit

Permalink
Lectures: Add dismiss modal for unsaved changes to title or period se…
Browse files Browse the repository at this point in the history
…ction (#10023)
  • Loading branch information
florian-glombik authored Dec 18, 2024
1 parent 3a6832e commit 92b2aad
Show file tree
Hide file tree
Showing 22 changed files with 533 additions and 160 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, ViewChild, effect, inject, input, signal } from '@angular/core';
import { Component, Input, OnChanges, SimpleChanges, ViewChild, effect, inject, input, output, signal } from '@angular/core';
import { Course, isCommunicationEnabled } from 'app/entities/course.model';
import { Exercise } from 'app/entities/exercise.model';
import { TitleChannelNameComponent } from 'app/shared/form/title-channel-name/title-channel-name.component';
Expand All @@ -22,8 +22,8 @@ export class ExerciseTitleChannelNameComponent implements OnChanges {

@ViewChild(TitleChannelNameComponent) titleChannelNameComponent: TitleChannelNameComponent;

@Output() onTitleChange = new EventEmitter<string>();
@Output() onChannelNameChange = new EventEmitter<string>();
onTitleChange = output<string>();
onChannelNameChange = output<string>();

private readonly exerciseService: ExerciseService = inject(ExerciseService);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<div class="modal-header">
<h4 class="modal-title" jhiTranslate="artemisApp.lecture.dismissChangesModal.title"></h4>
</div>
<div class="modal-body">
<span jhiTranslate="artemisApp.lecture.dismissChangesModal.message" class="fw-bold"></span><br />
<!-- check if translation should be singular or plural, to be exchanged
with computed signals once input signals are supported with ng-bootstrap modals -->
@if (hasUnsavedChangesInTitleSection && hasUnsavedChangesInPeriodSection) {
<span jhiTranslate="artemisApp.lecture.dismissChangesModal.sectionsThatContainUnsavedChangesPlural"></span>
} @else {
<span jhiTranslate="artemisApp.lecture.dismissChangesModal.sectionsThatContainUnsavedChangesSingular"></span>
}
<ul>
@if (hasUnsavedChangesInTitleSection) {
<li>
<span jhiTranslate="artemisApp.lecture.wizardMode.steps.titleStepTitle"></span>
</li>
}
@if (hasUnsavedChangesInPeriodSection) {
<li>
<span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepTitle"></span>
</li>
}
</ul>
</div>
<div class="modal-footer">
<button class="btn btn-default" (click)="closeWindow(true)">
<span jhiTranslate="entity.action.discardChanges"></span>
</button>
<button type="button" (click)="closeWindow(false)" class="btn btn-primary" type="submit">
<fa-icon [icon]="faTimes" />
<span class="ms-1" jhiTranslate="entity.action.cancel"></span>
</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Component, Input, inject } from '@angular/core';
import { TranslateDirective } from 'app/shared/language/translate.directive';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
selector: 'jhi-close-edit-lecture-modal',
standalone: true,
imports: [TranslateDirective, ArtemisSharedCommonModule],
templateUrl: './close-edit-lecture-modal.component.html',
})
export class CloseEditLectureModalComponent {
protected readonly faTimes = faTimes;

protected readonly activeModal = inject(NgbActiveModal);

// no input signals yet as they can not be initialized with current ng-bootstrap version https://stackoverflow.com/a/79094268/16540383
@Input() hasUnsavedChangesInTitleSection: boolean;
@Input() hasUnsavedChangesInPeriodSection: boolean;

closeWindow(isCloseConfirmed: boolean): void {
this.activeModal.close(isCloseConfirmed);
}
}
28 changes: 28 additions & 0 deletions src/main/webapp/app/lecture/hasLectureUnsavedChanges.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { inject } from '@angular/core';
import { CanDeactivateFn } from '@angular/router';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { LectureUpdateComponent } from 'app/lecture/lecture-update.component';
import { Observable, from, of } from 'rxjs';
import { CloseEditLectureModalComponent } from 'app/lecture/close-edit-lecture-dialog/close-edit-lecture-modal.component';

export const hasLectureUnsavedChangesGuard: CanDeactivateFn<LectureUpdateComponent> = (component: LectureUpdateComponent): Observable<boolean> => {
if (!component.shouldDisplayDismissWarning || component.isShowingWizardMode) {
return of(true);
}

if (component.isChangeMadeToTitleOrPeriodSection) {
const modalService = inject(NgbModal);

const modalRef: NgbModalRef = modalService.open(CloseEditLectureModalComponent, {
size: 'lg',
backdrop: 'static',
animation: true,
});
modalRef.componentInstance.hasUnsavedChangesInTitleSection = component.isChangeMadeToTitleSection();
modalRef.componentInstance.hasUnsavedChangesInPeriodSection = component.isChangeMadeToPeriodSection();

return from(modalRef.result);
}

return of(true);
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div>
<h1><span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepTitle"></span></h1>
<h2 id="artemisApp.lecture.wizardMode.steps.periodStepTitle"><span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepTitle"></span></h2>
<p><span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepMessage"></span></p>
<div class="d-flex">
<div class="form-group flex-grow-1">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.visibleDate' | artemisTranslate }}"
[(ngModel)]="lecture.visibleDate"
[(ngModel)]="lecture().visibleDate"
(valueChange)="validateDatesFunction()"
name="visibleDate"
id="visible-date"
Expand All @@ -14,7 +14,7 @@ <h1><span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepTitle"></s
<div class="form-group flex-grow-1 ms-3">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.startDate' | artemisTranslate }}"
[(ngModel)]="lecture.startDate"
[(ngModel)]="lecture().startDate"
(valueChange)="validateDatesFunction()"
name="startDate"
id="start-date"
Expand All @@ -23,7 +23,7 @@ <h1><span jhiTranslate="artemisApp.lecture.wizardMode.steps.periodStepTitle"></s
<div class="form-group flex-grow-1 ms-3">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.endDate' | artemisTranslate }}"
[(ngModel)]="lecture.endDate"
[(ngModel)]="lecture().endDate"
(valueChange)="validateDatesFunction()"
name="endDate"
id="end-date"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component, Input, Signal, computed, input, viewChildren } from '@angular/core';
import { Lecture } from 'app/entities/lecture.model';
import { FormDateTimePickerComponent } from 'app/shared/date-time-picker/date-time-picker.component';

@Component({
selector: 'jhi-lecture-update-period',
templateUrl: './lecture-period.component.html',
})
export class LectureUpdatePeriodComponent {
lecture = input.required<Lecture>();
@Input() validateDatesFunction: () => void;

periodSectionDatepickers = viewChildren(FormDateTimePickerComponent);

isPeriodSectionValid: Signal<boolean> = computed(() => {
for (const periodSectionDatepicker of this.periodSectionDatepickers()) {
if (!periodSectionDatepicker.isValid()) {
return false;
}
}
return true;
});
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit, viewChild } from '@angular/core';
import { isCommunicationEnabled } from 'app/entities/course.model';
import { Lecture } from 'app/entities/lecture.model';
import { TitleChannelNameComponent } from 'app/shared/form/title-channel-name/title-channel-name.component';

@Component({
selector: 'jhi-lecture-title-channel-name',
Expand All @@ -9,6 +10,8 @@ import { Lecture } from 'app/entities/lecture.model';
export class LectureTitleChannelNameComponent implements OnInit {
@Input() lecture: Lecture;

titleChannelNameComponent = viewChild.required(TitleChannelNameComponent);

hideChannelNameInput = false;
ngOnInit() {
this.hideChannelNameInput = !this.requiresChannelName(this.lecture);
Expand Down
56 changes: 21 additions & 35 deletions src/main/webapp/app/lecture/lecture-update.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[toggleModeFunction]="toggleModeFunction"
[saveLectureFunction]="saveLectureFunction"
[validateDatesFunction]="onDatesValuesChanged"
[lecture]="lecture"
[lecture]="lecture()"
[isSaving]="isSaving"
/>
}
Expand All @@ -27,45 +27,24 @@ <h2 id="jhi-lecture-heading" jhiTranslate="artemisApp.lecture.home.createOrEditL
</div>
</div>
<div>
<jhi-lecture-title-channel-name [lecture]="lecture" />
<h2 id="artemisApp.lecture.wizardMode.steps.titleStepTitle"><span jhiTranslate="artemisApp.lecture.wizardMode.steps.titleStepTitle"></span></h2>
<p><span jhiTranslate="artemisApp.lecture.wizardMode.steps.titleStepMessage"></span></p>
<jhi-lecture-title-channel-name [lecture]="lecture()" />
<div class="form-group" id="field_description">
<label class="form-control-label" jhiTranslate="artemisApp.lecture.description" for="field_description"></label>
<jhi-markdown-editor-monaco class="markdown-editor" [domainActions]="domainActionsDescription" [(markdown)]="lecture.description" />
</div>
<div class="d-flex">
<div class="form-group flex-grow-1">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.visibleDate' | artemisTranslate }}"
[(ngModel)]="lecture.visibleDate"
(valueChange)="onDatesValuesChanged()"
name="visibleDate"
id="visible-date"
/>
</div>
<div class="form-group flex-grow-1 ms-3">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.startDate' | artemisTranslate }}"
[(ngModel)]="lecture.startDate"
(valueChange)="onDatesValuesChanged()"
name="startDate"
id="start-date"
/>
</div>
<div class="form-group flex-grow-1 ms-3">
<jhi-date-time-picker
labelName="{{ 'artemisApp.lecture.endDate' | artemisTranslate }}"
[(ngModel)]="lecture.endDate"
(valueChange)="onDatesValuesChanged()"
name="endDate"
id="end-date"
/>
</div>
<jhi-markdown-editor-monaco
class="markdown-editor"
[domainActions]="domainActionsDescription"
[(markdown)]="lecture().description"
(markdownChange)="updateIsChangesMadeToTitleOrPeriodSection()"
/>
</div>
@if (lecture.course) {
<jhi-lecture-update-period [lecture]="lecture()" [validateDatesFunction]="onDatesValuesChanged" />
@if (lecture().course) {
<div class="form-group">
<label class="form-control-label" jhiTranslate="artemisApp.lecture.course" for="field_course"></label>
<div class="d-flex">
<input id="field_course" disabled type="text" class="form-control" name="course" [(ngModel)]="lecture.course.title" />
<input id="field_course" disabled type="text" class="form-control" name="course" [(ngModel)]="lecture().course!.title" />
</div>
</div>
}
Expand Down Expand Up @@ -116,7 +95,14 @@ <h2 id="jhi-lecture-heading" jhiTranslate="artemisApp.lecture.home.createOrEditL
<button type="button" id="cancel-save" class="btn btn-secondary" (click)="previousState()">
<fa-icon [icon]="faBan" />&nbsp;<span jhiTranslate="entity.action.cancel"></span>
</button>
<button type="submit" id="save-entity" [disabled]="editForm.form.invalid || isSaving || processUnitMode" class="btn btn-primary">
<button
type="submit"
id="save-entity"
[disabled]="
editForm.form.invalid || isSaving || processUnitMode || !isChangeMadeToTitleOrPeriodSection || !lecturePeriodSection()?.isPeriodSectionValid()
"
class="btn btn-primary"
>
<fa-icon [icon]="faSave" />&nbsp;<span jhiTranslate="entity.action.save"></span>
</button>
</div>
Expand Down
Loading

0 comments on commit 92b2aad

Please sign in to comment.