summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorVincent Petry <pvince81@owncloud.com>2016-02-03 16:18:14 +0100
committerVincent Petry <pvince81@owncloud.com>2016-02-03 16:18:14 +0100
commit85bec3ffcb0e2c948c57cee2817307af2826d847 (patch)
tree57d26e0d40e50d12da4d6913c3d30529a1e924cb /apps
parent8bb1437e240ce47e04f7bcb7dc3a56ef6b5d892b (diff)
downloadnextcloud-server-85bec3ffcb0e2c948c57cee2817307af2826d847.tar.gz
nextcloud-server-85bec3ffcb0e2c948c57cee2817307af2826d847.zip
Reset comments read marker after loading comments
Diffstat (limited to 'apps')
-rw-r--r--apps/comments/appinfo/app.php1
-rw-r--r--apps/comments/js/commentcollection.js61
-rw-r--r--apps/comments/js/commentmodel.js5
-rw-r--r--apps/comments/js/commentstabview.js27
-rw-r--r--apps/comments/js/commentsummarymodel.js65
-rw-r--r--apps/comments/tests/js/commentscollectionSpec.js44
-rw-r--r--apps/comments/tests/js/commentstabviewSpec.js42
7 files changed, 234 insertions, 11 deletions
diff --git a/apps/comments/appinfo/app.php b/apps/comments/appinfo/app.php
index c6f36567c51..a1eb4f6899d 100644
--- a/apps/comments/appinfo/app.php
+++ b/apps/comments/appinfo/app.php
@@ -27,6 +27,7 @@ $eventDispatcher->addListener(
\OCP\Util::addScript('comments', 'app');
\OCP\Util::addScript('comments', 'commentmodel');
\OCP\Util::addScript('comments', 'commentcollection');
+ \OCP\Util::addScript('comments', 'commentsummarymodel');
\OCP\Util::addScript('comments', 'commentstabview');
\OCP\Util::addScript('comments', 'filesplugin');
\OCP\Util::addStyle('comments', 'comments');
diff --git a/apps/comments/js/commentcollection.js b/apps/comments/js/commentcollection.js
index d10e5e00865..a15039cf484 100644
--- a/apps/comments/js/commentcollection.js
+++ b/apps/comments/js/commentcollection.js
@@ -10,8 +10,6 @@
(function(OC, OCA) {
- var NS_OWNCLOUD = 'http://owncloud.org/ns';
-
/**
* @class OCA.Comments.CommentCollection
* @classdesc
@@ -26,12 +24,40 @@
model: OCA.Comments.CommentModel,
+ /**
+ * Object type
+ *
+ * @type string
+ */
_objectType: 'files',
+
+ /**
+ * Object id
+ *
+ * @type string
+ */
_objectId: null,
+ /**
+ * True if there are no more page results left to fetch
+ *
+ * @type bool
+ */
_endReached: false,
+
+ /**
+ * Number of comments to fetch per page
+ *
+ * @type int
+ */
_limit : 20,
+ /**
+ * Initializes the collection
+ *
+ * @param {string} [options.objectType] object type
+ * @param {string} [options.objectId] object id
+ */
initialize: function(models, options) {
options = options || {};
if (options.objectType) {
@@ -58,6 +84,7 @@
reset: function() {
this._endReached = false;
+ this._summaryModel = null;
return OC.Backbone.Collection.prototype.reset.apply(this, arguments);
},
@@ -81,6 +108,7 @@
var success = options.success;
options = _.extend({
remove: false,
+ parse: true,
data: body,
davProperties: CommentCollection.prototype.model.prototype.davProperties,
success: function(resp) {
@@ -102,6 +130,35 @@
}, options);
return this.sync('REPORT', this, options);
+ },
+
+ /**
+ * Returns the matching summary model
+ *
+ * @return {OCA.Comments.CommentSummaryModel} summary model
+ */
+ getSummaryModel: function() {
+ if (!this._summaryModel) {
+ this._summaryModel = new OCA.Comments.CommentSummaryModel({
+ id: this._objectId,
+ objectType: this._objectType
+ });
+ }
+ return this._summaryModel;
+ },
+
+ /**
+ * Updates the read marker for this comment thread
+ *
+ * @param {Date} [date] optional date, defaults to now
+ * @param {Object} [options] backbone options
+ */
+ updateReadMarker: function(date, options) {
+ options = options || {};
+
+ return this.getSummaryModel().save({
+ readMarker: (date || new Date()).toUTCString()
+ }, options);
}
});
diff --git a/apps/comments/js/commentmodel.js b/apps/comments/js/commentmodel.js
index b945f71fdd2..ba04fd61de3 100644
--- a/apps/comments/js/commentmodel.js
+++ b/apps/comments/js/commentmodel.js
@@ -34,11 +34,12 @@
'actorDisplayName': '{' + NS_OWNCLOUD + '}actorDisplayName',
'creationDateTime': '{' + NS_OWNCLOUD + '}creationDateTime',
'objectType': '{' + NS_OWNCLOUD + '}objectType',
- 'objectId': '{' + NS_OWNCLOUD + '}objectId'
+ 'objectId': '{' + NS_OWNCLOUD + '}objectId',
+ 'isUnread': '{' + NS_OWNCLOUD + '}isUnread'
},
parse: function(data) {
- // TODO: parse non-string values
+ data.isUnread = (data.isUnread === 'true');
return data;
}
});
diff --git a/apps/comments/js/commentstabview.js b/apps/comments/js/commentstabview.js
index 463ac2d76ef..188d8c5943c 100644
--- a/apps/comments/js/commentstabview.js
+++ b/apps/comments/js/commentstabview.js
@@ -31,7 +31,7 @@
'<div class="loading hidden" style="height: 50px"></div>';
var COMMENT_TEMPLATE =
- '<li class="comment">' +
+ '<li class="comment{{#if isUnread}} unread{{/if}}" data-id="{{id}}">' +
' <div class="authorRow">' +
' {{#if avatarEnabled}}' +
' <div class="avatar" data-username="{{actorId}}"> </div>' +
@@ -97,12 +97,14 @@
setFileInfo: function(fileInfo) {
if (fileInfo) {
+ this.model = fileInfo;
this.render();
this.collection.setObjectId(fileInfo.id);
// reset to first page
this.collection.reset([], {silent: true});
this.nextPage();
} else {
+ this.model = null;
this.render();
this.collection.reset();
}
@@ -139,10 +141,29 @@
this.$el.find('.showMore').addClass('hidden');
},
- _onEndRequest: function() {
+ _onEndRequest: function(type) {
+ var fileInfoModel = this.model;
this._toggleLoading(false);
this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
this.$el.find('.showMore').toggleClass('hidden', !this.collection.hasMoreResults());
+
+ if (type !== 'REPORT') {
+ return;
+ }
+
+ // find first unread comment
+ var firstUnreadComment = this.collection.findWhere({isUnread: true});
+ if (firstUnreadComment) {
+ // update read marker
+ this.collection.updateReadMarker(
+ null,
+ {
+ success: function() {
+ fileInfoModel.set('commentsUnread', 0);
+ }
+ }
+ );
+ }
},
_onAddModel: function(model, collection, options) {
@@ -210,7 +231,7 @@
actorType: 'users',
verb: 'comment',
message: $textArea.val(),
- creationDateTime: (new Date()).getTime()
+ creationDateTime: (new Date()).toUTCString()
}, {
at: 0,
success: function() {
diff --git a/apps/comments/js/commentsummarymodel.js b/apps/comments/js/commentsummarymodel.js
new file mode 100644
index 00000000000..d405315ca1f
--- /dev/null
+++ b/apps/comments/js/commentsummarymodel.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function(OC, OCA) {
+ var NS_OWNCLOUD = 'http://owncloud.org/ns';
+ /**
+ * @class OCA.Comments.CommentSummaryModel
+ * @classdesc
+ *
+ * Model containing summary information related to comments
+ * like the read marker.
+ *
+ */
+ var CommentSummaryModel = OC.Backbone.Model.extend(
+ /** @lends OCA.Comments.CommentSummaryModel.prototype */ {
+ sync: OC.Backbone.davSync,
+
+ /**
+ * Object type
+ *
+ * @type string
+ */
+ _objectType: 'files',
+
+ /**
+ * Object id
+ *
+ * @type string
+ */
+ _objectId: null,
+
+ davProperties: {
+ 'readMarker': '{' + NS_OWNCLOUD + '}readMarker'
+ },
+
+ /**
+ * Initializes the summary model
+ *
+ * @param {string} [options.objectType] object type
+ * @param {string} [options.objectId] object id
+ */
+ initialize: function(attrs, options) {
+ options = options || {};
+ if (options.objectType) {
+ this._objectType = options.objectType;
+ }
+ },
+
+ url: function() {
+ return OC.linkToRemote('dav') + '/comments/' +
+ encodeURIComponent(this._objectType) + '/' +
+ encodeURIComponent(this.id) + '/';
+ }
+ });
+
+ OCA.Comments.CommentSummaryModel = CommentSummaryModel;
+})(OC, OCA);
+
diff --git a/apps/comments/tests/js/commentscollectionSpec.js b/apps/comments/tests/js/commentscollectionSpec.js
index 0dc68cc167c..2f41a272f67 100644
--- a/apps/comments/tests/js/commentscollectionSpec.js
+++ b/apps/comments/tests/js/commentscollectionSpec.js
@@ -100,5 +100,49 @@ describe('OCA.Comments.CommentCollection', function() {
expect(collection.hasMoreResults()).toEqual(true);
});
+ describe('resetting read marker', function() {
+ var updateStub;
+ var clock;
+
+ beforeEach(function() {
+ updateStub = sinon.stub(OCA.Comments.CommentSummaryModel.prototype, 'save');
+ clock = sinon.useFakeTimers(Date.UTC(2016, 1, 3, 10, 5, 9));
+ });
+ afterEach(function() {
+ updateStub.restore();
+ clock.restore();
+ });
+
+ it('resets read marker to the default date', function() {
+ var successStub = sinon.stub();
+ collection.updateReadMarker(null, {
+ success: successStub
+ });
+
+ expect(updateStub.calledOnce).toEqual(true);
+ expect(updateStub.lastCall.args[0]).toEqual({
+ readMarker: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
+ });
+
+ updateStub.yieldTo('success');
+
+ expect(successStub.calledOnce).toEqual(true);
+ });
+ it('resets read marker to the given date', function() {
+ var successStub = sinon.stub();
+ collection.updateReadMarker(new Date(Date.UTC(2016, 1, 2, 3, 4, 5)), {
+ success: successStub
+ });
+
+ expect(updateStub.calledOnce).toEqual(true);
+ expect(updateStub.lastCall.args[0]).toEqual({
+ readMarker: new Date(Date.UTC(2016, 1, 2, 3, 4, 5)).toUTCString()
+ });
+
+ updateStub.yieldTo('success');
+
+ expect(successStub.calledOnce).toEqual(true);
+ });
+ });
});
diff --git a/apps/comments/tests/js/commentstabviewSpec.js b/apps/comments/tests/js/commentstabviewSpec.js
index 0fb5eec0653..432fa5ddc4c 100644
--- a/apps/comments/tests/js/commentstabviewSpec.js
+++ b/apps/comments/tests/js/commentstabviewSpec.js
@@ -48,7 +48,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'First',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 5, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 0)).toUTCString()
});
var comment2 = new OCA.Comments.CommentModel({
id: 2,
@@ -58,7 +58,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'Second\nNewline',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 0, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 0, 0)).toUTCString()
});
testComments = [comment1, comment2];
@@ -142,7 +142,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
objectType: 'files',
objectId: 5,
message: 'Third',
- creationDateTime: Date.UTC(2016, 1, 3, 5, 0, 0)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 5, 0, 0)).toUTCString()
});
view.collection.add(comment3);
@@ -184,7 +184,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
actorType: 'users',
verb: 'comment',
message: 'New message',
- creationDateTime: Date.UTC(2016, 1, 3, 10, 5, 9)
+ creationDateTime: new Date(Date.UTC(2016, 1, 3, 10, 5, 9)).toUTCString()
});
});
it('does not create a comment if the field is empty', function() {
@@ -195,4 +195,38 @@ describe('OCA.Comments.CommentsTabView tests', function() {
});
});
+ describe('read marker', function() {
+ var updateMarkerStub;
+
+ beforeEach(function() {
+ updateMarkerStub = sinon.stub(OCA.Comments.CommentCollection.prototype, 'updateReadMarker');
+ });
+ afterEach(function() {
+ updateMarkerStub.restore();
+ });
+
+ it('resets the read marker after REPORT', function() {
+ testComments[0].set('isUnread', true, {silent: true});
+ testComments[1].set('isUnread', true, {silent: true});
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'REPORT');
+
+ expect(updateMarkerStub.calledOnce).toEqual(true);
+ expect(updateMarkerStub.lastCall.args[0]).toBeFalsy();
+ });
+ it('does not reset the read marker if there was no unread comments', function() {
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'REPORT');
+
+ expect(updateMarkerStub.notCalled).toEqual(true);
+ });
+ it('does not reset the read marker when posting comments', function() {
+ testComments[0].set('isUnread', true, {silent: true});
+ testComments[1].set('isUnread', true, {silent: true});
+ view.collection.set(testComments);
+ view.collection.trigger('sync', 'POST');
+
+ expect(updateMarkerStub.notCalled).toEqual(true);
+ });
+ });
});