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

Communication: Add undo button when deleting posts #9624

Merged
merged 10 commits into from
Nov 3, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
[isCommunicationPage]="isCommunicationPage"
[lastReadDate]="lastReadDate"
[hasChannelModerationRights]="hasChannelModerationRights"
[isDeleted]="isDeleted"
(isDeleteEvent)="onDeleteEvent(true)"
/>
@if (!createAnswerPostModal.isInputOpen) {
<div class="answer-post-content-margin">
Expand All @@ -15,6 +17,9 @@
[author]="posting.author"
[posting]="posting"
[isReply]="true"
[isDeleted]="isDeleted"
[deleteTimerInSeconds]="deleteTimerInSeconds"
(onUndoDeleteEvent)="onDeleteEvent(false)"
(userReferenceClicked)="userReferenceClicked.emit($event)"
(channelReferenceClicked)="channelReferenceClicked.emit($event)"
/>
Expand All @@ -23,14 +28,16 @@
<div class="answer-post-content-margin">
<ng-container #createEditAnswerPostContainer />
</div>
<div class="answer-post-content-margin">
<jhi-answer-post-footer
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openPostingCreateEditModal.emit()"
/>
</div>
@if (!isDeleted) {
<div class="answer-post-content-margin" @fade>
<jhi-answer-post-footer
[isReadOnlyMode]="isReadOnlyMode"
[posting]="posting"
[isLastAnswer]="isLastAnswer"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openPostingCreateEditModal.emit()"
/>
</div>
}
</div>
<jhi-answer-post-create-edit-modal #createAnswerPostModal [posting]="posting" [createEditAnswerPostContainerRef]="containerRef" />
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';

@import 'src/main/webapp/app/shared/metis/metis.component';

.answer-post {
background-color: var(--metis-answer-post-background-color);
border-radius: 7px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewCh
import { AnswerPost } from 'app/entities/metis/answer-post.model';
import { PostingDirective } from 'app/shared/metis/posting.directive';
import dayjs from 'dayjs/esm';
import { animate, style, transition, trigger } from '@angular/animations';

@Component({
selector: 'jhi-answer-post',
templateUrl: './answer-post.component.html',
styleUrls: ['./answer-post.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('fade', [
transition(':enter', [style({ opacity: 0 }), animate('300ms ease-in', style({ opacity: 1 }))]),
transition(':leave', [animate('300ms ease-out', style({ opacity: 0 }))]),
]),
],
})
export class AnswerPostComponent extends PostingDirective<AnswerPost> {
@Input() lastReadDate?: dayjs.Dayjs;
@Input() isLastAnswer: boolean;
@Output() openPostingCreateEditModal = new EventEmitter<void>();
@Output() userReferenceClicked = new EventEmitter<string>();
@Output() channelReferenceClicked = new EventEmitter<number>();
isAnswerPost = true;

@Input()
isReadOnlyMode = false;
Expand Down
31 changes: 31 additions & 0 deletions src/main/webapp/app/shared/metis/metis.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';

$delete-delay-duration: 6s;
PaRangger marked this conversation as resolved.
Show resolved Hide resolved

.post-result-information {
font-size: small;
font-style: italic;
Expand Down Expand Up @@ -98,3 +100,32 @@
font-size: 0.75rem !important;
}
}

.post-delete-button-background {
position: absolute;
top: 0;
left: 0;
bottom: 0;
z-index: 0;
background-color: rgba($primary, 0.3);
animation: increaseWidth $delete-delay-duration forwards linear;

@media (prefers-reduced-motion) {
animation: none;
}
}

.post-delete-button-label {
position: relative;
z-index: 1;
}

