Skip to content

Commit

Permalink
Merge pull request #1727 from WISE-Community/implement-tag-color
Browse files Browse the repository at this point in the history
feat(Tag): Implement tag color
  • Loading branch information
geoffreykwan authored Apr 12, 2024
2 parents 0883698 + 7c7c937 commit 1af2b6f
Show file tree
Hide file tree
Showing 24 changed files with 284 additions and 185 deletions.
6 changes: 6 additions & 0 deletions src/app/domain/projectAndTagsResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Tag } from './tag';

export interface ProjectAndTagsResponse {
projectId: number;
tags: Tag[];
}
1 change: 1 addition & 0 deletions src/app/domain/tag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export interface Tag {
checked?: boolean;
color: string;
id: number;
text: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class MockConfigService {
}
}

const archivedTag = { id: 1, text: 'archived' };
const archivedTag = { id: 1, text: 'archived', color: null };
let component: LibraryProjectMenuComponent;
let fixture: ComponentFixture<LibraryProjectMenuComponent>;
let harness: LibraryProjectMenuHarness;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { MatPaginatorModule } from '@angular/material/paginator';
import { ArchiveProjectsButtonComponent } from '../../../teacher/archive-projects-button/archive-projects-button.component';
import { HttpClient } from '@angular/common/http';

