Enable activity pagination

stable
Daniel García 2018-10-17 18:17:55 +02:00 committed by Alex Hermida
parent 27a69dc79a
commit 87fc89a84e
18 changed files with 330 additions and 266 deletions

View File

@ -148,7 +148,7 @@ urls = {
"history/us": "/history/userstory" "history/us": "/history/userstory"
"history/issue": "/history/issue" "history/issue": "/history/issue"
"history/task": "/history/task" "history/task": "/history/task"
"history/wiki": "/history/wiki/%s" "history/wiki": "/history/wiki"
# Attachments # Attachments
"attachments/epic": "/epics/attachments" "attachments/epic": "/epics/attachments"

View File

@ -213,7 +213,7 @@ WikiSummaryDirective = ($log, $template, $compile, $translate, avatarService) ->
module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translate", "tgAvatarService", WikiSummaryDirective]) module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translate", "tgAvatarService", WikiSummaryDirective])
WikiWysiwyg = ($modelTransform, $rootscope, $confirm, attachmentsFullService, WikiWysiwyg = ($modelTransform, $rootscope, $confirm, attachmentsFullService,
$qqueue, $repo, $analytics, wikiHistoryService) -> $qqueue, $repo, $analytics, activityService) ->
link = ($scope, $el, $attrs) -> link = ($scope, $el, $attrs) ->
$scope.editableDescription = false $scope.editableDescription = false
@ -223,7 +223,7 @@ $qqueue, $repo, $analytics, wikiHistoryService) ->
$analytics.trackEvent("wikipage", "create", "create wiki page", 1) $analytics.trackEvent("wikipage", "create", "create wiki page", 1)
$scope.$emit("wikipage:add") $scope.$emit("wikipage:add")
wikiHistoryService.loadHistoryEntries() activityService.fetchEntries(true)
$confirm.notify("success") $confirm.notify("success")
onError = -> onError = ->
@ -290,5 +290,5 @@ module.directive("tgWikiWysiwyg", [
"$rootScope", "$rootScope",
"$tgConfirm", "$tgConfirm",
"tgAttachmentsFullService", "tgAttachmentsFullService",
"$tgQqueue", "$tgRepo", "$tgAnalytics", "tgWikiHistoryService" "$tgQqueue", "$tgRepo", "$tgAnalytics", "tgActivityService"
WikiWysiwyg]) WikiWysiwyg])

View File