@keyframes increaseWidth {
from {
width: 0;
}

to {
width: 100%;
}
}
41 changes: 24 additions & 17 deletions src/main/webapp/app/shared/metis/post/post.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
[previewMode]="previewMode"
[readOnlyMode]="readOnlyMode"
[posting]="posting"
[isDeleted]="isDeleted"
[isCommunicationPage]="isCommunicationPage"
[hasChannelModerationRights]="hasChannelModerationRights"
(isModalOpen)="displayInlineInput = true"
[lastReadDate]="lastReadDate"
(isDeleteEvent)="onDeleteEvent(true)"
/>
</div>
<div class="align-items-center post-content-margin">
Expand Down Expand Up @@ -57,33 +59,38 @@
[isEdited]="!!posting.updatedDate"
[posting]="posting"
[isReply]="false"
[isDeleted]="isDeleted"
[deleteTimerInSeconds]="deleteTimerInSeconds"
(onUndoDeleteEvent)="onDeleteEvent(false)"
(userReferenceClicked)="onUserReferenceClicked($event)"
(channelReferenceClicked)="onChannelReferenceClicked($event)"
/>
}
</div>
</div>
@if (displayInlineInput && !readOnlyMode) {
@if (!isDeleted && displayInlineInput && !readOnlyMode) {
<div class="post-content-margin">
<jhi-message-inline-input [posting]="posting" (isModalOpen)="displayInlineInput = false" />
</div>
}
<div class="post-content-margin me-0 mt-2 justify-content-between" [ngClass]="{ 'mb-2': previewMode }">
<!-- Post reactions -->
@if (!previewMode) {
<jhi-post-reactions-bar
[lastReadDate]="lastReadDate"
[readOnlyMode]="readOnlyMode"
[posting]="posting"
[(showAnswers)]="showAnswers"
[sortedAnswerPosts]="sortedAnswerPosts"
[isCommunicationPage]="isCommunicationPage"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openCreateAnswerPostModal()"
(openThread)="openThread.emit()"
/>
}
</div>
@if (!isDeleted) {
<div class="post-content-margin me-0 mt-2 justify-content-between" [ngClass]="{ 'mb-2': previewMode }" @fade>
<!-- Post reactions -->
@if (!previewMode) {
<jhi-post-reactions-bar
[lastReadDate]="lastReadDate"
[readOnlyMode]="readOnlyMode"
[posting]="posting"
[(showAnswers)]="showAnswers"
[sortedAnswerPosts]="sortedAnswerPosts"
[isCommunicationPage]="isCommunicationPage"
[isThreadSidebar]="isThreadSidebar"
(openPostingCreateEditModal)="openCreateAnswerPostModal()"
(openThread)="openThread.emit()"
/>
}
</div>
}
</div>
<jhi-post-footer
#postFooter
Expand Down
24 changes: 8 additions & 16 deletions src/main/webapp/app/shared/metis/post/post.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
import {
AfterContentChecked,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
ViewChild,
ViewContainerRef,
} from '@angular/core';
import { AfterContentChecked, ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild, ViewContainerRef } from '@angular/core';
import { Post } from 'app/entities/metis/post.model';
import { PostingDirective } from 'app/shared/metis/posting.directive';
import { MetisService } from 'app/shared/metis/metis.service';
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import { ContextInformation, DisplayPriority, PageType, RouteComponents } from '../metis.util';
import { faBullhorn, faCheckSquare } from '@fortawesome/free-solid-svg-icons';
Expand All @@ -26,12 +13,19 @@ import { MetisConversationService } from 'app/shared/metis/metis-conversation.se
import { getAsChannelDTO } from 'app/entities/metis/conversation/channel.model';
import { AnswerPost } from 'app/entities/metis/answer-post.model';
import { AnswerPostCreateEditModalComponent } from 'app/shared/metis/posting-create-edit-modal/answer-post-create-edit-modal/answer-post-create-edit-modal.component';
import { animate, style, transition, trigger } from '@angular/animations';

@Component({
selector: 'jhi-post',
templateUrl: './post.component.html',
styleUrls: ['./post.component.scss', './../metis.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
animations: [
trigger('fade', [
transition(':enter', [style({ opacity: 0 }), animate('300ms ease-in', style({ opacity: 1 }))]),
transition(':leave', [animate('300ms ease-out', style({ opacity: 0 }))]),
]),
],
})
export class PostComponent extends PostingDirective<Post> implements OnInit, OnChanges, AfterContentChecked {
@Input() lastReadDate?: dayjs.Dayjs;
Expand Down Expand Up @@ -64,8 +58,6 @@ export class PostComponent extends PostingDirective<Post> implements OnInit, OnC
faCheckSquare = faCheckSquare;

constructor(
private metisService: MetisService,
protected changeDetector: ChangeDetectorRef,
private oneToOneChatService: OneToOneChatService,
private metisConversationService: MetisConversationService,
private router: Router,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
@if (currentlyLoadedPosts) {
@if (isDeleted()) {
<span class="posting-content-undo-delete d-inline-flex align-items-center">
<span class="text-secondary" jhiTranslate="artemisApp.metis.post.deletedContent" [translateValues]="{ progress: deleteTimerInSeconds() }"></span>
<button class="btn btn-outline-primary btn-sm ms-2 position-relative" (click)="onUndoDeleteEvent.emit()">
<span class="post-delete-button-label" jhiTranslate="artemisApp.metis.post.undoDelete"></span>
<span class="post-delete-button-background"></span>
</button>
</span>
} @else if (currentlyLoadedPosts) {
<!-- in preview mode (showing similar posts during creation): content can be expanded and collapsed shown -->
@if (previewMode) {
<div class="pb-1">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, signal } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, input, output, signal } from '@angular/core';
import { Params } from '@angular/router';
import { faAngleDown, faAngleUp } from '@fortawesome/free-solid-svg-icons';
import { Post } from 'app/entities/metis/post.model';
Expand All @@ -24,6 +24,9 @@ export class PostingContentComponent implements OnInit, OnChanges, OnDestroy {
@Input() isReply?: boolean;
@Output() userReferenceClicked = new EventEmitter<string>();
@Output() channelReferenceClicked = new EventEmitter<number>();
isDeleted = input<boolean>(false);
deleteTimerInSeconds = input<number>(0);
onUndoDeleteEvent = output<void>();

showContent = false;
currentlyLoadedPosts: Post[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</div>
</div>
<ng-container class="list-answer-post">
@for (answerPost of sortedAnswerPosts; track $index; let isLastAnswer = $last) {
@for (answerPost of sortedAnswerPosts; track postsTrackByFn($index, answerPost); let isLastAnswer = $last) {
<jhi-answer-post
[lastReadDate]="lastReadDate"
[isReadOnlyMode]="readOnlyMode"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ export class PostFooterComponent extends PostingFooterDirective<Post> implements
openCreateAnswerPostModal() {
this.createAnswerPostModalComponent.open();
}

protected postsTrackByFn(index: number, post: Post): number {
return post.id!;
}
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[authorName]="posting.author?.name"
[imageUrl]="posting.author?.imageUrl"
[isEditable]="currentUser !== undefined && posting.author.id === currentUser.id"
[isGray]="isDeleted()"
>
</jhi-profile-picture>
<span class="fs-small d-inline-flex flex-column align-items-start">
Expand All @@ -37,48 +38,47 @@
<span jhiTranslate="global.generic.new" class="badge bg-secondary hideAfter5Seconds"></span>
}
</div>

<div class="d-flex gap-2">
@if (mayEditOrDelete) {
<fa-icon
size="xs"
class="editIcon clickable icon"
[ngbTooltip]="'artemisApp.metis.editPosting' | artemisTranslate"
[icon]="faPencilAlt"
(click)="openPostingCreateEditModal.emit()"
/>
}
@if (mayEditOrDelete) {
<jhi-confirm-icon
iconSize="xs"
(confirmEvent)="deletePosting()"
[ngClass]="'deleteIcon clickable icon'"
[initialTooltip]="'artemisApp.metis.deleteAnswer' | artemisTranslate"
[confirmTooltip]="'artemisApp.metis.confirmDeleteAnswer' | artemisTranslate"
/>
}
@if (!isAnswerOfAnnouncement) {
<div id="toggleElement" class="resolve" [ngClass]="isAtLeastTutorInCourse || isAuthorOfOriginalPost ? 'clickable' : ''" (click)="toggleResolvesPost()">
@if (posting.resolvesPost) {
<div>
<fa-icon
class="resolved"
[icon]="faCheck"
[ngbTooltip]="
isAtLeastTutorInCourse || isAuthorOfOriginalPost
? ('artemisApp.metis.unmarkAsResolvingAnswerTooltip' | artemisTranslate)
: ('artemisApp.metis.resolvingAnswerTooltip' | artemisTranslate)
"
/>
</div>
} @else {
@if (isAtLeastTutorInCourse || isAuthorOfOriginalPost) {
@if (!isDeleted()) {
<div class="d-flex gap-2">
@if (mayEditOrDelete) {
<fa-icon
size="xs"
class="editIcon clickable icon"
[ngbTooltip]="'artemisApp.metis.editPosting' | artemisTranslate"
[icon]="faPencilAlt"
(click)="openPostingCreateEditModal.emit()"
/>
}
@if (mayEditOrDelete) {
<jhi-confirm-icon
iconSize="xs"
(confirmEvent)="deletePosting()"
[ngClass]="'deleteIcon clickable icon'"
[initialTooltip]="'artemisApp.metis.deleteAnswer' | artemisTranslate"
[confirmTooltip]="'artemisApp.metis.confirmDeleteAnswer' | artemisTranslate"
/>
}
PaRangger marked this conversation as resolved.
Show resolved Hide resolved
@if (!isAnswerOfAnnouncement) {
<div id="toggleElement" class="resolve" [ngClass]="isAtLeastTutorInCourse || isAuthorOfOriginalPost ? 'clickable' : ''" (click)="toggleResolvesPost()">
@if (posting.resolvesPost) {
<div>
<fa-icon
class="resolved"
[icon]="faCheck"
[ngbTooltip]="
isAtLeastTutorInCourse || isAuthorOfOriginalPost
? ('artemisApp.metis.unmarkAsResolvingAnswerTooltip' | artemisTranslate)
: ('artemisApp.metis.resolvingAnswerTooltip' | artemisTranslate)
"
/>
</div>
} @else if (isAtLeastTutorInCourse || isAuthorOfOriginalPost) {
<div>
<fa-icon class="icon notResolved" [icon]="faCheck" [ngbTooltip]="'artemisApp.metis.markAsResolvingAnswerTooltip' | artemisTranslate" />
</div>
}
}
</div>
}
</div>
</div>
}
</div>
}
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class AnswerPostHeaderComponent extends PostingHeaderDirective<AnswerPost
* invokes the metis service to delete an answer post
*/
deletePosting(): void {
this.metisService.deleteAnswerPost(this.posting);
this.isDeleteEvent.emit(true);
}

/**
Expand Down
Loading
Loading