UiFileManager plugin
This commit is contained in:
parent
85790f8866
commit
f0b0f57643
24 changed files with 2541 additions and 0 deletions
270
plugins/UiFileManager/media/js/FileList.coffee
Normal file
270
plugins/UiFileManager/media/js/FileList.coffee
Normal file
|
@ -0,0 +1,270 @@
|
|||
BINARY_EXTENSIONS = ["png", "gif", "jpg", "pdf", "doc", "msgpack", "zip", "rar", "gz", "tar", "exe"]
|
||||
|
||||
class FileList extends Class
|
||||
constructor: (@site, @inner_path, @is_owner=false) ->
|
||||
@need_update = true
|
||||
@error = null
|
||||
@url_root = "/list/" + @site + "/"
|
||||
if @inner_path
|
||||
@inner_path += "/"
|
||||
@url_root += @inner_path
|
||||
@log("inited", @url_root)
|
||||
@item_list = new FileItemList(@inner_path)
|
||||
@item_list.items = @item_list.items
|
||||
@menu_create = new Menu()
|
||||
|
||||
@select_action = null
|
||||
@selected = {}
|
||||
@selected_items_num = 0
|
||||
@selected_items_size = 0
|
||||
@selected_optional_empty_num = 0
|
||||
|
||||
isSelectedAll: ->
|
||||
false
|
||||
|
||||
update: =>
|
||||
@item_list.update =>
|
||||
document.body.classList.add("loaded")
|
||||
|
||||
getHref: (inner_path) =>
|
||||
return "/" + @site + "/" + inner_path
|
||||
|
||||
getListHref: (inner_path) =>
|
||||
return "/list/" + @site + "/" + inner_path
|
||||
|
||||
getEditHref: (inner_path, mode=null) =>
|
||||
href = @url_root + "?file=" + inner_path
|
||||
if mode
|
||||
href += "&edit_mode=#{mode}"
|
||||
return href
|
||||
|
||||
checkSelectedItems: =>
|
||||
@selected_items_num = 0
|
||||
@selected_items_size = 0
|
||||
@selected_optional_empty_num = 0
|
||||
for item in @item_list.items
|
||||
if @selected[item.inner_path]
|
||||
@selected_items_num += 1
|
||||
@selected_items_size += item.size
|
||||
optional_info = @item_list.getOptionalInfo(item.inner_path)
|
||||
if optional_info and not optional_info.downloaded_percent > 0
|
||||
@selected_optional_empty_num += 1
|
||||
|
||||
handleMenuCreateClick: =>
|
||||
@menu_create.items = []
|
||||
@menu_create.items.push ["File", @handleNewFileClick]
|
||||
@menu_create.items.push ["Directory", @handleNewDirectoryClick]
|
||||
@menu_create.toggle()
|
||||
return false
|
||||
|
||||
handleNewFileClick: =>
|
||||
Page.cmd "wrapperPrompt", "New file name:", (file_name) =>
|
||||
window.top.location.href = @getEditHref(@inner_path + file_name, "new")
|
||||
return false
|
||||
|
||||
handleNewDirectoryClick: =>
|
||||
Page.cmd "wrapperPrompt", "New directory name:", (res) =>
|
||||
alert("directory name #{res}")
|
||||
return false
|
||||
|
||||
handleSelectClick: (e) =>
|
||||
return false
|
||||
|
||||
handleSelectEnd: (e) =>
|
||||
document.body.removeEventListener('mouseup', @handleSelectEnd)
|
||||
@select_action = null
|
||||
|
||||
handleSelectMousedown: (e) =>
|
||||
inner_path = e.currentTarget.attributes.inner_path.value
|
||||
if @selected[inner_path]
|
||||
delete @selected[inner_path]
|
||||
@select_action = "deselect"
|
||||
else
|
||||
@selected[inner_path] = true
|
||||
@select_action = "select"
|
||||
@checkSelectedItems()
|
||||
document.body.addEventListener('mouseup', @handleSelectEnd)
|
||||
e.stopPropagation()
|
||||
Page.projector.scheduleRender()
|
||||
return false
|
||||
|
||||
handleRowMouseenter: (e) =>
|
||||
if e.buttons and @select_action
|
||||
inner_path = e.target.attributes.inner_path.value
|
||||
if @select_action == "select"
|
||||
@selected[inner_path] = true
|
||||
else
|
||||
delete @selected[inner_path]
|
||||
@checkSelectedItems()
|
||||
Page.projector.scheduleRender()
|
||||
return false
|
||||
|
||||
handleSelectbarCancel: =>
|
||||
@selected = {}
|
||||
@checkSelectedItems()
|
||||
Page.projector.scheduleRender()
|
||||
return false
|
||||
|
||||
handleSelectbarDelete: (e, remove_optional=false) =>
|
||||
for inner_path of @selected
|
||||
optional_info = @item_list.getOptionalInfo(inner_path)
|
||||
delete @selected[inner_path]
|
||||
if optional_info and not remove_optional
|
||||
Page.cmd "optionalFileDelete", inner_path
|
||||
else
|
||||
Page.cmd "fileDelete", inner_path
|
||||
@need_update = true
|
||||
Page.projector.scheduleRender()
|
||||
@checkSelectedItems()
|
||||
return false
|
||||
|
||||
handleSelectbarRemoveOptional: (e) =>
|
||||
return @handleSelectbarDelete(e, true)
|
||||
|
||||
renderSelectbar: =>
|
||||
h("div.selectbar", {classes: {visible: @selected_items_num > 0}}, [
|
||||
"Selected:",
|
||||
h("span.info", [
|
||||
h("span.num", "#{@selected_items_num} files"),
|
||||
h("span.size", "(#{Text.formatSize(@selected_items_size)})"),
|
||||
])
|
||||
h("div.actions", [
|
||||
if @selected_optional_empty_num > 0
|
||||
h("a.action.delete.remove_optional", {href: "#", onclick: @handleSelectbarRemoveOptional}, "Delete and remove optional")
|
||||
else
|
||||
h("a.action.delete", {href: "#", onclick: @handleSelectbarDelete}, "Delete")
|
||||
])
|
||||
h("a.cancel.link", {href: "#", onclick: @handleSelectbarCancel}, "Cancel")
|
||||
])
|
||||
|
||||
renderHead: =>
|
||||
parent_links = []
|
||||
inner_path_parent = ""
|
||||
for parent_dir in @inner_path.split("/")
|
||||
if not parent_dir
|
||||
continue
|
||||
if inner_path_parent
|
||||
inner_path_parent += "/"
|
||||
inner_path_parent += "#{parent_dir}"
|
||||
parent_links.push(
|
||||
[" / ", h("a", {href: @getListHref(inner_path_parent)}, parent_dir)]
|
||||
)
|
||||
return h("div.tr.thead", h("div.td.full",
|
||||
h("a", {href: @getListHref("")}, "root"),
|
||||
parent_links
|
||||
))
|
||||
|
||||
renderItemCheckbox: (item) =>
|
||||
if not @item_list.hasPermissionDelete(item)
|
||||
return [" "]
|
||||
|
||||
return h("a.checkbox-outer", {
|
||||
href: "#Select",
|
||||
onmousedown: @handleSelectMousedown,
|
||||
onclick: @handleSelectClick,
|
||||
inner_path: item.inner_path
|
||||
}, h("span.checkbox"))
|
||||
|
||||
renderItem: (item) =>
|
||||
if item.type == "parent"
|
||||
href = @url_root.replace(/^(.*)\/.{2,255}?$/, "$1/")
|
||||
else if item.type == "dir"
|
||||
href = @url_root + item.name
|
||||
else
|
||||
href = @url_root.replace(/^\/list\//, "/") + item.name
|
||||
|
||||
inner_path = @inner_path + item.name
|
||||
href_edit = @getEditHref(inner_path)
|
||||
is_dir = item.type in ["dir", "parent"]
|
||||
ext = item.name.split(".").pop()
|
||||
|
||||
is_editing = inner_path == Page.file_editor?.inner_path
|
||||
is_editable = not is_dir and item.size < 1024 * 1024 and ext not in BINARY_EXTENSIONS
|
||||
is_modified = @item_list.isModified(inner_path)
|
||||
is_added = @item_list.isAdded(inner_path)
|
||||
optional_info = @item_list.getOptionalInfo(inner_path)
|
||||
|
||||
style = ""
|
||||
title = ""
|
||||
|
||||
if optional_info
|
||||
downloaded_percent = optional_info.downloaded_percent
|
||||
if not downloaded_percent
|
||||
downloaded_percent = 0
|
||||
style += "background: linear-gradient(90deg, #fff6dd, #{downloaded_percent}%, white, #{downloaded_percent}%, white);"
|
||||
is_added = false
|
||||
|
||||
if item.ignored
|
||||
is_added = false
|
||||
|
||||
if is_modified then title += " (modified)"
|
||||
if is_added then title += " (new)"
|
||||
if optional_info or item.optional_empty then title += " (optional)"
|
||||
if item.ignored then title += " (ignored from content.json)"
|
||||
|
||||
classes = {
|
||||
"type-#{item.type}": true, editing: is_editing, nobuttons: not is_editable, selected: @selected[inner_path],
|
||||
modified: is_modified, added: is_added, ignored: item.ignored, optional: optional_info, optional_empty: item.optional_empty
|
||||
}
|
||||
|
||||
h("div.tr", {key: item.name, classes: classes, style: style, onmouseenter: @handleRowMouseenter, inner_path: inner_path}, [
|
||||
h("div.td.pre", {title: title},
|
||||
@renderItemCheckbox(item)
|
||||
),
|
||||
h("div.td.name", h("a.link", {href: href}, item.name))
|
||||
h("div.td.buttons", if is_editable then h("a.edit", {href: href_edit}, if Page.site_info.settings.own then "Edit" else "View"))
|
||||
h("div.td.size", if is_dir then "[DIR]" else Text.formatSize(item.size))
|
||||
])
|
||||
|
||||
|
||||
renderItems: =>
|
||||
return [
|
||||
if @item_list.error and not @item_list.items.length and not @item_list.updating then [
|
||||
h("div.tr", {key: "error"}, h("div.td.full.error", @item_list.error))
|
||||
],
|
||||
if @inner_path then @renderItem({"name": "..", type: "parent", size: 0})
|
||||
@item_list.items.map @renderItem
|
||||
]
|
||||
|
||||
renderFoot: =>
|
||||
files = (item for item in @item_list.items when item.type not in ["parent", "dir"])
|
||||
dirs = (item for item in @item_list.items when item.type == "dir")
|
||||
if files.length
|
||||
total_size = (item.size for file in files).reduce (a, b) -> a + b
|
||||
else
|
||||
total_size = 0
|
||||
|
||||
foot_text = "Total: "
|
||||
foot_text += "#{dirs.length} dir, #{files.length} file in #{Text.formatSize(total_size)}"
|
||||
|
||||
return [
|
||||
if dirs.length or files.length or Page.site_info?.settings?.own
|
||||
h("div.tr.foot-info.foot", h("div.td.full", [
|
||||
if @item_list.updating
|
||||
"Updating file list..."
|
||||
else
|
||||
if dirs.length or files.length then foot_text
|
||||
if Page.site_info?.settings?.own
|
||||
h("div.create", [
|
||||
h("a.link", {href: "#Create+new+file", onclick: @handleNewFileClick}, "+ New")
|
||||
@menu_create.render()
|
||||
])
|
||||
]))
|
||||
]
|
||||
|
||||
render: =>
|
||||
if @need_update
|
||||
@update()
|
||||
@need_update = false
|
||||
|
||||
if not @item_list.items
|
||||
return []
|
||||
|
||||
return h("div.files", [
|
||||
@renderSelectbar(),
|
||||
@renderHead(),
|
||||
h("div.tbody", @renderItems()),
|
||||
@renderFoot()
|
||||
])
|
||||
|
||||
window.FileList = FileList
|
Loading…
Add table
Add a link
Reference in a new issue