Skip to content

Commit 43605b1

Browse files
committed
feature(todoApp): add simple todo app
- add feature-b module - add todo-component - add TodoService - add service tests - adjust layouts and styles
1 parent 67ff2bf commit 43605b1

File tree

13 files changed

+350
-3
lines changed

13 files changed

+350
-3
lines changed

src/app/app-component/app-component.tpl.html

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<div id="navbar" class="collapse navbar-collapse">
1414
<ul class="nav navbar-nav">
1515
<li ui-sref-active="active"><a ui-sref="app.feature-a">Feature A</a></li>
16-
<!--<li ui-sref-active="active"><a ui-sref="app.feature-b">Feature B</a></li>-->
16+
<li ui-sref-active="active"><a ui-sref="app.feature-b">Feature B</a></li>
1717
</ul>
1818
<ul class="nav navbar-nav pull-right">
1919
<li><a href="javascript:void(0)" user-info-component></a></li>
@@ -23,4 +23,30 @@
2323
</nav>
2424

2525
<div class="container" ui-view></div>
26+
27+
<footer class="footer">
28+
<div class="container">
29+
<div class="row">
30+
<div class="col-md-3 col-sm-6">
31+
<i class="fa fa-medium fa-lg"></i></a> <a href="https://medium.com/@tomastrajan">Medium</a>
32+
</div>
33+
<div class="col-md-3 col-sm-6">
34+
<i class="fa fa-github fa-lg"></i> <a href="https://github.com/tomastrajan">Github</a>
35+
</div>
36+
<div class="col-md-3 col-sm-6">
37+
<i class="fa fa-twitter fa-lg"></i> <a href="https://twitter.com/tomastrajan">Twitter</a>
38+
</div>
39+
<div class="col-md-3 col-sm-6">
40+
<i class="fa fa-stack-overflow fa-lg"></i> <a href="http://stackoverflow.com/users/2650426/tomastrajan?tab=profile">StackOverflow</a>
41+
</div>
42+
</div>
43+
<hr />
44+
<div class="row">
45+
<div class="col-md-12">
46+
<p class="text-muted">Tomas Trajan 2015</p>
47+
</div>
48+
</div>
49+
</div>
50+
</footer>
51+
2652
</div>

src/feature-a/some-component/some-component.tpl.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ <h2>Feature A is implemented as Component using
1212
<p>The implemented counter functionality is tested in isolation without instantiating of Angular JS context</p>
1313
<br />
1414
<hr />
15-
<!--<button class="btn btn-info pull-right" ui-sref="app.feature-b">Try Feature B</button>-->
15+
<button class="btn btn-info pull-right" ui-sref="app.feature-b">Try Feature B</button>
1616
<button class="btn btn-success" ng-click="ctrl.increment()">Increment counter</button>
1717
<a class="btn btn-default" data-toggle="collapse" href="#testCode" aria-expanded="false" aria-controls="collapseExample">Toggle test code</a>
1818
<br />

src/feature-b/feature-b.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function routing($stateProvider) {
2+
3+
$stateProvider
4+
.state('app.feature-b', {
5+
url: '/feature-b',
6+
template: '<div todo-component></div>'
7+
});
8+
}