@ -23,11 +23,12 @@ CommentWysiwyg = ($modelTransform, $rootscope, $confirm, attachmentsFullService)
$scope.saveComment = (description, cb) -> $scope.saveComment = (description, cb) ->
$scope.content = '' $scope.content = ''
$scope.vm.type.comment = description $scope.type.comment = description
transform = $modelTransform.save (item) -> return transform = $modelTransform.save (item) -> return
transform.then -> transform.then ->
$rootscope.$broadcast("object:updated") if $scope.onAddComment
$scope.onAddComment()
transform.finally(cb) transform.finally(cb)
types = { types = {
@ -38,11 +39,11 @@ CommentWysiwyg = ($modelTransform, $rootscope, $confirm, attachmentsFullService)
} }
uploadFile = (file, cb) -> uploadFile = (file, cb) ->
return attachmentsFullService.addAttachment($scope.vm.projectId, $scope.vm.type.id, types[$scope.vm.type._name], file, true, true).then (result) -> return attachmentsFullService.addAttachment($scope.vm.projectId, $scope.type.id, types[$scope.type._name], file, true, true).then (result) ->
cb(result.getIn(['file', 'name']), result.getIn(['file', 'url'])) cb(result.getIn(['file', 'name']), result.getIn(['file', 'url']))
$scope.onChange = (markdown) -> $scope.onChange = (markdown) ->
$scope.vm.type.comment = markdown $scope.type.comment = markdown
$scope.uploadFiles = (files, cb) -> $scope.uploadFiles = (files, cb) ->
for file in files for file in files
@ -50,13 +51,16 @@ CommentWysiwyg = ($modelTransform, $rootscope, $confirm, attachmentsFullService)
$scope.content = '' $scope.content = ''
$scope.$watch "vm.type", (value) -> $scope.$watch "type", (value) ->
return if not value return if not value
$scope.storageKey = "comment-" + value.project + "-" + value.id + "-" + value._name $scope.storageKey = "comment-" + value.project + "-" + value.id + "-" + value._name
return { return {
scope: true, scope: {
type: '=',
onAddComment: '&'
},
link: link, link: link,
template: """ template: """
<div> <div>

View File

@ -0,0 +1,72 @@
###
# Copyright (C) 2014-2018 Taiga Agile LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: history/activity/activity.service.coffee
###
taiga = @.taiga
class ActivityService
@.$inject = [
'tgResources',
'tgXhrErrorService'
]
constructor: (@rs, @xhrError) ->
@._contentType = null
@._objectId = null
@.clear()
clear: () ->
@.page = 1
@.loadingEntries = false
@.disablePagination = false
@.entries = Immutable.List()
@.count = null
fetchEntries: (reset = false) ->
if reset
@.page = 1
@.loadingEntries = true
@.disablePagination = true
return @rs.history.getHistory('activity', @._contentType, @._objectId, @.page)
.then (result) =>
if reset
@.clear()
@.entries = result.list
else
@.entries = @.entries.concat(result.list)
@.loadingEntries = false
@.disablePagination = !result.headers('x-pagination-next')
@.count = result.headers('x-pagination-count')
return @.entries
.catch (xhr) =>
@xhrError.response(@.entries)
nextPage: (historyType = 'comment') ->
@.page++
@.fetchEntries()
init: (contentType, objectId) ->
@._contentType = contentType
@._objectId = objectId
@.clear()
angular.module('taigaHistory').service('tgActivityService', ActivityService)

View File

@ -0,0 +1,96 @@
###
# Copyright (C) 2014-2018 Taiga Agile LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: history/activity/activity.service.spec.coffee
###
describe "tgActivityService", ->
$provide = null
activityService = null
mocks = {}
_mockTgResources = () ->
mocks.tgResources = {
history: {
getHistory: sinon.stub()
}
}
$provide.value("tgResources", mocks.tgResources)
_mockXhrErrorService = () ->
mocks.xhrErrorService = {
response: sinon.stub()
}
$provide.value "tgXhrErrorService", mocks.xhrErrorService
_mocks = ->
module (_$provide_) ->
$provide = _$provide_
_mockTgResources()
_mockXhrErrorService()
return null
_inject = ->
inject (_tgActivityService_) ->
activityService = _tgActivityService_
_setup = ->
_mocks()
_inject()
beforeEach ->
module "taigaHistory"
_setup()
fixtures = {
contentType: 'foo',
objId: 43,
page: 1,
response: {
headers: sinon.stub()
list: Immutable.List([
{id: 1, name: 'history entry 1'},
{id: 2, name: 'history entry 2'},
{id: 3, name: 'history entry 3'},
])
}
}
it "populate history entries", (done) ->
f = fixtures
mocks.tgResources.history.getHistory.withArgs('activity', f.contentType, f.objId, f.page)
.promise().resolve(f.response)
activityService.init(f.contentType, f.objId)
expect(activityService._objectId).to.be.equal(f.objId)
expect(activityService.entries.size).to.be.equal(0)
activityService.fetchEntries().then () ->
expect(activityService.entries.size).to.be.equal(3)
done()
it "reset history entries if objectId change", () ->
f = fixtures
activityService.entries = f.response.list
expect(activityService.entries.size).to.be.equal(3)
activityService.init(f.contentType, f.objId + 1)
expect(activityService.entries.size).to.be.equal(0)

View File

@ -18,6 +18,6 @@ section.comments
tg-comment-wysiwyg( tg-comment-wysiwyg(
tg-check-permission="{{::vm.canAddCommentPermission}}" tg-check-permission="{{::vm.canAddCommentPermission}}"
on-update="updateComment(text)" on-add-comment="vm.onAddComment()"
type="vm.type" type="vm.type"
) )

View File

@ -25,30 +25,42 @@ class HistorySectionController
"$tgRepo", "$tgRepo",
"$tgStorage", "$tgStorage",
"tgProjectService", "tgProjectService",
"tgActivityService"
] ]
constructor: (@rs, @repo, @storage, @projectService) -> constructor: (@rs, @repo, @storage, @projectService, @activityService) ->
@.editing = null @.editing = null
@.deleting = null @.deleting = null
@.editMode = {} @.editMode = {}
@.viewComments = true @.viewComments = true
@.reverse = @storage.get("orderComments") @.reverse = @storage.get("orderComments")
@._loadHistory()
taiga.defineImmutableProperty @, 'disabledActivityPagination', () =>
return @activityService.disablePagination
taiga.defineImmutableProperty @, 'loadingActivity', () =>
return @activityService.loading
_loadHistory: () -> _loadHistory: () ->
@rs.history.get(@.name, @.id).then (history) => @._loadComments()
@._getComments(history) @._loadActivity()
@._getActivities(history)
_getComments: (comments) -> _loadActivity: () ->
@activityService.init(@.name, @.id)
@activityService.fetchEntries().then (response) =>
@.activitiesNum = @activityService.count
@.activities = response.toJS()
_loadComments: () ->
@rs.history.get(@.name, @.id).then (comments) =>
@.comments = _.filter(comments, (item) -> item.comment != "") @.comments = _.filter(comments, (item) -> item.comment != "")
if @.reverse if @.reverse
@.comments - _.reverse(@.comments) @.comments - _.reverse(@.comments)
@.commentsNum = @.comments.length @.commentsNum = @.comments.length
_getActivities: (activities) -> nextActivityPage: () ->
@.activities = _.filter(activities, (item) -> Object.keys(item.values_diff).length > 0) @activityService.nextPage().then (response) =>
@.activitiesNum = @.activities.length @.activities = response.toJS()
showHistorySection: () -> showHistorySection: () ->
return @.showCommentTab() or @.showActivityTab() return @.showCommentTab() or @.showActivityTab()
@ -71,7 +83,7 @@ class HistorySectionController
activityId = commentId activityId = commentId
@.deleting = commentId @.deleting = commentId
return @rs.history.deleteComment(type, objectId, activityId).then => return @rs.history.deleteComment(type, objectId, activityId).then =>
@._loadHistory() @._loadComments()
@.deleting = null @.deleting = null
editComment: (commentId, comment) -> editComment: (commentId, comment) ->
@ -80,7 +92,7 @@ class HistorySectionController
activityId = commentId activityId = commentId
@.editing = commentId @.editing = commentId
return @rs.history.editComment(type, objectId, activityId, comment).then => return @rs.history.editComment(type, objectId, activityId, comment).then =>
@._loadHistory() @._loadComments()
@.toggleEditMode(commentId) @.toggleEditMode(commentId)
@.editing = null @.editing = null
@ -90,17 +102,17 @@ class HistorySectionController
activityId = commentId activityId = commentId
@.editing = commentId @.editing = commentId
return @rs.history.undeleteComment(type, objectId, activityId).then => return @rs.history.undeleteComment(type, objectId, activityId).then =>
@._loadHistory() @._loadComments()
@.editing = null @.editing = null
addComment: (cb) -> addComment: () ->
return @repo.save(@.type).then => @.editMode = {}
@._loadHistory() @.editing = null
cb() @._loadComments()
onOrderComments: () -> onOrderComments: () ->
@.reverse = !@.reverse @.reverse = !@.reverse
@storage.set("orderComments", @.reverse) @storage.set("orderComments", @.reverse)
@._loadHistory() @._loadComments()
module.controller("HistorySection", HistorySectionController) module.controller("HistorySection", HistorySectionController)

