Skip to content

Commit f89d440

Browse files
author
Vlad Sternbach
committed
added tags and filtering functionality
1 parent b48f351 commit f89d440

11 files changed

+107
-26
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"dependencies": {
2121
"angular": "^1.5.3",
2222
"angular-sanitize": "^1.5.3",
23-
"angular-ui-router": "^0.2.18"
23+
"angular-ui-router": "^0.2.18",
24+
"ng-tags-input": "^3.0.0"
2425
},
2526
"scripts": {
2627
"prestart": "npm install",

src/assets/ng-tags-input.min.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/comment-list/comment-list.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
position: absolute;
1212
top: 0;
1313
bottom: 0;
14-
left: 79px;
14+
left: 15px;
1515
z-index: -1;
1616
display: block;
1717
width: 2px;

src/components/comment-list/comments.component.ts

+28-4
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,47 @@
33
*/
44
import Component from '../../decorators';
55
import './comment-list.scss';
6+
import {IComment} from "../../interfaces";
67

78
@Component('app.components', 'comments', {
89
template: `
910
<div class="container-fluid">
1011
<div class="discussion-timeline">
11-
<comment ng-repeat="comment in $ctrl.comments" comment="comment"></comment>
12-
<!--<comment></comment>-->
12+
<tags-input ng-model="$ctrl.tagFilter">
13+
<auto-complete source="$ctrl.tags"></auto-complete>
14+
</tags-input>
15+
<comment ng-repeat="comment in $ctrl.comments | filterByTags:$ctrl.tagFilter" comment="comment" tags="$ctrl.tags"></comment>
16+
<comment comment="$ctrl.emptyComment" on-add="$ctrl.addComment()" tags="$ctrl.tags"></comment>
1317
</div>
1418
</div>`
1519
})
1620
class CommentsController {
17-
comments;
21+
comments: IComment[];
22+
emptyComment: IComment;
23+
tags: string[];
24+
tagFilter: any[];
1825

1926
static $inject = ['Comments'];
2027
constructor(private Comments) {
28+
this.emptyComment = {};
29+
this.tagFilter = [];
2130
Comments.getComments().then((comments) => {
22-
this.comments = comments
31+
this.comments = comments;
32+
this.tags = this.comments
33+
.map((el) => el.tags)
34+
.reduce((prev, curr) => [...prev, ...curr])
35+
.filter((elem, pos, arr) => arr.indexOf(elem) == pos);
2336
});
2437
}
38+
39+
private getCommentId() {
40+
let arr = this.comments.map((el) => el.id);
41+
return Math.max(...arr) + 1;
42+
}
43+
44+
addComment() {
45+
this.emptyComment.id = this.getCommentId();
46+
this.comments.push(this.emptyComment);
47+
this.emptyComment = {};
48+
}
2549
}

src/components/comment/comment.component.ts

+19-9
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
*/
44
import Component from '../../decorators';
55
import './comment.scss';
6+
import {IComment} from "../../interfaces";
67

78
@Component('app.components', 'comment', {
9+
bindings: {
10+
comment: '=',
11+
tags: '=',
12+
onAdd: '&'
13+
},
814
template: `
915
<div class="comment-wrapper">
1016
<div class="comment" ng-class="{'comment-edit': $ctrl.editMode}">
@@ -32,23 +38,25 @@ import './comment.scss';
3238
</div>
3339
<div class="comment-body" ng-bind-html="$ctrl.comment.text"></div>
3440
</div>
41+
<tags-input ng-model="$ctrl.comment.inputTags" placeholder="Add tags">
42+
<auto-complete source="$ctrl.tags"></auto-complete>
43+
</tags-input>
3544
<div class="form-actions">
3645
<button ng-click="$ctrl.save()" class="btn btn-primary" tabindex="2">Comment</button>
37-
<button ng-click="$ctrl.discard()" class="btn" tabindex="3">Discard</button>
46+
<button ng-if="$ctrl.comment.id" ng-click="$ctrl.discard()" class="btn" tabindex="3">Discard</button>
3847
</div>
3948
</div>
40-
</div>`,
41-
bindings: {
42-
comment: '='
43-
}
49+
</div>`
4450
})
4551
class CommentController {
4652
editMode: boolean;
47-
comment: any;
48-
commentCopy: any;
53+
comment: IComment;
54+
commentCopy: IComment;
55+
onAdd: any;
4956

5057
constructor() {
51-
this.editMode = false;
58+
this.editMode = !this.comment.id;
59+
this.comment.inputTags = angular.copy(this.comment.tags);
5260
}
5361

5462
edit() {
@@ -57,7 +65,9 @@ class CommentController {
5765
}
5866

5967
save() {
60-
this.editMode = false;
68+
this.editMode = !this.comment.id;
69+
this.comment.tags = this.comment.inputTags.map((el:any) => el.text);
70+
(this.onAdd || angular.noop)();
6171
}
6272

6373
discard() {

src/components/comment/comment.scss

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
.comment-wrapper {
22
position: relative;
3-
padding-left: 64px;
43
margin-top: 15px;
54
margin-bottom: 15px;
65
border-top: 2px solid #fff;
@@ -12,6 +11,21 @@
1211
background-color: #fff;
1312
border: 1px solid #ddd;
1413
border-radius: 3px;
14+
&.comment-edit tags-input {
15+
display: block;
16+
}
17+
tags-input {
18+
display: none;
19+
margin: -5px 10px 10px 10px;
20+
}
21+
}
22+
23+
tags-input {
24+
.tags {
25+
border-radius: 3px;
26+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075);
27+
border: 1px solid #ddd;
28+
}
1529
}
1630

1731
.comment-header {
@@ -50,7 +64,6 @@
5064
width: 100%;
5165
padding: 6px 10px;
5266
font-size: 16px;
53-
background-color: #fafafa;
5467
min-height: 34px;
5568
color: #333;
5669
vertical-align: middle;

src/components/components.module.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
/**
22
* Created by voland on 4/2/16.
33
*/
4-
export default angular.module('app.components', [])
4+
5+
6+
export default angular.module('app.components', [])
7+
.filter('filterByTags', () => (comments, tags) => {
8+
if (!tags.length) return comments;
9+
function check(comment) {
10+
let filterArray = tags.map((tag: any) => tag.text);
11+
let findCount = filterArray
12+
.map((tag) => comment.tags.indexOf(tag) > -1 ? 1 : 0)
13+
.reduce((prev, curr) => prev + curr);
14+
return findCount === filterArray.length;
15+
}
16+
return comments.filter(check);
17+
})

src/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<meta charset="utf-8">
55
<meta http-equiv="X-UA-Compatible" content="IE=edge">
66
<title>My AngularJS App</title>
7+
<link href="assets/ng-tags-input.min.css" rel="stylesheet">
78
<meta name="description" content="">
89
<meta name="viewport" content="width=device-width, initial-scale=1">
910
</head>

src/interfaces.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface IComment {
2+
id?: number;
3+
title?: string;
4+
text?: string;
5+
tags?: string[]
6+
inputTags?: string[]
7+
}

src/main.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,37 @@
44
import 'angular';
55
import 'angular-sanitize';
66
import 'angular-ui-router';
7+
import 'ng-tags-input';
78

89
import services from './services/services.module';
910
import components from './components/components.module';
10-
import './components/comment/comment.component.ts';
11-
import './components/comment-list/comments.component.ts';
11+
import './components/comment/comment.component';
12+
import './components/comment-list/comments.component';
1213

1314
// configure the main module
1415
angular.module('app', [
16+
'ngTagsInput',
1517
'ngSanitize',
1618
'ui.router',
1719
services.name,
1820
components.name
1921
])
20-
.config(function($urlRouterProvider, $stateProvider) {
22+
.config(function($urlRouterProvider, $stateProvider, tagsInputConfigProvider) {
2123
$urlRouterProvider.otherwise('/');
2224
$stateProvider
2325
.state('index', {
2426
url: '/',
2527
template: '<comments></comments>'
2628
});
29+
30+
tagsInputConfigProvider
31+
.setDefaults('tagsInput', {
32+
placeholder: 'Search tags',
33+
addFromAutocompleteOnly: true
34+
})
35+
.setDefaults('autoComplete', {
36+
minLength: 1
37+
})
2738
});
2839

2940
// bootstrap angular

src/services/comments.service.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
/**
22
* Created by voland on 4/2/16.
33
*/
4+
import {IComment} from "../interfaces";
5+
46
export class Comments {
57

6-
static $inject = ['$http', '$q'];
7-
constructor(private $http, private $q) {
8-
console.log('Comments service')
8+
static $inject = ['$http'];
9+
constructor(private $http) {
910
}
1011

1112
getComments() {
12-
return this.$http.get('mock.json').then((response) => {
13+
return this.$http.get('mock.json').then((response: {data: IComment[]}) => {
1314
return response.data;
1415
});
1516
};
16-
1717
}

0 commit comments

Comments
 (0)