First working implementation of commenting

This commit is contained in:
raimund-schluessler 2014-07-19 09:54:15 +02:00
parent 65978357c0
commit bb0ddc1751
12 changed files with 427 additions and 50 deletions

View file

@ -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
*/

View file

@ -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%;

View file

@ -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;
}
}
}
}

View file

@ -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,

View file

@ -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)

View file

@ -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)
]

View file

@ -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)
]

View file

@ -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,17 +2671,38 @@
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: comment.taskID
},
data: {
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
},
data: {
comment: comment
taskID: taskID,
commentID: commentID
}
};
return this._request.post('/apps/tasks_enhanced/tasks/{taskID}/comment', params);
return this._request.post('/apps/tasks_enhanced/tasks/{taskID}/comment/\
{commentID}/delete', params);
};
return Persistence;

View file

@ -86,4 +86,5 @@
"Friday" => "Freitag",
"Saturday" => "Samstag",
"Sunday" => "Sonntag",
"Add Comment" => "Kommentar hinzufügen",
);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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>