Show history in all wiki pages
parent
e488fac8d1
commit
8de4db9e37
|
@ -18,6 +18,7 @@
|
||||||
- Wiki:
|
- Wiki:
|
||||||
- Drag & Drop ordering for wiki links.
|
- Drag & Drop ordering for wiki links.
|
||||||
- Add a list of all wiki pages
|
- Add a list of all wiki pages
|
||||||
|
- Add Wiki history
|
||||||
|
|
||||||
### Misc
|
### Misc
|
||||||
- Lots of small and not so small bugfixes.
|
- Lots of small and not so small bugfixes.
|
||||||
|
|
|
@ -779,6 +779,7 @@ modules = [
|
||||||
"taigaExternalApps",
|
"taigaExternalApps",
|
||||||
"taigaDiscover",
|
"taigaDiscover",
|
||||||
"taigaHistory",
|
"taigaHistory",
|
||||||
|
"taigaWikiHistory",
|
||||||
|
|
||||||
# template cache
|
# template cache
|
||||||
"templates",
|
"templates",
|
||||||
|
|
|
@ -131,7 +131,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"
|
"history/wiki": "/history/wiki/%s"
|
||||||
|
|
||||||
# Attachments
|
# Attachments
|
||||||
"attachments/us": "/userstories/attachments"
|
"attachments/us": "/userstories/attachments"
|
||||||
|
|
|
@ -218,7 +218,8 @@ module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translat
|
||||||
## Editable Wiki Content Directive
|
## Editable Wiki Content Directive
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $analytics, $qqueue, $translate) ->
|
EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $analytics, $qqueue, $translate,
|
||||||
|
$wikiHistoryService) ->
|
||||||
link = ($scope, $el, $attrs, $model) ->
|
link = ($scope, $el, $attrs, $model) ->
|
||||||
isEditable = ->
|
isEditable = ->
|
||||||
return $scope.project.my_permissions.indexOf("modify_wiki_page") != -1
|
return $scope.project.my_permissions.indexOf("modify_wiki_page") != -1
|
||||||
|
@ -260,6 +261,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
|
||||||
|
|
||||||
$model.$setViewValue wikiPage.clone()
|
$model.$setViewValue wikiPage.clone()
|
||||||
|
|
||||||
|
$wikiHistoryService.loadHistoryEntries()
|
||||||
$confirm.notify("success")
|
$confirm.notify("success")
|
||||||
switchToReadMode()
|
switchToReadMode()
|
||||||
|
|
||||||
|
@ -336,4 +338,5 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $
|
||||||
}
|
}
|
||||||
|
|
||||||
module.directive("tgEditableWikiContent", ["$window", "$document", "$tgRepo", "$tgConfirm", "$tgLoading",
|
module.directive("tgEditableWikiContent", ["$window", "$document", "$tgRepo", "$tgConfirm", "$tgLoading",
|
||||||
"$tgAnalytics", "$tgQqueue", "$translate", EditableWikiContentDirective])
|
"$tgAnalytics", "$tgQqueue", "$translate", "tgWikiHistoryService",
|
||||||
|
EditableWikiContentDirective])
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
nav.history-tabs
|
nav.history-tabs
|
||||||
a.history-tab.e2e-comments-tab(
|
a.history-tab.e2e-comments-tab(
|
||||||
href=""
|
href=""
|
||||||
title="Comments"
|
title="{{COMMENTS.COMMENT}}"
|
||||||
ng-click="onActiveComments()"
|
ng-click="onActiveComments()"
|
||||||
ng-class="{active: activeTab}"
|
ng-class="{active: activeTab}"
|
||||||
translate="COMMENTS.COMMENTS_COUNT"
|
translate="COMMENTS.COMMENTS_COUNT"
|
||||||
|
|
|
@ -1,25 +1,4 @@
|
||||||
.history-tabs {
|
.history-tabs {
|
||||||
background: $whitish;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
a {
|
|
||||||
color: $grayer;
|
|
||||||
display: inline-block;
|
|
||||||
padding: .75rem 1rem;
|
|
||||||
&:hover {
|
|
||||||
color: $primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.history-tab {
|
|
||||||
@include font-type(bold);
|
|
||||||
border-bottom: 3px solid transparent;
|
|
||||||
color: $gray-light;
|
|
||||||
transition: all .1s linear;
|
|
||||||
&.active {
|
|
||||||
border-bottom: 3px solid $grayer;
|
|
||||||
color: $grayer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.order-comments {
|
.order-comments {
|
||||||
@include font-type(light);
|
@include font-type(light);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|
|
@ -17,9 +17,12 @@
|
||||||
p {
|
p {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
del {
|
ins {
|
||||||
background: lighten(rgba($primary-light, .3), 20%);
|
background: lighten(rgba($primary-light, .3), 20%);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
del {
|
||||||
|
background: rgba($red-light, .3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
.activities {
|
.activity {
|
||||||
.activity {
|
align-items: flex-start;
|
||||||
align-items: flex-start;
|
border-bottom: 1px solid $whitish;
|
||||||
border-bottom: 1px solid $whitish;
|
display: flex;
|
||||||
display: flex;
|
padding: 2rem 0;
|
||||||
padding: 2rem 0;
|
|
||||||
}
|
|
||||||
.activity-avatar {
|
.activity-avatar {
|
||||||
flex-basis: 50px;
|
flex-basis: 50px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -20,30 +18,4 @@
|
||||||
.activity-date {
|
.activity-date {
|
||||||
color: $gray-light;
|
color: $gray-light;
|
||||||
}
|
}
|
||||||
.comment-options {
|
|
||||||
align-items: center;
|
|
||||||
align-self: stretch;
|
|
||||||
display: flex;
|
|
||||||
flex-basis: 50px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-left: 1.5rem;
|
|
||||||
.comment-option {
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity .2s;
|
|
||||||
}
|
|
||||||
.icon-edit {
|
|
||||||
fill: $gray-light;
|
|
||||||
margin-right: .5rem;
|
|
||||||
&:hover {
|
|
||||||
fill: $gray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.icon-trash {
|
|
||||||
fill: $red-light;
|
|
||||||
&:hover {
|
|
||||||
fill: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ services = [
|
||||||
"tgIssuesResource",
|
"tgIssuesResource",
|
||||||
"tgExternalAppsResource",
|
"tgExternalAppsResource",
|
||||||
"tgAttachmentsResource",
|
"tgAttachmentsResource",
|
||||||
"tgStatsResource"
|
"tgStatsResource",
|
||||||
|
"tgWikiHistory"
|
||||||
]
|
]
|
||||||
|
|
||||||
Resources = ($injector) ->
|
Resources = ($injector) ->
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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-resource.service.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
Resource = (urlsService, http) ->
|
||||||
|
service = {}
|
||||||
|
|
||||||
|
service.getWikiHistory = (wikiId) ->
|
||||||
|
url = urlsService.resolve("history/wiki", wikiId)
|
||||||
|
|
||||||
|
httpOptions = {
|
||||||
|
headers: {
|
||||||
|
"x-disable-pagination": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.get(url, null, httpOptions)
|
||||||
|
.then (result) ->
|
||||||
|
return Immutable.fromJS(result.data)
|
||||||
|
|
||||||
|
return () ->
|
||||||
|
return {"wikiHistory": service}
|
||||||
|
|
||||||
|
Resource.$inject = ["$tgUrls", "$tgHttp"]
|
||||||
|
|
||||||
|
module = angular.module("taigaResources2")
|
||||||
|
module.factory("tgWikiHistory", Resource)
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
//- New attachment added
|
||||||
|
.diff-attachments-new(
|
||||||
|
ng-if="diff.new.length"
|
||||||
|
ng-repeat="newAttachment in diff.new"
|
||||||
|
)
|
||||||
|
span.key(translate="ACTIVITY.NEW_ATTACHMENT")
|
||||||
|
span.diff {{newAttachment.filename}}
|
||||||
|
|
||||||
|
//- Attachment updated
|
||||||
|
.diff-attachments-update(
|
||||||
|
ng-if="diff.changed.length"
|
||||||
|
ng-repeat="editAttachment in diff.changed"
|
||||||
|
)
|
||||||
|
span.key(
|
||||||
|
translate="ACTIVITY.UPDATED_ATTACHMENT"
|
||||||
|
translate-values="{filename: editAttachment.filename}"
|
||||||
|
)
|
||||||
|
span.diff(ng-if="editAttachment.changes.is_deprecated")
|
||||||
|
span(
|
||||||
|
ng-if="editAttachment.changes.is_deprecated[1] == false"
|
||||||
|
translate="ACTIVITY.BECAME_UNDEPRECATED"
|
||||||
|
)
|
||||||
|
span(
|
||||||
|
ng-if="editAttachment.changes.is_deprecated[1] == true"
|
||||||
|
translate="ACTIVITY.BECAME_DEPRECATED"
|
||||||
|
)
|
||||||
|
span.diff(ng-if="editAttachment.changes.description")
|
||||||
|
span(ng-if='editAttachment.changes.description[0].length') {{editAttachment.changes.description[0]}}
|
||||||
|
span(ng-if='!editAttachment.changes.description[0].length') ...
|
||||||
|
tg-svg(
|
||||||
|
svg-icon="icon-arrow-right"
|
||||||
|
)
|
||||||
|
span {{editAttachment.changes.description[1]}}
|
||||||
|
|
||||||
|
//- Attachment deleted
|
||||||
|
.diff-attachments-deleted(
|
||||||
|
ng-if="diff.deleted.length"
|
||||||
|
ng-repeat="deletedAttachment in diff.deleted"
|
||||||
|
)
|
||||||
|
span.key(translate="ACTIVITY.DELETED_ATTACHMENT")
|
||||||
|
span.diff {{deletedAttachment.filename}}
|
|
@ -0,0 +1,31 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
module = angular.module('taigaWikiHistory')
|
||||||
|
|
||||||
|
WikiHistoryDiffDirective = () ->
|
||||||
|
return {
|
||||||
|
templateUrl:"wiki/history/wiki-history-diff.html",
|
||||||
|
scope: {
|
||||||
|
key: "<",
|
||||||
|
diff: "<"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgWikiHistoryDiff", WikiHistoryDiffDirective)
|
|
@ -0,0 +1,16 @@
|
||||||
|
.diff-status-wrapper(
|
||||||
|
ng-if="key === 'attachments'"
|
||||||
|
)
|
||||||
|
include history-templates/history-attachments
|
||||||
|
|
||||||
|
.diff-status-wrapper(
|
||||||
|
ng-if="key === 'content_diff'"
|
||||||
|
)
|
||||||
|
p.diff(
|
||||||
|
ng-if="diff[0]"
|
||||||
|
ng-bind-html="diff[0]"
|
||||||
|
)
|
||||||
|
p.diff(
|
||||||
|
ng-if="diff[1]"
|
||||||
|
ng-bind-html="diff[1]"
|
||||||
|
)
|
|
@ -0,0 +1,34 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
module = angular.module('taigaWikiHistory')
|
||||||
|
|
||||||
|
WikiHistoryEntryDirective = () ->
|
||||||
|
link = (scope, el, attr) ->
|
||||||
|
scope.singleHistoryEntry = scope.historyEntry.toJS()
|
||||||
|
|
||||||
|
return {
|
||||||
|
link: link,
|
||||||
|
templateUrl:"wiki/history/wiki-history-entry.html",
|
||||||
|
scope: {
|
||||||
|
historyEntry: "<"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgWikiHistoryEntry", WikiHistoryEntryDirective)
|
|
@ -0,0 +1,16 @@
|
||||||
|
.activity
|
||||||
|
img.activity-avatar(
|
||||||
|
ng-src="{{singleHistoryEntry.user.photo}}"
|
||||||
|
ng-alt="{{singleHistoryEntry.user.name}}"
|
||||||
|
)
|
||||||
|
.activity-main
|
||||||
|
.activity-data
|
||||||
|
span.activity-creator {{singleHistoryEntry.user.name}}
|
||||||
|
span.activity-date {{singleHistoryEntry.created_at | momentFormat:'DD MMM YYYY HH:mm'}}
|
||||||
|
|
||||||
|
.activity-diff(
|
||||||
|
ng-repeat="(key, diff) in singleHistoryEntry.values_diff"
|
||||||
|
tg-wiki-history-diff
|
||||||
|
key='key'
|
||||||
|
diff='diff'
|
||||||
|
)
|
|
@ -0,0 +1,38 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.controller.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
taiga = @.taiga
|
||||||
|
|
||||||
|
module = angular.module("taigaWikiHistory")
|
||||||
|
|
||||||
|
class WikiHistoryController
|
||||||
|
@.$inject = [
|
||||||
|
"tgWikiHistoryService"
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor: (@wikiHistoryService) ->
|
||||||
|
taiga.defineImmutableProperty @, 'historyEntries', () => return @wikiHistoryService.historyEntries
|
||||||
|
|
||||||
|
initializeHistoryEntries: (wikiId) ->
|
||||||
|
if wikiId
|
||||||
|
@wikiHistoryService.setWikiId(wikiId)
|
||||||
|
|
||||||
|
@wikiHistoryService.loadHistoryEntries()
|
||||||
|
|
||||||
|
module.controller("WikiHistoryCtrl", WikiHistoryController)
|
|
@ -0,0 +1,62 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.controller.spec.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
describe "WikiHistorySection", ->
|
||||||
|
provide = null
|
||||||
|
controller = null
|
||||||
|
mocks = {}
|
||||||
|
|
||||||
|
_mockTgWikiHistoryService = () ->
|
||||||
|
mocks.tgWikiHistoryService = {
|
||||||
|
setWikiId: sinon.stub(),
|
||||||
|
loadHistoryEntries: sinon.stub()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide.value "tgWikiHistoryService", mocks.tgWikiHistoryService
|
||||||
|
|
||||||
|
_mocks = () ->
|
||||||
|
module ($provide) ->
|
||||||
|
provide = $provide
|
||||||
|
_mockTgWikiHistoryService()
|
||||||
|
return null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
module "taigaWikiHistory"
|
||||||
|
|
||||||
|
_mocks()
|
||||||
|
|
||||||
|
inject ($controller) ->
|
||||||
|
controller = $controller
|
||||||
|
|
||||||
|
it "initialize histori entries with id", ->
|
||||||
|
wikiId = 42
|
||||||
|
|
||||||
|
historyCtrl = controller "WikiHistoryCtrl"
|
||||||
|
historyCtrl.initializeHistoryEntries(wikiId)
|
||||||
|
|
||||||
|
expect(mocks.tgWikiHistoryService.setWikiId).to.be.calledOnce
|
||||||
|
expect(mocks.tgWikiHistoryService.setWikiId).to.be.calledWith(wikiId)
|
||||||
|
expect(mocks.tgWikiHistoryService.loadHistoryEntries).to.be.calledOnce
|
||||||
|
|
||||||
|
it "initialize history entries without id", ->
|
||||||
|
historyCtrl = controller "WikiHistoryCtrl"
|
||||||
|
historyCtrl.initializeHistoryEntries()
|
||||||
|
|
||||||
|
expect(mocks.tgWikiHistoryService.setWikiId).to.not.be.calledOnce
|
||||||
|
expect(mocks.tgWikiHistoryService.loadHistoryEntries).to.be.calledOnce
|
|
@ -0,0 +1,41 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.directive.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
bindOnce = @.taiga.bindOnce
|
||||||
|
|
||||||
|
module = angular.module('taigaWikiHistory')
|
||||||
|
|
||||||
|
|
||||||
|
WikiHistoryDirective = () ->
|
||||||
|
link = (scope, el, attrs, ctrl) ->
|
||||||
|
bindOnce scope, 'vm.wikiId', (value) ->
|
||||||
|
ctrl.initializeHistoryEntries(value)
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: {},
|
||||||
|
bindToController: {
|
||||||
|
wikiId: "<"
|
||||||
|
}
|
||||||
|
controller: "WikiHistoryCtrl",
|
||||||
|
controllerAs: "vm",
|
||||||
|
templateUrl:"wiki/history/wiki-history.html",
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
|
||||||
|
module.directive("tgWikiHistory", WikiHistoryDirective)
|
|
@ -0,0 +1,12 @@
|
||||||
|
nav.history-tabs(ng-if="vm.historyEntries")
|
||||||
|
a.history-tab.active(
|
||||||
|
href=""
|
||||||
|
title="{{ACTIVITY.TITLE}}"
|
||||||
|
translate="ACTIVITY.TITLE"
|
||||||
|
)
|
||||||
|
|
||||||
|
section.wiki-history(ng-if="vm.historyEntries")
|
||||||
|
tg-wiki-history-entry.wiki-history-entry(
|
||||||
|
tg-repeat="historyEntry in vm.historyEntries"
|
||||||
|
history-entry="historyEntry"
|
||||||
|
)
|
|
@ -0,0 +1,20 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.module.coffee
|
||||||
|
###
|
||||||
|
|
||||||
|
angular.module("taigaWikiHistory", [])
|
|
@ -0,0 +1,3 @@
|
||||||
|
.wiki-history {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2016 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.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)
|
|
@ -0,0 +1,92 @@
|
||||||
|
###
|
||||||
|
# Copyright (C) 2014-2015 Taiga Agile LLC <taiga@taiga.io>
|
||||||
|
#
|
||||||
|
# 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.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)
|
|
@ -12,3 +12,12 @@
|
||||||
.wiki-times-edited
|
.wiki-times-edited
|
||||||
span.number <%- totalEditions %>
|
span.number <%- totalEditions %>
|
||||||
span.description(translate="WIKI.SUMMARY.TIMES_EDITED")
|
span.description(translate="WIKI.SUMMARY.TIMES_EDITED")
|
||||||
|
|
||||||
|
tg-svg.remove(
|
||||||
|
tg-check-permission="delete_wiki_page"
|
||||||
|
title="{{'WIKI.REMOVE' | translate}}"
|
||||||
|
ng-click="ctrl.delete()"
|
||||||
|
svg-icon="icon-trash"
|
||||||
|
ng-if="wiki.id"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
|
@ -16,15 +16,14 @@ div.wrapper(
|
||||||
span(tg-bo-bind="project.name")
|
span(tg-bo-bind="project.name")
|
||||||
span.green(translate="PROJECT.SECTION.WIKI")
|
span.green(translate="PROJECT.SECTION.WIKI")
|
||||||
|
|
||||||
|
|
||||||
h2.wiki-title(ng-bind='wikiTitle')
|
h2.wiki-title(ng-bind='wikiTitle')
|
||||||
section.wiki-content(
|
section.wiki-content(
|
||||||
tg-editable-wysiwyg,
|
tg-editable-wysiwyg,
|
||||||
tg-editable-wiki-content,
|
tg-editable-wiki-content,
|
||||||
ng-model="wiki"
|
ng-model="wiki"
|
||||||
)
|
)
|
||||||
|
|
||||||
div.summary.wiki-summary(
|
.summary.wiki-summary(
|
||||||
tg-wiki-summary
|
tg-wiki-summary
|
||||||
ng-model="wiki"
|
ng-model="wiki"
|
||||||
ng-if="wiki.id"
|
ng-if="wiki.id"
|
||||||
|
@ -38,12 +37,7 @@ div.wrapper(
|
||||||
edit-permission = "modify_wiki_page"
|
edit-permission = "modify_wiki_page"
|
||||||
)
|
)
|
||||||
|
|
||||||
a.remove(
|
tg-wiki-history(
|
||||||
href=""
|
|
||||||
ng-click="ctrl.delete()"
|
|
||||||
ng-if="wiki.id"
|
ng-if="wiki.id"
|
||||||
title="{{'WIKI.REMOVE' | translate}}"
|
wiki-id="wiki.id"
|
||||||
tg-check-permission="delete_wiki_page"
|
|
||||||
)
|
)
|
||||||
tg-svg(svg-icon="icon-trash")
|
|
||||||
span(translate="WIKI.REMOVE")
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
.history-tabs {
|
||||||
|
background: $whitish;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
a {
|
||||||
|
display: inline-block;
|
||||||
|
padding: .75rem 1rem;
|
||||||
|
&:hover {
|
||||||
|
color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.history-tab {
|
||||||
|
@include font-type(bold);
|
||||||
|
border-bottom: 3px solid transparent;
|
||||||
|
color: $gray-light;
|
||||||
|
transition: all .1s linear;
|
||||||
|
&.active {
|
||||||
|
border-bottom: 3px solid $grayer;
|
||||||
|
color: $grayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.order-comments {
|
||||||
|
@include font-type(light);
|
||||||
|
color: $grayer;
|
||||||
|
margin-left: auto;
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
.icon-arrow-up,
|
||||||
|
.icon-arrow-down {
|
||||||
|
@include svg-size(.75rem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
.wiki {
|
.wiki {
|
||||||
|
max-width: 1024px;
|
||||||
.wysiwyg {
|
.wysiwyg {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
@ -8,28 +9,10 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
.remove {
|
|
||||||
@include font-size(small);
|
|
||||||
color: $gray-light;
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
color: $red-light;
|
|
||||||
transition: color .1s linear;
|
|
||||||
.icon {
|
|
||||||
fill: $red-light;
|
|
||||||
transition: fill .1s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.icon {
|
|
||||||
color: $gray-light;
|
|
||||||
margin-right: .2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wiki-content {
|
.wiki-content {
|
||||||
@include font-size(large);
|
@include font-size(large);
|
||||||
max-width: 1024px;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
&.editable {
|
&.editable {
|
||||||
&:hover {
|
&:hover {
|
||||||
|
|
|
@ -27,4 +27,16 @@
|
||||||
@include font-size(large);
|
@include font-size(large);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
.remove {
|
||||||
|
fill: $gray-light;
|
||||||
|
margin-left: auto;
|
||||||
|
transition: fill .1s linear;
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
fill: $red-light;
|
||||||
|
}
|
||||||
|
svg {
|
||||||
|
@include svg-size(1.5rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue