mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Add in dropdown and context menu for files
This commit is contained in:
parent
4864eeba0a
commit
7aab6c4c0b
7 changed files with 159 additions and 40 deletions
|
@ -66,6 +66,8 @@
|
|||
i(class="sprite-{{ type }}")
|
||||
span.name {{ name }}
|
||||
input.rename.js-rename
|
||||
.dropdown-caret
|
||||
i.icon-chevron-down
|
||||
|
||||
script(type="text/template")#folderTemplate
|
||||
.entity-list-item(class="entity-{{ type }}", entity-type="{{ type }}", id="{{ id }}")
|
||||
|
@ -76,6 +78,8 @@
|
|||
i(class="sprite-{{ type }}")
|
||||
span.name {{ name }}
|
||||
input.rename.js-rename
|
||||
.dropdown-caret
|
||||
i.icon-chevron-down
|
||||
|
||||
script(type="text/template")#entityListTemplate
|
||||
.contents
|
||||
|
@ -110,6 +114,9 @@
|
|||
script(type="text/template")#contextMenuEntryTemplate
|
||||
li
|
||||
a(href="#") {{text}}
|
||||
|
||||
script(type="text/template")#contextMenuDividerTemplate
|
||||
li.divider
|
||||
|
||||
script(type="text/template")#genericModalTemplate
|
||||
.modal
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
define [
|
||||
"utils/ContextMenu"
|
||||
"libs/backbone"
|
||||
"libs/mustache"
|
||||
], () ->
|
||||
], (ContextMenu) ->
|
||||
EntityView = Backbone.View.extend
|
||||
entityTemplate: $("#entityTemplate").html()
|
||||
|
||||
|
@ -14,6 +15,8 @@ define [
|
|||
events: () ->
|
||||
events = {}
|
||||
events["click ##{@model.id} > .js-clickable"] = "parentOnClick"
|
||||
events["click .dropdown-caret"] = "showContextMenuFromCaret"
|
||||
events["contextmenu"] = "showContextMenuFromRightClick"
|
||||
return events
|
||||
|
||||
render: () ->
|
||||
|
@ -71,6 +74,47 @@ define [
|
|||
if @ide.isAllowedToDoIt "readAndWrite"
|
||||
@startRename()
|
||||
|
||||
showContextMenuFromCaret: (e) ->
|
||||
e.stopPropagation()
|
||||
caret = @$(".dropdown-caret")
|
||||
offset = caret.offset()
|
||||
position =
|
||||
top: offset.top + caret.outerHeight()
|
||||
right: $(document.body).width() - (offset.left + caret.outerWidth())
|
||||
@toggleContextMenu(position)
|
||||
|
||||
showContextMenuFromRightClick: (e) ->
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
position =
|
||||
left: e.pageX
|
||||
top: e.pageY
|
||||
@showContextMenu(position)
|
||||
|
||||
toggleContextMenu: (position) ->
|
||||
if @contextMenu?
|
||||
@contextMenu.destroy()
|
||||
else
|
||||
@showContextMenu(position)
|
||||
|
||||
showContextMenu: (position) ->
|
||||
entries = @getContextMenuEntries()
|
||||
|
||||
@contextMenu = new ContextMenu(position, entries)
|
||||
@contextMenu.on "destroy", () =>
|
||||
delete @contextMenu
|
||||
|
||||
getContextMenuEntries: () ->
|
||||
return [{
|
||||
text: "Rename"
|
||||
onClick: () =>
|
||||
@startRename()
|
||||
}, {
|
||||
text: "Delete"
|
||||
onClick: () =>
|
||||
@manager.confirmDelete(@model)
|
||||
}]
|
||||
|
||||
_initializeDrag: () ->
|
||||
@$entityListItemEl.draggable
|
||||
delay: 250
|
||||
|
|
|
@ -218,52 +218,53 @@ define [
|
|||
# value is "name.tex"
|
||||
input[0].setSelectionRange(0, defaultName.indexOf("|"))
|
||||
|
||||
showNewDocModal: () ->
|
||||
showNewDocModal: (parentFolder = @getCurrentFolder()) ->
|
||||
return if !parentFolder?
|
||||
@showNewEntityModal "Document", "name|.tex", (name) =>
|
||||
@addDocToCurrentFolder name
|
||||
@addDocToFolder parentFolder, name
|
||||
|
||||
showNewFolderModal: () ->
|
||||
showNewFolderModal: (parentFolder = @getCurrentFolder()) ->
|
||||
return if !parentFolder?
|
||||
@showNewEntityModal "Folder", "name|", (name) =>
|
||||
@addFolderToCurrentFolder name
|
||||
@addFolderToFolder parentFolder, name
|
||||
|
||||
showUploadFileModal: () ->
|
||||
folder = @getCurrentFolder()
|
||||
return if !folder?
|
||||
@ide.fileUploadManager.showUploadDialog folder.id
|
||||
showUploadFileModal: (parentFolder = @getCurrentFolder()) ->
|
||||
return if !parentFolder?
|
||||
@ide.fileUploadManager.showUploadDialog parentFolder.id
|
||||
|
||||
addDoc: (folder_id, name) ->
|
||||
@ide.socket.emit 'addDoc', folder_id, name
|
||||
|
||||
addDocToCurrentFolder: (name) ->
|
||||
folder = @getCurrentFolder()
|
||||
return if !folder?
|
||||
@addDoc folder.id, name
|
||||
addDocToFolder: (parentFolder, name) ->
|
||||
@addDoc parentFolder.id, name
|
||||
|
||||
addFolder: (parent_folder_id, name) ->
|
||||
@ide.socket.emit 'addFolder', parent_folder_id, name
|
||||
|
||||
addFolderToCurrentFolder: (name) ->
|
||||
parentFolder = @getCurrentFolder()
|
||||
addFolderToFolder: (parentFolder, name) ->
|
||||
return if !parentFolder?
|
||||
@addFolder parentFolder.id, name
|
||||
|
||||
# DELETING
|
||||
confirmDelete: () ->
|
||||
confirmDelete: (entity) ->
|
||||
Modal.createModal
|
||||
title: "Confirm Deletion"
|
||||
message: "Are you sure you want to delete the selected files?"
|
||||
message: "Are you sure you want to delete <strong>#{entity.get("name")}</strong>?"
|
||||
buttons: [{
|
||||
text: "Cancel"
|
||||
class: "btn"
|
||||
},{
|
||||
text: "Delete"
|
||||
class: "btn btn-danger"
|
||||
callback: () => @_doDelete()
|
||||
callback: () => @_doDelete(entity)
|
||||
}]
|
||||
|
||||
_doDelete: () ->
|
||||
confirmDeleteOfSelectedEntity: () ->
|
||||
entity = @getSelectedEntity()
|
||||
return if !entity?
|
||||
@confirmDelete(entity)
|
||||
|
||||
_doDelete: (entity) ->
|
||||
@ide.socket.emit 'deleteEntity', entity.id, entity.get("type")
|
||||
@onDeleteEntity entity.id
|
||||
|
||||
|
|
|
@ -119,3 +119,27 @@ define [
|
|||
@hideEntries()
|
||||
else
|
||||
@showEntries()
|
||||
|
||||
getContextMenuEntries: (args...) ->
|
||||
entries = EntityView::getContextMenuEntries.apply(this, args)
|
||||
entries.push {
|
||||
divider: true
|
||||
}
|
||||
entries.push @getFolderContextMenuEntries()...
|
||||
return entries
|
||||
|
||||
getFolderContextMenuEntries: () ->
|
||||
return [{
|
||||
text: "New file"
|
||||
onClick: () =>
|
||||
@manager.showNewDocModal(@model)
|
||||
}, {
|
||||
text: "New folder"
|
||||
onClick: () =>
|
||||
@manager.showNewFolderModal(@model)
|
||||
}, {
|
||||
text: "Upload file"
|
||||
onClick: () =>
|
||||
@manager.showUploadFileModal(@model)
|
||||
}]
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ define [
|
|||
@manager.showUploadFileModal()
|
||||
"click .js-delete-btn" : (e) ->
|
||||
e.preventDefault()
|
||||
@manager.confirmDelete()
|
||||
@manager.confirmDeleteOfSelectedEntity()
|
||||
"click .js-rename-btn" : (e) ->
|
||||
e.preventDefault()
|
||||
@manager.renameSelected()
|
||||
|
@ -50,6 +50,9 @@ define [
|
|||
onToggle: () ->
|
||||
e.preventDefault()
|
||||
|
||||
getContextMenuEntries: () ->
|
||||
@getFolderContextMenuEntries()
|
||||
|
||||
hideToggle: () ->
|
||||
@$(".js-toggle").hide()
|
||||
|
||||
|
|
|
@ -13,44 +13,50 @@ define [
|
|||
return @
|
||||
|
||||
onClick: (e) ->
|
||||
e.preventDefault()
|
||||
if @options.onClick
|
||||
@options.onClick()
|
||||
|
||||
ContextMenu = Backbone.View.extend
|
||||
template: $("#contextMenuTemplate").html()
|
||||
templates:
|
||||
menu: $("#contextMenuTemplate").html()
|
||||
divider: $("#contextMenuDividerTemplate").html()
|
||||
|
||||
initialize: () ->
|
||||
@entries = []
|
||||
initialize: (position, entries) ->
|
||||
if ContextMenu.currentMenu?
|
||||
ContextMenu.currentMenu.destroy()
|
||||
ContextMenu.currentMenu = @
|
||||
@render()
|
||||
@hide()
|
||||
for entry in entries
|
||||
@addEntry(entry)
|
||||
@show(position)
|
||||
|
||||
render: () ->
|
||||
@setElement($(@template))
|
||||
@setElement($(@templates.menu))
|
||||
$(document.body).append(@$el)
|
||||
return @
|
||||
|
||||
hide: () -> @$el.hide()
|
||||
destroy: () ->
|
||||
@$el.remove()
|
||||
@trigger "destroy"
|
||||
|
||||
show: (left, top) ->
|
||||
show: (position) ->
|
||||
page = $(document.body)
|
||||
page.on "click.hideContextMenu", (e) =>
|
||||
page.off "click.hideContextMenu"
|
||||
@hide()
|
||||
@destroy()
|
||||
@$el.css
|
||||
position: "absolute"
|
||||
"z-index": 10000
|
||||
top: (top || 0) + "px"
|
||||
left: (left || 0) + "px"
|
||||
@$el.show()
|
||||
@$el.css position
|
||||
|
||||
addEntry: (options) ->
|
||||
entry = new ContextMenuEntry(options)
|
||||
@$el.append entry.render().el
|
||||
@entries.push entry
|
||||
if options.divider
|
||||
@$el.append $(@templates.divider)
|
||||
else
|
||||
entry = new ContextMenuEntry(options)
|
||||
@$el.append entry.render().el
|
||||
|
||||
clearEntries: () ->
|
||||
while @entries.length > 0
|
||||
@entries.pop().remove()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -443,7 +443,7 @@ body.editor {
|
|||
overflow: hidden;
|
||||
cursor: default;
|
||||
border-right: 1px solid #aaa;
|
||||
background: url('/img/noise.png') #eee;
|
||||
background-color: rgb(238,238,238);
|
||||
padding: 6px 0 0 6px;
|
||||
|
||||
ul {
|
||||
|
@ -459,10 +459,14 @@ body.editor {
|
|||
list-style: none;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
.clickable {
|
||||
height: 24px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.dropdown-caret {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.entity-folder {
|
||||
|
@ -495,9 +499,33 @@ body.editor {
|
|||
}
|
||||
|
||||
li.selected, .entity-list-item.selected {
|
||||
background-color: rgba(55,120,194,0.3);
|
||||
background-color: rgb(185,201,227);
|
||||
.border-radius(5px 0 0 5px);
|
||||
color: #3d5979
|
||||
color: #3d5979;
|
||||
.dropdown-caret {
|
||||
display: block;
|
||||
padding: 4px 6px 4px 4px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgb(185,201,227);
|
||||
&:before {
|
||||
content: " ";
|
||||
#gradient > .horizontal(rgba(185,201,227,0), rgb(185,201,227));
|
||||
background-color: transparent;
|
||||
width: 12px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 20px
|
||||
}
|
||||
i {
|
||||
vertical-align: top;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li img, .entity-list-item i {
|
||||
|
@ -600,6 +628,12 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
display: block;
|
||||
left: auto;
|
||||
.border-radius(0);
|
||||
}
|
||||
|
||||
.clear-modal-backdrop {
|
||||
background: none;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue