(Todo app) ongoing..

This commit is contained in:
mustafahlvc 2017-07-28 17:40:11 +03:00
parent 1f8b1a3f27
commit 0339874110
13 changed files with 147 additions and 51 deletions

View File

@ -84,4 +84,14 @@ export class FuseUtils
} }
return false; return false;
} }
public static genearateGUID()
{
function S4()
{
return (((1 + Math.random()) * 0x10000) || 0).toString(16).substring(1);
}
return (S4() + S4());
}
} }

View File

@ -115,7 +115,7 @@
md-raised-button md-raised-button
(click)="dialogRef.close(eventForm)" (click)="dialogRef.close(eventForm)"
class="save-button mat-accent" class="save-button mat-accent"
[disabled]="eventForm.pristine" [disabled]="eventForm.invalid"
aria-label="SAVE"> aria-label="SAVE">
SAVE SAVE
</button> </button>
@ -124,7 +124,7 @@
md-raised-button md-raised-button
(click)="dialogRef.close(['save',eventForm])" (click)="dialogRef.close(['save',eventForm])"
class="save-button mat-accent" class="save-button mat-accent"
[disabled]="eventForm.pristine" [disabled]="eventForm.invalid"
aria-label="SAVE"> aria-label="SAVE">
SAVE SAVE
</button> </button>

View File

@ -4,6 +4,7 @@ import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http'; import { Http } from '@angular/http';
import { Subject } from 'rxjs/Subject'; import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { FuseUtils } from '../../../core/fuseUtils';
@Injectable() @Injectable()
export class ChatService implements Resolve<any> export class ChatService implements Resolve<any>
@ -80,7 +81,7 @@ export class ChatService implements Resolve<any>
return item.id === contactId; return item.id === contactId;
}); });
const chatId = this.guidGenerator(); const chatId = FuseUtils.genearateGUID();
const chat = { const chat = {
id : chatId, id : chatId,
@ -243,18 +244,4 @@ export class ChatService implements Resolve<any>
}, reject); }, reject);
}); });
} }
/**
* Random ID Generator
* @returns {string}
*/
guidGenerator()
{
function S4()
{
return (((1 + Math.random()) * 0x10000) || 0).toString(16).substring(1);
}
return (S4() + S4());
}
} }

View File

@ -22,6 +22,15 @@
<!-- SIDENAV CONTENT --> <!-- SIDENAV CONTENT -->
<div class="content" perfect-scrollbar> <div class="content" perfect-scrollbar>
<div class="p-24" fxFlexAlign="row" fxLayoutAlign="center center">
<button md-raised-button
class="mat-accent add-todo-button"
(click)="newTodo()"
aria-label="ADD TASK">
ADD TASK
</button>
</div>
<div class="nav"> <div class="nav">
<div class="nav-item"> <div class="nav-item">

View File

@ -26,5 +26,9 @@
.content { .content {
padding: 0 !important; padding: 0 !important;
.add-todo-button {
width: 100%;
}
} }
} }

View File