src/feature-b/feature-b.module.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import angular from 'angular';
2+
import uirouter from 'angular-ui-router';
3+
4+
import { routing } from './feature-b.config.js';
5+
6+
import todoComponent from './todo-component/todo-component.directive';
7+
import TodoService from './services/todo.service';
8+
9+
10+
export default angular
11+
.module('main.app.feature-b', [uirouter])
12+
.config(routing)
13+
.directive('todoComponent', todoComponent)
14+
.factory('TodoService', TodoService)
15+
.name;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import * as _ from 'lodash';
2+
3+
export default function TodoService(initialTodos) {
4+
5+
const defaultTodos = [
6+
{ label: 'Read blog post', done: true },
7+
{ label: 'Checkout from github & run example', done: true },
8+
{ label: 'Check github repository for implementation details', done: false },
9+
{ label: 'Use in your own project!', done: false }
10+
];
11+
12+
const todos = initialTodos || defaultTodos;
13+
14+
return {
15+
todos,
16+
addTodo,
17+
toggleTodo,
18+
removeDoneTodos
19+
};
20+
21+
function addTodo(label) {
22+
let todo = {
23+
label,
24+
done: false
25+
};
26+
todos.push(todo);
27+
}
28+
29+
function toggleTodo(label) {
30+
let toggledTodo = _.find(todos, function(todo) {
31+
return todo.label === label;
32+
});
33+
toggledTodo.done = !toggledTodo.done;
34+
}
35+
36+
function removeDoneTodos() {
37+
_.remove(todos, function(todo) {
38+
return todo.done;
39+
});
40+
}
41+
42+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { assert } from 'chai';
2+
3+
import TodoService from './todo.service.js';
4+
5+
let service;
6+
7+
describe('TodoService', function() {
8+
9+
beforeEach(function() {
10+
let initialTodos = [];
11+
service = TodoService(initialTodos);
12+
});
13+
14+
it('should contain empty todos after initialization', function () {
15+
assert.equal(service.todos.length, 0);
16+
});
17+
18+
it('should add todo', function () {
19+
service.addTodo('Finish example project');
20+
assert.equal(service.todos.length, 1);
21+
assert.equal(service.todos[0].label, 'Finish example project');
22+
assert.equal(service.todos[0].done, false);
23+
});
24+
25+
it('should toggle todo', function () {
26+
service.addTodo('Finish example project');
27+
assert.equal(service.todos[0].done, false);
28+
29+
service.toggleTodo('Finish example project');
30+
assert.equal(service.todos[0].done, true);
31+
32+
service.toggleTodo('Finish example project');
33+
assert.equal(service.todos[0].done, false);
34+
});
35+
36+
it('should remove done todos', function () {
37+
service.addTodo('Todo1');
38+
service.addTodo('Todo2');
39+
service.addTodo('Todo3');
40+
assert.equal(service.todos.length, 3);
41+
42+
service.toggleTodo('Todo1');
43+
service.removeDoneTodos();
44+
assert.equal(service.todos.length, 2);
45+
});
46+
47+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import template from './todo-component.tpl.html';
2+
import TodoComponent from './todo-component';
3+
4+
export default function() {
5+
6+
return {
7+
scope: {},
8+
controller: TodoComponent,
9+
controllerAs: 'ctrl',
10+
bindToController: true,
11+
template: template
12+
};
13+
14+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export default class TodoComponent {
2+
3+
constructor(TodoService) {
4+
this.TodoService = TodoService;
5+
this.todos = TodoService.todos;
6+
this.label = '';
7+
}
8+
9+
addTodo() {
10+
this.TodoService.addTodo(this.label);
11+
this.label = '';
12+
}
13+
14+
toggleTodo(todo) {
15+
this.TodoService.toggleTodo(todo.label);
16+
}
17+
18+
removeDoneTodos() {
19+
this.TodoService.removeDoneTodos();
20+
}
21+
22+
}

src/feature-b/todo-component/todo-component.test.js

Whitespace-only changes.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<div class="jumbotron">
2+
3+
<div class="row">
4+
<div class="col-md-12">
5+
<h1>Feature B!</h1>
6+
<h2>Feature B is implementation of simple Todo app</h2>
7+
</div>
8+
</div>
9+
10+
<br />
11+
<hr />
12+
13+
<div class="row">
14+
<div class="col-md-6">
15+
<label>Todos</label>
16+
<ul ng-if="ctrl.todos.length">
17+
<li class="todo" ng-repeat="todo in ctrl.todos" ng-click="ctrl.toggleTodo(todo);">
18+
<i ng-show="todo.done" class="done fa fa-check-circle fa-lg"></i>
19+
<i ng-show="!todo.done" class="fa fa-circle-o fa-lg"></i>
20+
{{todo.label}}
21+
</li>
22+
</ul>
23+
<p ng-if="!ctrl.todos.length">No `todos` yet, try to add some...</p>
24+
</div>
25+
<div class="col-md-3">
26+
<form>
27+
<label>Label</label>
28+
<input class="form-control" ng-model="ctrl.label">
29+
</form>
30+
</div>
31+
<div class="col-md-3">
32+
<form>
33+
<label>Actions</label>
34+
<button class="btn btn-success btn-block" ng-click="ctrl.addTodo()" ng-disabled="!ctrl.label.length">
35+
<i class="fa fa-plus fa-lg"></i> Add todo
36+
</button>
37+
<button class="btn btn-danger btn-block" ng-click="ctrl.removeDoneTodos()">
38+
<i class="fa fa-trash fa-lg"></i> Remove done todos
39+
</button>
40+
</form>
41+
</div>
42+
<div class="col-md-12">
43+
<br />
44+
<br />
45+
<p>The functionality implemnted in <strong>TodoService</strong> is tested in isolation without instantiating of Angular JS context</p>
46+
</div>
47+
</div>
48+
49+
<hr />
50+
<br />
51+
52+
<div class="row">
53+
<div class="col-md-12">
54+
<button class="btn btn-info pull-right" ui-sref="app.feature-a">Try Feature A</button>
55+
<a class="btn btn-default" data-toggle="collapse" href="#serviceTestCode" aria-expanded="false" aria-controls="serviceTestCode">Toggle service test code</a>
56+
57+
<br />
58+
<br />
59+
<pre class="collapse" id="serviceTestCode">
60+
<code class="javascript">
61+
import { assert } from 'chai';
62+
63+
import TodoService from './todo.service.js';
64+
65+
let service;
66+
67+
describe('TodoService', function() {
68+
69+
beforeEach(function() {
70+
service = TodoService();
71+
});
72+
73+
it('should contain empty todos after initialization', function () {
74+
assert.equal(service.todos.length, 0);
75+
});
76+
77+
it('should add todo', function () {
78+
service.addTodo('Finish example project');
79+
assert.equal(service.todos.length, 1);
80+
assert.equal(service.todos[0].label, 'Finish example project');
81+
assert.equal(service.todos[0].done, false);
82+
});
83+
84+
it('should toggle todo', function () {
85+
service.addTodo('Finish example project');
86+
assert.equal(service.todos[0].done, false);
87+
88+
service.toggleTodo('Finish example project');
89+
assert.equal(service.todos[0].done, true);
90+
91+
service.toggleTodo('Finish example project');
92+
assert.equal(service.todos[0].done, false);
93+
});
94+
95+
it('should remove done todos', function () {
96+
service.addTodo('Todo1');
97+
service.addTodo('Todo2');
98+
service.addTodo('Todo3');
99+
assert.equal(service.todos.length, 3);
100+
101+
service.toggleTodo('Todo1');
102+
service.removeDoneTodos();
103+
assert.equal(service.todos.length, 2);
104+
});
105+
106+
});
107+
</code>
108+
</pre>
109+
</div>
110+
</div>
111+
112+
</div>

0 commit comments

Comments
 (0)