Add suport for read-only mode in the file manager
This commit is contained in:
parent
5bc7766f44
commit
4646d5c866
@ -18,29 +18,29 @@
|
|||||||
<div id="contextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="contextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
||||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
||||||
<li><a tabindex="-1" href="#" class="open" data-localization="fc_open">Open</a></li>
|
<li><a tabindex="-1" href="#" class="open" data-localization="fc_open">Open</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="rename" data-localization="fc_rename">Rename</a></li>
|
<li><a tabindex="-1" href="#" class="rename editable" data-localization="fc_rename">Rename</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="delete" data-localization="fc_delete">Delete</a></li>
|
<li><a tabindex="-1" href="#" class="delete editable" data-localization="fc_delete">Delete</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newfolder" data-localization="fc_newfolder">New folder</a></li>
|
<li><a tabindex="-1" href="#" class="newfolder editable" data-localization="fc_newfolder">New folder</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="contentContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="contentContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
||||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
||||||
<li><a tabindex="-1" href="#" class="newfolder" data-localization="fc_newfolder">New folder</a></li>
|
<li><a tabindex="-1" href="#" class="newfolder editable" data-localization="fc_newfolder">New folder</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc" data-type="pad" data-localization="fc_newpad" target="_blank">New pad</a></li>
|
<li><a tabindex="-1" href="#" class="newdoc own editable" data-type="pad" data-localization="fc_newpad" target="_blank">New pad</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc" data-type="code" data-localization="fc_newcode" target="_blank">New code</a></li>
|
<li><a tabindex="-1" href="#" class="newdoc own editable" data-type="code" data-localization="fc_newcode" target="_blank">New code</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc" data-type="slide" data-localization="fc_newslide" target="_blank">New slide</a></li>
|
<li><a tabindex="-1" href="#" class="newdoc own editable" data-type="slide" data-localization="fc_newslide" target="_blank">New slide</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc" data-type="poll" data-localization="fc_newpoll" target="_blank">New poll</a></li>
|
<li><a tabindex="-1" href="#" class="newdoc own editable" data-type="poll" data-localization="fc_newpoll" target="_blank">New poll</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="trashTreeContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="trashTreeContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
||||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
||||||
<li><a tabindex="-1" href="#" class="empty" data-localization="fc_empty">Empty the trash</a></li>
|
<li><a tabindex="-1" href="#" class="empty editable" data-localization="fc_empty">Empty the trash</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="trashContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="trashContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
||||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu" style="display:block;position:static;margin-bottom:5px;">
|
||||||
<li><a tabindex="-1" href="#" class="remove" data-localization="fc_remove">Delete permanently</a></li>
|
<li><a tabindex="-1" href="#" class="remove editable" data-localization="fc_remove">Delete permanently</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="restore" data-localization="fc_restore">Restore</a></li>
|
<li><a tabindex="-1" href="#" class="restore editable" data-localization="fc_restore">Restore</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="properties" data-localization="fc_prop">Properties</a></li>
|
<li><a tabindex="-1" href="#" class="properties" data-localization="fc_prop">Properties</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -19,7 +19,8 @@ define([
|
|||||||
var ifrw = $('#pad-iframe')[0].contentWindow;
|
var ifrw = $('#pad-iframe')[0].contentWindow;
|
||||||
|
|
||||||
var APP = window.APP = {
|
var APP = window.APP = {
|
||||||
$bar: $iframe.find('#toolbar')
|
$bar: $iframe.find('#toolbar'),
|
||||||
|
editable: false
|
||||||
};
|
};
|
||||||
|
|
||||||
var ROOT = "root";
|
var ROOT = "root";
|
||||||
@ -117,6 +118,12 @@ define([
|
|||||||
return new Date().getTime();
|
return new Date().getTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var setEditable = function (state) {
|
||||||
|
APP.editable = state;
|
||||||
|
if (state) { $iframe.find('[draggable="true"]').attr('draggable', false); }
|
||||||
|
else { $iframe.find('[draggable="false"]').attr('draggable', true); }
|
||||||
|
};
|
||||||
|
|
||||||
var keyPressed = [];
|
var keyPressed = [];
|
||||||
var pressKey = function (key, state) {
|
var pressKey = function (key, state) {
|
||||||
if (state) {
|
if (state) {
|
||||||
@ -200,7 +207,9 @@ define([
|
|||||||
var $sortAscIcon = $('<span>', {"class": "fa fa-angle-up"});
|
var $sortAscIcon = $('<span>', {"class": "fa fa-angle-up"});
|
||||||
var $sortDescIcon = $('<span>', {"class": "fa fa-angle-down"});
|
var $sortDescIcon = $('<span>', {"class": "fa fa-angle-down"});
|
||||||
|
|
||||||
|
if (!APP.readOnly) {
|
||||||
|
setEditable(true);
|
||||||
|
}
|
||||||
|
|
||||||
var appStatus = {
|
var appStatus = {
|
||||||
isReady: true,
|
isReady: true,
|
||||||
@ -223,6 +232,10 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var ownFileManager = function () {
|
||||||
|
return localStorage.FS_hash === APP.hash;
|
||||||
|
};
|
||||||
|
|
||||||
var removeSelected = function () {
|
var removeSelected = function () {
|
||||||
$iframe.find('.selected').removeClass("selected");
|
$iframe.find('.selected').removeClass("selected");
|
||||||
};
|
};
|
||||||
@ -265,6 +278,7 @@ define([
|
|||||||
|
|
||||||
// Replace a file/folder name by an input to change its value
|
// Replace a file/folder name by an input to change its value
|
||||||
var displayRenameInput = function ($element, path) {
|
var displayRenameInput = function ($element, path) {
|
||||||
|
if (!APP.editable) { debug("Read-only mode"); return; }
|
||||||
if (!path || path.length < 2) {
|
if (!path || path.length < 2) {
|
||||||
logError("Renaming a top level element (root, trash or filesData) is forbidden.");
|
logError("Renaming a top level element (root, trash or filesData) is forbidden.");
|
||||||
return;
|
return;
|
||||||
@ -334,14 +348,29 @@ define([
|
|||||||
// Open the selected context menu on the closest "li" element
|
// Open the selected context menu on the closest "li" element
|
||||||
var openContextMenu = function (e, $menu) {
|
var openContextMenu = function (e, $menu) {
|
||||||
module.hideMenu();
|
module.hideMenu();
|
||||||
e.stopPropagation();
|
|
||||||
var path = $(e.target).closest('li').data('path');
|
var path = $(e.target).closest('li').data('path');
|
||||||
if (!path) { return; }
|
if (!path) { return; }
|
||||||
|
|
||||||
|
if (!APP.editable) {
|
||||||
|
$menu.find('a.editable').parent('li').hide();
|
||||||
|
}
|
||||||
|
if (!ownFileManager()) {
|
||||||
|
$menu.find('a.own').parent('li').hide();
|
||||||
|
}
|
||||||
|
|
||||||
$menu.css({
|
$menu.css({
|
||||||
display: "block",
|
display: "block",
|
||||||
left: e.pageX,
|
left: e.pageX,
|
||||||
top: e.pageY
|
top: e.pageY
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ($menu.find('li:visible').length === 0) {
|
||||||
|
debug("No visible element in the context menu. Abort.");
|
||||||
|
$menu.hide();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// $element should be the <span class="element">, find it if it's not the case
|
// $element should be the <span class="element">, find it if it's not the case
|
||||||
var $element = $(e.target).closest('li').children('span.element');
|
var $element = $(e.target).closest('li').children('span.element');
|
||||||
onElementClick($element);
|
onElementClick($element);
|
||||||
@ -390,11 +419,26 @@ define([
|
|||||||
if (!path) { return; }
|
if (!path) { return; }
|
||||||
var $menu = $contentContextMenu;
|
var $menu = $contentContextMenu;
|
||||||
removeSelected();
|
removeSelected();
|
||||||
|
|
||||||
|
if (!APP.editable) {
|
||||||
|
$menu.find('a.editable').parent('li').hide();
|
||||||
|
}
|
||||||
|
if (!ownFileManager()) {
|
||||||
|
$menu.find('a.own').parent('li').hide();
|
||||||
|
}
|
||||||
|
|
||||||
$menu.css({
|
$menu.css({
|
||||||
display: "block",
|
display: "block",
|
||||||
left: e.pageX,
|
left: e.pageX,
|
||||||
top: e.pageY
|
top: e.pageY
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if ($menu.find('li:visible').length === 0) {
|
||||||
|
debug("No visible element in the context menu. Abort.");
|
||||||
|
$menu.hide();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
$menu.find('a').data('path', path);
|
$menu.find('a').data('path', path);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -402,6 +446,7 @@ define([
|
|||||||
// filesOp.moveElements is able to move several paths to a new location, including
|
// filesOp.moveElements is able to move several paths to a new location, including
|
||||||
// the Trash or the "Unsorted files" folder
|
// the Trash or the "Unsorted files" folder
|
||||||
var moveElements = function (paths, newPath, force, cb) {
|
var moveElements = function (paths, newPath, force, cb) {
|
||||||
|
if (!APP.editable) { debug("Read-only mode"); return; }
|
||||||
var andThen = function () {
|
var andThen = function () {
|
||||||
filesOp.moveElements(paths, newPath, cb);
|
filesOp.moveElements(paths, newPath, cb);
|
||||||
};
|
};
|
||||||
@ -454,6 +499,7 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
|
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
|
||||||
|
if (!APP.editable) { debug("Read-only mode"); return; }
|
||||||
// "dragenter" is fired for an element and all its children
|
// "dragenter" is fired for an element and all its children
|
||||||
// "dragleave" may be fired when entering a child
|
// "dragleave" may be fired when entering a child
|
||||||
// --> we use pointer-events: none in CSS, but we still need a counter to avoid some issues
|
// --> we use pointer-events: none in CSS, but we still need a counter to avoid some issues
|
||||||
@ -885,9 +931,7 @@ define([
|
|||||||
var $icon = $fileIcon.clone();
|
var $icon = $fileIcon.clone();
|
||||||
var $name = $('<span>', { 'class': 'file-element element' });
|
var $name = $('<span>', { 'class': 'file-element element' });
|
||||||
addFileData(file.href, file.title, $name, false);
|
addFileData(file.href, file.title, $name, false);
|
||||||
var $element = $('<li>', {
|
var $element = $('<li>').append($icon).append($name).dblclick(function () {
|
||||||
draggable: false
|
|
||||||
}).append($icon).append($name).dblclick(function () {
|
|
||||||
openFile(file.href);
|
openFile(file.href);
|
||||||
});
|
});
|
||||||
$element.click(function(e) {
|
$element.click(function(e) {
|
||||||
@ -1041,9 +1085,8 @@ define([
|
|||||||
if (collapsable) {
|
if (collapsable) {
|
||||||
$collapse = $expandIcon.clone();
|
$collapse = $expandIcon.clone();
|
||||||
}
|
}
|
||||||
var $element = $('<li>', {
|
var $element = $('<li>').append($collapse).append($icon).append($name);
|
||||||
draggable: draggable
|
if (draggable) { $element.attr('draggable', true); }
|
||||||
}).append($collapse).append($icon).append($name);
|
|
||||||
if (collapsable) {
|
if (collapsable) {
|
||||||
$element.addClass('collapsed');
|
$element.addClass('collapsed');
|
||||||
$collapse.click(function() {
|
$collapse.click(function() {
|
||||||
@ -1406,12 +1449,13 @@ define([
|
|||||||
|
|
||||||
var hash = window.location.hash.slice(1) || localStorage.FS_hash;
|
var hash = window.location.hash.slice(1) || localStorage.FS_hash;
|
||||||
var secret = Cryptpad.getSecrets(hash);
|
var secret = Cryptpad.getSecrets(hash);
|
||||||
|
var readOnly = APP.readOnly = secret.keys && !secret.keys.editKeyStr;
|
||||||
|
|
||||||
var listmapConfig = module.config = {
|
var listmapConfig = module.config = {
|
||||||
data: {},
|
data: {},
|
||||||
websocketURL: Cryptpad.getWebsocketURL(),
|
websocketURL: Cryptpad.getWebsocketURL(),
|
||||||
channel: secret.channel,
|
channel: secret.channel,
|
||||||
readOnly: false,
|
readOnly: readOnly,
|
||||||
validateKey: secret.keys.validateKey || undefined,
|
validateKey: secret.keys.validateKey || undefined,
|
||||||
crypto: Crypto.createEncryptor(secret.keys),
|
crypto: Crypto.createEncryptor(secret.keys),
|
||||||
logging: false
|
logging: false
|
||||||
@ -1421,8 +1465,11 @@ define([
|
|||||||
rt.proxy.on('create', function (info) {
|
rt.proxy.on('create', function (info) {
|
||||||
var realtime = module.realtime = info.realtime;
|
var realtime = module.realtime = info.realtime;
|
||||||
|
|
||||||
var editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys);
|
var editHash = !readOnly ? Cryptpad.getEditHashFromKeys(info.channel, secret.keys) : undefined;
|
||||||
if (!window.location.hash || !localStorage.FS_hash) {
|
var viewHash = Cryptpad.getViewHashFromKeys(info.channel, secret.keys);
|
||||||
|
|
||||||
|
APP.hash = readOnly ? viewHash : editHash;
|
||||||
|
if (!readOnly && (!window.location.hash || !localStorage.FS_hash)) {
|
||||||
localStorage.FS_hash = editHash;
|
localStorage.FS_hash = editHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1431,7 +1478,6 @@ define([
|
|||||||
logging: true,
|
logging: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
var readOnly = false;
|
|
||||||
userList = APP.userList = info.userList;
|
userList = APP.userList = info.userList;
|
||||||
var config = {
|
var config = {
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
@ -1462,7 +1508,7 @@ define([
|
|||||||
init(rt.proxy);
|
init(rt.proxy);
|
||||||
})
|
})
|
||||||
.on('disconnect', function (info) {
|
.on('disconnect', function (info) {
|
||||||
//setEditable(false);
|
setEditable(false);
|
||||||
console.error('err');
|
console.error('err');
|
||||||
Cryptpad.alert(Messages.common_connectionLost);
|
Cryptpad.alert(Messages.common_connectionLost);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user