View File

@ -54,6 +54,14 @@ describe "HistorySection", ->
} }
provide.value "tgProjectService", mocks.tgProjectService provide.value "tgProjectService", mocks.tgProjectService
_mockTgActivityService = () ->
mocks.tgActivityService = {
init: sinon.stub()
fetchEntries: sinon.stub()
count: null
}
provide.value "tgActivityService", mocks.tgActivityService
_mocks = () -> _mocks = () ->
module ($provide) -> module ($provide) ->
provide = $provide provide = $provide
@ -61,6 +69,7 @@ describe "HistorySection", ->
_mockTgRepo() _mockTgRepo()
_mocktgStorage() _mocktgStorage()
_mockTgProjectService() _mockTgProjectService()
_mockTgActivityService()
return null return null
beforeEach -> beforeEach ->
@ -70,61 +79,57 @@ describe "HistorySection", ->
inject ($controller) -> inject ($controller) ->
controller = $controller controller = $controller
promise = mocks.tgResources.history.get.promise().resolve() mocks.tgResources.history.get.promise().resolve()
mocks.tgActivityService.fetchEntries.promise().resolve()
it "load historic", (done) -> it "load historic", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._getComments = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl._getActivities = sinon.stub() historyCtrl._loadActivity = sinon.stub()
name = "name" historyCtrl._loadHistory()
id = 4 expect(historyCtrl._loadComments).have.been.called
expect(historyCtrl._loadActivity).have.been.called
promise = mocks.tgResources.history.get.withArgs(name, id).promise().resolve()
historyCtrl._loadHistory().then (data) ->
expect(historyCtrl._getComments).have.been.calledWith(data)
expect(historyCtrl._getActivities).have.been.calledWith(data)
done()
it "get Comments older first", () -> it "get Comments older first", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl.name = 'foo'
comments = ['comment3', 'comment2', 'comment1'] historyCtrl.id = 3
historyCtrl.reverse = false historyCtrl.reverse = false
historyCtrl._getComments(comments) comments = ['comment3', 'comment2', 'comment1']
mocks.tgResources.history.get.withArgs('foo', 3).promise().resolve(comments)
historyCtrl._loadComments().then () ->
expect(historyCtrl.comments).to.be.eql(['comment3', 'comment2', 'comment1']) expect(historyCtrl.comments).to.be.eql(['comment3', 'comment2', 'comment1'])
expect(historyCtrl.commentsNum).to.be.equal(3) expect(historyCtrl.commentsNum).to.be.equal(3)
it "get Comments newer first", () -> it "get Comments newer first", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl.name = 'foo'
comments = ['comment3', 'comment2', 'comment1'] historyCtrl.id = 3
historyCtrl.reverse = true historyCtrl.reverse = true
historyCtrl._getComments(comments) comments = ['comment3', 'comment2', 'comment1']
mocks.tgResources.history.get.withArgs('foo', 3).promise().resolve(comments)
historyCtrl._loadComments().then () ->
expect(historyCtrl.comments).to.be.eql(['comment1', 'comment2', 'comment3']) expect(historyCtrl.comments).to.be.eql(['comment1', 'comment2', 'comment3'])
expect(historyCtrl.commentsNum).to.be.equal(3) expect(historyCtrl.commentsNum).to.be.equal(3)
it "get activities", () -> it "get activities", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
activities = {
'activity1': {
'values_diff': {"k1": [0, 1]}
},
'activity2': {
'values_diff': {"k2": [0, 1]}
},
'activity3': {
'values_diff': {"k3": [0, 1]}
},
}
historyCtrl._getActivities(activities) activities = Immutable.List([
{id: 1, name: 'history entry 1'},
{id: 2, name: 'history entry 2'},
{id: 3, name: 'history entry 3'},
])
mocks.tgActivityService.fetchEntries.withArgs().promise().resolve(activities)
historyCtrl.activities = activities historyCtrl._loadActivity().then () ->
expect(historyCtrl.activitiesNum).to.be.equal(3) expect(historyCtrl.activities.length).to.be.equal(3)
it "on active history tab", () -> it "on active history tab", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
@ -140,7 +145,7 @@ describe "HistorySection", ->
it "delete comment", () -> it "delete comment", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._loadHistory = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl.name = "type" historyCtrl.name = "type"
historyCtrl.id = 1 historyCtrl.id = 1
@ -149,7 +154,8 @@ describe "HistorySection", ->
objectId = historyCtrl.id objectId = historyCtrl.id
commentId = 7 commentId = 7
deleteCommentPromise = mocks.tgResources.history.deleteComment.withArgs(type, objectId, commentId).promise() deleteCommentPromise = mocks.tgResources.history.deleteComment
.withArgs(type, objectId, commentId).promise()
ctrlPromise = historyCtrl.deleteComment(commentId) ctrlPromise = historyCtrl.deleteComment(commentId)
expect(historyCtrl.deleting).to.be.equal(7) expect(historyCtrl.deleting).to.be.equal(7)
@ -157,12 +163,12 @@ describe "HistorySection", ->
deleteCommentPromise.resolve() deleteCommentPromise.resolve()
ctrlPromise.then () -> ctrlPromise.then () ->
expect(historyCtrl._loadHistory).have.been.called expect(historyCtrl._loadComments).have.been.called
expect(historyCtrl.deleting).to.be.null expect(historyCtrl.deleting).to.be.null
it "edit comment", () -> it "edit comment", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._loadHistory = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl.name = "type" historyCtrl.name = "type"
historyCtrl.id = 1 historyCtrl.id = 1
@ -173,16 +179,17 @@ describe "HistorySection", ->
objectId = historyCtrl.id objectId = historyCtrl.id
commentId = activityId commentId = activityId
promise = mocks.tgResources.history.editComment.withArgs(type, objectId, activityId, comment).promise().resolve() promise = mocks.tgResources.history.editComment
.withArgs(type, objectId, activityId, comment).promise().resolve()
historyCtrl.editing = 7 historyCtrl.editing = 7
historyCtrl.editComment(commentId, comment).then () -> historyCtrl.editComment(commentId, comment).then () ->
expect(historyCtrl._loadHistory).has.been.called expect(historyCtrl._loadComments).has.been.called
expect(historyCtrl.editing).to.be.null expect(historyCtrl.editing).to.be.null
it "restore comment", () -> it "restore comment", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._loadHistory = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl.name = "type" historyCtrl.name = "type"
historyCtrl.id = 1 historyCtrl.id = 1
@ -196,12 +203,12 @@ describe "HistorySection", ->
historyCtrl.editing = 7 historyCtrl.editing = 7
historyCtrl.restoreDeletedComment(commentId).then () -> historyCtrl.restoreDeletedComment(commentId).then () ->
expect(historyCtrl._loadHistory).has.been.called expect(historyCtrl._loadComments).has.been.called
expect(historyCtrl.editing).to.be.null expect(historyCtrl.editing).to.be.null
it "add comment", () -> it "add comment", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._loadHistory = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl.type = "type" historyCtrl.type = "type"
type = historyCtrl.type type = historyCtrl.type
@ -210,18 +217,17 @@ describe "HistorySection", ->
promise = mocks.tgRepo.save.withArgs(type).promise().resolve() promise = mocks.tgRepo.save.withArgs(type).promise().resolve()
historyCtrl.addComment(cb).then () -> historyCtrl.addComment()
expect(historyCtrl._loadHistory).has.been.called expect(historyCtrl._loadComments).has.been.called
expect(cb).to.have.been.called
it "order comments", () -> it "order comments", () ->
historyCtrl = controller "HistorySection" historyCtrl = controller "HistorySection"
historyCtrl._loadHistory = sinon.stub() historyCtrl._loadComments = sinon.stub()
historyCtrl.reverse = false historyCtrl.reverse = false
historyCtrl.onOrderComments() historyCtrl.onOrderComments()
expect(historyCtrl.reverse).to.be.true expect(historyCtrl.reverse).to.be.true
expect(mocks.tgStorage.set).has.been.calledWith("orderComments", historyCtrl.reverse) expect(mocks.tgStorage.set).has.been.calledWith("orderComments", historyCtrl.reverse)
expect(historyCtrl._loadHistory).has.been.called expect(historyCtrl._loadComments).has.been.called

