Skip to content

Commit

Permalink
Updated notes sidepanel (#1673)
Browse files Browse the repository at this point in the history
Updated notes sidepanel
  • Loading branch information
lastminutediorama authored Aug 21, 2024
1 parent 740aca2 commit 84ab3b7
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
[disabled]="saving"
cdkTextareaAutosize
matInput
placeholder="add a note">
placeholder="Add a note">
</textarea>
<mat-spinner diameter="20" matSuffix *ngIf="saving"></mat-spinner>
<svg
Expand Down
10 changes: 3 additions & 7 deletions src/interface/src/app/plan/area-notes/area-notes.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import "colors";
@import "mixins";
@import 'colors';
@import 'mixins';

:host {
display: flex;
Expand All @@ -10,7 +10,6 @@
::ng-deep .mat-form-field-wrapper {
margin: 0;
padding: 8px;

}

::ng-deep {
Expand All @@ -31,7 +30,6 @@
padding: 2px;
top: 2px;
}

}

.notes {
Expand All @@ -42,7 +40,6 @@
.note {
padding: 16px;
color: $color-black;

}

.note-head {
Expand Down Expand Up @@ -76,13 +73,12 @@ textarea {
}

.delete-note-button {

.delete-icon {
color: $color-error;
line-height: 20px;
width: 20px;
}

color: $color-error;
@include regular-paragraph()
@include regular-paragraph();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class AreaNotesComponent implements OnInit {
@Input() plan!: Plan;
notes: Note[] = [];
note = '';
saving = false;

ngOnInit() {
this.loadNotes();
Expand All @@ -34,8 +35,6 @@ export class AreaNotesComponent implements OnInit {
.subscribe((notes) => (this.notes = notes));
}

saving = false;

openDeleteNoteDialog(note: Note) {
const dialogRef = this.dialog.open(DeleteNoteDialogComponent, {});
dialogRef
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<div class="notes-header">Notes</div>
<div class="notes">
<div *ngFor="let note of notes" class="note-enclosed">
<div class="note-left">
<div class="note-head">
<div>{{ note.user_name }}</div>
<div class="date">{{ note.created_at | date }}</div>
</div>
<div class="note-content">
{{ note.content }}
</div>
</div>
<div class="note-right">
<button
*ngIf="canDelete(note)"
mat-icon-button
[matMenuTriggerFor]="menu"
aria-label="more note options">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button
mat-menu-item
(click)="openDeleteNoteDialog(note)"
class="delete-note-button">
<mat-icon class="delete-icon">delete_outline</mat-icon>
<span>Delete</span>
</button>
</mat-menu>
</div>
</div>
</div>
<mat-form-field
*appFeatureFlag="'new_planning_area'"
appearance="outline"
class="add-note-field">
<textarea
(keydown.enter)="addNote($event)"
[(ngModel)]="note"
[disabled]="saving"
cdkTextareaAutosize
matInput
placeholder="Add a note">
</textarea>
<mat-spinner diameter="20" matSuffix *ngIf="saving"></mat-spinner>
<svg
*ngIf="!saving"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
class="arrow-up"
(click)="addNote($event)"
[ngClass]="{ active: !!note }"
matSuffix>
<g clip-path="url(#clip0_229_19311)">
<path
d="M17 3.33989C18.5083 4.21075 19.7629 5.46042 20.6398 6.96519C21.5167 8.46997 21.9854 10.1777 21.9994 11.9192C22.0135 13.6608 21.5725 15.3758 20.72 16.8946C19.8676 18.4133 18.6332 19.6831 17.1392 20.5782C15.6452 21.4733 13.9434 21.9627 12.2021 21.998C10.4608 22.0332 8.74055 21.6131 7.21155 20.7791C5.68256 19.9452 4.39787 18.7264 3.48467 17.2434C2.57146 15.7604 2.06141 14.0646 2.005 12.3239L2 11.9999L2.005 11.6759C2.061 9.94888 2.56355 8.26585 3.46364 6.79089C4.36373 5.31592 5.63065 4.09934 7.14089 3.25977C8.65113 2.42021 10.3531 1.98629 12.081 2.00033C13.8089 2.01437 15.5036 2.47589 17 3.33989ZM12.02 6.99989L11.857 7.00989L11.771 7.02589L11.629 7.07089L11.516 7.12489L11.446 7.16789L11.351 7.23889L11.293 7.29289L7.293 11.2929L7.21 11.3869C7.05459 11.5879 6.98151 11.8405 7.0056 12.0934C7.02969 12.3463 7.14916 12.5806 7.33972 12.7486C7.53029 12.9167 7.77767 13.0059 8.03162 12.9981C8.28557 12.9904 8.52704 12.8862 8.707 12.7069L11 10.4139V15.9999L11.007 16.1169C11.0371 16.37 11.1627 16.602 11.3582 16.7656C11.5536 16.9292 11.8042 17.012 12.0586 16.9971C12.313 16.9821 12.5522 16.8706 12.7272 16.6853C12.9021 16.4999 12.9997 16.2548 13 15.9999V10.4149L15.293 12.7069L15.387 12.7899C15.588 12.9453 15.8406 13.0184 16.0935 12.9943C16.3464 12.9702 16.5807 12.8507 16.7488 12.6602C16.9168 12.4696 17.006 12.2222 16.9982 11.9683C16.9905 11.7143 16.8863 11.4728 16.707 11.2929L12.707 7.29289L12.625 7.21989L12.536 7.15589L12.423 7.09389L12.342 7.05989L12.229 7.02589L12.117 7.00589L12.019 6.99989H12.02Z"
fill="currentColor" />
</g>
<defs>
<clipPath id="clip0_229_19311">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
</mat-form-field>
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
@import 'colors';
@import 'mixins';

:host {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;

::ng-deep .mat-form-field-wrapper {
margin: 0;
padding: 8px;
}

::ng-deep {
.mat-form-field-outline-start,
.mat-form-field-outline-end {
background-color: $color-light-gray;
}

.mat-form-field-infix {
padding-bottom: 10px;
border-top: 0;
top: -2px;
padding-top: 21px;
}
}

mat-spinner {
padding: 2px;
top: 2px;
}
}

.notes {
overflow-y: auto;
flex: 1;
flex-grow: 1;
}

.note {
padding: 16px;
color: $color-black;
}

.note-head {
@include small-input-label();
display: flex;
gap: 8px;
margin-bottom: 8px;
}

.date {
color: $color-md-gray;
font-weight: 400;
}

.arrow-up {
color: #767575;

&.active {
cursor: pointer;
color: $color-standard-blue;
}
}

textarea {
resize: none;
overflow: hidden;
}

.delete-note-menu {
width: 100px;
}

.delete-note-button {
.delete-icon {
color: $color-error;
line-height: 20px;
width: 20px;
}

color: $color-error;
@include regular-paragraph();
}

.notes-header {
@include h4();
width: 100%;
padding: 16px 229px 16px 16px;
gap: 8px;
border-bottom: 1px $color-soft-gray solid;
}

.note-right {
width: 28px;
}

.add-note-field {
height: 70px;
flex-shrink: 0;
border-top: 1px $color-soft-gray solid;
}

.note-enclosed {
padding: 16px;
color: $color-black;
display: flex;
flex-direction: row;
justify-content: space-between;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AuthService, PlanNotesService } from '@services';
import { MatLegacyDialogModule as MatDialogModule } from '@angular/material/legacy-dialog';
import { MatLegacySnackBarModule as MatSnackBarModule } from '@angular/material/legacy-snack-bar';

import { AreaScrollingNotesComponent } from './area-scrolling-notes.component';
import { MockProvider } from 'ng-mocks';
import { of } from 'rxjs';

describe('AreaScrollingNotesComponent', () => {
let component: AreaScrollingNotesComponent;
let fixture: ComponentFixture<AreaScrollingNotesComponent>;
let fakeAuthService: AuthService;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AreaScrollingNotesComponent],
imports: [MatDialogModule, MatSnackBarModule],
providers: [
{
provide: AuthService,
useValue: fakeAuthService,
},
MockProvider(PlanNotesService, {
getNotes: () => of([]),
}),
],
}).compileComponents();

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Component, Input, OnInit } from '@angular/core';
import { MatLegacyDialog as MatDialog } from '@angular/material/legacy-dialog';
import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar';
import { DeleteNoteDialogComponent } from '../delete-note-dialog/delete-note-dialog.component';
import { take } from 'rxjs';
import { Plan } from '@types';
import { AuthService, Note, PlanNotesService } from '@services';
import { SNACK_ERROR_CONFIG, SNACK_NOTICE_CONFIG } from '@shared';

@Component({
selector: 'app-area-scrolling-notes',
templateUrl: './area-scrolling-notes.component.html',
styleUrls: ['./area-scrolling-notes.component.scss'],
})
export class AreaScrollingNotesComponent implements OnInit {
constructor(
private planNotesService: PlanNotesService,
private dialog: MatDialog,
private snackbar: MatSnackBar,
private authService: AuthService
) {}

@Input() plan!: Plan;
notes: Note[] = [];
note = '';

ngOnInit() {
this.loadNotes();
}

loadNotes() {
this.planNotesService
.getNotes(this.plan?.id)
.subscribe((notes) => (this.notes = notes));
}

saving = false;

openDeleteNoteDialog(note: Note) {
const dialogRef = this.dialog.open(DeleteNoteDialogComponent, {});
dialogRef
.afterClosed()
.pipe(take(1))
.subscribe((confirmed) => {
if (confirmed) {
this.planNotesService.deleteNote(this.plan.id, note.id).subscribe({
next: () => {
this.snackbar.open(
`Deleted note`,
'Dismiss',
SNACK_NOTICE_CONFIG
);
this.loadNotes();
},
error: (err) => {
this.snackbar.open(
`Error: ${err.statusText}`,
'Dismiss',
SNACK_ERROR_CONFIG
);
},
});
}
});
}

addNote(event: Event) {
if (this.note) {
this.saving = true;
this.planNotesService
.addNote(this.plan.id, this.note)
.subscribe((note) => {
// add the note
this.notes.unshift(note);
// but then refresh as well.
this.loadNotes();
this.saving = false;
this.note = '';
});
}
event.preventDefault();
}

canDelete(note: Note) {
const userId = this.authService.loggedInUser$.value?.id;
return note.user_id === userId || this.plan.user === userId;
}
}
Loading

0 comments on commit 84ab3b7

Please sign in to comment.