Skip to content

Commit

Permalink
Merge pull request #1 from mohsammarraie/feature/mindsmash#29-user-ma…
Browse files Browse the repository at this point in the history
…rk-task-as-done

Feature/mindsmash#29 user mark task as done
  • Loading branch information
mohsammarraie authored Feb 29, 2020
2 parents e646e0f + c006fb7 commit b9e3e1d
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 18 deletions.
8 changes: 7 additions & 1 deletion src/main/webapp/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<div class="mat-typography">
<mat-toolbar color="primary" class="mat-elevation-z4">
<div class="wrapper">
<div></div>
<p>{{ now$ | async | date : 'MMMM d, y, h:mm a' }}</p>
<tiny-task-form (created)="created($event)"></tiny-task-form>
</div>
</mat-toolbar>
<section>
<div class="wrapper">
<button mat-icon-button color="primary">
<mat-icon aria-label="clear tasks" (click)="clear()">clear</mat-icon>
</button>
</div>
</section>
<section class="content">
<div class="wrapper">
<tiny-task-list [tasks]="tasks$ | async" (deleted)="deleted($event)"></tiny-task-list>
Expand Down
5 changes: 5 additions & 0 deletions src/main/webapp/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ export class AppComponent implements OnInit {
deleted(): void {
this.tasks$ = this.taskService.getAll();
}

clear(): void {
this.taskService.clear();
this.tasks$ = this.taskService.getAll();
}
}
8 changes: 8 additions & 0 deletions src/main/webapp/app/tasks/default-task.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ export class DefaultTaskService implements TaskService {
getAll(): Observable<Task[]> {
return this.http.get<Task[]>(this.baseUrl + '/tasks');
}

changeStatus(id: string, status: string): Observable<void> {
return this.http.get<void>(this.baseUrl + '/tasks/' + id);
}

clear(): Observable<void> {
return this.http.get<void>(this.baseUrl + '/tasks/');
}
}
5 changes: 3 additions & 2 deletions src/main/webapp/app/tasks/local-task.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { Task } from './task';
describe('LocalTaskService', () => {
const id = 'de4f576e-d1b5-488a-8c77-63d4c8726909';
const name = 'Doing the do!';
const mockTask = `{"id":"${id}","name":"${name}"}`;
const status = 'Todo';
const mockTask = `{"id":"${id}","name":"${name}","status":"${status}"}`;

let taskService: LocalTaskService;

Expand Down Expand Up @@ -38,7 +39,7 @@ describe('LocalTaskService', () => {

it('should write task to local storage', () => {
// when
taskService.create('Drinking the drink!');
taskService.create('Drinking the drink!', 'Todo');

// then
expect(localStorage.setItem).toHaveBeenCalled();
Expand Down
23 changes: 21 additions & 2 deletions src/main/webapp/app/tasks/local-task.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export class LocalTaskService implements TaskService {
return of(this.readTasks());
}

create(name: string): Observable<Task> {
create(name: string, status: string): Observable<Task> {
const tasks = this.readTasks();
const task = {id: uuid(), name};
const task = {id: uuid(), name, status};
tasks.push(task);
this.writeTasks(tasks);
return of(task);
Expand All @@ -40,4 +40,23 @@ export class LocalTaskService implements TaskService {
private writeTasks(tasks: Task[]): void {
localStorage.setItem(LocalTaskService.STORAGE_KEY, JSON.stringify(tasks));
}

changeStatus(id: string, status: string): Observable<void> {
const tasks = this.readTasks();
const updated_tasks = tasks.map(task => {
if (task.id === id) {
task.status = 'Done';
}
return task;
});
this.writeTasks(updated_tasks);
return of(null);
}

clear(): Observable<void> {
const tasks = this.readTasks();
const clearedTasks = tasks.filter(task => task.status !== 'Done');
this.writeTasks(clearedTasks);
return of(null);
}
}
10 changes: 5 additions & 5 deletions src/main/webapp/app/tasks/task-form/task-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,32 @@ describe('TaskFormComponent', () => {
it('should create a task', () => {
// given
component.taskForm.setValue({name: 'My task'});
taskService.create.and.returnValue(of({id: 'id', name: 'My task'}));
taskService.create.and.returnValue(of({id: 'id', name: 'My task', status: 'Todo'}));

// when
component.onSubmit();

// then
expect(taskService.create).toHaveBeenCalledWith('My task');
expect(taskService.create).toHaveBeenCalledWith('My task', 'Todo');
});

it('should emit the task after creation', () => {
// given
component.taskForm.setValue({name: 'My task'});
taskService.create.and.returnValue(of({id: 'id', name: 'My task'}));
taskService.create.and.returnValue(of({id: 'id', name: 'My task', status: 'Todo'}));
const createEmitter = spyOn(component.created, 'emit');

// when
component.onSubmit();

// then
expect(createEmitter).toHaveBeenCalledWith({id: 'id', name: 'My task'});
expect(createEmitter).toHaveBeenCalledWith({id: 'id', name: 'My task', status: 'Todo'});
});

it('should reset the form after creation', () => {
// given
component.taskForm.setValue({name: 'My task'});
taskService.create.and.returnValue(of({id: 'id', name: 'My task'}));
taskService.create.and.returnValue(of({id: 'id', name: 'My task', status: 'Todo'}));
const formReset = spyOn(component.taskForm, 'reset');

// when
Expand Down
2 changes: 1 addition & 1 deletion src/main/webapp/app/tasks/task-form/task-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class TaskFormComponent {
constructor(@Inject('TaskService') private taskService: TaskService) { }

onSubmit(): void {
this.taskService.create(this.taskForm.value.name).subscribe(task => {
this.taskService.create(this.taskForm.value.name, 'Todo').subscribe(task => {
this.created.emit(task);
this.taskForm.reset();
});
Expand Down
20 changes: 18 additions & 2 deletions src/main/webapp/app/tasks/task-list/task-list.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
<mat-list data-cy="task-list">
<mat-list-item *ngFor="let task of tasks" class="mat-elevation-z1">
<mat-list-item *ngFor="let task of todoTasks" class="mat-elevation-z1" >
<mat-icon mat-list-icon>assignment</mat-icon>
<h4 mat-line>{{task.name}}</h4>
<h4 mat-line class="todo">{{ task.status }}</h4>
<p mat-line>ID: {{task.id}}</p>
<button mat-icon-button color="primary">
<mat-icon aria-label="Delete task" (click)="delete(task)">delete</mat-icon>
</button>
<button mat-icon-button color="primary">
<mat-icon aria-label="done task" (click)="changeStatus(task)">done</mat-icon>
</button>
</mat-list-item>
<mat-list-item *ngFor="let task of doneTasks" class="mat-elevation-z1" >
<mat-icon mat-list-icon>assignment</mat-icon>
<h4 mat-line>{{task.name}}</h4>
<h4 mat-line class="done">{{ task.status }}</h4>
<p mat-line>ID: {{task.id}}</p>
<button mat-icon-button color="primary">
<mat-icon aria-label="Delete task" (click)="delete(task)">delete</mat-icon>
</button>
</mat-list-item>
<button mat-icon-button color="primary" [disabled] = "task.status === 'Done'">
<mat-icon aria-label="done task" (click)="changeStatus(task)">done</mat-icon>
</button>
</mat-list-item>
</mat-list>
8 changes: 8 additions & 0 deletions src/main/webapp/app/tasks/task-list/task-list.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@
p {
color: rgba(0, 0, 0, 0.54);
}

.todo {
color: #f5222d;
}

.done {
color: #52c41a;
}
30 changes: 26 additions & 4 deletions src/main/webapp/app/tasks/task-list/task-list.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('TaskListComponent', () => {
declarations: [TaskListComponent],
providers: [{
provide: 'TaskService',
useValue: jasmine.createSpyObj('taskService', ['delete'])
useValue: jasmine.createSpyObj('taskService', ['delete', 'clear', 'changeStatus'])
}]
}).overrideTemplate(TaskListComponent, '')
.compileComponents();
Expand All @@ -37,7 +37,7 @@ describe('TaskListComponent', () => {
taskService.delete.and.returnValue(of(null));

// when
component.delete({id: 'id', name: 'My task'});
component.delete({id: 'id', name: 'My task', status: 'Todo'});

// then
expect(taskService.delete).toHaveBeenCalledWith('id');
Expand All @@ -49,9 +49,31 @@ describe('TaskListComponent', () => {
const deleteEmitter = spyOn(component.deleted, 'emit');

// when
component.delete({id: 'id', name: 'My task'});
component.delete({id: 'id', name: 'My task', status: 'Todo'});

// then
expect(deleteEmitter).toHaveBeenCalledWith({id: 'id', name: 'My task'});
expect(deleteEmitter).toHaveBeenCalledWith({id: 'id', name: 'My task', status: 'Todo'});
});

it('should change status of a task', () => {
// given
taskService.changeStatus.and.returnValue(of(null));

// when
component.changeStatus({id: 'id', name: 'My task', status: 'Todo'});

// then
expect(taskService.changeStatus).toHaveBeenCalledWith('id', 'Todo');
});

it('should clear tasks', () => {
// given
taskService.clear.and.returnValue(of(null));

// when
taskService.clear();

// then
expect(taskService.clear).toHaveBeenCalled();
});
});
16 changes: 16 additions & 0 deletions src/main/webapp/app/tasks/task-list/task-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ export class TaskListComponent {

@Input() tasks: Task[];

@Input()
get doneTasks(): Task[] {
return this.tasks.filter(task => task.status === 'Done');
}

@Input()
get todoTasks(): Task[] {
return this.tasks.filter(task => task.status === 'Todo');
}

@Output() deleted: EventEmitter<Task> = new EventEmitter();

constructor(@Inject('TaskService') private taskService: TaskService) { }
Expand All @@ -25,4 +35,10 @@ export class TaskListComponent {
this.deleted.emit(task);
});
}

changeStatus(task: Task): void {
this.taskService.changeStatus(task.id, task.status).subscribe(() => {
this.deleted.emit(task);
});
}
}
6 changes: 5 additions & 1 deletion src/main/webapp/app/tasks/task.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface TaskService {
* @param name the task's name
* @returns an `Observable` holding the created task
*/
create(name: string): Observable<Task>;
create(name: string, status: string): Observable<Task>;

/**
* Removes the task with the given ID from the list of tasks.
Expand All @@ -29,4 +29,8 @@ export interface TaskService {
* @returns an empty `Observable`
*/
delete(id: string): Observable<void>;

changeStatus(id: string, status: string): Observable<void>;

clear(): Observable<void>;
}
1 change: 1 addition & 0 deletions src/main/webapp/app/tasks/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
export interface Task {
id: string;
name: string;
status: string;
}

0 comments on commit b9e3e1d

Please sign in to comment.