View File

@ -19,9 +19,14 @@
module = angular.module('taigaHistory') module = angular.module('taigaHistory')
bindOnce = @.taiga.bindOnce
HistorySectionDirective = () -> HistorySectionDirective = () ->
link = (scope, el, attr, ctrl) -> link = (scope, el, attr, ctrl) ->
scope.$on "object:updated", -> ctrl._loadHistory(scope.type, scope.id) scope.$on "object:updated", -> ctrl._loadActivity()
scope.$watch 'vm.id', (value) ->
ctrl._loadHistory()
return { return {
link: link, link: link,

View File

@ -30,7 +30,10 @@ section.history(
deleting="vm.deleting" deleting="vm.deleting"
project-id="vm.projectId" project-id="vm.projectId"
) )
tg-history( div(
ng-if="!vm.viewComments" ng-if="!vm.viewComments"
activities="vm.activities" infinite-scroll="vm.nextActivityPage()"
infinite-scroll-disabled="vm.disabledActivityPagination"
infinite-scroll-immediate-check="false"
) )
tg-history(activities="vm.activities")

View File

@ -14,29 +14,25 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
# File: resources/wiki-resource.service.coffee # File: resources/history-resource.service.coffee
### ###
Resource = (urlsService, http) -> Resource = (urlsService, http) ->
service = {} service = {}
service.getWikiHistory = (wikiId) -> service.getHistory = (historyType, contentType, objectId, page) ->
url = urlsService.resolve("history/wiki", wikiId) url = urlsService.resolve("history/#{contentType}", )
return http.get("#{url}/#{objectId}", {page: page, type: historyType})
httpOptions = {
headers: {
"x-disable-pagination": "1"
}
}
return http.get(url, null, httpOptions)
.then (result) -> .then (result) ->
return Immutable.fromJS(result.data) return {
list: Immutable.fromJS(result.data)
headers: result.headers
}
return () -> return () ->
return {"wikiHistory": service} return {"history": service}
Resource.$inject = ["$tgUrls", "$tgHttp"] Resource.$inject = ["$tgUrls", "$tgHttp"]
module = angular.module("taigaResources2") module = angular.module("taigaResources2")
module.factory("tgWikiHistory", Resource) module.factory("tgHistory", Resource)

View File

@ -27,7 +27,7 @@ services = [
"tgExternalAppsResource", "tgExternalAppsResource",
"tgAttachmentsResource", "tgAttachmentsResource",
"tgStatsResource", "tgStatsResource",
"tgWikiHistory", "tgHistory",
"tgEpicsResource", "tgEpicsResource",
"tgTrelloImportResource", "tgTrelloImportResource",
"tgJiraImportResource", "tgJiraImportResource",

View File

@ -23,17 +23,25 @@ module = angular.module("taigaWikiHistory")
class WikiHistoryController class WikiHistoryController
@.$inject = [ @.$inject = [
"tgWikiHistoryService" "tgActivityService"
] ]
constructor: (@wikiHistoryService) -> constructor: (@activityService) ->
taiga.defineImmutableProperty @, 'historyEntries', () => return @wikiHistoryService.historyEntries taiga.defineImmutableProperty @, 'historyEntries', () =>
return @activityService.entries
taiga.defineImmutableProperty @, 'disablePagination', () =>
return @activityService.disablePagination
@.toggle = false @.toggle = false
initializeHistoryEntries: (wikiId) -> initializeHistory: (wikiId) ->
if wikiId if wikiId
@wikiHistoryService.setWikiId(wikiId) @activityService.init('wiki', wikiId)
@.loadHistory()
@wikiHistoryService.loadHistoryEntries() loadHistory: ()->
@activityService.fetchEntries()
nextPage: () ->
@activityService.nextPage()
module.controller("WikiHistoryCtrl", WikiHistoryController) module.controller("WikiHistoryCtrl", WikiHistoryController)

View File

@ -22,18 +22,18 @@ describe "WikiHistorySection", ->
controller = null controller = null
mocks = {} mocks = {}
_mockTgWikiHistoryService = () -> _mockTgActivityService = () ->
mocks.tgWikiHistoryService = { mocks.tgActivityService = {
setWikiId: sinon.stub(), init: sinon.stub(),
loadHistoryEntries: sinon.stub() fetchEntries: sinon.stub()
} }
provide.value "tgWikiHistoryService", mocks.tgWikiHistoryService provide.value "tgActivityService", mocks.tgActivityService
_mocks = () -> _mocks = () ->
module ($provide) -> module ($provide) ->
provide = $provide provide = $provide
_mockTgWikiHistoryService() _mockTgActivityService()
return null return null
beforeEach -> beforeEach ->
@ -44,19 +44,19 @@ describe "WikiHistorySection", ->
inject ($controller) -> inject ($controller) ->
controller = $controller controller = $controller
it "initialize histori entries with id", -> it "initialize history entries with id", ->
wikiId = 42 wikiId = 42
historyCtrl = controller "WikiHistoryCtrl" historyCtrl = controller "WikiHistoryCtrl"
historyCtrl.initializeHistoryEntries(wikiId) historyCtrl.initializeHistory(wikiId)
expect(mocks.tgWikiHistoryService.setWikiId).to.be.calledOnce expect(mocks.tgActivityService.init).to.be.calledOnce
expect(mocks.tgWikiHistoryService.setWikiId).to.be.calledWith(wikiId) expect(mocks.tgActivityService.init).to.be.calledWith('wiki', wikiId)
expect(mocks.tgWikiHistoryService.loadHistoryEntries).to.be.calledOnce expect(mocks.tgActivityService.fetchEntries).to.be.calledOnce
it "initialize history entries without id", -> it "initialize history entries without id", ->
historyCtrl = controller "WikiHistoryCtrl" historyCtrl = controller "WikiHistoryCtrl"
historyCtrl.initializeHistoryEntries() historyCtrl.initializeHistory()
expect(mocks.tgWikiHistoryService.setWikiId).to.not.be.calledOnce expect(mocks.tgActivityService.init).to.not.be.calledOnce
expect(mocks.tgWikiHistoryService.loadHistoryEntries).to.be.calledOnce expect(mocks.tgActivityService.fetchEntries).to.be.calledOnce

View File

@ -25,7 +25,7 @@ module = angular.module('taigaWikiHistory')
WikiHistoryDirective = () -> WikiHistoryDirective = () ->
link = (scope, el, attrs, ctrl) -> link = (scope, el, attrs, ctrl) ->
bindOnce scope, 'vm.wikiId', (value) -> bindOnce scope, 'vm.wikiId', (value) ->
ctrl.initializeHistoryEntries(value) ctrl.initializeHistory(value)
return { return {
scope: {}, scope: {},

View File

@ -6,8 +6,13 @@ nav.history-tabs(ng-if="vm.historyEntries.count()>0")
title="{{ACTIVITY.TITLE}}" title="{{ACTIVITY.TITLE}}"
translate="ACTIVITY.TITLE" translate="ACTIVITY.TITLE"
) )
p {{ disablePagination }}
section.wiki-history(ng-if="vm.historyEntries.count()>0 && vm.toggle") section.wiki-history(
ng-if="vm.historyEntries.count()>0 && vm.toggle"
infinite-scroll="vm.nextPage()"
infinite-scroll-immediate-check="false"
infinite-scroll-disabled="vm.disablePagination"
)
tg-wiki-history-entry.wiki-history-entry( tg-wiki-history-entry.wiki-history-entry(
tg-repeat="historyEntry in vm.historyEntries" tg-repeat="historyEntry in vm.historyEntries"
history-entry="historyEntry" history-entry="historyEntry"

View File

@ -1,51 +0,0 @@
###
# Copyright (C) 2014-2018 Taiga Agile LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: wiki/history/wiki-history.service.coffee
###
taiga = @.taiga
module = angular.module('taigaWikiHistory')
class WikiHistoryService extends taiga.Service
@.$inject = [
"tgResources"
"tgXhrErrorService"
]
constructor: (@rs, @xhrError) ->
@._wikiId = null
@._historyEntries = Immutable.List()
taiga.defineImmutableProperty @, "wikiId", () => return @._wikiId
taiga.defineImmutableProperty @, "historyEntries", () => return @._historyEntries
setWikiId: (wikiId) ->
@._wikiId = wikiId
@._historyEntries = Immutable.List()
loadHistoryEntries: () ->
return if not @._wikiId
return @rs.wikiHistory.getWikiHistory(@._wikiId)
.then (historyEntries) =>
if historyEntries.size
@._historyEntries = historyEntries.reverse()
.catch (xhr) =>
@xhrError.response(xhr)
_
module.service("tgWikiHistoryService", WikiHistoryService)

View File

@ -1,92 +0,0 @@
###
# Copyright (C) 2014-2018 Taiga Agile LLC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# File: wiki/history/wiki-history.service.spec.coffee
###
describe "tgWikiHistoryService", ->
$provide = null
wikiHistoryService = null
mocks = {}
_mockTgResources = () ->
mocks.tgResources = {
wikiHistory: {
getWikiHistory: sinon.stub()
}
}
$provide.value("tgResources", mocks.tgResources)
_mockXhrErrorService = () ->
mocks.xhrErrorService = {
response: sinon.stub()
}
$provide.value "tgXhrErrorService", mocks.xhrErrorService
_mocks = ->
module (_$provide_) ->
$provide = _$provide_
_mockTgResources()
_mockXhrErrorService()
return null
_inject = ->
inject (_tgWikiHistoryService_) ->
wikiHistoryService = _tgWikiHistoryService_
_setup = ->
_mocks()
_inject()
beforeEach ->
module "taigaWikiHistory"
_setup()
it "populate history entries", (done) ->
wikiId = 42
historyEntries = Immutable.List([
{id: 1, name: 'history entrie 1'},
{id: 2, name: 'history entrie 2'},
{id: 3, name: 'history entrie 3'},
])
mocks.tgResources.wikiHistory.getWikiHistory.withArgs(wikiId).promise().resolve(historyEntries)
wikiHistoryService.setWikiId(wikiId)
expect(wikiHistoryService.wikiId).to.be.equal(wikiId)
expect(wikiHistoryService.historyEntries.size).to.be.equal(0)
wikiHistoryService.loadHistoryEntries().then () ->
expect(wikiHistoryService.historyEntries.size).to.be.equal(3)
done()
it "reset history entries if wikiId change", () ->
wikiId = 42
wikiHistoryService._historyEntries = Immutable.List([
{id: 1, name: 'history entrie 1'},
{id: 2, name: 'history entrie 2'},
{id: 3, name: 'history entrie 3'},
])
expect(wikiHistoryService.historyEntries.size).to.be.equal(3)
wikiHistoryService.setWikiId(wikiId)
expect(wikiHistoryService.historyEntries.size).to.be.equal(0)