Просмотр исходного кода

Merge pull request #884 from sharelatex/pr-pre-launch-ui-fixes

Pre-launch UI fixes
Paulo Jorge Reis 8 лет назад
Родитель
Сommit
d3aad256e3

+ 2 - 2
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -346,8 +346,8 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
 	webRouter.use (req, res, next) ->
 		if Settings.overleaf?
 			res.locals.overallThemes = [
-				{ name: "Default", val: "",       path: res.locals.buildCssPath(res.locals.buildCssFileName()) }
-				{ name: "Light",   val: "light-", path: res.locals.buildCssPath(res.locals.buildCssFileName("light-")) }
+				{ name: "Default", val: "",       path: res.locals.buildCssPath(res.locals.buildCssFileName(), {hashedPath:true}) }
+				{ name: "Light",   val: "light-", path: res.locals.buildCssPath(res.locals.buildCssFileName("light-"), {hashedPath:true}) }
 			]
 		next()
 

+ 11 - 6
services/web/app/views/project/editor/header.pug

@@ -93,17 +93,22 @@ header.toolbar.toolbar-header.toolbar-with-labels(
 		a.btn.btn-full-height(
 			href,
 			ng-if="project.features.trackChangesVisible",
-			ng-class="{ active: ui.reviewPanelOpen }"
+			ng-class="{ active: ui.reviewPanelOpen && ui.view !== 'history' }"
+			ng-disabled="ui.view === 'history'"
 			ng-click="toggleReviewPanel()"
 		)
 			i.review-icon
 			p.toolbar-label
 				| #{translate("review")}
-		a.btn.btn-full-height#shareButton(
-			href,
-			ng-if="permissions.admin",
-			ng-click="openShareProjectModal();",
-			ng-controller="ShareController",
+
+		a.btn.btn-full-height(
+			href
+			ng-class="{ 'btn-full-height-disabled' : !permissions.admin }"
+			ng-click="openShareProjectModal(permissions.admin);"
+			ng-controller="ShareController"
+			tooltip-enable="!permissions.admin"
+			tooltip="Only the project owner can use the Share menu at the moment, but we're working on making it accessible to collaborators, too."
+			tooltip-placement="bottom"
 		)
 			i.fa.fa-fw.fa-group
 			p.toolbar-label #{translate("share")}

+ 12 - 5
services/web/app/views/project/editor/review-panel.pug

@@ -306,14 +306,21 @@ script(type='text/ng-template', id='aggregateChangeEntryTemplate')
 				.rp-entry-details
 					.rp-entry-description
 						| #{translate("aggregate_changed")} 
-						del.rp-content-highlight {{ entry.metadata.replaced_content }}
+						del.rp-content-highlight
+							| {{ entry.metadata.replaced_content | limitTo:(isDeletionCollapsed ? contentLimit : entry.metadata.replaced_contentlength) }}
+						a.rp-collapse-toggle(
+							href
+							ng-if="deletionNeedsCollapsing"
+							ng-click="toggleDeletionCollapse();"
+						) {{ isDeletionCollapsed ? '... (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
 						|  #{translate("aggregate_to")} 
-						ins.rp-content-highlight {{ entry.content }}
+						ins.rp-content-highlight
+							| {{ entry.content | limitTo:(isInsertionCollapsed ? contentLimit : entry.contentlength) }}
 						a.rp-collapse-toggle(
 							href
-							ng-if="needsCollapsing"
-							ng-click="toggleCollapse();"
-						) {{ isCollapsed ? '... (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
+							ng-if="insertionNeedsCollapsing"
+							ng-click="toggleInsertionCollapse();"
+						) {{ isInsertionCollapsed ? '... (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
 					.rp-entry-metadata
 						| {{ entry.metadata.ts | date : 'MMM d, y h:mm a' }} • 
 						span.rp-entry-user(style="color: hsl({{ user.hue }}, 70%, 40%);") {{ user.name }} 

+ 51 - 36
services/web/app/views/project/list/item.pug

@@ -49,41 +49,56 @@ div(class=lastUpdatedClasses)
 
 if settings.overleaf
 	.hidden-xs.col-sm-3.col-md-2.action-btn-row
-		button.btn.btn-link.action-btn(
-			tooltip=translate('copy'),
-			tooltip-placement="top",
-			tooltip-append-to-body="true",
-			ng-click="clone($event)"
+		div(
+			ng-if="!project.isTableActionInflight"
 		)
-			i.icon.fa.fa-files-o
-		button.btn.btn-link.action-btn(
-			tooltip=translate('download'),
-			tooltip-placement="top",
-			tooltip-append-to-body="true",
-			ng-click="download($event)"
-		)
-			i.icon.fa.fa-cloud-download
-		button.btn.btn-link.action-btn(
-			ng-if="!project.archived && isOwner()"
-			tooltip=translate('archive'),
-			tooltip-placement="top",
-			tooltip-append-to-body="true",
-			ng-click="archiveOrLeave($event)"
-		)
-			i.icon.fa.fa-inbox
-		button.btn.btn-link.action-btn(
-			ng-if="!project.archived && !isOwner()"
-			tooltip=translate('leave'),
-			tooltip-placement="top",
-			tooltip-append-to-body="true",
-			ng-click="archiveOrLeave($event)"
-		)
-			i.icon.fa.fa-sign-out
-		button.btn.btn-link.action-btn(
-			ng-if="project.archived"
-			tooltip=translate('unarchive'),
-			tooltip-placement="top",
-			tooltip-append-to-body="true",
-			ng-click="restore($event)"
+			button.btn.btn-link.action-btn(
+				tooltip=translate('copy'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="clone($event)"
+			)
+				i.icon.fa.fa-files-o
+			button.btn.btn-link.action-btn(
+				tooltip=translate('download'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="download($event)"
+			)
+				i.icon.fa.fa-cloud-download
+			button.btn.btn-link.action-btn(
+				ng-if="!project.archived && isOwner()"
+				tooltip=translate('archive'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="archiveOrLeave($event)"
+			)
+				i.icon.fa.fa-inbox
+			button.btn.btn-link.action-btn(
+				ng-if="!project.archived && !isOwner()"
+				tooltip=translate('leave'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="archiveOrLeave($event)"
+			)
+				i.icon.fa.fa-sign-out
+			button.btn.btn-link.action-btn(
+				ng-if="project.archived"
+				tooltip=translate('unarchive'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="restore($event)"
+			)
+				i.icon.fa.fa-reply
+			button.btn.btn-link.action-btn(
+				ng-if="project.archived && isOwner()"
+				tooltip=translate('delete_forever'),
+				tooltip-placement="top",
+				tooltip-append-to-body="true",
+				ng-click="deleteProject($event)"
+			)
+				i.icon.fa.fa-trash
+		div(
+			ng-if="project.isTableActionInflight"
 		)
-			i.icon.fa.fa-reply
+			i.fa.fa-spinner.fa-spin

+ 4 - 1
services/web/app/views/project/list/side-bar.pug

@@ -1,4 +1,7 @@
-.dropdown(dropdown)
+.dropdown(
+	dropdown
+	dropdown-append-to-body
+)
 	a.btn.btn-primary.sidebar-new-proj-btn.dropdown-toggle(
 		href="#",
 		data-toggle="dropdown",

+ 2 - 1
services/web/public/coffee/ide/editor/components/spellMenu.coffee

@@ -4,6 +4,7 @@ define ["base"], (App) ->
       open: "<"
       top: "<"
       left: "<"
+      layoutFromBottom: "<"
       highlight: "<"
       replaceWord: "&"
       learnWord: "&"
@@ -13,7 +14,7 @@ define ["base"], (App) ->
     class="dropdown context-menu spell-check-menu"
     ng-show="$ctrl.open"
     ng-style="{top: $ctrl.top, left: $ctrl.left}"
-    ng-class="{open: $ctrl.open}"
+    ng-class="{open: $ctrl.open, 'spell-check-menu-from-bottom': $ctrl.layoutFromBottom}"
   >
     <ul class="dropdown-menu">
       <li ng-repeat="suggestion in $ctrl.highlight.suggestions | limitTo:8">

+ 1 - 0
services/web/public/coffee/ide/editor/directives/aceEditor.coffee

@@ -544,6 +544,7 @@ define [
 						open="spellMenu.open"
 						top="spellMenu.top"
 						left="spellMenu.left"
+						layout-from-bottom="spellMenu.layoutFromBottom"
 						highlight="spellMenu.highlight"
 						replace-word="replaceWord(highlight, suggestion)"
 						learn-word="learnWord(highlight)"

+ 6 - 0
services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckAdapter.coffee

@@ -30,6 +30,12 @@ define [
 				end: position
 			})
 
+		isContextMenuEventOnBottomHalf: (e) ->
+			clientY = e.domEvent.clientY
+			editorBoundingRect = e.target.container.getBoundingClientRect()
+			relativeYPos = (clientY - editorBoundingRect.top) / editorBoundingRect.height
+			return relativeYPos > 0.5
+
 		selectHighlightedWord: (highlight) ->
 			row = highlight.range.start.row
 			startColumn = highlight.range.start.column

+ 2 - 0
services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/SpellCheckManager.coffee

@@ -55,6 +55,7 @@ define [], () ->
 		openContextMenu: (e) ->
 			coords = @adapter.getCoordsFromContextMenuEvent(e)
 			highlight = @adapter.getHighlightFromCoords(coords)
+			shouldPositionFromBottom = @adapter.isContextMenuEventOnBottomHalf(e)
 			if highlight
 				@adapter.preventContextMenuEventDefault(e)
 				@adapter.selectHighlightedWord(highlight)
@@ -63,6 +64,7 @@ define [], () ->
 						open: true
 						top: coords.y + 'px'
 						left: coords.x + 'px'
+						layoutFromBottom: shouldPositionFromBottom
 						highlight: highlight
 					}
 				return false

+ 17 - 7
services/web/public/coffee/ide/review-panel/directives/aggregateChangeEntry.coffee

@@ -13,18 +13,28 @@ define [
 			onIndicatorClick: "&"
 			onBodyClick: "&"
 		link: (scope, element, attrs) ->
-			scope.contentLimit = 35
-			scope.isCollapsed = true
-			scope.needsCollapsing = false
+			scope.contentLimit = 17
+			scope.isDeletionCollapsed = true
+			scope.isInsertionCollapsed = true
+			scope.deletionNeedsCollapsing = false
+			scope.insertionNeedsCollapsing = false
 
 			element.on "click", (e) ->
 				if $(e.target).is('.rp-entry, .rp-entry-description, .rp-entry-body, .rp-entry-action-icon i')
 					scope.onBodyClick()
 
-			scope.toggleCollapse = () ->
-				scope.isCollapsed = !scope.isCollapsed
+			scope.toggleDeletionCollapse = () ->
+				scope.isDeletionCollapsed = !scope.isDeletionCollapsed
 				$timeout () ->
 					scope.$emit "review-panel:layout"
 
-			scope.$watch "entry.content.length + entry.metadata.agg_op.content.length", (contentLength) ->
-					scope.needsCollapsing = contentLength > scope.contentLimit
+			scope.toggleInsertionCollapse = () ->
+				scope.isInsertionCollapsed = !scope.isInsertionCollapsed
+				$timeout () ->
+					scope.$emit "review-panel:layout"
+
+			scope.$watch "entry.metadata.replaced_content.length", (deletionContentLength) ->
+					scope.deletionNeedsCollapsing = deletionContentLength > scope.contentLimit
+
+			scope.$watch "entry.content.length", (insertionContentLength) ->
+					scope.insertionNeedsCollapsing = insertionContentLength > scope.contentLimit

+ 4 - 1
services/web/public/coffee/ide/share/controllers/ShareController.coffee

@@ -3,7 +3,10 @@ define [
 ], (App) ->
 	App.controller "ShareController", ["$scope", "$modal", "ide", "projectInvites", "projectMembers", "event_tracking",
 	($scope, $modal, ide, projectInvites, projectMembers, event_tracking) ->
-			$scope.openShareProjectModal = () ->
+			$scope.openShareProjectModal = (isAdmin) ->
+				if !isAdmin
+					return
+					
 				event_tracking.sendMBOnce "ide-open-share-modal-once"
 
 				$modal.open(

+ 29 - 1
services/web/public/coffee/main/project-list/project-list.coffee

@@ -469,7 +469,7 @@ define [
 		else
 			$scope.updateVisibleProjects()
 
-	App.controller "ProjectListItemController", ($scope) ->
+	App.controller "ProjectListItemController", ($scope, $modal, queuedHttp) ->
 
 		$scope.shouldDisableCheckbox = (project) ->
 			$scope.filter == 'archived' && project.accessLevel != 'owner'
@@ -502,7 +502,10 @@ define [
 
 		$scope.clone = (e) ->
 			e.stopPropagation()
+			$scope.project.isTableActionInflight = true
 			$scope.cloneProject($scope.project, "#{$scope.project.name} (Copy)")
+				.then () -> $scope.project.isTableActionInflight = false
+				.catch () -> $scope.project.isTableActionInflight = false
 
 		$scope.download = (e) ->
 			e.stopPropagation()
@@ -515,3 +518,28 @@ define [
 		$scope.restore = (e) ->
 			e.stopPropagation()
 			$scope.restoreProjects([$scope.project])
+
+		$scope.deleteProject = (e) ->
+			e.stopPropagation()
+			modalInstance = $modal.open(
+				templateUrl: "deleteProjectsModalTemplate"
+				controller: "DeleteProjectsModalController"
+				resolve:
+					projects: () -> [ $scope.project ]
+			)
+
+			modalInstance.result.then () ->
+				$scope.project.isTableActionInflight = true
+				queuedHttp({
+					method: "DELETE"
+					url: "/project/#{$scope.project.id}?forever=true"
+					headers:
+						"X-CSRF-Token": window.csrfToken
+				}).then () -> 
+					$scope.project.isTableActionInflight = false
+					$scope._removeProjectFromList $scope.project
+					for tag in $scope.tags
+						$scope._removeProjectIdsFromTagArray(tag, [ $scope.project.id ])
+					$scope.updateVisibleProjects()
+				.catch () -> 
+					$scope.project.isTableActionInflight = false

+ 15 - 2
services/web/public/stylesheets/app/editor.less

@@ -378,11 +378,11 @@ CodeMirror
 	display: flex;
 	align-items: center;
 	justify-content: center;
-	width: @ui-resizer-size !important;;	
+	width: @ui-resizer-size !important;
 	height: 50px;
 	margin-top: -25px;
 	top: 50%;
-	z-index: 6;
+	z-index: 3;
 	background-color: @editor-toggler-bg-color;
 
 	&:hover,
@@ -649,3 +649,16 @@ CodeMirror
 	height: auto;
 	border-bottom: 1px solid @modal-header-border-color;
 }
+
+.spell-check-menu {
+	> .dropdown-menu > li > a {
+		padding: 2px 15px;
+	}
+}
+
+.spell-check-menu-from-bottom {
+	> .dropdown-menu {
+		top: auto;
+		bottom: 100%;
+	}
+}

+ 1 - 0
services/web/public/stylesheets/app/editor/review-panel.less

@@ -571,6 +571,7 @@
 		border: solid 1px @rp-border-grey;
 		resize: vertical;
 		color: @rp-type-darkgrey;
+		background-color: #FFF;
 		margin-top: 3px;
 		overflow-x: hidden;
 		min-height: 3em;

+ 11 - 0
services/web/public/stylesheets/app/editor/toolbar.less

@@ -72,6 +72,17 @@
 			background-color: @toolbar-btn-active-bg-color;
 			box-shadow: @toolbar-btn-active-shadow;
 		}
+		&.btn-full-height-disabled {
+			opacity: 0.65;
+			&:hover,
+			&.active,
+			&:active {
+				text-shadow: none;
+				background-color: transparent;
+				color: @toolbar-btn-color;
+				box-shadow: none;
+			}
+		}
 		.label {
 			top: 4px;
 			right: 4px;

+ 3 - 0
services/web/public/stylesheets/components/alerts.less

@@ -71,4 +71,7 @@
     color: white;
     text-decoration: underline;
   }
+  .btn {
+    text-decoration: none;
+  }
 }

+ 8 - 0
services/web/public/stylesheets/core/mixins.less

@@ -438,6 +438,7 @@
   .alert-link-as-btn when (@is-overleaf = true) {
     display: inline-block;
     font-weight: bold;
+    text-decoration: none;
     .button-variant(#FFF, shade(@background, 20%), transparent);
     .button-size(@padding-xs-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);
     &:hover {
@@ -511,6 +512,10 @@
   background-color: @background;
   border-color: @border;
 
+  .alert & when (@is-overleaf = true) {
+      background-color: darken(@background, 16%);
+  }
+
   &:hover,
   &:focus,
   &:active,
@@ -520,6 +525,9 @@
     color: @color;
     background-color: darken(@background, 8%);
         border-color: darken(@border, 12%);
+      .alert & when (@is-overleaf = true) {
+          background-color: darken(@background, 24%);
+      }
   }
   &:active,
   &.active,