ソースを参照

Sort out permissions and displaying anonymous users

James Allen 12 年 前
親
コミット
a8d371d2f6

+ 2 - 1
services/web/app/views/project/editor/editor.jade

@@ -25,7 +25,8 @@ div.full-size(
 			cursor-position="editor.cursorPosition",
 			goto-line="editor.gotoLine",
 			resize-on="layout:main:resize,layout:pdf:resize",
-			annotations="pdf.logEntryAnnotations[editor.open_doc_id]"
+			annotations="pdf.logEntryAnnotations[editor.open_doc_id]",
+			read-only="!permissions.write"
 		)
 
 	.ui-layout-east

+ 35 - 13
services/web/app/views/project/editor/file-tree.jade

@@ -1,5 +1,5 @@
 aside#file-tree(ng-controller="FileTreeController")
-	.toolbar.toolbar-small
+	.toolbar.toolbar-small(ng-if="permissions.write")
 		a(
 			href,
 			ng-click="openNewDocModal()",
@@ -39,14 +39,19 @@ aside#file-tree(ng-controller="FileTreeController")
 			)
 				i.fa.fa-trash-o
 
-	.file-tree-inner(ng-if="rootFolder", ng-controller="FileTreeRootFolderController")
+	.file-tree-inner(
+		ng-if="rootFolder", 
+		ng-controller="FileTreeRootFolderController",
+		ng-class="{ 'no-toolbar': !permissions.write }"
+	)
 		ul.list-unstyled.file-tree-list(
-			droppable
+			droppable="permissions.write"
 			accept=".entity-name"
 			on-drop-callback="onDrop"
 		)
 			file-entity(
 				entity="entity",
+				permissions="permissions",
 				ng-repeat="entity in rootFolder.children | orderBy:[orderByFoldersFirst, 'name']"
 			)
 
@@ -76,11 +81,12 @@ script(type='text/ng-template', id='entityListItemTemplate')
 		.entity(ng-if="entity.type != 'folder'")
 			.entity-name(
 				ng-click="select()"
-				ng-dblclick="startRenaming()"
-				draggable
+				ng-dblclick="permissions.write && startRenaming()"
+				draggable="permissions.write"
 				context-menu
 				data-target="context-menu-{{ entity.id }}"
 				context-menu-container="body"
+				context-menu-disabled="!permissions.write"
 			)
 				//- Just a spacer to align with folders
 				i.fa.fa-fw.toggle(ng-if="entity.type != 'folder'")
@@ -92,6 +98,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
 					ng-hide="entity.renaming"
 				)  {{ entity.name }}
 				input(
+					ng-if="permissions.write",
 					ng-show="entity.renaming",
 					ng-model="inputs.name",
 					ng-blur="finishRenaming()",
@@ -99,7 +106,10 @@ script(type='text/ng-template', id='entityListItemTemplate')
 					on-enter="finishRenaming()"
 				)
 
-				span.dropdown(ng-show="entity.selected")
+				span.dropdown(
+					ng-show="entity.selected",
+					ng-if="permissions.write"
+				)
 					a.dropdown-toggle(href)
 						i.fa.fa-chevron-down
 
@@ -117,7 +127,10 @@ script(type='text/ng-template', id='entityListItemTemplate')
 								ng-click="openDeleteModal()"
 							) Delete
 
-				div.dropdown.context-menu(id="context-menu-{{ entity.id }}")
+				div.dropdown.context-menu(
+					id="context-menu-{{ entity.id }}",
+					ng-if="permissions.write"
+				)
 					ul.dropdown-menu
 						li
 							a(
@@ -138,9 +151,9 @@ script(type='text/ng-template', id='entityListItemTemplate')
 		.entity(ng-if="entity.type == 'folder'", ng-controller="FileTreeFolderController")
 			.entity-name(
 				ng-click="select()"
-				ng-dblclick="startRenaming()"
-				draggable
-				droppable
+				ng-dblclick="permissions.write && startRenaming()"
+				draggable="permissions.write"
+				droppable="permissions.write"
 				accept=".entity-name"
 				on-drop-callback="onDrop"
 			)
@@ -148,6 +161,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
 					context-menu
 					data-target="context-menu-{{ entity.id }}"
 					context-menu-container="body"
+					context-menu-disabled="!permissions.write"
 				)
 					i.fa.fa-fw.toggle(
 						ng-if="entity.type == 'folder'"
@@ -168,6 +182,7 @@ script(type='text/ng-template', id='entityListItemTemplate')
 						ng-hide="entity.renaming"
 					)  {{ entity.name }}
 					input(
+						ng-if="permissions.write",
 						ng-show="entity.renaming",
 						ng-model="inputs.name",
 						ng-blur="finishRenaming()",
@@ -175,7 +190,10 @@ script(type='text/ng-template', id='entityListItemTemplate')
 						on-enter="finishRenaming()"
 					)
 
