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

feat(Tag): Implement tag color #1727

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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