@ -1,6 +1,7 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { TodoService } from '../../todo.service'; import { TodoService } from '../../todo.service';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { Router } from '@angular/router';
@Component({ @Component({
selector : 'fuse-todo-main-sidenav', selector : 'fuse-todo-main-sidenav',
@ -18,7 +19,7 @@ export class MainSidenavComponent implements OnInit, OnDestroy
onFiltersChanged: Subscription; onFiltersChanged: Subscription;
onTagsChanged: Subscription; onTagsChanged: Subscription;
constructor(private todoService: TodoService) constructor(private todoService: TodoService, private router: Router)
{ {
// Data // Data
this.accounts = { this.accounts = {
@ -49,4 +50,13 @@ export class MainSidenavComponent implements OnInit, OnDestroy
this.onFiltersChanged.unsubscribe(); this.onFiltersChanged.unsubscribe();
this.onTagsChanged.unsubscribe(); this.onTagsChanged.unsubscribe();
} }
newTodo()
{
this.router.navigate(['/apps/todo/all']).then(() => {
setTimeout(() => {
this.todoService.onNewTodoClicked.next('');
});
});
}
} }

View File

@ -46,14 +46,16 @@
<div class="todo-content"> <div class="todo-content">
<form [formGroup]="todoForm"> <form [formGroup]="todoForm" (submit)="addTodo()">
<md-input-container class="title mt-8" floatPlaceholder="never" fxFill> <md-input-container class="title mt-8" floatPlaceholder="never" fxFill>
<textarea mdInput <textarea mdInput
#titleInput
name="title" name="title"
formControlName="title" formControlName="title"
placeholder="Title" placeholder="Title"
mdTextareaAutosize> mdTextareaAutosize
required>
</textarea> </textarea>
</md-input-container> </md-input-container>
@ -96,6 +98,11 @@
mdAutosizeMinRows="6"> mdAutosizeMinRows="6">
</textarea> </textarea>
</md-input-container> </md-input-container>
<button *ngIf="formType === 'new'"
md-raised-button class="mat-accent"
[disabled]="todoForm.invalid">SAVE
</button>
</form> </form>
</div> </div>

View File

@ -1,8 +1,9 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { AfterViewInit, Component, OnDestroy, OnInit, ViewChildren } from '@angular/core';
import { TodoService } from '../todo.service'; import { TodoService } from '../todo.service';
import { Todo } from '../todo.model'; import { Todo } from '../todo.model';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { FuseUtils } from '../../../../core/fuseUtils';
@Component({ @Component({
selector : 'fuse-todo-details', selector : 'fuse-todo-details',
@ -13,17 +14,19 @@ export class TodoDetailsComponent implements OnInit, OnDestroy
{ {
todo: Todo; todo: Todo;
tags: any[]; tags: any[];
formType: string;
todoForm: FormGroup; todoForm: FormGroup;
@ViewChildren('titleInput') titleInputField;
onFormChange: any; onFormChange: any;
onCurrentTodoChanged: Subscription; onCurrentTodoChanged: Subscription;
onTagsChanged: Subscription; onTagsChanged: Subscription;
onNewTodoClicked: Subscription;
constructor(private todoService: TodoService, constructor(private todoService: TodoService,
private formBuilder: FormBuilder) private formBuilder: FormBuilder)
{ {
} }
ngOnInit() ngOnInit()
@ -31,12 +34,16 @@ export class TodoDetailsComponent implements OnInit, OnDestroy
// Subscribe to update the current todo // Subscribe to update the current todo
this.onCurrentTodoChanged = this.onCurrentTodoChanged =
this.todoService.onCurrentTodoChanged this.todoService.onCurrentTodoChanged
.subscribe(currentTodo => { .subscribe(todo => {
this.todo = currentTodo;
this.formType = 'edit';
this.todo = todo;
if ( this.todo ) if ( this.todo )
{ {
this.todoForm = this.createTodoForm(); this.todoForm = this.createTodoForm();
this.onFormChange = this.todoForm.valueChanges this.onFormChange = this.todoForm.valueChanges
.debounceTime(500) .debounceTime(500)
.distinctUntilChanged() .distinctUntilChanged()
@ -52,6 +59,23 @@ export class TodoDetailsComponent implements OnInit, OnDestroy
.subscribe(labels => { .subscribe(labels => {
this.tags = labels; this.tags = labels;
}); });
// Subscribe to update on tag change
this.onNewTodoClicked = this.todoService.onNewTodoClicked
.subscribe(() => {
this.todo = new Todo({});
this.todo.id = FuseUtils.genearateGUID();
this.formType = 'new';
this.todoForm = this.createTodoForm();
this.focusTitleField();
});
}
focusTitleField()
{
setTimeout(() => {
this.titleInputField.first.nativeElement.focus();
});
} }
createTodoForm() createTodoForm()
@ -120,12 +144,20 @@ export class TodoDetailsComponent implements OnInit, OnDestroy
this.todoService.toggleTagOnTodo(tagId, this.todo); this.todoService.toggleTagOnTodo(tagId, this.todo);
} }
addTodo()
{
this.todoService.updateTodo(this.todoForm.getRawValue());
}
ngOnDestroy() ngOnDestroy()
{ {
if ( this.onFormChange ) if ( this.onFormChange )
{ {
this.onFormChange.unsubscribe(); this.onFormChange.unsubscribe();
} }
this.onCurrentTodoChanged.unsubscribe(); this.onCurrentTodoChanged.unsubscribe();
this.onNewTodoClicked.unsubscribe();
} }
} }

View File

@ -24,6 +24,12 @@
user-select: none; user-select: none;
} }
&.move-disabled {
.handle {
display: none;
}
}
.tags { .tags {
font-size: 12px; font-size: 12px;

View File

@ -2,6 +2,7 @@ import { Component, HostBinding, Input, OnDestroy, OnInit, ViewEncapsulation } f
import { Todo } from '../../todo.model'; import { Todo } from '../../todo.model';
import { TodoService } from '../../todo.service'; import { TodoService } from '../../todo.service';
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from 'rxjs/Subscription';
import { ActivatedRoute, ActivatedRouteSnapshot, Route, Router } from '@angular/router';
@Component({ @Component({
selector : 'fuse-todo-list-item', selector : 'fuse-todo-list-item',
@ -15,12 +16,19 @@ export class TodoListItemComponent implements OnInit, OnDestroy
tags: any[]; tags: any[];
@HostBinding('class.selected') selected: boolean; @HostBinding('class.selected') selected: boolean;
@HostBinding('class.completed') completed: boolean; @HostBinding('class.completed') completed: boolean;
@HostBinding('class.move-disabled') moveDisabled: boolean;
onSelectedTodosChanged: Subscription; onSelectedTodosChanged: Subscription;
onTagsChanged: Subscription; onTagsChanged: Subscription;
constructor(private todoService: TodoService) constructor(private todoService: TodoService,
private route: ActivatedRoute)
{ {
// Disable move if path is not /all
if ( route.snapshot.url[0].path !== 'all' )
{
this.moveDisabled = true;
}
} }
ngOnInit() ngOnInit()

View File

@ -1,7 +1,7 @@
<div *ngIf="todos.length === 0" fxLayout="column" fxLayoutAlign="center center" fxFlex> <div *ngIf="todos.length === 0" fxLayout="column" fxLayoutAlign="center center" fxFlex>
<span class="hint-text mat-h3">There are no todos!</span> <span class="hint-text mat-h3">There are no todos!</span>
</div> </div>
<div class="todo-list" ngxDroppable [model]="todos" (out)="log($event)"> <div class="todo-list" ngxDroppable [model]="todos" (out)="onDrop($event)">
<fuse-todo-list-item class="todo-list-item has-handle" <fuse-todo-list-item class="todo-list-item has-handle"
*ngFor="let todo of todos" [todo]="todo" *ngFor="let todo of todos" [todo]="todo"
ngxDraggable ngxDraggable

View File

@ -74,29 +74,12 @@ export class TodoListComponent implements OnInit, OnDestroy
*/ */
readTodo(todoId) readTodo(todoId)
{ {
const tagHandle = this.route.snapshot.params.tagHandle,
filterHandle = this.route.snapshot.params.filterHandle;
if ( tagHandle )
{
this.location.go('apps/todo/tag/' + tagHandle + '/' + todoId);
}
else if ( filterHandle )
{
this.location.go('apps/todo/filter/' + filterHandle + '/' + todoId);
}
else
{
this.location.go('apps/todo/all/' + todoId);
}
// Set current todo // Set current todo
this.todoService.setCurrentTodo(todoId); this.todoService.setCurrentTodo(todoId);
} }
log(ev) onDrop(ev)
{ {
console.info(this.todos); this.todoService.updateTodos(this.todos);
console.info(ev);
} }
} }

View File

@ -4,8 +4,9 @@ import { Observable } from 'rxjs/Observable';
import { Http } from '@angular/http'; import { Http } from '@angular/http';
import { Todo } from './todo.model'; import { Todo } from './todo.model';
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
import { FuseUtils } from '../../../core/fuseUtils'; import { FuseUtils } from '../../../core/fuseUtils';
import { Subject } from 'rxjs/Subject';
import { Location } from '@angular/common';
@Injectable() @Injectable()
export class TodoService implements Resolve<any> export class TodoService implements Resolve<any>
@ -26,8 +27,10 @@ export class TodoService implements Resolve<any>
onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]); onFiltersChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onTagsChanged: BehaviorSubject<any> = new BehaviorSubject([]); onTagsChanged: BehaviorSubject<any> = new BehaviorSubject([]);
onSearchTextChanged: BehaviorSubject<any> = new BehaviorSubject(''); onSearchTextChanged: BehaviorSubject<any> = new BehaviorSubject('');
onNewTodoClicked: Subject<any> = new Subject();
constructor(private http: Http) constructor(private http: Http,
private location: Location)
{ {
this.selectedTodos = []; this.selectedTodos = [];
} }
@ -317,6 +320,23 @@ export class TodoService implements Resolve<any>
}); });
this.onCurrentTodoChanged.next(this.currentTodo); this.onCurrentTodoChanged.next(this.currentTodo);
const tagHandle = this.routeParams.tagHandle,
filterHandle = this.routeParams.filterHandle;
if ( tagHandle )
{
this.location.go('apps/todo/tag/' + tagHandle + '/' + id);
}
else if ( filterHandle )
{
this.location.go('apps/todo/filter/' + filterHandle + '/' + id);
}
else
{
this.location.go('apps/todo/all/' + id);
}
} }
/** /**
@ -360,10 +380,7 @@ export class TodoService implements Resolve<any>
this.getTodos().then(todos => { this.getTodos().then(todos => {
if ( todos && this.currentTodo ) this.setCurrentTodo(todo.id);
{
this.setCurrentTodo(this.currentTodo.id);
}
resolve(todos); resolve(todos);
@ -371,4 +388,27 @@ export class TodoService implements Resolve<any>
}); });
}); });
} }
/**
* Update the todo
* @param todo
* @returns {Promise<any>}
*/
updateTodos(todos)
{
/* return new Promise((resolve, reject) => {
this.http.post('api/todo-todos/', {...todos})
.subscribe(response => {
this.getTodos().then(_todos => {
console.log(response);
resolve(_todos);
}, reject);
});
});*/
}
} }