Sort out permissions and displaying anonymous users

This commit is contained in:
James Allen 2014-07-03 15:05:35 +01:00
parent 58e4e92d84
commit a8d371d2f6
15 changed files with 111 additions and 43 deletions

View file

@ -25,7 +25,8 @@ div.full-size(
cursor-position="editor.cursorPosition", cursor-position="editor.cursorPosition",
goto-line="editor.gotoLine", goto-line="editor.gotoLine",
resize-on="layout:main:resize,layout:pdf:resize", 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 .ui-layout-east

View file

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

View file

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

View file

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

View file

@ -70,8 +70,11 @@ div#trackChanges(ng-show="ui.view == 'track-changes'")
div.users div.users
div.user(ng-repeat="update_user in update.meta.users") div.user(ng-repeat="update_user in update.meta.users")
.color-square(ng-style="{'background-color': 'hsl({{ update_user.hue }}, 100%, 50%)'}") .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 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") .loading(ng-show="trackChanges.loading")
i.fa.fa-spin.fa-refresh i.fa.fa-spin.fa-refresh

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,10 +6,18 @@ define [
restrict: "E" restrict: "E"
scope: { scope: {
entity: "=" entity: "="
permissions: "="
} }
templateUrl: "entityListItemTemplate" templateUrl: "entityListItemTemplate"
compile: (element) -> compile: (element) ->
RecursionHelper.compile element, (scope, element, attrs, ctrl) -> 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);
} }
] ]

View file

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

View file

@ -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

View file

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

View file

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