From 8de4db9e377c8176de1f9f08f1fdaea65f07c1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xavier=20Juli=C3=A1n?= Date: Tue, 7 Jun 2016 10:17:47 +0200 Subject: [PATCH] Show history in all wiki pages --- CHANGELOG.md | 1 + app/coffee/app.coffee | 1 + app/coffee/modules/resources.coffee | 2 +- app/coffee/modules/wiki/main.coffee | 7 +- .../history/history-tabs/history-tabs.jade | 2 +- .../history/history-tabs/history-tabs.scss | 21 ----- .../history-templates/history-templates.scss | 5 +- app/modules/history/history/history.scss | 38 +------- app/modules/resources/resources.coffee | 3 +- .../resources/wiki-resource.service.coffee | 42 +++++++++ .../history-attachments.jade | 42 +++++++++ .../wiki-history-diff.directive.coffee | 31 +++++++ .../wiki/history/wiki-history-diff.jade | 16 ++++ .../wiki-history-entry.directive.coffee | 34 +++++++ .../wiki/history/wiki-history-entry.jade | 16 ++++ .../history/wiki-history.controller.coffee | 38 ++++++++ .../wiki-history.controller.spec.coffee | 62 +++++++++++++ .../history/wiki-history.directive.coffee | 41 +++++++++ app/modules/wiki/history/wiki-history.jade | 12 +++ .../wiki/history/wiki-history.module.coffee | 20 ++++ app/modules/wiki/history/wiki-history.scss | 3 + .../wiki/history/wiki-history.service.coffee | 51 ++++++++++ .../history/wiki-history.service.spec.coffee | 92 +++++++++++++++++++ app/partials/wiki/wiki-summary.jade | 9 ++ app/partials/wiki/wiki.jade | 14 +-- app/styles/components/history.scss | 32 +++++++ app/styles/layout/wiki.scss | 19 +--- app/styles/modules/wiki/wiki-summary.scss | 12 +++ 28 files changed, 578 insertions(+), 88 deletions(-) create mode 100644 app/modules/resources/wiki-resource.service.coffee create mode 100644 app/modules/wiki/history/history-templates/history-attachments.jade create mode 100644 app/modules/wiki/history/wiki-history-diff.directive.coffee create mode 100644 app/modules/wiki/history/wiki-history-diff.jade create mode 100644 app/modules/wiki/history/wiki-history-entry.directive.coffee create mode 100644 app/modules/wiki/history/wiki-history-entry.jade create mode 100644 app/modules/wiki/history/wiki-history.controller.coffee create mode 100644 app/modules/wiki/history/wiki-history.controller.spec.coffee create mode 100644 app/modules/wiki/history/wiki-history.directive.coffee create mode 100644 app/modules/wiki/history/wiki-history.jade create mode 100644 app/modules/wiki/history/wiki-history.module.coffee create mode 100644 app/modules/wiki/history/wiki-history.scss create mode 100644 app/modules/wiki/history/wiki-history.service.coffee create mode 100644 app/modules/wiki/history/wiki-history.service.spec.coffee create mode 100644 app/styles/components/history.scss diff --git a/CHANGELOG.md b/CHANGELOG.md index c460a6f1..0c840d86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Wiki: - Drag & Drop ordering for wiki links. - Add a list of all wiki pages + - Add Wiki history ### Misc - Lots of small and not so small bugfixes. diff --git a/app/coffee/app.coffee b/app/coffee/app.coffee index c212486b..a1840ebf 100644 --- a/app/coffee/app.coffee +++ b/app/coffee/app.coffee @@ -779,6 +779,7 @@ modules = [ "taigaExternalApps", "taigaDiscover", "taigaHistory", + "taigaWikiHistory", # template cache "templates", diff --git a/app/coffee/modules/resources.coffee b/app/coffee/modules/resources.coffee index c32a9f56..8d30fb0f 100644 --- a/app/coffee/modules/resources.coffee +++ b/app/coffee/modules/resources.coffee @@ -131,7 +131,7 @@ urls = { "history/us": "/history/userstory" "history/issue": "/history/issue" "history/task": "/history/task" - "history/wiki": "/history/wiki" + "history/wiki": "/history/wiki/%s" # Attachments "attachments/us": "/userstories/attachments" diff --git a/app/coffee/modules/wiki/main.coffee b/app/coffee/modules/wiki/main.coffee index 6b89edaf..f10479b9 100644 --- a/app/coffee/modules/wiki/main.coffee +++ b/app/coffee/modules/wiki/main.coffee @@ -218,7 +218,8 @@ module.directive("tgWikiSummary", ["$log", "$tgTemplate", "$compile", "$translat ## 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) -> isEditable = -> return $scope.project.my_permissions.indexOf("modify_wiki_page") != -1 @@ -260,6 +261,7 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $ $model.$setViewValue wikiPage.clone() + $wikiHistoryService.loadHistoryEntries() $confirm.notify("success") switchToReadMode() @@ -336,4 +338,5 @@ EditableWikiContentDirective = ($window, $document, $repo, $confirm, $loading, $ } module.directive("tgEditableWikiContent", ["$window", "$document", "$tgRepo", "$tgConfirm", "$tgLoading", - "$tgAnalytics", "$tgQqueue", "$translate", EditableWikiContentDirective]) + "$tgAnalytics", "$tgQqueue", "$translate", "tgWikiHistoryService", + EditableWikiContentDirective]) diff --git a/app/modules/history/history-tabs/history-tabs.jade b/app/modules/history/history-tabs/history-tabs.jade index 8b0c175a..deb458de 100644 --- a/app/modules/history/history-tabs/history-tabs.jade +++ b/app/modules/history/history-tabs/history-tabs.jade @@ -1,7 +1,7 @@ nav.history-tabs a.history-tab.e2e-comments-tab( href="" - title="Comments" + title="{{COMMENTS.COMMENT}}" ng-click="onActiveComments()" ng-class="{active: activeTab}" translate="COMMENTS.COMMENTS_COUNT" diff --git a/app/modules/history/history-tabs/history-tabs.scss b/app/modules/history/history-tabs/history-tabs.scss index 48cb8471..9c7bef56 100644 --- a/app/modules/history/history-tabs/history-tabs.scss +++ b/app/modules/history/history-tabs/history-tabs.scss @@ -1,25 +1,4 @@ .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 { @include font-type(light); margin-left: auto; diff --git a/app/modules/history/history/history-templates/history-templates.scss b/app/modules/history/history/history-templates/history-templates.scss index 69773c26..77d5d7ed 100644 --- a/app/modules/history/history/history-templates/history-templates.scss +++ b/app/modules/history/history/history-templates/history-templates.scss @@ -17,9 +17,12 @@ p { display: inline-block; } - del { + ins { background: lighten(rgba($primary-light, .3), 20%); text-decoration: underline; } + del { + background: rgba($red-light, .3); + } } } diff --git a/app/modules/history/history/history.scss b/app/modules/history/history/history.scss index 840e79f2..48bd6da8 100644 --- a/app/modules/history/history/history.scss +++ b/app/modules/history/history/history.scss @@ -1,10 +1,8 @@ -.activities { - .activity { - align-items: flex-start; - border-bottom: 1px solid $whitish; - display: flex; - padding: 2rem 0; - } +.activity { + align-items: flex-start; + border-bottom: 1px solid $whitish; + display: flex; + padding: 2rem 0; .activity-avatar { flex-basis: 50px; flex-shrink: 0; @@ -20,30 +18,4 @@ .activity-date { 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; - } - } - } } diff --git a/app/modules/resources/resources.coffee b/app/modules/resources/resources.coffee index e8a4c33a..5fafa0bf 100644 --- a/app/modules/resources/resources.coffee +++ b/app/modules/resources/resources.coffee @@ -26,7 +26,8 @@ services = [ "tgIssuesResource", "tgExternalAppsResource", "tgAttachmentsResource", - "tgStatsResource" + "tgStatsResource", + "tgWikiHistory" ] Resources = ($injector) -> diff --git a/app/modules/resources/wiki-resource.service.coffee b/app/modules/resources/wiki-resource.service.coffee new file mode 100644 index 00000000..6c3a67fe --- /dev/null +++ b/app/modules/resources/wiki-resource.service.coffee @@ -0,0 +1,42 @@ +### +# Copyright (C) 2014-2016 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 . +# +# 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) diff --git a/app/modules/wiki/history/history-templates/history-attachments.jade b/app/modules/wiki/history/history-templates/history-attachments.jade new file mode 100644 index 00000000..b9a9d074 --- /dev/null +++ b/app/modules/wiki/history/history-templates/history-attachments.jade @@ -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}} diff --git a/app/modules/wiki/history/wiki-history-diff.directive.coffee b/app/modules/wiki/history/wiki-history-diff.directive.coffee new file mode 100644 index 00000000..3388d969 --- /dev/null +++ b/app/modules/wiki/history/wiki-history-diff.directive.coffee @@ -0,0 +1,31 @@ +### +# Copyright (C) 2014-2016 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 . +# +# 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) diff --git a/app/modules/wiki/history/wiki-history-diff.jade b/app/modules/wiki/history/wiki-history-diff.jade new file mode 100644 index 00000000..4ae07bc0 --- /dev/null +++ b/app/modules/wiki/history/wiki-history-diff.jade @@ -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]" + ) diff --git a/app/modules/wiki/history/wiki-history-entry.directive.coffee b/app/modules/wiki/history/wiki-history-entry.directive.coffee new file mode 100644 index 00000000..7f0905ab --- /dev/null +++ b/app/modules/wiki/history/wiki-history-entry.directive.coffee @@ -0,0 +1,34 @@ +### +# Copyright (C) 2014-2016 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 . +# +# 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) diff --git a/app/modules/wiki/history/wiki-history-entry.jade b/app/modules/wiki/history/wiki-history-entry.jade new file mode 100644 index 00000000..d8d2633c --- /dev/null +++ b/app/modules/wiki/history/wiki-history-entry.jade @@ -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' + ) diff --git a/app/modules/wiki/history/wiki-history.controller.coffee b/app/modules/wiki/history/wiki-history.controller.coffee new file mode 100644 index 00000000..45f7b983 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.controller.coffee @@ -0,0 +1,38 @@ +### +# Copyright (C) 2014-2015 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 . +# +# 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) diff --git a/app/modules/wiki/history/wiki-history.controller.spec.coffee b/app/modules/wiki/history/wiki-history.controller.spec.coffee new file mode 100644 index 00000000..d0a0fbc8 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.controller.spec.coffee @@ -0,0 +1,62 @@ +### +# Copyright (C) 2014-2015 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 . +# +# 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 diff --git a/app/modules/wiki/history/wiki-history.directive.coffee b/app/modules/wiki/history/wiki-history.directive.coffee new file mode 100644 index 00000000..34d96c31 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.directive.coffee @@ -0,0 +1,41 @@ +### +# Copyright (C) 2014-2016 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 . +# +# 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) diff --git a/app/modules/wiki/history/wiki-history.jade b/app/modules/wiki/history/wiki-history.jade new file mode 100644 index 00000000..57715241 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.jade @@ -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" + ) diff --git a/app/modules/wiki/history/wiki-history.module.coffee b/app/modules/wiki/history/wiki-history.module.coffee new file mode 100644 index 00000000..4ed5d8d0 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.module.coffee @@ -0,0 +1,20 @@ +### +# Copyright (C) 2014-2016 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 . +# +# File: wiki-history.module.coffee +### + +angular.module("taigaWikiHistory", []) diff --git a/app/modules/wiki/history/wiki-history.scss b/app/modules/wiki/history/wiki-history.scss new file mode 100644 index 00000000..3e0f5a02 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.scss @@ -0,0 +1,3 @@ +.wiki-history { + margin-bottom: 2rem; +} diff --git a/app/modules/wiki/history/wiki-history.service.coffee b/app/modules/wiki/history/wiki-history.service.coffee new file mode 100644 index 00000000..6b3107ad --- /dev/null +++ b/app/modules/wiki/history/wiki-history.service.coffee @@ -0,0 +1,51 @@ +### +# Copyright (C) 2014-2016 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 . +# +# 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) diff --git a/app/modules/wiki/history/wiki-history.service.spec.coffee b/app/modules/wiki/history/wiki-history.service.spec.coffee new file mode 100644 index 00000000..26410361 --- /dev/null +++ b/app/modules/wiki/history/wiki-history.service.spec.coffee @@ -0,0 +1,92 @@ +### +# Copyright (C) 2014-2015 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 . +# +# 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) diff --git a/app/partials/wiki/wiki-summary.jade b/app/partials/wiki/wiki-summary.jade index d10e398f..e1708e7b 100644 --- a/app/partials/wiki/wiki-summary.jade +++ b/app/partials/wiki/wiki-summary.jade @@ -12,3 +12,12 @@ .wiki-times-edited span.number <%- totalEditions %> 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" + +) diff --git a/app/partials/wiki/wiki.jade b/app/partials/wiki/wiki.jade index ab482e0d..cde221a6 100644 --- a/app/partials/wiki/wiki.jade +++ b/app/partials/wiki/wiki.jade @@ -16,15 +16,14 @@ div.wrapper( span(tg-bo-bind="project.name") span.green(translate="PROJECT.SECTION.WIKI") - h2.wiki-title(ng-bind='wikiTitle') section.wiki-content( tg-editable-wysiwyg, tg-editable-wiki-content, ng-model="wiki" ) - - div.summary.wiki-summary( + + .summary.wiki-summary( tg-wiki-summary ng-model="wiki" ng-if="wiki.id" @@ -38,12 +37,7 @@ div.wrapper( edit-permission = "modify_wiki_page" ) - a.remove( - href="" - ng-click="ctrl.delete()" + tg-wiki-history( ng-if="wiki.id" - title="{{'WIKI.REMOVE' | translate}}" - tg-check-permission="delete_wiki_page" + wiki-id="wiki.id" ) - tg-svg(svg-icon="icon-trash") - span(translate="WIKI.REMOVE") diff --git a/app/styles/components/history.scss b/app/styles/components/history.scss new file mode 100644 index 00000000..d949df35 --- /dev/null +++ b/app/styles/components/history.scss @@ -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); + } +} diff --git a/app/styles/layout/wiki.scss b/app/styles/layout/wiki.scss index 5b5c8874..3930ca41 100644 --- a/app/styles/layout/wiki.scss +++ b/app/styles/layout/wiki.scss @@ -1,4 +1,5 @@ .wiki { + max-width: 1024px; .wysiwyg { margin-bottom: 0; } @@ -8,28 +9,10 @@ margin-bottom: 0; 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 { @include font-size(large); - max-width: 1024px; position: relative; &.editable { &:hover { diff --git a/app/styles/modules/wiki/wiki-summary.scss b/app/styles/modules/wiki/wiki-summary.scss index 30e7d128..8abcf6bf 100644 --- a/app/styles/modules/wiki/wiki-summary.scss +++ b/app/styles/modules/wiki/wiki-summary.scss @@ -27,4 +27,16 @@ @include font-size(large); 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); + } + } }