From 9a27a39f55731cadac6b3244cb255e01fc86c1c0 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 8 Aug 2018 11:01:20 +0100 Subject: [PATCH 01/14] Make tooltip optional in the label component. --- services/web/app/views/project/editor/history.pug | 1 + .../public/coffee/ide/history/components/historyLabel.coffee | 3 +++ 2 files changed, 4 insertions(+) diff --git a/services/web/app/views/project/editor/history.pug b/services/web/app/views/project/editor/history.pug index 2f3f317561..bfb7df256b 100644 --- a/services/web/app/views/project/editor/history.pug +++ b/services/web/app/views/project/editor/history.pug @@ -77,6 +77,7 @@ script(type="text/ng-template", id="historyLabelTpl") tooltip-append-to-body="true" tooltip-template="'historyLabelTooltipTpl'" tooltip-placement="left" + tooltip-enable="$ctrl.showTooltip" ) i.fa.fa-tag |  {{ $ctrl.labelText }} diff --git a/services/web/public/coffee/ide/history/components/historyLabel.coffee b/services/web/public/coffee/ide/history/components/historyLabel.coffee index 2394b76f8b..03253663dd 100644 --- a/services/web/public/coffee/ide/history/components/historyLabel.coffee +++ b/services/web/public/coffee/ide/history/components/historyLabel.coffee @@ -3,6 +3,8 @@ define [ ], (App) -> historyLabelController = ($scope, $element, $attrs, $filter, _) -> ctrl = @ + ctrl.$onInit = () -> + ctrl.showTooltip ?= true return App.component "historyLabel", { @@ -12,6 +14,7 @@ define [ labelCreationDateTime: "<" isOwnedByCurrentUser: "<" onLabelDelete: "&" + showTooltip: " Date: Wed, 8 Aug 2018 11:01:51 +0100 Subject: [PATCH 02/14] Create history labels list component. --- .../project/editor/history/entriesListV2.pug | 18 +++++++++++- .../components/historyLabelsList.coffee | 29 +++++++++++++++++++ .../stylesheets/app/editor/history-v2.less | 8 +++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 services/web/public/coffee/ide/history/components/historyLabelsList.coffee diff --git a/services/web/app/views/project/editor/history/entriesListV2.pug b/services/web/app/views/project/editor/history/entriesListV2.pug index e08de0effd..fa1ece2fdf 100644 --- a/services/web/app/views/project/editor/history/entriesListV2.pug +++ b/services/web/app/views/project/editor/history/entriesListV2.pug @@ -3,6 +3,7 @@ aside.change-list( ng-controller="HistoryV2ListController" ) history-entries-list( + ng-if="!history.showOnlyLabels" entries="history.updates" current-user="user" users="projectUsers" @@ -13,6 +14,10 @@ aside.change-list( on-entry-select="handleEntrySelect(selectedEntry)" on-label-delete="handleLabelDelete(label)" ) + history-labels-list( + ng-if="history.showOnlyLabels" + labels="history.labels" + ) aside.change-list( ng-if="history.isV2 && history.viewMode === HistoryViewModes.COMPARE" @@ -193,4 +198,15 @@ script(type="text/ng-template", id="historyEntryTpl") li.history-entry-metadata-user(ng-if="::$ctrl.entry.meta.users.length == 0") span.name( ng-style="$ctrl.getUserCSSStyle();" - ) #{translate("anonymous")} \ No newline at end of file + ) #{translate("anonymous")} + +script(type="text/ng-template", id="historyLabelsListTpl") + history-label( + ng-repeat="label in $ctrl.labels" + show-tooltip="false" + label-text="label.comment" + label-owner-name="$ctrl.displayNameById(label.user_id)" + label-creation-date-time="label.created_at" + is-owned-by-current-user="label.user_id === $ctrl.currentUser.id" + on-label-delete="$ctrl.onLabelDelete({ label: label })" + ) \ No newline at end of file diff --git a/services/web/public/coffee/ide/history/components/historyLabelsList.coffee b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee new file mode 100644 index 0000000000..b692233a7e --- /dev/null +++ b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee @@ -0,0 +1,29 @@ +define [ + "base" + "ide/history/util/displayNameForUser" +], (App, displayNameForUser) -> + historyLabelsListController = ($scope, $element, $attrs) -> + ctrl = @ + # This method (and maybe the one below) will be removed soon. User details data will be + # injected into the history API responses, so we won't need to fetch user data from other + # local data structures. + _getUserById = (id) -> + _.find ctrl.users, (user) -> + curUserId = user?._id or user?.id + curUserId == id + ctrl.displayName = displayNameForUser + ctrl.displayNameById = (id) -> + displayNameForUser(_getUserById(id)) + return + + App.component "historyLabelsList", { + bindings: + labels: "<" + users: "<" + isLoading: "<" + currentUser: "<" + onLabelSelect: "&" + onLabelDelete: "&" + controller: historyLabelsListController + templateUrl: "historyLabelsListTpl" + } diff --git a/services/web/public/stylesheets/app/editor/history-v2.less b/services/web/public/stylesheets/app/editor/history-v2.less index 404609917a..abbcef147d 100644 --- a/services/web/public/stylesheets/app/editor/history-v2.less +++ b/services/web/public/stylesheets/app/editor/history-v2.less @@ -27,6 +27,14 @@ margin-left: (@line-height-computed / 2); } + .history-toolbar-entries-list { + position: absolute; + right: 0; + width: @changesListWidth; + padding: 0 10px; + border-left: 1px solid @editor-border-color; + } + .history-entries { font-size: @history-base-font-size; color: @history-base-color; From cd853abb3c039a9ee0fa912e34502fb90ea30c43 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 8 Aug 2018 11:02:14 +0100 Subject: [PATCH 03/14] Load labels list from the backend. --- .../views/project/editor/history/toolbarV2.pug | 8 ++++++++ .../coffee/ide/history/HistoryV2Manager.coffee | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index 2a4c222bad..8774754de2 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -20,6 +20,14 @@ i.fa.fa-exchange |  #{translate("compare_to_another_version")} + .history-toolbar-entries-list + toggle-switch( + ng-model="history.showOnlyLabels" + label-true="Labels" + label-false="All history" + description="Show all of the project history or only labelled versions." + ) + script(type="text/ng-template", id="historyV2AddLabelModalTemplate") form( name="addLabelModalForm" diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index 7ff41985f4..519a94a54a 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -12,6 +12,7 @@ define [ "ide/history/directives/infiniteScroll" "ide/history/components/historyEntriesList" "ide/history/components/historyEntry" + "ide/history/components/historyLabelsList" "ide/history/components/historyLabel" "ide/history/components/historyFileTree" "ide/history/components/historyFileEntity" @@ -72,6 +73,7 @@ define [ toV: null } } + showOnlyLabels: false labels: null files: [] diff: null # When history.viewMode == HistoryViewModes.COMPARE @@ -134,17 +136,26 @@ define [ updatesURL = "/project/#{@ide.project_id}/updates?min_count=#{@BATCH_SIZE}" if @$scope.history.nextBeforeTimestamp? updatesURL += "&before=#{@$scope.history.nextBeforeTimestamp}" - + labelsURL = "/project/#{@ide.project_id}/labels" + @$scope.history.loading = true @$scope.history.loadingFileTree = true - @ide.$http.get updatesURL + requests = + updates: @ide.$http.get updatesURL + + if !@$scope.history.labels? + requests.labels = @ide.$http.get labelsURL + + @ide.$q.all requests .then (response) => - updatesData = response.data + updatesData = response.updates.data @_loadUpdates(updatesData.updates) @$scope.history.nextBeforeTimestamp = updatesData.nextBeforeTimestamp if !updatesData.nextBeforeTimestamp? @$scope.history.atEnd = true + if response.labels? + @$scope.history.labels = response.labels.data @$scope.history.loading = false loadFileAtPointInTime: () -> From f2b957e5b33fed3931f3197c87208e88de06bc2d Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Wed, 8 Aug 2018 13:46:43 +0100 Subject: [PATCH 04/14] Add history labels view. --- .../web/app/views/project/editor/history.pug | 8 +- .../project/editor/history/entriesListV2.pug | 44 ++- .../history/components/historyEntry.coffee | 6 +- .../history/components/historyLabel.coffee | 4 +- .../components/historyLabelsList.coffee | 16 +- .../HistoryV2ListController.coffee | 3 + .../stylesheets/app/editor/history-v2.less | 349 +----------------- .../stylesheets/app/editor/toolbar.less | 57 +-- 8 files changed, 103 insertions(+), 384 deletions(-) diff --git a/services/web/app/views/project/editor/history.pug b/services/web/app/views/project/editor/history.pug index bfb7df256b..4782a5fa3d 100644 --- a/services/web/app/views/project/editor/history.pug +++ b/services/web/app/views/project/editor/history.pug @@ -70,10 +70,10 @@ script(type="text/ng-template", id="historyRestoreDiffModalTemplate") script(type="text/ng-template", id="historyLabelTpl") - .history-entry-label( - ng-class="{ 'history-entry-label-own' : $ctrl.isOwnedByCurrentUser }" + .history-label( + ng-class="{ 'history-label-own' : $ctrl.isOwnedByCurrentUser }" ) - span.history-entry-label-comment( + span.history-label-comment( tooltip-append-to-body="true" tooltip-template="'historyLabelTooltipTpl'" tooltip-placement="left" @@ -81,7 +81,7 @@ script(type="text/ng-template", id="historyLabelTpl") ) i.fa.fa-tag |  {{ $ctrl.labelText }} - button.history-entry-label-delete-btn( + button.history-label-delete-btn( ng-if="$ctrl.isOwnedByCurrentUser" stop-propagation="click" ng-click="$ctrl.onLabelDelete()" diff --git a/services/web/app/views/project/editor/history/entriesListV2.pug b/services/web/app/views/project/editor/history/entriesListV2.pug index fa1ece2fdf..e8bebabe69 100644 --- a/services/web/app/views/project/editor/history/entriesListV2.pug +++ b/services/web/app/views/project/editor/history/entriesListV2.pug @@ -17,6 +17,11 @@ aside.change-list( history-labels-list( ng-if="history.showOnlyLabels" labels="history.labels" + current-user="user" + users="projectUsers" + is-loading="history.loading" + on-label-select="handleLabelSelect(label)" + on-label-delete="handleLabelDelete(label)" ) aside.change-list( @@ -201,12 +206,33 @@ script(type="text/ng-template", id="historyEntryTpl") ) #{translate("anonymous")} script(type="text/ng-template", id="historyLabelsListTpl") - history-label( - ng-repeat="label in $ctrl.labels" - show-tooltip="false" - label-text="label.comment" - label-owner-name="$ctrl.displayNameById(label.user_id)" - label-creation-date-time="label.created_at" - is-owned-by-current-user="label.user_id === $ctrl.currentUser.id" - on-label-delete="$ctrl.onLabelDelete({ label: label })" - ) \ No newline at end of file + .history-labels-list + .history-entry-label( + ng-repeat="label in $ctrl.labels | orderBy : [ '-version', '-created_at' ] track by label.id" + ng-click="$ctrl.onLabelSelect({ label: label })" + ) + history-label( + show-tooltip="false" + label-text="label.comment" + is-owned-by-current-user="label.user_id === $ctrl.currentUser.id" + on-label-delete="$ctrl.onLabelDelete({ label: label })" + ) + .history-entry-label-metadata + .history-entry-label-metadata-user(ng-init="user = $ctrl.getUserById(label.user_id)") + | Saved by + span.name( + ng-if="user && user._id !== $ctrl.currentUser.id" + ng-style="$ctrl.getUserCSSStyle(user);" + ) {{ ::$ctrl.displayName(user) }} + span.name( + ng-if="user && user._id == $ctrl.currentUser.id" + ng-style="$ctrl.getUserCSSStyle(user);" + ) You + span.name( + ng-if="user == null" + ng-style="$ctrl.getUserCSSStyle(user);" + ) #{translate("anonymous")} + time.history-entry-label-metadata-time {{ ::label.created_at | formatDate }} + .loading(ng-show="$ctrl.isLoading") + i.fa.fa-spin.fa-refresh + |    #{translate("loading")}... \ No newline at end of file diff --git a/services/web/public/coffee/ide/history/components/historyEntry.coffee b/services/web/public/coffee/ide/history/components/historyEntry.coffee index 0942613ef2..8af726b509 100644 --- a/services/web/public/coffee/ide/history/components/historyEntry.coffee +++ b/services/web/public/coffee/ide/history/components/historyEntry.coffee @@ -1,7 +1,8 @@ define [ "base" + "ide/colors/ColorManager" "ide/history/util/displayNameForUser" -], (App, displayNameForUser) -> +], (App, ColorManager, displayNameForUser) -> historyEntryController = ($scope, $element, $attrs, _) -> ctrl = @ # This method (and maybe the one below) will be removed soon. User details data will be @@ -19,7 +20,8 @@ define [ else if projectOp.add? then "#{ projectOp.add.pathname}" else if projectOp.remove? then "#{ projectOp.remove.pathname}" ctrl.getUserCSSStyle = (user) -> - hue = user?.hue or 100 + curUserId = user?._id or user?.id + hue = ColorManager.getHueForUserId(curUserId) or 100 if ctrl.entry.inSelection color : "#FFF" else diff --git a/services/web/public/coffee/ide/history/components/historyLabel.coffee b/services/web/public/coffee/ide/history/components/historyLabel.coffee index 03253663dd..680d610d99 100644 --- a/services/web/public/coffee/ide/history/components/historyLabel.coffee +++ b/services/web/public/coffee/ide/history/components/historyLabel.coffee @@ -10,8 +10,8 @@ define [ App.component "historyLabel", { bindings: labelText: "<" - labelOwnerName: "<" - labelCreationDateTime: "<" + labelOwnerName: " +], (App, ColorManager, displayNameForUser) -> historyLabelsListController = ($scope, $element, $attrs) -> ctrl = @ # This method (and maybe the one below) will be removed soon. User details data will be # injected into the history API responses, so we won't need to fetch user data from other # local data structures. - _getUserById = (id) -> + ctrl.getUserById = (id) -> _.find ctrl.users, (user) -> curUserId = user?._id or user?.id curUserId == id ctrl.displayName = displayNameForUser - ctrl.displayNameById = (id) -> - displayNameForUser(_getUserById(id)) + ctrl.getUserCSSStyle = (user) -> + curUserId = user?._id or user?.id + hue = ColorManager.getHueForUserId(curUserId) or 100 + if false #ctrl.entry.inSelection + color : "#FFF" + else + color: "hsl(#{ hue }, 70%, 50%)" return App.component "historyLabelsList", { bindings: labels: "<" users: "<" - isLoading: "<" currentUser: "<" + isLoading: "<" onLabelSelect: "&" onLabelDelete: "&" controller: historyLabelsListController diff --git a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee index f7c602733f..a2873d47d8 100644 --- a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee +++ b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee @@ -16,6 +16,9 @@ define [ ide.historyManager.selectUpdate(entry) $scope.recalculateSelectedUpdates() + $scope.handleLabelSelect = (label) -> + console.log label + $scope.handleLabelDelete = (labelDetails) -> $modal.open( templateUrl: "historyV2DeleteLabelModalTemplate" diff --git a/services/web/public/stylesheets/app/editor/history-v2.less b/services/web/public/stylesheets/app/editor/history-v2.less index abbcef147d..c2e7ce6b26 100644 --- a/services/web/public/stylesheets/app/editor/history-v2.less +++ b/services/web/public/stylesheets/app/editor/history-v2.less @@ -61,8 +61,7 @@ color: #FFF; } } - - .history-entry-label { + .history-label { display: inline-block; color: @history-entry-label-color; font-size: @font-size-small; @@ -73,8 +72,8 @@ color: @history-entry-selected-label-color; } } - .history-entry-label-comment, - .history-entry-label-delete-btn { + .history-label-comment, + .history-label-delete-btn { padding: 0 @padding-xs-horizontal 1px @padding-xs-horizontal; border: 0; background-color: @history-entry-label-bg-color; @@ -82,19 +81,19 @@ background-color: @history-entry-selected-label-bg-color; } } - .history-entry-label-comment { + .history-label-comment { display: block; float: left; border-radius: 9999px; max-width: 190px; overflow: hidden; text-overflow: ellipsis; - .history-entry-label-own & { + .history-label-own & { padding-right: (@padding-xs-horizontal / 2); border-radius: 9999px 0 0 9999px; } } - .history-entry-label-delete-btn { + .history-label-delete-btn { padding-left: (@padding-xs-horizontal / 2); padding-right: @padding-xs-horizontal; border-radius: 0 9999px 9999px 0; @@ -163,6 +162,15 @@ } } +.history-labels-list { + .history-entries; + overflow-y: auto; +} + .history-entry-label { + .history-entry-details; + padding: 7px 10px; + } + .history-file-tree-inner { .full-size; overflow-y: auto; @@ -239,330 +247,3 @@ color: @brand-primary; } } -// @changesListWidth: 250px; -// @changesListPadding: @line-height-computed / 2; - -// @selector-padding-vertical: 10px; -// @selector-padding-horizontal: @line-height-computed / 2; -// @day-header-height: 24px; - -// @range-bar-color: @link-color; -// @range-bar-selected-offset: 14px; - -// #history { -// .upgrade-prompt { -// position: absolute; -// top: 0; -// bottom: 0; -// left: 0; -// right: 0; -// z-index: 100; -// background-color: rgba(128,128,128,0.4); -// .message { -// margin: auto; -// margin-top: 100px; -// padding: (@line-height-computed / 2) @line-height-computed; -// width: 400px; -// background-color: white; -// border-radius: 8px; -// } -// .message-wider { -// width: 650px; -// margin-top: 60px; -// padding: 0; -// } - -// .message-header { -// .modal-header; -// } - -// .message-body { -// .modal-body; -// } -// } - -// .diff-panel { -// .full-size; -// margin-right: @changesListWidth; -// } - -// .diff { -// .full-size; -// .toolbar { -// padding: 3px; -// .name { -// float: left; -// padding: 3px @line-height-computed / 4; -// display: inline-block; -// } -// } -// .diff-editor { -// .full-size; -// top: 40px; -// } -// .hide-ace-cursor { -// .ace_active-line, .ace_cursor-layer, .ace_gutter-active-line { -// display: none; -// } -// } -// .diff-deleted { -// padding: @line-height-computed; -// } -// .deleted-warning { -// background-color: @brand-danger; -// color: white; -// padding: @line-height-computed / 2; -// margin-right: @line-height-computed / 4; -// } -// &-binary { -// .alert { -// margin: @line-height-computed / 2; -// } -// } -// } - -// aside.change-list { -// border-left: 1px solid @editor-border-color; -// height: 100%; -// width: @changesListWidth; -// position: absolute; -// right: 0; - -// .loading { -// text-align: center; -// font-family: @font-family-serif; -// } - -// ul { -// li.change { -// position: relative; -// user-select: none; -// -ms-user-select: none; -// -moz-user-select: none; -// -webkit-user-select: none; - -// .day { -// background-color: #fafafa; -// border-bottom: 1px solid @editor-border-color; -// padding: 4px; -// font-weight: bold; -// text-align: center; -// height: @day-header-height; -// font-size: 14px; -// line-height: 1; -// } -// .selectors { -// input { -// margin: 0; -// } -// position: absolute; -// left: @selector-padding-horizontal; -// top: 0; -// bottom: 0; -// width: 24px; -// .selector-from { -// position: absolute; -// bottom: @selector-padding-vertical; -// left: 0; -// opacity: 0.8; -// } -// .selector-to { -// position: absolute; -// top: @selector-padding-vertical; -// left: 0; -// opacity: 0.8; -// } -// .range { -// position: absolute; -// left: 5px; -// width: 4px; -// top: 0; -// bottom: 0; -// } -// } -// .description { -// padding: (@line-height-computed / 4); -// padding-left: 38px; -// min-height: 38px; -// border-bottom: 1px solid @editor-border-color; -// cursor: pointer; -// &:hover { -// background-color: @gray-lightest; -// } -// } -// .users { -// .user { -// font-size: 0.8rem; -// color: @gray; -// text-transform: capitalize; -// position: relative; -// padding-left: 16px; -// .color-square { -// height: 12px; -// width: 12px; -// border-radius: 3px; -// position: absolute; -// left: 0; -// bottom: 3px; -// } -// .name { -// width: 94%; -// white-space: nowrap; -// overflow: hidden; -// text-overflow: ellipsis; -// } -// } -// } -// .time { -// float: right; -// color: @gray; -// display: inline-block; -// padding-right: (@line-height-computed / 2); -// font-size: 0.8rem; -// line-height: @line-height-computed; -// } -// .doc { -// font-size: 0.9rem; -// font-weight: bold; -// } -// .action { -// color: @gray; -// text-transform: uppercase; -// font-size: 0.7em; -// margin-bottom: -2px; -// margin-top: 2px; -// &-edited { -// margin-top: 0; -// } -// } -// } -// li.loading-changes, li.empty-message { -// padding: 6px; -// cursor: default; -// &:hover { -// background-color: inherit; -// } -// } -// li.selected { -// border-left: 4px solid @range-bar-color; -// .day { -// padding-left: 0; -// } -// .description { -// padding-left: 34px; -// } -// .selectors { -// left: @selector-padding-horizontal - 4px; -// .range { -// background-color: @range-bar-color; -// } -// } -// } -// li.selected-to { -// .selectors { -// .range { -// top: @range-bar-selected-offset; -// } -// .selector-to { -// opacity: 1; -// } -// } -// } -// li.selected-from { -// .selectors { -// .range { -// bottom: @range-bar-selected-offset; -// } -// .selector-from { -// opacity: 1; -// } -// } -// } -// li.first-in-day { -// .selectors { -// .selector-to { -// top: @day-header-height + @selector-padding-vertical; -// } -// } -// } -// li.first-in-day.selected-to { -// .selectors { -// .range { -// top: @day-header-height + @range-bar-selected-offset; -// } -// } -// } -// } -// ul.hover-state { -// li { -// .selectors { -// .range { -// background-color: transparent; -// top: 0; -// bottom: 0; -// } -// } -// } -// li.hover-selected { -// .selectors { -// .range { -// top: 0; -// background-color: @gray-light; -// } -// } -// } -// li.hover-selected-to { -// .selectors { -// .range { -// top: @range-bar-selected-offset; -// } -// .selector-to { -// opacity: 1; -// } -// } -// } -// li.hover-selected-from { -// .selectors { -// .range { -// bottom: @range-bar-selected-offset; -// } -// .selector-from { -// opacity: 1; -// } -// } -// } -// li.first-in-day.hover-selected-to { -// .selectors { -// .range { -// top: @day-header-height + @range-bar-selected-offset; -// } -// } -// } -// } -// } -// } - -// .diff-deleted { -// padding-top: 15px; -// } - -// .editor-dark { -// #history { -// aside.change-list { -// border-color: @editor-dark-toolbar-border-color; - -// ul li.change { -// .day { -// background-color: darken(@editor-dark-background-color, 10%); -// border-bottom: 1px solid @editor-dark-toolbar-border-color; -// } -// .description { -// border-bottom: 1px solid @editor-dark-toolbar-border-color; -// &:hover { -// background-color: black; -// } -// } -// } -// } -// } -// } diff --git a/services/web/public/stylesheets/app/editor/toolbar.less b/services/web/public/stylesheets/app/editor/toolbar.less index 4006b56a7b..c5499180e0 100644 --- a/services/web/public/stylesheets/app/editor/toolbar.less +++ b/services/web/public/stylesheets/app/editor/toolbar.less @@ -194,56 +194,57 @@ } .toggle-switch { - position: relative; + position: relative; height: 100%; width: 100%; - background-color: @toggle-switch-bg; - border-radius: @btn-border-radius-base; + background-color: @toggle-switch-bg; + border-radius: @btn-border-radius-base; } .toggle-switch-label { position: relative; display: block; font-weight: normal; - z-index: 2; - float: left; - width: 50%; - height: 100%; - line-height: 24px; + z-index: 2; + float: left; + width: 50%; + height: 100%; + line-height: 24px; text-align: center; margin-bottom: 0; - cursor: pointer; - user-select: none; - transition: color 0.12s ease-out; + cursor: pointer; + user-select: none; + color: @text-color; + transition: color 0.12s ease-out; } .toggle-switch-input { - position: absolute; - opacity: 0; + position: absolute; + opacity: 0; } .toggle-switch-input:checked + .toggle-switch-label { - color: #fff; - font-weight: bold; + color: #fff; + font-weight: bold; } .toggle-switch-selection { - display: block; - position: absolute; - z-index: 1; - top: 2px; - left: 2px; - right: 2px; - width: calc(~"50% - 2px"); - height: calc(~"100% - 4px"); - background: @toggle-switch-highlight-color; - border-radius: @btn-border-radius-base 0 0 @btn-border-radius-base; - transition: transform 0.12s ease-out, border-radius 0.12s ease-out; + display: block; + position: absolute; + z-index: 1; + top: 2px; + left: 2px; + right: 2px; + width: calc(~"50% - 2px"); + height: calc(~"100% - 4px"); + background: @toggle-switch-highlight-color; + border-radius: @btn-border-radius-base 0 0 @btn-border-radius-base; + transition: transform 0.12s ease-out, border-radius 0.12s ease-out; } .toggle-switch-input:checked:nth-child(4) ~ .toggle-switch-selection { - transform: translate(100%); - border-radius: 0 @btn-border-radius-base @btn-border-radius-base 0; + transform: translate(100%); + border-radius: 0 @btn-border-radius-base @btn-border-radius-base 0; } /************************************** From d59fe61a83feb9775066012378968e4df14199f7 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 9 Aug 2018 11:03:00 +0100 Subject: [PATCH 05/14] Handle sorting of labels; keep selection between view changes. --- .../project/editor/history/entriesListV2.pug | 11 +-- .../project/editor/history/toolbarV2.pug | 1 + .../ide/history/HistoryV2Manager.coffee | 69 +++++++++++++++---- .../components/historyLabelsList.coffee | 4 +- ...HistoryV2DeleteLabelModalController.coffee | 2 +- .../HistoryV2ListController.coffee | 5 +- .../web/public/coffee/ide/services/ide.coffee | 3 +- .../stylesheets/app/editor/history-v2.less | 19 +++-- 8 files changed, 85 insertions(+), 29 deletions(-) diff --git a/services/web/app/views/project/editor/history/entriesListV2.pug b/services/web/app/views/project/editor/history/entriesListV2.pug index e8bebabe69..3f936a8d11 100644 --- a/services/web/app/views/project/editor/history/entriesListV2.pug +++ b/services/web/app/views/project/editor/history/entriesListV2.pug @@ -152,7 +152,7 @@ script(type="text/ng-template", id="historyEntryTpl") .history-entry-details(ng-click="$ctrl.onSelect({ selectedEntry: $ctrl.entry })") history-label( - ng-repeat="label in $ctrl.entry.labels" + ng-repeat="label in $ctrl.entry.labels | orderBy : '-created_at'" label-text="label.comment" label-owner-name="$ctrl.displayNameById(label.user_id)" label-creation-date-time="label.created_at" @@ -208,8 +208,9 @@ script(type="text/ng-template", id="historyEntryTpl") script(type="text/ng-template", id="historyLabelsListTpl") .history-labels-list .history-entry-label( - ng-repeat="label in $ctrl.labels | orderBy : [ '-version', '-created_at' ] track by label.id" + ng-repeat="label in $ctrl.labels track by label.id" ng-click="$ctrl.onLabelSelect({ label: label })" + ng-class="{ 'history-entry-label-selected': label.selected }" ) history-label( show-tooltip="false" @@ -222,15 +223,15 @@ script(type="text/ng-template", id="historyLabelsListTpl") | Saved by span.name( ng-if="user && user._id !== $ctrl.currentUser.id" - ng-style="$ctrl.getUserCSSStyle(user);" + ng-style="$ctrl.getUserCSSStyle(user, label);" ) {{ ::$ctrl.displayName(user) }} span.name( ng-if="user && user._id == $ctrl.currentUser.id" - ng-style="$ctrl.getUserCSSStyle(user);" + ng-style="$ctrl.getUserCSSStyle(user, label);" ) You span.name( ng-if="user == null" - ng-style="$ctrl.getUserCSSStyle(user);" + ng-style="$ctrl.getUserCSSStyle(user, label);" ) #{translate("anonymous")} time.history-entry-label-metadata-time {{ ::label.created_at | formatDate }} .loading(ng-show="$ctrl.isLoading") diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index 8774754de2..6abe167f42 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -9,6 +9,7 @@ time.history-toolbar-time {{ history.selection.updates[0].meta.end_ts | formatDate:'Do MMM YYYY, h:mm a' }} button.history-toolbar-btn( ng-click="showAddLabelDialog();" + ng-if="!history.showOnlyLabels" ng-disabled="history.loadingFileTree" ) i.fa.fa-tag diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index 519a94a54a..2e56d955ce 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -49,6 +49,10 @@ define [ else @reloadDiff() + @$scope.$watch "history.showOnlyLabels", (showOnlyLabels, prevVal) => + if showOnlyLabels? and showOnlyLabels != prevVal and showOnlyLabels + @selectedLabelFromUpdatesSelection() + show: () -> @$scope.ui.view = "history" @reset() @@ -131,6 +135,36 @@ define [ @$scope.history.updates[selectedUpdateIndex].selectedFrom = true @loadFileTreeForUpdate @$scope.history.updates[selectedUpdateIndex] + selectLastLabel = () -> + return if @$scope.history.labels.length == 0 + # TODO Select last label + + selectedLabelFromUpdatesSelection: () -> + nLabels = @$scope.history.selection.updates?[0]?.labels?.length + if nLabels == 1 + @selectLabel @$scope.history.selection.updates[0].labels[0] + else if nLabels > 1 + sortedLabels = @ide.$filter("orderBy")(@$scope.history.selection.updates[0].labels, '-created_at') + lastLabelFromUpdate = sortedLabels[0] + @selectLabel lastLabelFromUpdate + + selectLabel: (labelToSelect) -> + labelToSelectIndex = -1 + for update, i in @$scope.history.updates + if update.toV == labelToSelect.version + labelToSelectIndex = i + break + if labelToSelectIndex == -1 + labelToSelectIndex = 0 + for update in @$scope.history.updates + update.selectedTo = false + update.selectedFrom = false + for label in @$scope.history.labels + label.selected = (labelToSelect.id == label.id) + @$scope.history.updates[labelToSelectIndex].selectedTo = true + @$scope.history.updates[labelToSelectIndex].selectedFrom = true + @loadFileTreeForUpdate @$scope.history.updates[labelToSelectIndex] + BATCH_SIZE: 10 fetchNextBatchOfUpdates: () -> updatesURL = "/project/#{@ide.project_id}/updates?min_count=#{@BATCH_SIZE}" @@ -155,9 +189,12 @@ define [ if !updatesData.nextBeforeTimestamp? @$scope.history.atEnd = true if response.labels? - @$scope.history.labels = response.labels.data + @$scope.history.labels = @_sortLabelsByVersionAndDate response.labels.data @$scope.history.loading = false + _sortLabelsByVersionAndDate: (labels) -> + @ide.$filter("orderBy")(labels, [ '-version', '-created_at' ]) + loadFileAtPointInTime: () -> pathname = @$scope.history.selection.pathname toV = @$scope.history.selection.updates[0].toV @@ -219,8 +256,8 @@ define [ labelCurrentVersion: (labelComment) => @_labelVersion labelComment, @$scope.history.selection.updates[0].toV - deleteLabel: (labelId) => - url = "/project/#{@$scope.project_id}/labels/#{labelId}" + deleteLabel: (label) => + url = "/project/#{@$scope.project_id}/labels/#{label.id}" @ide.$http({ url, @@ -228,14 +265,16 @@ define [ headers: "X-CSRF-Token": window.csrfToken }).then (response) => - @_deleteLabelFromLocalCollection @$scope.history.updates, labelId - @_deleteLabelFromLocalCollection @$scope.history.selection, labelId + @_deleteLabelLocally label - - _deleteLabelFromLocalCollection: (collection, labelId) -> - for update in collection - update.labels = _.filter update.labels, (label) -> - label.id != labelId + _deleteLabelLocally: (labelToDelete) -> + for update, i in @$scope.history.updates + if update.toV == labelToDelete.version + update.labels = _.filter update.labels, (label) -> + label.id != labelToDelete.id + break + @$scope.history.labels = _.filter @$scope.history.labels, (label) -> + label.id != labelToDelete.id _parseDiff: (diff) -> if diff.binary @@ -314,7 +353,10 @@ define [ if @$scope.history.viewMode == HistoryViewModes.COMPARE @autoSelectRecentUpdates() else - @autoSelectLastUpdate() + if @$scope.history.showOnlyLabels + @selectLastLabel() + else + @autoSelectLastUpdate() _labelVersion: (comment, version) -> url = "/project/#{@$scope.project_id}/labels" @@ -327,10 +369,11 @@ define [ .then (response) => @_addLabelToLocalUpdate response.data - _addLabelToLocalUpdate: (label) -> + _addLabelToLocalUpdate: (label) => localUpdate = _.find @$scope.history.updates, (update) -> update.toV == label.version if localUpdate? - localUpdate.labels.push label + localUpdate.labels = @_sortLabelsByVersionAndDate localUpdate.labels.concat label + @$scope.history.labels = @_sortLabelsByVersionAndDate @$scope.history.labels.concat label _perDocSummaryOfUpdates: (updates) -> # Track current_pathname -> original_pathname diff --git a/services/web/public/coffee/ide/history/components/historyLabelsList.coffee b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee index b95700250f..44c9a54742 100644 --- a/services/web/public/coffee/ide/history/components/historyLabelsList.coffee +++ b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee @@ -13,10 +13,10 @@ define [ curUserId = user?._id or user?.id curUserId == id ctrl.displayName = displayNameForUser - ctrl.getUserCSSStyle = (user) -> + ctrl.getUserCSSStyle = (user, label) -> curUserId = user?._id or user?.id hue = ColorManager.getHueForUserId(curUserId) or 100 - if false #ctrl.entry.inSelection + if label.selected color : "#FFF" else color: "hsl(#{ hue }, 70%, 50%)" diff --git a/services/web/public/coffee/ide/history/controllers/HistoryV2DeleteLabelModalController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryV2DeleteLabelModalController.coffee index d03786c2c6..6001c33762 100644 --- a/services/web/public/coffee/ide/history/controllers/HistoryV2DeleteLabelModalController.coffee +++ b/services/web/public/coffee/ide/history/controllers/HistoryV2DeleteLabelModalController.coffee @@ -9,7 +9,7 @@ define [ $scope.deleteLabel = () -> $scope.state.inflight = true - ide.historyManager.deleteLabel labelDetails.id + ide.historyManager.deleteLabel labelDetails .then (response) -> $scope.state.inflight = false $modalInstance.close() diff --git a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee index a2873d47d8..7129e0374c 100644 --- a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee +++ b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee @@ -17,8 +17,9 @@ define [ $scope.recalculateSelectedUpdates() $scope.handleLabelSelect = (label) -> - console.log label - + ide.historyManager.selectLabel(label) + $scope.recalculateSelectedUpdates() + $scope.handleLabelDelete = (labelDetails) -> $modal.open( templateUrl: "historyV2DeleteLabelModalTemplate" diff --git a/services/web/public/coffee/ide/services/ide.coffee b/services/web/public/coffee/ide/services/ide.coffee index 6462859df2..f9c61b4114 100644 --- a/services/web/public/coffee/ide/services/ide.coffee +++ b/services/web/public/coffee/ide/services/ide.coffee @@ -3,11 +3,12 @@ define [ ], (App) -> # We create and provide this as service so that we can access the global ide # from within other parts of the angular app. - App.factory "ide", ["$http", "queuedHttp", "$modal", "$q", ($http, queuedHttp, $modal, $q) -> + App.factory "ide", ["$http", "queuedHttp", "$modal", "$q", "$filter", ($http, queuedHttp, $modal, $q, $filter) -> ide = {} ide.$http = $http ide.queuedHttp = queuedHttp ide.$q = $q + ide.$filter = $filter @recentEvents = [] ide.pushEvent = (type, meta = {}) => diff --git a/services/web/public/stylesheets/app/editor/history-v2.less b/services/web/public/stylesheets/app/editor/history-v2.less index c2e7ce6b26..7bb10f88f2 100644 --- a/services/web/public/stylesheets/app/editor/history-v2.less +++ b/services/web/public/stylesheets/app/editor/history-v2.less @@ -56,7 +56,8 @@ padding: 5px 10px; cursor: pointer; - .history-entry-selected & { + .history-entry-selected &, + .history-entry-label-selected & { background-color: @history-entry-selected-bg; color: #FFF; } @@ -68,7 +69,8 @@ margin-bottom: 3px; margin-right: 10px; white-space: nowrap; - .history-entry-selected & { + .history-entry-selected &, + .history-entry-label-selected & { color: @history-entry-selected-label-color; } } @@ -77,7 +79,8 @@ padding: 0 @padding-xs-horizontal 1px @padding-xs-horizontal; border: 0; background-color: @history-entry-label-bg-color; - .history-entry-selected & { + .history-entry-selected &, + .history-entry-label-selected & { background-color: @history-entry-selected-label-bg-color; } } @@ -99,7 +102,8 @@ border-radius: 0 9999px 9999px 0; &:hover { background-color: darken(@history-entry-label-bg-color, 8%); - .history-entry-selected & { + .history-entry-selected &, + .history-entry-label-selected & { background-color: darken(@history-entry-selected-label-bg-color, 8%); } } @@ -137,7 +141,8 @@ color: @history-highlight-color; font-weight: bold; word-break: break-all; - .history-entry-selected & { + .history-entry-selected &, + .history-entry-label-selected & { color: #FFF; } } @@ -169,6 +174,10 @@ .history-entry-label { .history-entry-details; padding: 7px 10px; + &.history-entry-label-selected { + background-color: @history-entry-selected-bg; + color: #FFF; + } } .history-file-tree-inner { From 7e86218b212f4ca06f1793c5e0c0573a35636166 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 10 Aug 2018 11:28:17 +0100 Subject: [PATCH 06/14] Allow multiple events to trigger layout external resizes. --- services/web/app/views/project/editor.pug | 2 +- .../public/coffee/ide/directives/layout.coffee | 3 ++- .../coffee/ide/history/HistoryV2Manager.coffee | 17 ++++++++++------- .../web/public/coffee/ide/services/ide.coffee | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/services/web/app/views/project/editor.pug b/services/web/app/views/project/editor.pug index 6d7d18687d..08124c334c 100644 --- a/services/web/app/views/project/editor.pug +++ b/services/web/app/views/project/editor.pug @@ -65,7 +65,7 @@ block content ng-class="{ 'ide-history-open' : (ui.view == 'history' && history.isV2 && history.viewMode === HistoryViewModes.POINT_IN_TIME) }", layout="main", ng-hide="state.loading", - resize-on="layout:chat:resize", + resize-on="layout:chat:resize,history:toggle", minimum-restore-size-west="130" custom-toggler-pane=hasFeature('custom-togglers') ? "'west'" : "false" custom-toggler-msg-when-open=hasFeature('custom-togglers') ? "'" + translate("tooltip_hide_filetree") + "'" : "false" diff --git a/services/web/public/coffee/ide/directives/layout.coffee b/services/web/public/coffee/ide/directives/layout.coffee index b4e2e7f83d..8c30943f39 100644 --- a/services/web/public/coffee/ide/directives/layout.coffee +++ b/services/web/public/coffee/ide/directives/layout.coffee @@ -112,7 +112,8 @@ define [ element.layout().resizeAll() if attrs.resizeOn? - scope.$on attrs.resizeOn, () -> onExternalResize() + for event in attrs.resizeOn.split "," + scope.$on event, () -> onExternalResize() if hasCustomToggler state = element.layout().readState() diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index 2e56d955ce..e7a2c071e3 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -27,6 +27,9 @@ define [ @hide() else @show() + @ide.$timeout () => + @$scope.$broadcast "history:toggle" + , 0 @$scope.toggleHistoryViewMode = () => if @$scope.history.viewMode == HistoryViewModes.COMPARE @@ -124,6 +127,10 @@ define [ return if @$scope.history.updates.length == 0 @selectUpdate @$scope.history.updates[0] + autoSelectLastLabel: () -> + return if @$scope.history.labels.length == 0 + @selectLabel @$scope.history.labels[0] + selectUpdate: (update) -> selectedUpdateIndex = @$scope.history.updates.indexOf update if selectedUpdateIndex == -1 @@ -135,10 +142,6 @@ define [ @$scope.history.updates[selectedUpdateIndex].selectedFrom = true @loadFileTreeForUpdate @$scope.history.updates[selectedUpdateIndex] - selectLastLabel = () -> - return if @$scope.history.labels.length == 0 - # TODO Select last label - selectedLabelFromUpdatesSelection: () -> nLabels = @$scope.history.selection.updates?[0]?.labels?.length if nLabels == 1 @@ -184,12 +187,12 @@ define [ @ide.$q.all requests .then (response) => updatesData = response.updates.data + if response.labels? + @$scope.history.labels = @_sortLabelsByVersionAndDate response.labels.data @_loadUpdates(updatesData.updates) @$scope.history.nextBeforeTimestamp = updatesData.nextBeforeTimestamp if !updatesData.nextBeforeTimestamp? @$scope.history.atEnd = true - if response.labels? - @$scope.history.labels = @_sortLabelsByVersionAndDate response.labels.data @$scope.history.loading = false _sortLabelsByVersionAndDate: (labels) -> @@ -354,7 +357,7 @@ define [ @autoSelectRecentUpdates() else if @$scope.history.showOnlyLabels - @selectLastLabel() + @autoSelectLastLabel() else @autoSelectLastUpdate() diff --git a/services/web/public/coffee/ide/services/ide.coffee b/services/web/public/coffee/ide/services/ide.coffee index f9c61b4114..24805b6270 100644 --- a/services/web/public/coffee/ide/services/ide.coffee +++ b/services/web/public/coffee/ide/services/ide.coffee @@ -3,12 +3,13 @@ define [ ], (App) -> # We create and provide this as service so that we can access the global ide # from within other parts of the angular app. - App.factory "ide", ["$http", "queuedHttp", "$modal", "$q", "$filter", ($http, queuedHttp, $modal, $q, $filter) -> + App.factory "ide", ["$http", "queuedHttp", "$modal", "$q", "$filter", "$timeout", ($http, queuedHttp, $modal, $q, $filter, $timeout) -> ide = {} ide.$http = $http ide.queuedHttp = queuedHttp ide.$q = $q ide.$filter = $filter + ide.$timeout = $timeout @recentEvents = [] ide.pushEvent = (type, meta = {}) => From c13e0264e555ec7bb190eb2bd4221cf85c6ee04b Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 10 Aug 2018 14:07:35 +0100 Subject: [PATCH 07/14] Fix a few bugs related to keeping the selection when moving from labels to full history. --- .../ide/history/HistoryV2Manager.coffee | 84 ++++++++++++++----- .../HistoryV2ListController.coffee | 62 -------------- 2 files changed, 62 insertions(+), 84 deletions(-) diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index e7a2c071e3..e8a3f46f24 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -53,8 +53,15 @@ define [ @reloadDiff() @$scope.$watch "history.showOnlyLabels", (showOnlyLabels, prevVal) => - if showOnlyLabels? and showOnlyLabels != prevVal and showOnlyLabels - @selectedLabelFromUpdatesSelection() + if showOnlyLabels? and showOnlyLabels != prevVal + if showOnlyLabels + @selectedLabelFromUpdatesSelection() + else + if @$scope.history.selection.updates.length == 0 + @autoSelectLastUpdate() + + @$scope.$watch "history.updates.length", () => + @recalculateSelectedUpdates() show: () -> @$scope.ui.view = "history" @@ -95,10 +102,9 @@ define [ _csrf: window.csrfToken }) - loadFileTreeForUpdate: (update) -> - {fromV, toV} = update + loadFileTreeForVersion: (version) -> url = "/project/#{@$scope.project_id}/filetree/diff" - query = [ "from=#{toV}", "to=#{toV}" ] + query = [ "from=#{version}", "to=#{version}" ] url += "?" + query.join("&") @$scope.history.loadingFileTree = true @$scope.history.selectedFile = null @@ -140,33 +146,66 @@ define [ update.selectedFrom = false @$scope.history.updates[selectedUpdateIndex].selectedTo = true @$scope.history.updates[selectedUpdateIndex].selectedFrom = true - @loadFileTreeForUpdate @$scope.history.updates[selectedUpdateIndex] + @recalculateSelectedUpdates() + @loadFileTreeForVersion @$scope.history.updates[selectedUpdateIndex].toV selectedLabelFromUpdatesSelection: () -> - nLabels = @$scope.history.selection.updates?[0]?.labels?.length - if nLabels == 1 + # Get the number of labels associated with the currently selected update + nSelectedLabels = @$scope.history.selection.updates?[0]?.labels?.length + # If the currently selected update has no labels, select the last one (version-wise) + if nSelectedLabels == 0 + @autoSelectLastLabel() + # If the update has one label, select it + else if nSelectedLabels == 1 @selectLabel @$scope.history.selection.updates[0].labels[0] - else if nLabels > 1 + # If there are multiple labels for the update, select the latest + else if nSelectedLabels > 1 sortedLabels = @ide.$filter("orderBy")(@$scope.history.selection.updates[0].labels, '-created_at') lastLabelFromUpdate = sortedLabels[0] @selectLabel lastLabelFromUpdate selectLabel: (labelToSelect) -> - labelToSelectIndex = -1 - for update, i in @$scope.history.updates - if update.toV == labelToSelect.version - labelToSelectIndex = i - break - if labelToSelectIndex == -1 - labelToSelectIndex = 0 + updateToSelect = null + alreadySelected = false for update in @$scope.history.updates - update.selectedTo = false - update.selectedFrom = false + if update.toV == labelToSelect.version + updateToSelect = update + break + for label in @$scope.history.labels - label.selected = (labelToSelect.id == label.id) - @$scope.history.updates[labelToSelectIndex].selectedTo = true - @$scope.history.updates[labelToSelectIndex].selectedFrom = true - @loadFileTreeForUpdate @$scope.history.updates[labelToSelectIndex] + matchingLabel = (labelToSelect.id == label.id) + if matchingLabel and label.selected + alreadySelected = true + label.selected = matchingLabel + + if alreadySelected + return + + if updateToSelect? + @selectUpdate updateToSelect + else + @$scope.history.selection.updates = [] + @loadFileTreeForVersion labelToSelect.version + + recalculateSelectedUpdates: () -> + beforeSelection = true + afterSelection = false + @$scope.history.selection.updates = [] + for update in @$scope.history.updates + if update.selectedTo + inSelection = true + beforeSelection = false + + update.beforeSelection = beforeSelection + update.inSelection = inSelection + update.afterSelection = afterSelection + + if inSelection + @$scope.history.selection.updates.push update + + if update.selectedFrom + inSelection = false + afterSelection = true BATCH_SIZE: 10 fetchNextBatchOfUpdates: () -> @@ -199,6 +238,7 @@ define [ @ide.$filter("orderBy")(labels, [ '-version', '-created_at' ]) loadFileAtPointInTime: () -> + console.log @$scope.history.selection.pathname, @$scope.history.selection.updates pathname = @$scope.history.selection.pathname toV = @$scope.history.selection.updates[0].toV url = "/project/#{@$scope.project_id}/diff" diff --git a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee index 7129e0374c..55c2d791a9 100644 --- a/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee +++ b/services/web/public/coffee/ide/history/controllers/HistoryV2ListController.coffee @@ -14,11 +14,9 @@ define [ $scope.handleEntrySelect = (entry) -> ide.historyManager.selectUpdate(entry) - $scope.recalculateSelectedUpdates() $scope.handleLabelSelect = (label) -> ide.historyManager.selectLabel(label) - $scope.recalculateSelectedUpdates() $scope.handleLabelDelete = (labelDetails) -> $modal.open( @@ -27,64 +25,4 @@ define [ resolve: labelDetails: () -> labelDetails ) - - $scope.recalculateSelectedUpdates = () -> - beforeSelection = true - afterSelection = false - $scope.history.selection.updates = [] - for update in $scope.history.updates - if update.selectedTo - inSelection = true - beforeSelection = false - - update.beforeSelection = beforeSelection - update.inSelection = inSelection - update.afterSelection = afterSelection - - if inSelection - $scope.history.selection.updates.push update - - if update.selectedFrom - inSelection = false - afterSelection = true - - $scope.recalculateHoveredUpdates = () -> - hoverSelectedFrom = false - hoverSelectedTo = false - for update in $scope.history.updates - # Figure out whether the to or from selector is hovered over - if update.hoverSelectedFrom - hoverSelectedFrom = true - if update.hoverSelectedTo - hoverSelectedTo = true - - if hoverSelectedFrom - # We want to 'hover select' everything between hoverSelectedFrom and selectedTo - inHoverSelection = false - for update in $scope.history.updates - if update.selectedTo - update.hoverSelectedTo = true - inHoverSelection = true - update.inHoverSelection = inHoverSelection - if update.hoverSelectedFrom - inHoverSelection = false - if hoverSelectedTo - # We want to 'hover select' everything between hoverSelectedTo and selectedFrom - inHoverSelection = false - for update in $scope.history.updates - if update.hoverSelectedTo - inHoverSelection = true - update.inHoverSelection = inHoverSelection - if update.selectedFrom - update.hoverSelectedFrom = true - inHoverSelection = false - - $scope.resetHoverState = () -> - for update in $scope.history.updates - delete update.hoverSelectedFrom - delete update.hoverSelectedTo - delete update.inHoverSelection - - $scope.$watch "history.updates.length", () -> - $scope.recalculateSelectedUpdates() ] \ No newline at end of file From 035ff0a1f0b0984560d9589f289db86fa66d8dce Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 10 Aug 2018 15:57:10 +0100 Subject: [PATCH 08/14] More bugfixing. --- .../public/coffee/ide/history/HistoryV2Manager.coffee | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index e8a3f46f24..ddd098a5f5 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -238,9 +238,15 @@ define [ @ide.$filter("orderBy")(labels, [ '-version', '-created_at' ]) loadFileAtPointInTime: () -> - console.log @$scope.history.selection.pathname, @$scope.history.selection.updates pathname = @$scope.history.selection.pathname - toV = @$scope.history.selection.updates[0].toV + if @$scope.history.selection.updates?[0]? + toV = @$scope.history.selection.updates[0].toV + else + for label in @$scope.history.labels or [] + if label.selected + toV = label.version + if !toV? + return url = "/project/#{@$scope.project_id}/diff" query = ["pathname=#{encodeURIComponent(pathname)}", "from=#{toV}", "to=#{toV}"] url += "?" + query.join("&") From 2ee42af1de4fd6e0408840050041d8aaf2b8efa1 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Mon, 13 Aug 2018 13:39:25 +0100 Subject: [PATCH 09/14] Change strategy to store selected label; improve the history toolbar layout to accomodate larger labels; fix issues with layout not being updated when changing history view modes. --- .../project/editor/history/entriesListV2.pug | 3 +- .../project/editor/history/toolbarV2.pug | 37 +++++++++++-------- .../ide/history/HistoryV2Manager.coffee | 31 +++++++++------- .../components/historyLabelsList.coffee | 3 +- .../stylesheets/app/editor/history-v2.less | 32 +++++++++------- 5 files changed, 62 insertions(+), 44 deletions(-) diff --git a/services/web/app/views/project/editor/history/entriesListV2.pug b/services/web/app/views/project/editor/history/entriesListV2.pug index 345eab8dd6..21c2438742 100644 --- a/services/web/app/views/project/editor/history/entriesListV2.pug +++ b/services/web/app/views/project/editor/history/entriesListV2.pug @@ -20,6 +20,7 @@ aside.change-list( current-user="user" users="projectUsers" is-loading="history.loading" + selected-label="history.selection.label" on-label-select="handleLabelSelect(label)" on-label-delete="handleLabelDelete(label)" ) @@ -209,7 +210,7 @@ script(type="text/ng-template", id="historyLabelsListTpl") .history-entry-label( ng-repeat="label in $ctrl.labels track by label.id" ng-click="$ctrl.onLabelSelect({ label: label })" - ng-class="{ 'history-entry-label-selected': label.selected }" + ng-class="{ 'history-entry-label-selected': label.id === $ctrl.selectedLabel.id }" ) history-label( show-tooltip="false" diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index 6abe167f42..4e4b6f7ae3 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -2,24 +2,31 @@ ng-controller="HistoryV2ToolbarController" ng-if="ui.view == 'history' && history.isV2 && history.viewMode === HistoryViewModes.POINT_IN_TIME" ) - span(ng-show="history.loadingFileTree") + span.history-toolbar-selected-version(ng-show="history.loadingFileTree") i.fa.fa-spin.fa-refresh |    #{translate("loading")}... - span(ng-show="!history.loadingFileTree") #{translate("browsing_project_as_of")}  + span.history-toolbar-selected-version( + ng-show="!history.loadingFileTree && !history.showOnlyLabels" + ) #{translate("browsing_project_as_of")}  time.history-toolbar-time {{ history.selection.updates[0].meta.end_ts | formatDate:'Do MMM YYYY, h:mm a' }} - button.history-toolbar-btn( - ng-click="showAddLabelDialog();" - ng-if="!history.showOnlyLabels" - ng-disabled="history.loadingFileTree" - ) - i.fa.fa-tag - |  #{translate("history_label_this_version")} - button.history-toolbar-btn( - ng-click="toggleHistoryViewMode();" - ng-disabled="history.loadingFileTree" - ) - i.fa.fa-exchange - |  #{translate("compare_to_another_version")} + span.history-toolbar-selected-version( + ng-show="!history.loadingFileTree && history.showOnlyLabels && history.selection.label" + ) Browsing project version labelled + span.history-toolbar-selected-label "{{ history.selection.label.comment }}" + div.history-toolbar-actions + button.history-toolbar-btn( + ng-click="showAddLabelDialog();" + ng-if="!history.showOnlyLabels" + ng-disabled="history.loadingFileTree" + ) + i.fa.fa-tag + |  #{translate("history_label_this_version")} + button.history-toolbar-btn( + ng-click="toggleHistoryViewMode();" + ng-disabled="history.loadingFileTree" + ) + i.fa.fa-exchange + |  #{translate("compare_to_another_version")} .history-toolbar-entries-list toggle-switch( diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index ddd098a5f5..aa4ba09d62 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -38,6 +38,9 @@ define [ else @reset() @$scope.history.viewMode = HistoryViewModes.COMPARE + @ide.$timeout () => + @$scope.$broadcast "history:toggle" + , 0 @$scope.$watch "history.selection.updates", (updates) => if @$scope.history.viewMode == HistoryViewModes.COMPARE @@ -57,6 +60,7 @@ define [ if showOnlyLabels @selectedLabelFromUpdatesSelection() else + @$scope.history.selection.label = null if @$scope.history.selection.updates.length == 0 @autoSelectLastUpdate() @@ -79,6 +83,7 @@ define [ nextBeforeTimestamp: null atEnd: false selection: { + label: null updates: [] docs: {} pathname: null @@ -166,21 +171,17 @@ define [ selectLabel: (labelToSelect) -> updateToSelect = null - alreadySelected = false + + if @_isLabelSelected labelToSelect + # Label already selected + return + for update in @$scope.history.updates if update.toV == labelToSelect.version updateToSelect = update break - for label in @$scope.history.labels - matchingLabel = (labelToSelect.id == label.id) - if matchingLabel and label.selected - alreadySelected = true - label.selected = matchingLabel - - if alreadySelected - return - + @$scope.history.selection.label = labelToSelect if updateToSelect? @selectUpdate updateToSelect else @@ -241,10 +242,9 @@ define [ pathname = @$scope.history.selection.pathname if @$scope.history.selection.updates?[0]? toV = @$scope.history.selection.updates[0].toV - else - for label in @$scope.history.labels or [] - if label.selected - toV = label.version + else if @$scope.history.selection.label? + toV = @$scope.history.selection.label.version + if !toV? return url = "/project/#{@$scope.project_id}/diff" @@ -316,6 +316,9 @@ define [ }).then (response) => @_deleteLabelLocally label + _isLabelSelected: (label) -> + label.id == @$scope.history.selection.label?.id + _deleteLabelLocally: (labelToDelete) -> for update, i in @$scope.history.updates if update.toV == labelToDelete.version diff --git a/services/web/public/coffee/ide/history/components/historyLabelsList.coffee b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee index 44c9a54742..75486b9081 100644 --- a/services/web/public/coffee/ide/history/components/historyLabelsList.coffee +++ b/services/web/public/coffee/ide/history/components/historyLabelsList.coffee @@ -16,7 +16,7 @@ define [ ctrl.getUserCSSStyle = (user, label) -> curUserId = user?._id or user?.id hue = ColorManager.getHueForUserId(curUserId) or 100 - if label.selected + if label.id == ctrl.selectedLabel?.id color : "#FFF" else color: "hsl(#{ hue }, 70%, 50%)" @@ -28,6 +28,7 @@ define [ users: "<" currentUser: "<" isLoading: "<" + selectedLabel: "<" onLabelSelect: "&" onLabelDelete: "&" controller: historyLabelsListController diff --git a/services/web/public/stylesheets/app/editor/history-v2.less b/services/web/public/stylesheets/app/editor/history-v2.less index 7bb10f88f2..cfefbb462c 100644 --- a/services/web/public/stylesheets/app/editor/history-v2.less +++ b/services/web/public/stylesheets/app/editor/history-v2.less @@ -15,22 +15,28 @@ .history-toolbar when (@is-overleaf = false) { border-bottom: @toolbar-border-bottom; } - .history-toolbar-time { - font-weight: bold; + .history-toolbar-selected-version { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } - .history-toolbar-btn { - .btn; - .btn-info; - .btn-xs; - padding-left: @padding-small-horizontal; - padding-right: @padding-small-horizontal; - margin-left: (@line-height-computed / 2); + .history-toolbar-time, + .history-toolbar-selected-label { + font-weight: bold; + } + .history-toolbar-actions { + flex-grow: 1; } - + .history-toolbar-btn { + .btn; + .btn-info; + .btn-xs; + padding-left: @padding-small-horizontal; + padding-right: @padding-small-horizontal; + margin-left: (@line-height-computed / 2); + } .history-toolbar-entries-list { - position: absolute; - right: 0; - width: @changesListWidth; + flex: 0 0 @changesListWidth; padding: 0 10px; border-left: 1px solid @editor-border-color; } From 663ca275cb02760895ae0fa0aaca4b6fb316cef6 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Mon, 13 Aug 2018 17:09:18 +0100 Subject: [PATCH 10/14] Add i18n. --- .../app/views/project/editor/history/previewPanelV2.pug | 4 ++-- .../web/app/views/project/editor/history/toolbarV2.pug | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/services/web/app/views/project/editor/history/previewPanelV2.pug b/services/web/app/views/project/editor/history/previewPanelV2.pug index 3d7a1ac3df..773d79878f 100644 --- a/services/web/app/views/project/editor/history/previewPanelV2.pug +++ b/services/web/app/views/project/editor/history/previewPanelV2.pug @@ -45,7 +45,7 @@ text="history.diff.text", highlights="history.diff.highlights", read-only="true", - resize-on="layout:main:resize", + resize-on="layout:main:resize,history:toggle", navigate-highlights="true" ) .alert.alert-info(ng-if="history.diff.binary") @@ -70,7 +70,7 @@ font-size="settings.fontSize", text="history.selectedFile.text", read-only="true", - resize-on="layout:main:resize", + resize-on="layout:main:resize,history:toggle", ) .alert.alert-info(ng-if="history.selectedFile.binary") | We're still working on showing image and binary changes, sorry. Stay tuned! diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index 4e4b6f7ae3..aa459e0b32 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -11,7 +11,7 @@ time.history-toolbar-time {{ history.selection.updates[0].meta.end_ts | formatDate:'Do MMM YYYY, h:mm a' }} span.history-toolbar-selected-version( ng-show="!history.loadingFileTree && history.showOnlyLabels && history.selection.label" - ) Browsing project version labelled + ) #{translate("browsing_project_labelled")}  span.history-toolbar-selected-label "{{ history.selection.label.comment }}" div.history-toolbar-actions button.history-toolbar-btn( @@ -31,9 +31,9 @@ .history-toolbar-entries-list toggle-switch( ng-model="history.showOnlyLabels" - label-true="Labels" - label-false="All history" - description="Show all of the project history or only labelled versions." + label-true=translate("history_view_labels") + label-false=translate("history_view_all") + description=translate("history_view_a11y_description") ) script(type="text/ng-template", id="historyV2AddLabelModalTemplate") From 6b31268bfa65096b82dd17bd0b28f9c6f451a4dd Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Tue, 14 Aug 2018 15:27:07 +0100 Subject: [PATCH 11/14] Scroll to selected history update when coming back from the labels view. --- .../history/components/historyEntriesList.coffee | 16 ++++++++++++++++ .../ide/history/components/historyEntry.coffee | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/services/web/public/coffee/ide/history/components/historyEntriesList.coffee b/services/web/public/coffee/ide/history/components/historyEntriesList.coffee index 934ca304fe..de4e4f1b92 100644 --- a/services/web/public/coffee/ide/history/components/historyEntriesList.coffee +++ b/services/web/public/coffee/ide/history/components/historyEntriesList.coffee @@ -3,6 +3,22 @@ define [ ], (App) -> historyEntriesListController = ($scope, $element, $attrs) -> ctrl = @ + ctrl.$entryListViewportEl = null + _isEntryElVisible = ($entryEl) -> + entryElTop = $entryEl.offset().top + entryElBottom = entryElTop + $entryEl.outerHeight() + entryListViewportElTop = ctrl.$entryListViewportEl.offset().top + entryListViewportElBottom = entryListViewportElTop + ctrl.$entryListViewportEl.height() + return entryElTop >= entryListViewportElTop and entryElBottom <= entryListViewportElBottom; + _getScrollTopPosForEntry = ($entryEl) -> + halfViewportElHeight = ctrl.$entryListViewportEl.height() / 2 + return $entryEl.offset().top - halfViewportElHeight + ctrl.onEntryLinked = (entry, $entryEl) -> + if entry.selectedTo and entry.selectedFrom and !_isEntryElVisible $entryEl + $scope.$applyAsync () -> + ctrl.$entryListViewportEl.scrollTop _getScrollTopPosForEntry $entryEl + ctrl.$onInit = () -> + ctrl.$entryListViewportEl = $element.find "> .history-entries" return App.component "historyEntriesList", { diff --git a/services/web/public/coffee/ide/history/components/historyEntry.coffee b/services/web/public/coffee/ide/history/components/historyEntry.coffee index 8af726b509..6d5eed53d5 100644 --- a/services/web/public/coffee/ide/history/components/historyEntry.coffee +++ b/services/web/public/coffee/ide/history/components/historyEntry.coffee @@ -26,6 +26,8 @@ define [ color : "#FFF" else color: "hsl(#{ hue }, 70%, 50%)" + ctrl.$onInit = () -> + ctrl.historyEntriesList.onEntryLinked ctrl.entry, $element.find "> .history-entry" return App.component "historyEntry", { @@ -35,6 +37,8 @@ define [ users: "<" onSelect: "&" onLabelDelete: "&" + require: + historyEntriesList: '^historyEntriesList' controller: historyEntryController templateUrl: "historyEntryTpl" } \ No newline at end of file From 23bb866988ac026c2c61595b8dfcffdcfe534b3c Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 16 Aug 2018 11:26:34 +0100 Subject: [PATCH 12/14] Show an error message when history fails to load updates. --- .../views/project/editor/history/entriesListV2.pug | 4 ++-- .../views/project/editor/history/previewPanelV2.pug | 11 +++++++++++ .../app/views/project/editor/history/toolbarV2.pug | 12 ++++++++---- .../coffee/ide/history/HistoryV2Manager.coffee | 6 ++++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/services/web/app/views/project/editor/history/entriesListV2.pug b/services/web/app/views/project/editor/history/entriesListV2.pug index 21c2438742..5e4c4b66c6 100644 --- a/services/web/app/views/project/editor/history/entriesListV2.pug +++ b/services/web/app/views/project/editor/history/entriesListV2.pug @@ -3,7 +3,7 @@ aside.change-list( ng-controller="HistoryV2ListController" ) history-entries-list( - ng-if="!history.showOnlyLabels" + ng-if="!history.showOnlyLabels && !history.error" entries="history.updates" current-user="user" users="projectUsers" @@ -15,7 +15,7 @@ aside.change-list( on-label-delete="handleLabelDelete(label)" ) history-labels-list( - ng-if="history.showOnlyLabels" + ng-if="history.showOnlyLabels && !history.error" labels="history.labels" current-user="user" users="projectUsers" diff --git a/services/web/app/views/project/editor/history/previewPanelV2.pug b/services/web/app/views/project/editor/history/previewPanelV2.pug index 773d79878f..bd814c2da4 100644 --- a/services/web/app/views/project/editor/history/previewPanelV2.pug +++ b/services/web/app/views/project/editor/history/previewPanelV2.pug @@ -77,5 +77,16 @@ .loading-panel(ng-show="history.selectedFile.loading") i.fa.fa-spin.fa-refresh |   #{translate("loading")}... + .error-panel(ng-show="history.error") + .alert.alert-danger + | #{translate("generic_history_error")} + a( + ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}" + ) #{settings.adminEmail} + .clearfix + a.alert-link-as-btn.pull-right( + href + ng-click="toggleHistory()" + ) #{translate("back_to_editor")} .error-panel(ng-show="history.selectedFile.error") .alert.alert-danger #{translate("generic_something_went_wrong")} diff --git a/services/web/app/views/project/editor/history/toolbarV2.pug b/services/web/app/views/project/editor/history/toolbarV2.pug index aa459e0b32..a683facba4 100644 --- a/services/web/app/views/project/editor/history/toolbarV2.pug +++ b/services/web/app/views/project/editor/history/toolbarV2.pug @@ -6,14 +6,16 @@ i.fa.fa-spin.fa-refresh |    #{translate("loading")}... span.history-toolbar-selected-version( - ng-show="!history.loadingFileTree && !history.showOnlyLabels" + ng-show="!history.loadingFileTree && !history.showOnlyLabels && !history.error" ) #{translate("browsing_project_as_of")}  time.history-toolbar-time {{ history.selection.updates[0].meta.end_ts | formatDate:'Do MMM YYYY, h:mm a' }} span.history-toolbar-selected-version( - ng-show="!history.loadingFileTree && history.showOnlyLabels && history.selection.label" + ng-show="!history.loadingFileTree && history.showOnlyLabels && history.selection.label && !history.error" ) #{translate("browsing_project_labelled")}  span.history-toolbar-selected-label "{{ history.selection.label.comment }}" - div.history-toolbar-actions + div.history-toolbar-actions( + ng-if="!history.error" + ) button.history-toolbar-btn( ng-click="showAddLabelDialog();" ng-if="!history.showOnlyLabels" @@ -28,7 +30,9 @@ i.fa.fa-exchange |  #{translate("compare_to_another_version")} - .history-toolbar-entries-list + .history-toolbar-entries-list( + ng-if="!history.error" + ) toggle-switch( ng-model="history.showOnlyLabels" label-true=translate("history_view_labels") diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee index aa4ba09d62..3f231c046b 100644 --- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee +++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee @@ -92,6 +92,7 @@ define [ toV: null } } + error: null showOnlyLabels: false labels: null files: [] @@ -234,6 +235,11 @@ define [ if !updatesData.nextBeforeTimestamp? @$scope.history.atEnd = true @$scope.history.loading = false + .catch (error) => + { status, statusText } = error + @$scope.history.error = { status, statusText } + @$scope.history.loading = false + @$scope.history.loadingFileTree = false _sortLabelsByVersionAndDate: (labels) -> @ide.$filter("orderBy")(labels, [ '-version', '-created_at' ]) From 652be9efe693622851ca6adad47ec41c20f03c60 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 16 Aug 2018 11:41:19 +0100 Subject: [PATCH 13/14] Slightly adapt the markup for the generic history error. --- .../views/project/editor/history/previewPanelV2.pug | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/services/web/app/views/project/editor/history/previewPanelV2.pug b/services/web/app/views/project/editor/history/previewPanelV2.pug index bd814c2da4..e75af8db90 100644 --- a/services/web/app/views/project/editor/history/previewPanelV2.pug +++ b/services/web/app/views/project/editor/history/previewPanelV2.pug @@ -79,11 +79,12 @@ |   #{translate("loading")}... .error-panel(ng-show="history.error") .alert.alert-danger - | #{translate("generic_history_error")} - a( - ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}" - ) #{settings.adminEmail} - .clearfix + p + | #{translate("generic_history_error")} + a( + ng-href="mailto:#{settings.adminEmail}?Subject=Error%20loading%20history%20for%project%20{{ project_id }}" + ) #{settings.adminEmail} + p.clearfix a.alert-link-as-btn.pull-right( href ng-click="toggleHistory()" From 713a39171ae4334ec6128bb620cccc752f509edb Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Thu, 16 Aug 2018 13:44:48 +0100 Subject: [PATCH 14/14] Fix history frontend tests. --- .../coffee/ide/history/HistoryV2ManagerTests.coffee | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee b/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee index 725befb721..2fc5c5b3b6 100644 --- a/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee +++ b/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee @@ -15,14 +15,17 @@ define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) -> nextBeforeTimestamp: null atEnd: false selection: { + label: null updates: [] - pathname: null docs: {} + pathname: null range: { fromV: null toV: null } } + error: null + showOnlyLabels: false labels: null diff: null files: []