-					span.dropdown(ng-show="entity.selected")
+					span.dropdown(
+						ng-if="permissions.write"
+						ng-show="entity.selected"
+					)
 						a.dropdown-toggle(href)
 							i.fa.fa-chevron-down
 
@@ -212,7 +230,10 @@ script(type='text/ng-template', id='entityListItemTemplate')
 									ng-click="openUploadFileModal()"
 								) Upload File
 
-					.dropdown.context-menu(id="context-menu-{{ entity.id }}")
+					.dropdown.context-menu(
+						ng-if="permissions.write"
+						id="context-menu-{{ entity.id }}"
+					)
 						ul.dropdown-menu
 							li
 								a(
@@ -254,12 +275,13 @@ script(type='text/ng-template', id='entityListItemTemplate')
 			ul.list-unstyled(
 				ng-if="entity.type == 'folder'"
 				ng-show="expanded"
-				droppable
+				droppable="permissions.write"
 				accept=".entity-name"
 				on-drop-callback="onDrop"
 			)
 				file-entity(
 					entity="child",
+					permissions="permissions",
 					ng-repeat="child in entity.children | orderBy:[orderByFoldersFirst, 'name']"
 				)
 			

+ 1 - 0
services/web/app/views/project/editor/header.jade

@@ -15,6 +15,7 @@ header.toolbar.toolbar-header(ng-cloak, ng-hide="state.loading")
 	.toolbar-right
 		a.btn.btn-full-height(
 			href,
+			ng-if="permissions.admin",
 			tooltip="Share",
 			tooltip-placement="bottom",
 			ng-click="openShareProjectModal()",

+ 7 - 7
services/web/app/views/project/editor/share.jade

@@ -9,7 +9,7 @@ script(type='text/ng-template', id='shareProjectModalTemplate')
 	.modal-body.modal-body-share
 		.container-fluid
 			.row.public-access-level(ng-show="project.publicAccesLevel == 'private'")
-				.col-md-12.text-center
+				.col-xs-12.text-center
 					| This project is private and can only be accessed by the people below.
 					|   
 					a(
@@ -17,7 +17,7 @@ script(type='text/ng-template', id='shareProjectModalTemplate')
 						ng-click="openMakePublicModal()"
 					) Make Public
 			.row.public-access-level(ng-show="project.publicAccesLevel != 'private'")
-				.col-md-12.text-center
+				.col-xs-12.text-center
 					strong(ng-if="project.publicAccesLevel == 'readAndWrite'") This project is public and can be edited by anyone with the URL.
 					strong(ng-if="project.publicAccesLevel == 'readOnly'") This project is public and can be viewed by anyone with the URL.
 					|   
@@ -26,16 +26,16 @@ script(type='text/ng-template', id='shareProjectModalTemplate')
 						ng-click="openMakePrivateModal()"
 					) Make Private
 			.row.project-member
-				.col-md-8 {{ project.owner.email }}
+				.col-xs-8 {{ project.owner.email }}
 				.text-right(
-					ng-class="{'col-md-3': project.members.length > 0, 'col-md-4': project.members.length == 0}"
+					ng-class="{'col-xs-3': project.members.length > 0, 'col-xs-4': project.members.length == 0}"
 				) Owner
 			.row.project-member(ng-repeat="member in project.members")
-				.col-md-8 {{ member.email }}
-				.col-md-3.text-right
+				.col-xs-8 {{ member.email }}
+				.col-xs-3.text-right
 					span(ng-show="member.privileges == 'readAndWrite'") Can Edit
 					span(ng-show="member.privileges == 'readOnly'") Read Only
-				.col-md-1
+				.col-xs-1
 					a(
 						href
 						tooltip="Remove collaborator"

+ 4 - 1
services/web/app/views/project/editor/track-changes.jade

@@ -70,8 +70,11 @@ div#trackChanges(ng-show="ui.view == 'track-changes'")
 						div.users
 							div.user(ng-repeat="update_user in update.meta.users")
 								.color-square(ng-style="{'background-color': 'hsl({{ update_user.hue }}, 100%, 50%)'}")
-								span(ng-if="update_user.id != user.id") {{user.first_name}} {{user.last_name}}
+								span(ng-if="update_user.id != user.id") {{update_user.first_name}} {{update_user.last_name}}
 								span(ng-if="update_user.id == user.id") You
+							div.user(ng-if="update.meta.users.length == 0")
+								.color-square(style="background-color: hsl(100, 100%, 50%)")
+								span Anonymous
 
 			.loading(ng-show="trackChanges.loading")
 				i.fa.fa-spin.fa-refresh

+ 3 - 0
services/web/public/coffee/app/ide.coffee

@@ -5,6 +5,7 @@ define [
 	"ide/editor/EditorManager"
 	"ide/online-users/OnlineUsersManager"
 	"ide/track-changes/TrackChangesManager"
+	"ide/permissions/PermissionsManager"
 	"ide/pdf/PdfManager"
 	"ide/settings/index"
 	"ide/share/index"
@@ -22,6 +23,7 @@ define [
 	EditorManager
 	OnlineUsersManager
 	TrackChangesManager
+	PermissionsManager
 	PdfManager
 ) ->
 	App.controller "IdeController", ["$scope", "$timeout", "ide", ($scope, $timeout, ide) ->
@@ -59,6 +61,7 @@ define [
 		ide.onlineUsersManager = new OnlineUsersManager(ide, $scope)
 		ide.trackChangesManager = new TrackChangesManager(ide, $scope)
 		ide.pdfManager = new PdfManager(ide, $scope)
+		ide.permissionsManager = new PermissionsManager(ide, $scope)
 	]
 
 	angular.bootstrap(document.body, ["SharelatexApp"])

+ 1 - 0
services/web/public/coffee/app/ide/connection/ConnectionManager.coffee

@@ -57,6 +57,7 @@ define [], () ->
 				@$scope.$apply () =>
 					@$scope.protocolVersion = protocolVersion
 					@$scope.project = project
+					@$scope.permissionsLevel = permissionsLevel
 					@$scope.state.load_progress = 100
 					@$scope.state.loading = false
 					@$scope.$emit "project:joined"

+ 4 - 4
services/web/public/coffee/app/ide/editor/highlights/HighlightsManager.coffee

@@ -204,16 +204,16 @@ define [
 		_getColorScheme: (hue) ->
 			if @_isDarkTheme()
 				return {
-					cursor: "hsl(#{hue}, 100%, 50%)"
-					labelBackgroundColor: "hsl(#{hue}, 100%, 50%)"
+					cursor: "hsl(#{hue}, 70%, 50%)"
+					labelBackgroundColor: "hsl(#{hue}, 70%, 50%)"
 					highlightBackgroundColor: "hsl(#{hue}, 100%, 28%);"
 					strikeThroughBackgroundColor: "hsl(#{hue}, 100%, 20%);"
 					strikeThroughForegroundColor: "hsl(#{hue}, 100%, 60%);"
 				}
 			else
 				return {
-					cursor: "hsl(#{hue}, 100%, 50%)"
-					labelBackgroundColor: "hsl(#{hue}, 100%, 50%)"
+					cursor: "hsl(#{hue}, 70%, 50%)"
+					labelBackgroundColor: "hsl(#{hue}, 70%, 50%)"
 					highlightBackgroundColor: "hsl(#{hue}, 70%, 85%);"
 					strikeThroughBackgroundColor: "hsl(#{hue}, 70%, 95%);"
 					strikeThroughForegroundColor: "hsl(#{hue}, 70%, 40%);"

+ 7 - 5
services/web/public/coffee/app/ide/file-tree/directives/draggable.coffee

@@ -4,9 +4,11 @@ define [
 	App.directive "draggable", () ->
 		return {
 			link: (scope, element, attrs) ->
-				element.draggable
-					delay: 250
-					opacity: 0.7
-					helper: "clone"
-					scroll: true
+				scope.$watch attrs.draggable, (draggable) ->
+					if draggable
+						element.draggable
+							delay: 250
+							opacity: 0.7
+							helper: "clone"
+							scroll: true
 		}

+ 7 - 6
services/web/public/coffee/app/ide/file-tree/directives/droppable.coffee

@@ -7,10 +7,11 @@ define [
 				onDropCallback: "="
 			}
 			link: (scope, element, attrs) ->
-				console.log "DROPPABLE", element, scope.onDropCallback
-				element.droppable
-					greedy: true
-					hoverClass: "droppable-hover"
-					accept: attrs.accept
-					drop: scope.onDropCallback
+				scope.$watch attrs.droppable, (droppable) ->
+					if droppable
+						element.droppable
+							greedy: true
+							hoverClass: "droppable-hover"
+							accept: attrs.accept
+							drop: scope.onDropCallback
 		}

+ 9 - 1
services/web/public/coffee/app/ide/file-tree/directives/fileEntity.coffee

@@ -6,10 +6,18 @@ define [
 			restrict: "E"
 			scope: {
 				entity: "="
+				permissions: "="
 			}
 			templateUrl: "entityListItemTemplate"
 			compile: (element) ->
 				RecursionHelper.compile element, (scope, element, attrs, ctrl) ->
-					# Link function here if needed
+					# Don't freak out if we're already in an apply callback
+					scope.$originalApply = scope.$apply
+					scope.$apply = (fn = () ->) ->
+						phase = @$root.$$phase
+						if (phase == '$apply' || phase == '$digest')
+							fn()
+						else
+							@$originalApply(fn);
 		}
 	]

+ 1 - 1
services/web/public/coffee/app/ide/online-users/OnlineUsersManager.coffee

@@ -56,7 +56,7 @@ define [
 		OWN_HUE: 200 # We will always appear as this color to ourselves
 		ANONYMOUS_HUE: 100
 		getHueForUserId: (user_id) ->
-			if !user_id?
+			if !user_id? or user_id == "anonymous-user"
 				return @ANONYMOUS_HUE
 
 			if window.user.id == user_id

+ 19 - 0
services/web/public/coffee/app/ide/permissions/PermissionsManager.coffee

@@ -0,0 +1,19 @@
+define [], () ->
+	class PermissionsManager
+		constructor: (@ide, @$scope) ->
+			@$scope.$watch "permissionsLevel", (permissionsLevel) =>
+				@$scope.permissions =
+					read:  false
+					write: false
+					admin: false
+				if permissionsLevel?
+					if permissionsLevel == "readOnly"
+						@$scope.permissions.read = true
+					else if permissionsLevel == "readAndWrite"
+						@$scope.permissions.read = true
+						@$scope.permissions.write = true
+					else if permissionsLevel == "owner"
+						@$scope.permissions.read = true
+						@$scope.permissions.write = true
+						@$scope.permissions.admin = true
+

+ 7 - 4
services/web/public/coffee/app/ide/track-changes/TrackChangesManager.coffee

@@ -157,21 +157,24 @@ define [
 				}
 
 				if entry.i? or entry.d?
-					name = "#{entry.meta.user.first_name} #{entry.meta.user.last_name}"
-					if entry.meta.user.id == @$scope.user.id
+					if entry.meta.user?
+						name = "#{entry.meta.user.first_name} #{entry.meta.user.last_name}"
+					else
+						name = "Anonymous"
+					if entry.meta.user?.id == @$scope.user.id
 						name = "you"
 					date = moment(entry.meta.end_ts).format("Do MMM YYYY, h:mm a")
 					if entry.i?
 						highlights.push {
 							label: "Added by #{name} on #{date}"
 							highlight: range
-							hue: @ide.onlineUsersManager.getHueForUserId(entry.meta.user.id)
+							hue: @ide.onlineUsersManager.getHueForUserId(entry.meta.user?.id)
 						}
 					else if entry.d?
 						highlights.push {
 							label: "Deleted by #{name} on #{date}"
 							strikeThrough: range
-							hue: @ide.onlineUsersManager.getHueForUserId(entry.meta.user.id)
+							hue: @ide.onlineUsersManager.getHueForUserId(entry.meta.user?.id)
 						}
 
 			return {text, highlights}

+ 4 - 0
services/web/public/stylesheets/app/editor/file-tree.less

@@ -9,6 +9,10 @@ aside#file-tree {
 		left: 0;
 		right: 0;
 		overflow-y: auto;
+
+		&.no-toolbar {
+			top: 0;
+		}
 	}
 
 	h3 {