const archivedTag = { id: 1, text: 'archived' };
const archivedTag = { id: 1, text: 'archived', color: null };
let archiveProjectService: ArchiveProjectService;
let component: PersonalLibraryComponent;
let fixture: ComponentFixture<PersonalLibraryComponent>;
Expand Down
37 changes: 0 additions & 37 deletions src/app/teacher/abstract-tag-dialog.component.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
(change)="toggleTagOnProjects(tag, $event.checked)"
(click)="$event.stopPropagation()"
>
{{ tag.text }}
<div [ngStyle]="{ color: tag.color }">{{ tag.text }}</div>
</mat-checkbox>
</div>
<mat-divider></mat-divider>
Expand Down
11 changes: 7 additions & 4 deletions src/app/teacher/apply-tags-button/apply-tags-button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class ApplyTagsButtonComponent implements OnInit {
this.projectTagService.tagUpdated$.subscribe((tagThatChanged: Tag) => {
const tag = this.tags.find((t: Tag) => t.id === tagThatChanged.id);
tag.text = tagThatChanged.text;
tag.color = tagThatChanged.color;
this.projectTagService.sortTags(this.tags);
})
);
Expand Down Expand Up @@ -76,11 +77,13 @@ export class ApplyTagsButtonComponent implements OnInit {

protected toggleTagOnProjects(tag: Tag, addTag: boolean): void {
if (addTag) {
this.addTagToProjects(tag, this.selectedProjects);
this.projectTagService.applyTagToProjects(tag, this.selectedProjects);
this.projectTagService.applyTagToProjects(tag, this.selectedProjects).subscribe(() => {
this.addTagToProjects(tag, this.selectedProjects);
});
} else {
this.removeTagFromProjects(tag, this.selectedProjects);
this.projectTagService.removeTagFromProjects(tag, this.selectedProjects);
this.projectTagService.removeTagFromProjects(tag, this.selectedProjects).subscribe(() => {
this.removeTagFromProjects(tag, this.selectedProjects);
});
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<h2 mat-dialog-title i18n>Create New Tag</h2>
<mat-dialog-content>
<mat-form-field class="tag-name">
<mat-label i18n>Tag Name</mat-label>
<input matInput (keyup.enter)="create()" [formControl]="tagControl" autofocus />
<mat-error *ngIf="tagControl.hasError('required')" i18n>Required</mat-error>
<mat-error *ngIf="tagControl.hasError('tagAlreadyExists')" i18n>Tag already exists</mat-error>
</mat-form-field>
<edit-tag
[nameControl]="nameControl"
[colorControl]="colorControl"
(enterKeyEvent)="create()"
></edit-tag>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button mat-dialog-close i18n>Cancel</button>
<button mat-raised-button color="primary" [disabled]="!tagControl.valid" (click)="create()" i18n>
<button mat-raised-button color="primary" [disabled]="!nameControl.valid" (click)="create()" i18n>
Create
</button>
</mat-dialog-actions>
38 changes: 21 additions & 17 deletions src/app/teacher/create-tag-dialog/create-tag-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ProjectTagService } from '../../../assets/wise5/services/projectTagService';
import { AbstractTagDialogComponent } from '../abstract-tag-dialog.component';
import { EditTagComponent } from '../edit-tag/edit-tag.component';

@Component({
selector: 'create-tag-dialog',
Expand All @@ -16,6 +16,7 @@ import { AbstractTagDialogComponent } from '../abstract-tag-dialog.component';
standalone: true,
imports: [
CommonModule,
EditTagComponent,
FormsModule,
MatButtonModule,
MatDialogModule,
Expand All @@ -24,26 +25,29 @@ import { AbstractTagDialogComponent } from '../abstract-tag-dialog.component';
ReactiveFormsModule
]
})
export class CreateTagDialogComponent extends AbstractTagDialogComponent {
export class CreateTagDialogComponent {
protected nameControl = new FormControl('', [Validators.required]);
protected colorControl = new FormControl('');

constructor(
private dialogRef: MatDialogRef<CreateTagDialogComponent>,
protected projectTagService: ProjectTagService,
private projectTagService: ProjectTagService,
private snackBar: MatSnackBar
) {
super(projectTagService);
}
) {}

protected create(): void {
this.projectTagService.createTag(this.tagControl.value.trim()).subscribe({
next: () => {
this.snackBar.open($localize`Tag created`);
this.dialogRef.close();
},
error: ({ error }) => {
if (error.messageCode === 'tagAlreadyExists') {
this.tagControl.setErrors({ tagAlreadyExists: true });
this.projectTagService
.createTag(this.nameControl.value.trim(), this.colorControl.value.trim())
.subscribe({
next: () => {
this.snackBar.open($localize`Tag created`);
this.dialogRef.close();
},
error: ({ error }) => {
if (error.messageCode === 'tagAlreadyExists') {
this.nameControl.setErrors({ tagAlreadyExists: true });
}
}
}
});
});
}
}
14 changes: 7 additions & 7 deletions src/app/teacher/edit-tag-dialog/edit-tag-dialog.component.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<h2 mat-dialog-title i18n>Edit Tag</h2>
<mat-dialog-content>
<mat-form-field class="tag-name">
<mat-label i18n>Tag Name</mat-label>
<input matInput (keyup.enter)="save()" [formControl]="tagControl" autofocus />
<mat-error *ngIf="tagControl.hasError('required')" i18n>Required</mat-error>
<mat-error *ngIf="tagControl.hasError('tagAlreadyExists')" i18n>Tag already exists</mat-error>
</mat-form-field>
<edit-tag
[tag]="tag"
[nameControl]="nameControl"
[colorControl]="colorControl"
(enterKeyEvent)="save()"
></edit-tag>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button mat-dialog-close i18n>Cancel</button>
<button mat-raised-button color="primary" [disabled]="!tagControl.valid" (click)="save()" i18n>
<button mat-raised-button color="primary" [disabled]="!nameControl.valid" (click)="save()" i18n>
Save
</button>
</mat-dialog-actions>
28 changes: 13 additions & 15 deletions src/app/teacher/edit-tag-dialog/edit-tag-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormControl, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { AbstractTagDialogComponent } from '../abstract-tag-dialog.component';
import { MatSnackBar } from '@angular/material/snack-bar';
import { ProjectTagService } from '../../../assets/wise5/services/projectTagService';
import { CreateTagDialogComponent } from '../create-tag-dialog/create-tag-dialog.component';
import { Tag } from '../../domain/tag';
import { EditTagComponent } from '../edit-tag/edit-tag.component';

@Component({
selector: 'edit-tag-dialog',
Expand All @@ -18,6 +18,7 @@ import { Tag } from '../../domain/tag';
standalone: true,
imports: [
CommonModule,
EditTagComponent,
FormsModule,
MatButtonModule,
MatDialogModule,
Expand All @@ -26,31 +27,28 @@ import { Tag } from '../../domain/tag';
ReactiveFormsModule
]
})
export class EditTagDialogComponent extends AbstractTagDialogComponent {
export class EditTagDialogComponent {
protected nameControl = new FormControl('', [Validators.required]);
protected colorControl = new FormControl('');

constructor(
private dialogRef: MatDialogRef<CreateTagDialogComponent>,
protected projectTagService: ProjectTagService,
private projectTagService: ProjectTagService,
private snackBar: MatSnackBar,
@Inject(MAT_DIALOG_DATA) private tag: Tag
) {
super(projectTagService);
}

ngOnInit(): void {
super.ngOnInit();
this.tagControl.setValue(this.tag.text);
}
@Inject(MAT_DIALOG_DATA) protected tag: Tag
) {}

protected save(): void {
this.tag.text = this.tagControl.value.trim();
this.tag.text = this.nameControl.value.trim();
this.tag.color = this.colorControl.value.trim();
this.projectTagService.updateTag(this.tag).subscribe({
next: () => {
this.snackBar.open($localize`Tag updated`);
this.dialogRef.close();
},
error: ({ error }) => {
if (error.messageCode === 'tagAlreadyExists') {
this.tagControl.setErrors({ tagAlreadyExists: true });
this.nameControl.setErrors({ tagAlreadyExists: true });
}
}
});
Expand Down
12 changes: 12 additions & 0 deletions src/app/teacher/edit-tag/edit-tag.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div fxLayout="row" fxLayoutAlign="space-between">
<mat-form-field class="name-input">
<mat-label i18n>Tag Name</mat-label>
<input matInput (keyup.enter)="enterKeyPressed()" [formControl]="nameControl" />
<mat-error *ngIf="nameControl.errors?.required" i18n>Required</mat-error>
<mat-error *ngIf="nameControl.errors?.tagAlreadyExists" i18n>Tag already exists</mat-error>
</mat-form-field>
<mat-form-field class="color-input">
<mat-label i18n>Color</mat-label>
<input matInput (keyup.enter)="enterKeyPressed()" [formControl]="colorControl" />
</mat-form-field>
</div>
7 changes: 7 additions & 0 deletions src/app/teacher/edit-tag/edit-tag.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.name-input {
width: 80%;
}

.color-input {
width: 15%;
}
27 changes: 27 additions & 0 deletions src/app/teacher/edit-tag/edit-tag.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EditTagComponent } from './edit-tag.component';
import { ProjectTagService } from '../../../assets/wise5/services/projectTagService';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { FormControl, Validators } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

describe('EditTagComponent', () => {
let component: EditTagComponent;
let fixture: ComponentFixture<EditTagComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [BrowserAnimationsModule, EditTagComponent, HttpClientTestingModule],
providers: [ProjectTagService]
});
fixture = TestBed.createComponent(EditTagComponent);
component = fixture.componentInstance;
component.nameControl = new FormControl('', [Validators.required]);
component.colorControl = new FormControl('');
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading

0 comments on commit 1af2b6f

Please sign in to comment.