Merge pull request #22101 from owncloud/comments-filerow
Add file row indicator for unread comments
This commit is contained in:
commit
da04620155
|
@ -27,6 +27,7 @@ $eventDispatcher->addListener(
|
||||||
\OCP\Util::addScript('comments', 'app');
|
\OCP\Util::addScript('comments', 'app');
|
||||||
\OCP\Util::addScript('comments', 'commentmodel');
|
\OCP\Util::addScript('comments', 'commentmodel');
|
||||||
\OCP\Util::addScript('comments', 'commentcollection');
|
\OCP\Util::addScript('comments', 'commentcollection');
|
||||||
|
\OCP\Util::addScript('comments', 'commentsummarymodel');
|
||||||
\OCP\Util::addScript('comments', 'commentstabview');
|
\OCP\Util::addScript('comments', 'commentstabview');
|
||||||
\OCP\Util::addScript('comments', 'filesplugin');
|
\OCP\Util::addScript('comments', 'filesplugin');
|
||||||
\OCP\Util::addStyle('comments', 'comments');
|
\OCP\Util::addStyle('comments', 'comments');
|
||||||
|
|
|
@ -49,3 +49,7 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-files .action-comment>img {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@
|
||||||
|
|
||||||
(function(OC, OCA) {
|
(function(OC, OCA) {
|
||||||
|
|
||||||
var NS_OWNCLOUD = 'http://owncloud.org/ns';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class OCA.Comments.CommentCollection
|
* @class OCA.Comments.CommentCollection
|
||||||
* @classdesc
|
* @classdesc
|
||||||
|
@ -26,12 +24,40 @@
|
||||||
|
|
||||||
model: OCA.Comments.CommentModel,
|
model: OCA.Comments.CommentModel,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object type
|
||||||
|
*
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
_objectType: 'files',
|
_objectType: 'files',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object id
|
||||||
|
*
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
_objectId: null,
|
_objectId: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if there are no more page results left to fetch
|
||||||
|
*
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
_endReached: false,
|
_endReached: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of comments to fetch per page
|
||||||
|
*
|
||||||
|
* @type int
|
||||||
|
*/
|
||||||
_limit : 20,
|
_limit : 20,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the collection
|
||||||
|
*
|
||||||
|
* @param {string} [options.objectType] object type
|
||||||
|
* @param {string} [options.objectId] object id
|
||||||
|
*/
|
||||||
initialize: function(models, options) {
|
initialize: function(models, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
if (options.objectType) {
|
if (options.objectType) {
|
||||||
|
@ -58,6 +84,7 @@
|
||||||
|
|
||||||
reset: function() {
|
reset: function() {
|
||||||
this._endReached = false;
|
this._endReached = false;
|
||||||
|
this._summaryModel = null;
|
||||||
return OC.Backbone.Collection.prototype.reset.apply(this, arguments);
|
return OC.Backbone.Collection.prototype.reset.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -81,6 +108,7 @@
|
||||||
var success = options.success;
|
var success = options.success;
|
||||||
options = _.extend({
|
options = _.extend({
|
||||||
remove: false,
|
remove: false,
|
||||||
|
parse: true,
|
||||||
data: body,
|
data: body,
|
||||||
davProperties: CommentCollection.prototype.model.prototype.davProperties,
|
davProperties: CommentCollection.prototype.model.prototype.davProperties,
|
||||||
success: function(resp) {
|
success: function(resp) {
|
||||||
|
@ -102,6 +130,35 @@
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
return this.sync('REPORT', this, 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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -34,11 +34,12 @@
|
||||||
'actorDisplayName': '{' + NS_OWNCLOUD + '}actorDisplayName',
|
'actorDisplayName': '{' + NS_OWNCLOUD + '}actorDisplayName',
|
||||||
'creationDateTime': '{' + NS_OWNCLOUD + '}creationDateTime',
|
'creationDateTime': '{' + NS_OWNCLOUD + '}creationDateTime',
|
||||||
'objectType': '{' + NS_OWNCLOUD + '}objectType',
|
'objectType': '{' + NS_OWNCLOUD + '}objectType',
|
||||||
'objectId': '{' + NS_OWNCLOUD + '}objectId'
|
'objectId': '{' + NS_OWNCLOUD + '}objectId',
|
||||||
|
'isUnread': '{' + NS_OWNCLOUD + '}isUnread'
|
||||||
},
|
},
|
||||||
|
|
||||||
parse: function(data) {
|
parse: function(data) {
|
||||||
// TODO: parse non-string values
|
data.isUnread = (data.isUnread === 'true');
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
'<div class="loading hidden" style="height: 50px"></div>';
|
'<div class="loading hidden" style="height: 50px"></div>';
|
||||||
|
|
||||||
var COMMENT_TEMPLATE =
|
var COMMENT_TEMPLATE =
|
||||||
'<li class="comment">' +
|
'<li class="comment{{#if isUnread}} unread{{/if}}" data-id="{{id}}">' +
|
||||||
' <div class="authorRow">' +
|
' <div class="authorRow">' +
|
||||||
' {{#if avatarEnabled}}' +
|
' {{#if avatarEnabled}}' +
|
||||||
' <div class="avatar" data-username="{{actorId}}"> </div>' +
|
' <div class="avatar" data-username="{{actorId}}"> </div>' +
|
||||||
|
@ -97,12 +97,14 @@
|
||||||
|
|
||||||
setFileInfo: function(fileInfo) {
|
setFileInfo: function(fileInfo) {
|
||||||
if (fileInfo) {
|
if (fileInfo) {
|
||||||
|
this.model = fileInfo;
|
||||||
this.render();
|
this.render();
|
||||||
this.collection.setObjectId(fileInfo.id);
|
this.collection.setObjectId(fileInfo.id);
|
||||||
// reset to first page
|
// reset to first page
|
||||||
this.collection.reset([], {silent: true});
|
this.collection.reset([], {silent: true});
|
||||||
this.nextPage();
|
this.nextPage();
|
||||||
} else {
|
} else {
|
||||||
|
this.model = null;
|
||||||
this.render();
|
this.render();
|
||||||
this.collection.reset();
|
this.collection.reset();
|
||||||
}
|
}
|
||||||
|
@ -139,10 +141,29 @@
|
||||||
this.$el.find('.showMore').addClass('hidden');
|
this.$el.find('.showMore').addClass('hidden');
|
||||||
},
|
},
|
||||||
|
|
||||||
_onEndRequest: function() {
|
_onEndRequest: function(type) {
|
||||||
|
var fileInfoModel = this.model;
|
||||||
this._toggleLoading(false);
|
this._toggleLoading(false);
|
||||||
this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
|
this.$el.find('.empty').toggleClass('hidden', !!this.collection.length);
|
||||||
this.$el.find('.showMore').toggleClass('hidden', !this.collection.hasMoreResults());
|
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) {
|
_onAddModel: function(model, collection, options) {
|
||||||
|
@ -210,7 +231,7 @@
|
||||||
actorType: 'users',
|
actorType: 'users',
|
||||||
verb: 'comment',
|
verb: 'comment',
|
||||||
message: $textArea.val(),
|
message: $textArea.val(),
|
||||||
creationDateTime: (new Date()).getTime()
|
creationDateTime: (new Date()).toUTCString()
|
||||||
}, {
|
}, {
|
||||||
at: 0,
|
at: 0,
|
||||||
success: function() {
|
success: function() {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -8,7 +8,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global Handlebars */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
var TEMPLATE_COMMENTS_UNREAD =
|
||||||
|
'<a class="action action-comment permanent" title="{{countMessage}}" href="#">' +
|
||||||
|
'<img class="svg" src="{{iconUrl}}"/>' +
|
||||||
|
'{{count}}' +
|
||||||
|
'</a>';
|
||||||
|
|
||||||
OCA.Comments = _.extend({}, OCA.Comments);
|
OCA.Comments = _.extend({}, OCA.Comments);
|
||||||
if (!OCA.Comments) {
|
if (!OCA.Comments) {
|
||||||
/**
|
/**
|
||||||
|
@ -26,12 +34,88 @@
|
||||||
'favorites'
|
'favorites'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
_formatCommentCount: function(count) {
|
||||||
|
if (!this._commentsUnreadTemplate) {
|
||||||
|
this._commentsUnreadTemplate = Handlebars.compile(TEMPLATE_COMMENTS_UNREAD);
|
||||||
|
}
|
||||||
|
return this._commentsUnreadTemplate({
|
||||||
|
count: count,
|
||||||
|
countMessage: t('comments', '{count} unread comments', {count: count}),
|
||||||
|
iconUrl: OC.imagePath('core', 'actions/comment')
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
attach: function(fileList) {
|
attach: function(fileList) {
|
||||||
|
var self = this;
|
||||||
if (this.allowedLists.indexOf(fileList.id) < 0) {
|
if (this.allowedLists.indexOf(fileList.id) < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileList.registerTabView(new OCA.Comments.CommentsTabView('commentsTabView'));
|
fileList.registerTabView(new OCA.Comments.CommentsTabView('commentsTabView'));
|
||||||
|
|
||||||
|
var NS_OC = 'http://owncloud.org/ns';
|
||||||
|
|
||||||
|
var oldGetWebdavProperties = fileList._getWebdavProperties;
|
||||||
|
fileList._getWebdavProperties = function() {
|
||||||
|
var props = oldGetWebdavProperties.apply(this, arguments);
|
||||||
|
props.push('{' + NS_OC + '}comments-unread');
|
||||||
|
return props;
|
||||||
|
};
|
||||||
|
|
||||||
|
fileList.filesClient.addFileInfoParser(function(response) {
|
||||||
|
var data = {};
|
||||||
|
var props = response.propStat[0].properties;
|
||||||
|
var commentsUnread = props['{' + NS_OC + '}comments-unread'];
|
||||||
|
if (!_.isUndefined(commentsUnread) && commentsUnread !== '') {
|
||||||
|
data.commentsUnread = parseInt(commentsUnread, 10);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
|
fileList.$el.addClass('has-comments');
|
||||||
|
var oldCreateRow = fileList._createRow;
|
||||||
|
fileList._createRow = function(fileData) {
|
||||||
|
var $tr = oldCreateRow.apply(this, arguments);
|
||||||
|
if (fileData.commentsUnread) {
|
||||||
|
$tr.attr('data-comments-unread', fileData.commentsUnread);
|
||||||
|
}
|
||||||
|
return $tr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// register "comment" action for reading comments
|
||||||
|
fileList.fileActions.registerAction({
|
||||||
|
name: 'Comment',
|
||||||
|
displayName: t('comments', 'Comment'),
|
||||||
|
mime: 'all',
|
||||||
|
permissions: OC.PERMISSION_READ,
|
||||||
|
type: OCA.Files.FileActions.TYPE_INLINE,
|
||||||
|
render: function(actionSpec, isDefault, context) {
|
||||||
|
var $file = context.$file;
|
||||||
|
var unreadComments = $file.data('comments-unread');
|
||||||
|
if (unreadComments) {
|
||||||
|
var $actionLink = $(self._formatCommentCount(unreadComments));
|
||||||
|
context.$file.find('a.name>span.fileactions').append($actionLink);
|
||||||
|
return $actionLink;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
actionHandler: function(fileName, context) {
|
||||||
|
context.$file.find('.action-comment').tooltip('hide');
|
||||||
|
// open sidebar in comments section
|
||||||
|
context.fileList.showDetailsView(fileName, 'commentsTabView');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// add attribute to "elementToFile"
|
||||||
|
var oldElementToFile = fileList.elementToFile;
|
||||||
|
fileList.elementToFile = function($el) {
|
||||||
|
var fileInfo = oldElementToFile.apply(this, arguments);
|
||||||
|
var commentsUnread = $el.data('comments-unread');
|
||||||
|
if (commentsUnread) {
|
||||||
|
fileInfo.commentsUnread = commentsUnread;
|
||||||
|
}
|
||||||
|
return fileInfo;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,5 +100,49 @@ describe('OCA.Comments.CommentCollection', function() {
|
||||||
|
|
||||||
expect(collection.hasMoreResults()).toEqual(true);
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
||||||
objectType: 'files',
|
objectType: 'files',
|
||||||
objectId: 5,
|
objectId: 5,
|
||||||
message: 'First',
|
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({
|
var comment2 = new OCA.Comments.CommentModel({
|
||||||
id: 2,
|
id: 2,
|
||||||
|
@ -58,7 +58,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
||||||
objectType: 'files',
|
objectType: 'files',
|
||||||
objectId: 5,
|
objectId: 5,
|
||||||
message: 'Second\nNewline',
|
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];
|
testComments = [comment1, comment2];
|
||||||
|
@ -142,7 +142,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
||||||
objectType: 'files',
|
objectType: 'files',
|
||||||
objectId: 5,
|
objectId: 5,
|
||||||
message: 'Third',
|
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);
|
view.collection.add(comment3);
|
||||||
|
@ -184,7 +184,7 @@ describe('OCA.Comments.CommentsTabView tests', function() {
|
||||||
actorType: 'users',
|
actorType: 'users',
|
||||||
verb: 'comment',
|
verb: 'comment',
|
||||||
message: 'New message',
|
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() {
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Vincent Petry <pvince81@owncloud.com>
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3
|
||||||
|
* or later.
|
||||||
|
*
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('OCA.Comments.FilesPlugin tests', function() {
|
||||||
|
var fileList;
|
||||||
|
var testFiles;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
var $content = $('<div id="content"></div>');
|
||||||
|
$('#testArea').append($content);
|
||||||
|
// dummy file list
|
||||||
|
var $div = $(
|
||||||
|
'<div>' +
|
||||||
|
'<table id="filestable">' +
|
||||||
|
'<thead></thead>' +
|
||||||
|
'<tbody id="fileList"></tbody>' +
|
||||||
|
'</table>' +
|
||||||
|
'</div>');
|
||||||
|
$('#content').append($div);
|
||||||
|
|
||||||
|
fileList = new OCA.Files.FileList($div);
|
||||||
|
OCA.Comments.FilesPlugin.attach(fileList);
|
||||||
|
|
||||||
|
testFiles = [{
|
||||||
|
id: 1,
|
||||||
|
type: 'file',
|
||||||
|
name: 'One.txt',
|
||||||
|
path: '/subdir',
|
||||||
|
mimetype: 'text/plain',
|
||||||
|
size: 12,
|
||||||
|
permissions: OC.PERMISSION_ALL,
|
||||||
|
etag: 'abc',
|
||||||
|
shareOwner: 'User One',
|
||||||
|
isShareMountPoint: false,
|
||||||
|
commentsUnread: 3
|
||||||
|
}];
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
fileList.destroy();
|
||||||
|
fileList = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Comment icon', function() {
|
||||||
|
it('does not render icon when no unread comments available', function() {
|
||||||
|
testFiles[0].commentsUnread = 0;
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
var $tr = fileList.findFileEl('One.txt');
|
||||||
|
expect($tr.find('.action-comment').length).toEqual(0);
|
||||||
|
});
|
||||||
|
it('renders comment icon and extra data', function() {
|
||||||
|
var $action, $tr;
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
$tr = fileList.findFileEl('One.txt');
|
||||||
|
$action = $tr.find('.action-comment');
|
||||||
|
expect($action.length).toEqual(1);
|
||||||
|
expect($action.hasClass('permanent')).toEqual(true);
|
||||||
|
|
||||||
|
expect($tr.attr('data-comments-unread')).toEqual('3');
|
||||||
|
});
|
||||||
|
it('clicking icon opens sidebar', function() {
|
||||||
|
var sidebarStub = sinon.stub(fileList, 'showDetailsView');
|
||||||
|
var $action, $tr;
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
$tr = fileList.findFileEl('One.txt');
|
||||||
|
$action = $tr.find('.action-comment');
|
||||||
|
$action.click();
|
||||||
|
|
||||||
|
expect(sidebarStub.calledOnce).toEqual(true);
|
||||||
|
expect(sidebarStub.lastCall.args[0]).toEqual('One.txt');
|
||||||
|
expect(sidebarStub.lastCall.args[1]).toEqual('commentsTabView');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('elementToFile', function() {
|
||||||
|
it('returns comment count', function() {
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
var $tr = fileList.findFileEl('One.txt');
|
||||||
|
var data = fileList.elementToFile($tr);
|
||||||
|
expect(data.commentsUnread).toEqual(3);
|
||||||
|
});
|
||||||
|
it('does not set comment count when not set', function() {
|
||||||
|
delete testFiles[0].commentsUnread;
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
var $tr = fileList.findFileEl('One.txt');
|
||||||
|
var data = fileList.elementToFile($tr);
|
||||||
|
expect(data.commentsUnread).not.toBeDefined();
|
||||||
|
});
|
||||||
|
it('does not set comment count when zero', function() {
|
||||||
|
testFiles[0].commentsUnread = 0;
|
||||||
|
fileList.setFiles(testFiles);
|
||||||
|
var $tr = fileList.findFileEl('One.txt');
|
||||||
|
var data = fileList.elementToFile($tr);
|
||||||
|
expect(data.commentsUnread).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Binary file not shown.
After Width: | Height: | Size: 169 B |
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.0" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||||
|
<path style="color:#000000;block-progression:tb;text-transform:none;text-indent:0" d="m2.3496 1.002c-0.1975 0.0382-0.3531 0.2333-0.3496 0.4375v13.122c0 0.23 0.2061 0.438 0.4316 0.438h11.138c0.226 0 0.432-0.208 0.432-0.438v-10.142c-0.004-0.0669-0.023-0.133-0.055-0.1915l-3.312-3.1992c-0.043-0.0164-0.089-0.0255-0.135-0.0273h-8.0684c-0.0268-0.00265-0.0552-0.00265-0.082 0zm1.6504 1.998h6v1h-6v-1zm0 3h5v1h-5v-1zm0 3h8v1h-8v-1zm0 3h4v1h-4v-1z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 726 B |
|
@ -89,8 +89,9 @@ module.exports = function(config) {
|
||||||
'apps/comments/js/app.js',
|
'apps/comments/js/app.js',
|
||||||
'apps/comments/js/commentmodel.js',
|
'apps/comments/js/commentmodel.js',
|
||||||
'apps/comments/js/commentcollection.js',
|
'apps/comments/js/commentcollection.js',
|
||||||
|
'apps/comments/js/commentsummarymodel.js',
|
||||||
'apps/comments/js/commentstabview.js',
|
'apps/comments/js/commentstabview.js',
|
||||||
'apps/comments/js/filesplugin'
|
'apps/comments/js/filesplugin.js'
|
||||||
],
|
],
|
||||||
testFiles: ['apps/comments/tests/js/**/*.js']
|
testFiles: ['apps/comments/tests/js/**/*.js']
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue