Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/tasks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorraimund-schluessler <raimund.schluessler@googlemail.com>2014-07-19 11:54:15 +0400
committerraimund-schluessler <raimund.schluessler@googlemail.com>2014-07-19 11:54:15 +0400
commitbb0ddc1751ed8b0c54e516cec2f27de2a595e1fd (patch)
treef47085318dacda89c570bf6ee76790bcbc1657a6
parent65978357c0279930efeac3cbb90aa9323e923813 (diff)
First working implementation of commenting
-rw-r--r--appinfo/routes.php10
-rw-r--r--css/style.css80
-rw-r--r--css/style.less84
-rw-r--r--js/app/controllers/detailscontroller.coffee26
-rw-r--r--js/app/services/businesslayer/tasksbusinesslayer.coffee21
-rw-r--r--js/app/services/models/tasksmodel.coffee22
-rw-r--r--js/app/services/persistence.coffee18
-rw-r--r--js/public/app.js119
-rw-r--r--l10n/de.php1
-rw-r--r--lib/controller/taskscontroller.php30
-rw-r--r--lib/helper.php16
-rw-r--r--templates/part.details.php46
12 files changed, 425 insertions, 48 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index c0523484..9af9e280 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -253,6 +253,16 @@ $this->create('task_comment', '/tasks/{taskID}/comment')
}
);
+$this->create('task_deletecomment', '/tasks/{taskID}/comment/{commentID}/delete')
+ ->post()
+ ->action(
+ function($params){
+ session_write_close();
+ $dispatcher = new Dispatcher($params);
+ $dispatcher->dispatch('TasksController', 'deleteComment');
+ }
+ );
+
/*
* Settings
*/
diff --git a/css/style.css b/css/style.css
index 0ab32ac0..d65b6919 100644
--- a/css/style.css
+++ b/css/style.css
@@ -636,7 +636,7 @@
border-top: 1px solid #D3D3D3;
bottom: 0;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset;
- height: 35px;
+ height: 65px;
left: 0;
position: absolute;
right: 0;
@@ -647,9 +647,34 @@
}
#task-details div.footer .icon {
position: absolute;
- top: 8px;
+ bottom: 7px;
left: 8px;
}
+#task-details div.footer .detail-addcomment {
+ padding: 4px 10px 0;
+}
+#task-details div.footer .detail-addcomment input {
+ background: none repeat scroll 0 0 white;
+ border: 1px solid #bdbcbb;
+ border-radius: 0;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
+ box-sizing: border-box;
+ color: #423e3e;
+ font-family: "Helvetica Neue", "Helvetica", "Arial", Sans-Serif;
+ font-size: 13px;
+ font-weight: 500;
+ margin-top: 2px;
+ outline: medium none;
+ padding: 4px;
+ transition: all 0.2s ease-in-out 0s;
+}
+#task-details div.footer .detail-addcomment input[type="text"] {
+ width: 260px;
+}
+#task-details div.footer .detail-addcomment input[type="button"] {
+ float: right;
+ margin-right: 0;
+}
#task-details.completed .body .section .section-title {
color: #9FA2A6 !important;
}
@@ -723,7 +748,7 @@
position: relative;
}
#task-details .body {
- bottom: 36px;
+ bottom: 65px;
left: 0;
overflow: auto;
position: absolute;
@@ -742,7 +767,7 @@
border-color: #CFCFCF;
font-size: 13px;
line-height: 26px;
- margin: 20px;
+ margin: 0 20px;
padding: 5px 15px;
cursor: text;
}
@@ -956,6 +981,53 @@
#task-details .body .section.detail-reminder.date .section-description {
display: block;
}
+#task-details .body .section.detail-note {
+ padding: 20px 0;
+ height: auto;
+}
+#task-details .body .section.detail-comments {
+ background: none;
+ padding: 10px 0;
+ height: auto;
+}
+#task-details .body .section.detail-comments .comment-item {
+ padding: 5px 60px 0;
+ position: relative;
+}
+#task-details .body .section.detail-comments .comment-item .icon.detail-delete {
+ top: 5px;
+}
+#task-details .body .section.detail-comments .comment-item:hover .icon.detail-delete {
+ display: block;
+}
+#task-details .body .section.detail-comments .comment-item .avatar {
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ left: 10px;
+ top: 10px;
+ border-radius: 2px;
+ overflow: hidden;
+}
+#task-details .body .section.detail-comments .comment-item .avatar img {
+ height: 100%;
+ width: 100%;
+}
+#task-details .body .section.detail-comments .comment-item .username {
+ display: inline-block;
+ font-weight: bold;
+}
+#task-details .body .section.detail-comments .comment-item .time {
+ color: #9fa2a6;
+ font-size: 11px;
+}
+#task-details .body .section.detail-addcomment {
+ background: url("../img/divider.svg") repeat-x scroll center top transparent;
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+}
#modal-wrapper {
position: absolute;
width: 100%;
diff --git a/css/style.less b/css/style.less
index 0761850f..fba94a42 100644
--- a/css/style.less
+++ b/css/style.less
@@ -674,12 +674,11 @@
position: relative;
}
div.footer{
- // background: none repeat scroll 0 0 #f1f1f1;
background: url("../img/bgTask.png") repeat scroll 0 0 #FFFFFF;
border-top: 1px solid #D3D3D3;
bottom: 0;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset;
- height: 35px;
+ height: 65px;
left: 0;
position: absolute;
right: 0;
@@ -689,9 +688,34 @@
}
.icon{
position:absolute;
- top:8px;
+ bottom:7px;
left:8px;
}
+ .detail-addcomment{
+ padding: 4px 10px 0;
+ input{
+ background: none repeat scroll 0 0 white;
+ border: 1px solid #bdbcbb;
+ border-radius: 0;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset;
+ box-sizing: border-box;
+ color: #423e3e;
+ font-family: "Helvetica Neue","Helvetica","Arial",Sans-Serif;
+ font-size: 13px;
+ font-weight: 500;
+ margin-top: 2px;
+ outline: medium none;
+ padding: 4px;
+ transition: all 0.2s ease-in-out 0s;
+ &[type="text"]{
+ width: 260px;
+ }
+ &[type="button"]{
+ float: right;
+ margin-right: 0;
+ }
+ }
+ }
}
&.completed{
.body{
@@ -772,7 +796,7 @@
}
}
.body{
- bottom: 36px;
+ bottom: 65px;
left: 0;
overflow: auto;
position: absolute;
@@ -786,7 +810,7 @@
// box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 1px 0 #F8F5DB inset;
font-size: 13px;
line-height: 26px;
- margin: 20px;
+ margin: 0 20px;
padding: 5px 15px;
cursor:text;
.expandingArea{
@@ -1002,6 +1026,56 @@
}
}
}
+ &.detail-note{
+ padding: 20px 0;
+ height:auto;
+ }
+ &.detail-comments{
+ background: none;
+ padding: 10px 0;
+ height: auto;
+ .comment-item{
+ padding: 5px 60px 0;
+ position: relative;
+ .icon.detail-delete{
+ top: 5px;
+ }
+ &:hover{
+ .icon.detail-delete{
+ display: block;
+ }
+ }
+ .avatar{
+ width: 40px;
+ height: 40px;
+ position: absolute;
+ left: 10px;
+ top: 10px;
+ border-radius: 2px;
+ overflow: hidden;
+ img{
+ height: 100%;
+ width: 100%;
+ }
+ }
+ .username{
+ display: inline-block;
+ font-weight: bold;
+ }
+ .comment{}
+ .time{
+ color: #9fa2a6;
+ font-size: 11px;
+ }
+ }
+ }
+ &.detail-addcomment{
+ background: url("../img/divider.svg") repeat-x scroll center top transparent;
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ }
}
}
}
diff --git a/js/app/controllers/detailscontroller.coffee b/js/app/controllers/detailscontroller.coffee
index 95743e56..c80f00b7 100644
--- a/js/app/controllers/detailscontroller.coffee
+++ b/js/app/controllers/detailscontroller.coffee
@@ -40,6 +40,8 @@ $timeout, $routeParams, SettingsModel) ->
@_$scope.settingsmodel = @_$settingsmodel
+ @_$scope.isAddingComment = false
+
@_$scope.durations = [
{
name: t('tasks_enhanced','week'),
@@ -288,8 +290,28 @@ $timeout, $routeParams, SettingsModel) ->
@_$scope.setReminderDuration = (taskID) ->
_tasksbusinesslayer.setReminder(_$scope.route.taskID)
- @_$scope.addComment = () ->
- _tasksbusinesslayer.addComment(_$scope.route.taskID,'test')
+ @_$scope.addComment = (CommentContent) ->
+ _$scope.isAddingComment = true
+
+ comment = {
+ tmpID: 'newComment' + Date.now()
+ comment: CommentContent
+ taskID: _$scope.route.taskID
+ time: moment().format('YYYYMMDDTHHmmss')
+ }
+
+ _tasksbusinesslayer.addComment comment
+ , (data) =>
+ _$tasksmodel.updateComment(data.comment)
+ _$scope.isAddingComment = false
+ , =>
+ _$scope.isAddingComment = false
+
+ _$scope.CommentContent = ''
+
+ @_$scope.deleteComment = (commentID) ->
+ _tasksbusinesslayer.deleteComment(_$scope.route.taskID, commentID)
+
return new DetailsController($scope, $window, TasksModel,
TasksBusinessLayer, $route, $location, $timeout, $routeParams,
diff --git a/js/app/services/businesslayer/tasksbusinesslayer.coffee b/js/app/services/businesslayer/tasksbusinesslayer.coffee
index 70f849d3..1d74c127 100644
--- a/js/app/services/businesslayer/tasksbusinesslayer.coffee
+++ b/js/app/services/businesslayer/tasksbusinesslayer.coffee
@@ -332,8 +332,25 @@ angular.module('Tasks').factory 'TasksBusinessLayer',
setShowHidden: (showHidden) ->
@_persistence.setShowHidden(showHidden)
- addComment: (taskID, comment) ->
- @_persistence.addComment(taskID, comment)
+ # addComment: (taskID, comment) ->
+ # @_persistence.addComment(taskID, comment)
+
+ addComment: (comment, onSuccess=null, onFailure=null) ->
+ onSuccess or= ->
+ onFailure or= ->
+
+ @_$tasksmodel.addComment(comment)
+
+ success = (response) =>
+ if response.status == 'error'
+ onFailure()
+ else
+ onSuccess(response.data)
+ @_persistence.addComment(comment, success)
+
+ deleteComment: (taskID, commentID) ->
+ @_$tasksmodel.deleteComment(taskID, commentID)
+ @_persistence.deleteComment(taskID, commentID)
return new TasksBusinessLayer(TasksModel, Persistence)
diff --git a/js/app/services/models/tasksmodel.coffee b/js/app/services/models/tasksmodel.coffee
index 299661e7..af884cc2 100644
--- a/js/app/services/models/tasksmodel.coffee
+++ b/js/app/services/models/tasksmodel.coffee
@@ -165,5 +165,27 @@ angular.module('Tasks').factory 'TasksModel',
setNote: (taskID, note) ->
@update({id:taskID,note:note})
+ addComment: (comment) ->
+ task = @getById(comment.taskID)
+ task.comments.push(comment)
+
+ updateComment: (comment) ->
+ task = @getById(comment.taskID)
+ i = 0
+ for com in task.comments
+ if com.tmpID == comment.tmpID
+ task.comments[i] = comment
+ break
+ i++
+
+ deleteComment: (taskID, commentID) ->
+ task = @getById(taskID)
+ i = 0
+ for comment in task.comments
+ if comment.id == commentID
+ task.comments.splice(i,1)
+ break
+ i++
+
return new TasksModel(Utils)
] \ No newline at end of file
diff --git a/js/app/services/persistence.coffee b/js/app/services/persistence.coffee
index 39f9df66..dab98b69 100644
--- a/js/app/services/persistence.coffee
+++ b/js/app/services/persistence.coffee
@@ -326,16 +326,28 @@ angular.module('Tasks').factory 'Persistence',
@_request.post '/apps/tasks_enhanced/settings/showhidden/{showHidden}',
params
- addComment: (taskID, comment) ->
+ addComment: (comment, onSuccess=null, onFailure=null) ->
params =
routeParams:
- taskID: taskID
+ taskID: comment.taskID
data:
- comment: comment
+ comment: comment.comment
+ tmpID: comment.tmpID
+ onSuccess: onSuccess
+ onFailure: onFailure
@_request.post '/apps/tasks_enhanced/tasks/{taskID}/comment',
params
+ deleteComment: (taskID, commentID) ->
+ params =
+ routeParams:
+ taskID: taskID
+ commentID: commentID
+
+ @_request.post '/apps/tasks_enhanced/tasks/{taskID}/comment/
+ {commentID}/delete', params
+
return new Persistence(Request, Loading, $rootScope)
] \ No newline at end of file
diff --git a/js/public/app.js b/js/public/app.js
index 61579472..26dd4fc6 100644
--- a/js/public/app.js
+++ b/js/public/app.js
@@ -410,6 +410,7 @@
return _$scope.task = _$tasksmodel.getById(_$scope.route.taskID);
});
this._$scope.settingsmodel = this._$settingsmodel;
+ this._$scope.isAddingComment = false;
this._$scope.durations = [
{
name: t('tasks_enhanced', 'week'),
@@ -663,8 +664,26 @@
this._$scope.setReminderDuration = function(taskID) {
return _tasksbusinesslayer.setReminder(_$scope.route.taskID);
};
- this._$scope.addComment = function() {
- return _tasksbusinesslayer.addComment(_$scope.route.taskID, 'test');
+ this._$scope.addComment = function(CommentContent) {
+ var comment,
+ _this = this;
+ _$scope.isAddingComment = true;
+ comment = {
+ tmpID: 'newComment' + Date.now(),
+ comment: CommentContent,
+ taskID: _$scope.route.taskID,
+ time: moment().format('YYYYMMDDTHHmmss')
+ };
+ _tasksbusinesslayer.addComment(comment, function(data) {
+ _$tasksmodel.updateComment(data.comment);
+ return _$scope.isAddingComment = false;
+ }, function() {
+ return _$scope.isAddingComment = false;
+ });
+ return _$scope.CommentContent = '';
+ };
+ this._$scope.deleteComment = function(commentID) {
+ return _tasksbusinesslayer.deleteComment(_$scope.route.taskID, commentID);
};
}
@@ -1630,8 +1649,31 @@
return this._persistence.setShowHidden(showHidden);
};
- TasksBusinessLayer.prototype.addComment = function(taskID, comment) {
- return this._persistence.addComment(taskID, comment);
+ TasksBusinessLayer.prototype.addComment = function(comment, onSuccess, onFailure) {
+ var success,
+ _this = this;
+ if (onSuccess == null) {
+ onSuccess = null;
+ }
+ if (onFailure == null) {
+ onFailure = null;
+ }
+ onSuccess || (onSuccess = function() {});
+ onFailure || (onFailure = function() {});
+ this._$tasksmodel.addComment(comment);
+ success = function(response) {
+ if (response.status === 'error') {
+ return onFailure();
+ } else {
+ return onSuccess(response.data);
+ }
+ };
+ return this._persistence.addComment(comment, success);
+ };
+
+ TasksBusinessLayer.prototype.deleteComment = function(taskID, commentID) {
+ this._$tasksmodel.deleteComment(taskID, commentID);
+ return this._persistence.deleteComment(taskID, commentID);
};
return TasksBusinessLayer;
@@ -2156,6 +2198,46 @@
});
};
+ TasksModel.prototype.addComment = function(comment) {
+ var task;
+ task = this.getById(comment.taskID);
+ return task.comments.push(comment);
+ };
+
+ TasksModel.prototype.updateComment = function(comment) {
+ var com, i, task, _i, _len, _ref, _results;
+ task = this.getById(comment.taskID);
+ i = 0;
+ _ref = task.comments;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ com = _ref[_i];
+ if (com.tmpID === comment.tmpID) {
+ task.comments[i] = comment;
+ break;
+ }
+ _results.push(i++);
+ }
+ return _results;
+ };
+
+ TasksModel.prototype.deleteComment = function(taskID, commentID) {
+ var comment, i, task, _i, _len, _ref, _results;
+ task = this.getById(taskID);
+ i = 0;
+ _ref = task.comments;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ comment = _ref[_i];
+ if (comment.id === commentID) {
+ task.comments.splice(i, 1);
+ break;
+ }
+ _results.push(i++);
+ }
+ return _results;
+ };
+
return TasksModel;
})(_Model);
@@ -2589,19 +2671,40 @@
return this._request.post('/apps/tasks_enhanced/settings/showhidden/{showHidden}', params);
};
- Persistence.prototype.addComment = function(taskID, comment) {
+ Persistence.prototype.addComment = function(comment, onSuccess, onFailure) {
var params;
+ if (onSuccess == null) {
+ onSuccess = null;
+ }
+ if (onFailure == null) {
+ onFailure = null;
+ }
params = {
routeParams: {
- taskID: taskID
+ taskID: comment.taskID
},
data: {
- comment: comment
- }
+ comment: comment.comment,
+ tmpID: comment.tmpID
+ },
+ onSuccess: onSuccess,
+ onFailure: onFailure
};
return this._request.post('/apps/tasks_enhanced/tasks/{taskID}/comment', params);
};
+ Persistence.prototype.deleteComment = function(taskID, commentID) {
+ var params;
+ params = {
+ routeParams: {
+ taskID: taskID,
+ commentID: commentID
+ }
+ };
+ return this._request.post('/apps/tasks_enhanced/tasks/{taskID}/comment/\
+ {commentID}/delete', params);
+ };
+
return Persistence;
})();
diff --git a/l10n/de.php b/l10n/de.php
index 50940550..e5be8371 100644
--- a/l10n/de.php
+++ b/l10n/de.php
@@ -86,4 +86,5 @@
"Friday" => "Freitag",
"Saturday" => "Samstag",
"Sunday" => "Sonntag",
+"Add Comment" => "Kommentar hinzufügen",
); \ No newline at end of file
diff --git a/lib/controller/taskscontroller.php b/lib/controller/taskscontroller.php
index 4a071079..bfaea758 100644
--- a/lib/controller/taskscontroller.php
+++ b/lib/controller/taskscontroller.php
@@ -439,8 +439,6 @@ class TasksController extends Controller {
}
}
-
-
return $response;
}
@@ -500,17 +498,30 @@ class TasksController extends Controller {
$commentId = 1+max($commentIds);
$now = new \DateTime();
- $now = $now->format('Ymd\THis\Z');
- $tmp = $vtodo->addProperty('COMMENT',$comment,
+ $vtodo->addProperty('COMMENT',$comment,
array(
'ID' => $commentId,
'USERID' => $userId,
- 'DATE-TIME' => $now
+ 'DATE-TIME' => $now->format('Ymd\THis\Z')
)
);
\OC_Calendar_Object::edit($taskId, $vcalendar->serialize());
- $response->setData();
-
+ $user_timezone = \OC_Calendar_App::getTimezone();
+ $now->setTimezone(new \DateTimeZone($user_timezone));
+ $comment = array(
+ 'taskID' => $taskId,
+ 'id' => $commentId,
+ 'tmpID' => $this->params('tmpID'),
+ 'userID' => $userId,
+ 'comment' => $comment,
+ 'time' => $now->format('Ymd\THis')
+ );
+ $result = array(
+ 'data' => array(
+ 'comment' => $comment
+ )
+ );
+ $response->setData($result);
} catch(\Exception $e) {
// throw new BusinessLayerException($e->getMessage());
}
@@ -520,12 +531,11 @@ class TasksController extends Controller {
/**
* @NoAdminRequired
*/
- public function deleteCommentById(){
+ public function deleteComment(){
$taskId = $this->params('taskID');
$commentId = $this->params('commentID');
$userId = $this->api->getUserId();
$response = new JSONResponse();
- $test = array();
try {
$vcalendar = \OC_Calendar_App::getVCalendar($taskId);
$vtodo = $vcalendar->VTODO;
@@ -535,7 +545,7 @@ class TasksController extends Controller {
} catch(\Exception $e) {
// throw new BusinessLayerException($e->getMessage());
}
- $response->setData($test);
+ $response->setData();
return $response;
}
diff --git a/lib/helper.php b/lib/helper.php
index aabecbf7..ca7c8bcb 100644
--- a/lib/helper.php
+++ b/lib/helper.php
@@ -169,6 +169,22 @@ Class helper {
$task['completed'] = false;
}
$task['complete'] = $vtodo->getAsString('PERCENT-COMPLETE')==''?'0':$vtodo->getAsString('PERCENT-COMPLETE');
+ $comments = $vtodo->COMMENT;
+ if($comments){
+ $comments_parsed = array();
+ foreach($comments as $com) {
+ $time = new \DateTime($com['DATE-TIME']->value);
+ $time->setTimezone(new \DateTimeZone($user_timezone));
+ $time = $time->format('Ymd\THis');
+ $comments_parsed[] = array(
+ 'id' => (int)$com['ID']->value,
+ 'userID' => $com['USERID']->value,
+ 'comment' => $com->value,
+ 'time' => $time
+ );
+ }
+ }
+ $task['comments'] = $comments_parsed;
return $task;
}
diff --git a/templates/part.details.php b/templates/part.details.php
index 5797d1cb..61efe3f4 100644
--- a/templates/part.details.php
+++ b/templates/part.details.php
@@ -85,32 +85,50 @@
</div>
</div>
<!-- <ul class="subtasks buffer"></ul> -->
- <div class="note">
- <div class="note-body selectable" ng-click="editNote()" stop-event="click" oc-click-focus="{selector: '.expandingArea textarea', timeout: 0}">
- <!--
- <a class="open-fullscreen-note">
- <span class="icon note-fullscreen"></span>
- </a>
- -->
- <div class="content-fakeable">
- <div class="display-view" ng-hide="route.parameter=='note'">{{ task.note }}</div>
- <div class="edit-view" ng-show="route.parameter=='note'">
- <div class="expandingArea active">
- <pre><span>{{ task.note }}</span><br /><br /></pre>
- <textarea ng-model="task.note"></textarea>
+ <div class="section detail-note">
+ <div class="note">
+ <div class="note-body selectable" ng-click="editNote()" stop-event="click" oc-click-focus="{selector: '.expandingArea textarea', timeout: 0}">
+ <!--
+ <a class="open-fullscreen-note">
+ <span class="icon note-fullscreen"></span>
+ </a>
+ -->
+ <div class="content-fakeable">
+ <div class="display-view" ng-hide="route.parameter=='note'">{{ task.note }}</div>
+ <div class="edit-view" ng-show="route.parameter=='note'">
+ <div class="expandingArea active">
+ <pre><span>{{ task.note }}</span><br /><br /></pre>
+ <textarea ng-model="task.note"></textarea>
+ </div>
</div>
</div>
</div>
</div>
</div>
+ <div class="section detail-comments">
+ <ul>
+ <li ng-repeat="comment in task.comments" class="comment-item" rel=" {{ comment.id }} ">
+ <div class="avatar"><img src=""></div>
+ <a class="detail-delete" ng-click="deleteComment(comment.id)" stop-event="click">
+ <span class="icon detail-delete"></span>
+ </a>
+ <span class="username">{{ comment.userID }}</span>
+ <div class="comment">{{ comment.comment }}</div>
+ <span class="time"> {{ comment.time}} </span>
+ </li>
+ </ul>
+ </div>
</div>
<div class="footer">
+ <div class="detail-addcomment">
+ <input type="text" placeholder="Add comment" ng-model="CommentContent">
+ <input type="button" ng-click="addComment(CommentContent)" name="addComment" value="Comment">
+ </div>
<a class="detail-trash" ng-click="deleteTask(task.id)" stop-event="click">
<span class="icon detail-trash"></span>
</a>
<a class="detail-close" ng-click="closeDetails()" stop-event="click">
<span class="icon detail-close"></span>
</a>
- <a ng-click="addComment()">Comment</a>
</div>
</div> \ No newline at end of file