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

Merge pull request #1679 from sharelatex/cmg-dashboard-owner

Fix ordering by Owner on the dashboard

GitOrigin-RevId: ec780ae8de5221e151f970638f3fa55c00bd6767
Paulo Jorge Reis 7 лет назад
Родитель
Сommit
5a6cdf0999

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

@@ -32,7 +32,7 @@ div(class=titleClasses)
 				) ×
 
 .col-xs-2
-	span.owner {{ownerName()}}
+	span.owner {{getOwnerName(project)}}
 		|  
 		i.fa.fa-question-circle.small(
 			ng-if="hasGenericOwnerName()"

+ 5 - 8
services/web/app/views/project/list/project-list.pug

@@ -1,8 +1,5 @@
 .row
 	.col-xs-12(ng-cloak)
-
-
-
 		form.project-search.form-horizontal(role="form")
 			.form-group.has-feedback.has-feedback-left.col-md-7.col-xs-12
 				input.form-control.col-md-7.col-xs-12(
@@ -154,18 +151,18 @@
 								i.tablesort.fa(ng-class="getSortIconClass('name')" aria-hidden="true")
 							button.sr-only(ng-click="changePredicate('name')") Sort by #{translate("title")}
 						.col-xs-2
-							span.header.clickable(ng-click="changePredicate('accessLevel')") #{translate("owner")}
-								i.tablesort.fa(ng-class="getSortIconClass('accessLevel')" aria-hidden="true")
-							button.sr-only(ng-click="changePredicate('accessLevel')") Sort by #{translate("owner")}
+							span.header.clickable(ng-click="changePredicate('ownerName')") #{translate("owner")}
+								i.tablesort.fa(ng-class="getSortIconClass('ownerName')" aria-hidden="true")
+							button.sr-only(ng-click="changePredicate('ownerName')") Sort by #{translate("owner")}
 						div(class=lastUpdatedClasses)
 							span.header.clickable(ng-click="changePredicate('lastUpdated')") #{translate("last_modified")}
 								i.tablesort.fa(ng-class="getSortIconClass('lastUpdated')" aria-hidden="true")
-							button.sr-only(ng-click="changePredicate('accessLevel')") Sort by #{translate("last_modified")}
+							button.sr-only(ng-click="changePredicate('lastUpdated')") Sort by #{translate("last_modified")}
 						if settings.overleaf
 							.hidden-xs.col-sm-3.col-md-2.action-btn-row-header
 								span.header #{translate("actions")}
 				li.project_entry.container-fluid(
-					ng-repeat="project in visibleProjects | orderBy:predicate:reverse",
+					ng-repeat="project in visibleProjects | orderBy:getValueForCurrentPredicate:reverse:comparator",
 					ng-controller="ProjectListItemController"
 				)
 					.row(

+ 1 - 1
services/web/app/views/project/list/v1-item.pug

@@ -22,7 +22,7 @@
 				) {{project.name}}
 
 .col-xs-2
-	span.owner {{ownerName()}}
+	span.owner {{ownerName(project)}}
 
 .col-xs-4.col-sm-3.col-md-2
 	span.last-modified(tooltip="{{project.lastUpdated | formatDate}}") {{project.lastUpdated | fromNowDate}}

+ 79 - 19
services/web/public/src/main/project-list/project-list.js

@@ -12,7 +12,7 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-define(['base'], function(App) {
+define(['base', 'main/project-list/services/project-list'], function(App) {
   App.controller('ProjectPageController', function(
     $scope,
     $modal,
@@ -21,7 +21,8 @@ define(['base'], function(App) {
     queuedHttp,
     event_tracking,
     $timeout,
-    localStorage
+    localStorage,
+    ProjectListService
   ) {
     $scope.projects = window.data.projects
     $scope.tags = window.data.tags
@@ -34,6 +35,10 @@ define(['base'], function(App) {
     $scope.nUntagged = 0
     $scope.reverse = true
     $scope.searchText = { value: '' }
+    $scope.$watch('predicate', function(newValue) {
+      $scope.comparator =
+        newValue === 'ownerName' ? ownerNameComparator : defaultComparator
+    })
     $scope.shouldShowSurveyLink = false
 
     const surveyStartDate = new Date(2019, 3, 2)
@@ -89,6 +94,67 @@ define(['base'], function(App) {
       return ($scope.projectListHeight = height)
     }
 
+    function defaultComparator(v1, v2) {
+      var result = 0
+      var type1 = v1.type
+      var type2 = v2.type
+
+      if ($scope.predicate === 'ownerName') {
+        return
+      }
+
+      if (type1 === type2) {
+        var value1 = v1.value
+        var value2 = v2.value
+
+        if (type1 === 'string') {
+          // Compare strings case-insensitively
+          value1 = value1.toLowerCase()
+          value2 = value2.toLowerCase()
+        } else if (type1 === 'object') {
+          // For basic objects, use the position of the object
+          // in the collection instead of the value
+          if (angular.isObject(value1)) value1 = v1.index
+          if (angular.isObject(value2)) value2 = v2.index
+        }
+
+        if (value1 !== value2) {
+          result = value1 < value2 ? -1 : 1
+        }
+      } else {
+        result = type1 < type2 ? -1 : 1
+      }
+
+      return result
+    }
+
+    function ownerNameComparator(v1, v2) {
+      if ($scope.predicate !== 'ownerName') {
+        return
+      }
+      if (v1.value === 'You') {
+        if (v2.value === 'You') {
+          return v1.index < v2.index ? -1 : 1
+        } else {
+          return 1
+        }
+      } else if (v1.value === 'An Overleaf v1 User' || v1.value === 'None') {
+        if (v2.value === 'An Overleaf v1 User' || v2.value === 'None') {
+          return v1.index < v2.index ? -1 : 1
+        } else {
+          return -1
+        }
+      } else {
+        if (v2.value === 'You') {
+          return -1
+        } else if (v2.value === 'An Overleaf v1 User' || v2.value === 'None') {
+          return 1
+        } else {
+          return v1.value > v2.value ? -1 : 1
+        }
+      }
+    }
+
     angular.element($window).bind('resize', function() {
       recalculateProjectListHeight()
       return $scope.$apply()
@@ -599,6 +665,14 @@ define(['base'], function(App) {
       }
     }
 
+    $scope.getValueForCurrentPredicate = function(project) {
+      if ($scope.predicate === 'ownerName') {
+        return ProjectListService.getOwnerName(project)
+      } else {
+        return project[$scope.predicate]
+      }
+    }
+
     $scope.openDeleteProjectsModal = function() {
       const modalInstance = $modal.open({
         templateUrl: 'deleteProjectsModalTemplate',
@@ -713,7 +787,8 @@ define(['base'], function(App) {
   return App.controller('ProjectListItemController', function(
     $scope,
     $modal,
-    queuedHttp
+    queuedHttp,
+    ProjectListService
   ) {
     $scope.shouldDisableCheckbox = project =>
       $scope.filter === 'archived' && project.accessLevel !== 'owner'
@@ -741,22 +816,7 @@ define(['base'], function(App) {
       return !first_name && !last_name && !email
     }
 
-    $scope.ownerName = function() {
-      if ($scope.project.accessLevel === 'owner') {
-        return 'You'
-      } else if ($scope.project.owner != null) {
-        const { first_name, last_name, email } = $scope.project.owner
-        if (first_name || last_name) {
-          return [first_name, last_name].filter(n => n != null).join(' ')
-        } else if (email) {
-          return email
-        } else {
-          return 'An Overleaf v1 User'
-        }
-      } else {
-        return 'None'
-      }
-    }
+    $scope.getOwnerName = ProjectListService.getOwnerName
 
     $scope.isOwner = () => window.user_id === $scope.project.owner._id
 

+ 24 - 0
services/web/public/src/main/project-list/services/project-list.js

@@ -0,0 +1,24 @@
+/* eslint-disable
+    camelcase
+*/
+define(['base'], App =>
+  App.service('ProjectListService', [
+    () => ({
+      getOwnerName(project) {
+        if (project.accessLevel === 'owner') {
+          return 'You'
+        } else if (project.owner != null) {
+          const { first_name, last_name, email } = project.owner
+          if (first_name || last_name) {
+            return [first_name, last_name].filter(n => n != null).join(' ')
+          } else if (email) {
+            return email
+          } else {
+            return 'An Overleaf v1 User'
+          }
+        } else {
+          return 'None'
+        }
+      }
+    })
+  ]))