mirror of https://github.com/xwiki-labs/cryptpad
Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging
This commit is contained in:
commit
89bee8cf6b
|
@ -50,9 +50,26 @@ define(req, function(Default, Language) {
|
||||||
var langs = arguments;
|
var langs = arguments;
|
||||||
Object.keys(externalMap).forEach(function (code, i) {
|
Object.keys(externalMap).forEach(function (code, i) {
|
||||||
var translation = langs[i];
|
var translation = langs[i];
|
||||||
|
var updated = {};
|
||||||
|
Object.keys(Default).forEach(function (k) {
|
||||||
|
if (/^updated_[0-9]+_/.test(k) && !translation[k]) {
|
||||||
|
var key = k.split('_').slice(2).join('_');
|
||||||
|
// Make sure we don't already have an update for that key. It should not happen
|
||||||
|
// but if it does, keep the latest version
|
||||||
|
if (updated[key]) {
|
||||||
|
var ek = updated[key];
|
||||||
|
if (parseInt(ek.split('_')[1]) > parseInt(k.split('_')[1])) { return; }
|
||||||
|
}
|
||||||
|
updated[key] = k;
|
||||||
|
}
|
||||||
|
});
|
||||||
Object.keys(Default).forEach(function (k) {
|
Object.keys(Default).forEach(function (k) {
|
||||||
if (/^_/.test(k)) { return; }
|
if (/^_/.test(k)) { return; }
|
||||||
if (!translation[k]) {
|
if (!translation[k] || updated[k]) {
|
||||||
|
if (updated[k]) {
|
||||||
|
missing.push([code, k, 2, 'out.' + updated[k]]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
missing.push([code, k, 1]);
|
missing.push([code, k, 1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -62,10 +79,6 @@ define(req, function(Default, Language) {
|
||||||
missing.push([code, k, 0]);
|
missing.push([code, k, 0]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
/*if (typeof(translation._languageName) !== 'string') {
|
|
||||||
var warning = 'key [_languageName] is missing from translation [' + code + ']';
|
|
||||||
missing.push(warning);
|
|
||||||
}*/
|
|
||||||
});
|
});
|
||||||
cb(missing);
|
cb(missing);
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,8 @@ define(function () {
|
||||||
out.type.poll = 'Encuesta';
|
out.type.poll = 'Encuesta';
|
||||||
out.type.slide = 'Presentación';
|
out.type.slide = 'Presentación';
|
||||||
|
|
||||||
out.common_connectionLost = "<b>Connexión perdida</b><br>El documento está ahora en modo solo lectura hasta que la conexión vuelva.";
|
out.updated_0_common_connectionLost = "<b>Connexión perdida</b><br>El documento está ahora en modo solo lectura hasta que la conexión vuelva.";
|
||||||
|
out.common_connectionLost = out.updated_0_common_connectionLost;
|
||||||
|
|
||||||
out.disconnected = "Desconectado";
|
out.disconnected = "Desconectado";
|
||||||
out.synchronizing = "Sincronización";
|
out.synchronizing = "Sincronización";
|
||||||
|
|
|
@ -16,7 +16,8 @@ define(function () {
|
||||||
out.button_newpoll = 'Nouveau sondage';
|
out.button_newpoll = 'Nouveau sondage';
|
||||||
out.button_newslide = 'Nouvelle présentation';
|
out.button_newslide = 'Nouvelle présentation';
|
||||||
|
|
||||||
out.common_connectionLost = "<b>Connexion au serveur perdue</b><br>Vous êtes désormais en mode lecture seule jusqu'au retour de la connexion.";
|
out.updated_0_common_connectionLost = "<b>Connexion au serveur perdue</b><br>Vous êtes désormais en mode lecture seule jusqu'au retour de la connexion.";
|
||||||
|
out.common_connectionLost = out.updated_0_common_connectionLost;
|
||||||
|
|
||||||
out.websocketError = 'Impossible de se connecter au serveur WebSocket...';
|
out.websocketError = 'Impossible de se connecter au serveur WebSocket...';
|
||||||
out.typeError = "Ce document temps-réel n'est pas compatible avec l'application sélectionnée";
|
out.typeError = "Ce document temps-réel n'est pas compatible avec l'application sélectionnée";
|
||||||
|
|
|
@ -18,8 +18,8 @@ define(function () {
|
||||||
|
|
||||||
// NOTE: We want to update the 'common_connectionLost' key.
|
// NOTE: We want to update the 'common_connectionLost' key.
|
||||||
// Please do not add a new 'updated_common_connectionLostAndInfo' but change directly the value of 'common_connectionLost'
|
// Please do not add a new 'updated_common_connectionLostAndInfo' but change directly the value of 'common_connectionLost'
|
||||||
out.updated_common_connectionLostAndInfo = "<b>Server Connection Lost</b><br>You're now in read-only mode until the connection is back.";
|
out.updated_0_common_connectionLost = "<b>Server Connection Lost</b><br>You're now in read-only mode until the connection is back.";
|
||||||
out.common_connectionLost = out.updated_common_connectionLostAndInfo;
|
out.common_connectionLost = out.updated_0_common_connectionLost;
|
||||||
|
|
||||||
out.websocketError = 'Unable to connect to the websocket server...';
|
out.websocketError = 'Unable to connect to the websocket server...';
|
||||||
out.typeError = "That realtime document is not compatible with the selected application";
|
out.typeError = "That realtime document is not compatible with the selected application";
|
||||||
|
|
|
@ -141,22 +141,6 @@ define([
|
||||||
strungJSON(orig);
|
strungJSON(orig);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert(function () {
|
|
||||||
var todo = function (missing) {
|
|
||||||
if (missing.length !== 0) {
|
|
||||||
missing.forEach(function (msg) {
|
|
||||||
console.log('* ' + msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
// No, this is crappy, it's going to cause tests to fail basically all of the time.
|
|
||||||
//return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Cryptpad.Messages._checkTranslationState(todo);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}, "expected all translation keys in default language to be present in all translations. See console for details.");
|
|
||||||
|
|
||||||
var swap = function (str, dict) {
|
var swap = function (str, dict) {
|
||||||
return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
|
return str.replace(/\{\{(.*?)\}\}/g, function (all, key) {
|
||||||
return typeof dict[key] !== 'undefined'? dict[key] : all;
|
return typeof dict[key] !== 'undefined'? dict[key] : all;
|
||||||
|
|
|
@ -21,6 +21,7 @@ define([
|
||||||
var code = msg[0];
|
var code = msg[0];
|
||||||
var key = msg[1];
|
var key = msg[1];
|
||||||
var needed = msg[2];
|
var needed = msg[2];
|
||||||
|
var value = msg[3] || '""';
|
||||||
|
|
||||||
if (str !== code) {
|
if (str !== code) {
|
||||||
if (str !== "")
|
if (str !== "")
|
||||||
|
@ -38,10 +39,11 @@ define([
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res += (need ? '' : '// ') + 'out.' + key + ' = "";';
|
res += (need ? '' : '// ') + 'out.' + key + ' = ' + value + ';';
|
||||||
if (need)
|
if (need === 1) {
|
||||||
{
|
|
||||||
res += ' // ' + JSON.stringify(English[key]);
|
res += ' // ' + JSON.stringify(English[key]);
|
||||||
|
} else if (need === 2) {
|
||||||
|
res += ' // TODO: Key updated --> make sure the updated key "'+ value +'" exists and is translated before that one.';
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}).join('\n')));
|
}).join('\n')));
|
||||||
|
|
|
@ -706,7 +706,6 @@ define([
|
||||||
common.initialName = sessionStorage[newPadNameKey];
|
common.initialName = sessionStorage[newPadNameKey];
|
||||||
delete sessionStorage[newPadNameKey];
|
delete sessionStorage[newPadNameKey];
|
||||||
}
|
}
|
||||||
// Deprecated
|
|
||||||
if (sessionStorage[newPadPathKey]) {
|
if (sessionStorage[newPadPathKey]) {
|
||||||
common.initialPath = sessionStorage[newPadPathKey];
|
common.initialPath = sessionStorage[newPadPathKey];
|
||||||
delete sessionStorage[newPadPathKey];
|
delete sessionStorage[newPadPathKey];
|
||||||
|
|
|
@ -392,6 +392,10 @@ span.fa-folder-open {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
width: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
direction: rtl;
|
||||||
}
|
}
|
||||||
#driveToolbar .path .element {
|
#driveToolbar .path .element {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
@ -406,3 +410,10 @@ span.fa-folder-open {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
}
|
}
|
||||||
|
#driveToolbar #contextButtonsContainer {
|
||||||
|
float: right;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
#driveToolbar #contextButtonsContainer button {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
|
@ -451,6 +451,10 @@ span {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
width: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
direction: rtl;
|
||||||
.element {
|
.element {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 1px solid @toolbar-bg;
|
border: 1px solid @toolbar-bg;
|
||||||
|
@ -465,6 +469,13 @@ span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#contextButtonsContainer {
|
||||||
|
float: right;
|
||||||
|
margin: 5px;
|
||||||
|
button {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,39 +19,39 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="treeContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="treeContextMenu" 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 dropdown-item" data-localization="fc_open">Open</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-folder-open" class="open dropdown-item" data-localization="fc_open">Open</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="open_ro dropdown-item" data-localization="fc_open_ro">Open (read-only)</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-eye" class="open_ro dropdown-item" data-localization="fc_open_ro">Open (read-only)</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="rename editable dropdown-item" data-localization="fc_rename">Rename</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-pencil" class="rename editable dropdown-item" data-localization="fc_rename">Rename</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="delete editable dropdown-item" data-localization="fc_delete">Delete</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-trash" class="delete editable dropdown-item" data-localization="fc_delete">Delete</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newfolder editable dropdown-item" data-localization="fc_newfolder">New folder</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-folder" class="newfolder editable dropdown-item" 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 editable dropdown-item" data-localization="fc_newfolder">New folder</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-folder" class="newfolder editable dropdown-item" data-localization="fc_newfolder">New folder</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc own editable dropdown-item" data-type="pad" data-localization="button_newpad">New pad</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-file-word-o" class="newdoc own editable dropdown-item" data-type="pad" data-localization="button_newpad">New pad</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc own editable dropdown-item" data-type="code" data-localization="button_newcode">New code</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-file-code-o" class="newdoc own editable dropdown-item" data-type="code" data-localization="button_newcode">New code</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc own editable dropdown-item" data-type="slide" data-localization="button_newslide">New slide</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-file-powerpoint-o" class="newdoc own editable dropdown-item" data-type="slide" data-localization="button_newslide">New slide</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="newdoc own editable dropdown-item" data-type="poll" data-localization="button_newpoll">New poll</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-calendar" class="newdoc own editable dropdown-item" data-type="poll" data-localization="button_newpoll">New poll</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="defaultContextMenu" class="contextMenu dropdown clearfix" oncontextmenu="return false;">
|
<div id="defaultContextMenu" 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 dropdown-item" data-localization="fc_open">Open</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-folder-open" class="open dropdown-item" data-localization="fc_open">Open</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="open_ro dropdown-item" data-localization="fc_open_ro">Open (read-only)</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-eye" class="open_ro dropdown-item" data-localization="fc_open_ro">Open (read-only)</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="delete dropdown-item" data-localization="fc_delete">Delete</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-trash" class="delete dropdown-item" data-localization="fc_delete">Delete</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 editable dropdown-item" data-localization="fc_empty">Empty the trash</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-trash-o" class="empty editable dropdown-item" 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 editable dropdown-item" data-localization="fc_remove">Delete permanently</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-eraser" class="remove editable dropdown-item" data-localization="fc_remove">Delete permanently</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="restore editable dropdown-item" data-localization="fc_restore">Restore</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-repeat" class="restore editable dropdown-item" data-localization="fc_restore">Restore</a></li>
|
||||||
<li><a tabindex="-1" href="#" class="properties dropdown-item" data-localization="fc_prop">Properties</a></li>
|
<li><a tabindex="-1" href="#" data-icon="fa-database" class="properties dropdown-item" data-localization="fc_prop">Properties</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -281,6 +281,8 @@ 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) {
|
||||||
|
// NOTE: setTimeout(f, 0) otherwise the "rename" button in the toolbar is not working
|
||||||
|
window.setTimeout(function () {
|
||||||
if (!APP.editable) { return; }
|
if (!APP.editable) { 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.");
|
||||||
|
@ -331,6 +333,38 @@ define([
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
$input.parents('li').attr("draggable", true);
|
$input.parents('li').attr("draggable", true);
|
||||||
});
|
});
|
||||||
|
},0);
|
||||||
|
};
|
||||||
|
|
||||||
|
var filterContextMenu = function ($menu, $element) {
|
||||||
|
var path = $element.data('path');
|
||||||
|
|
||||||
|
var hide = [];
|
||||||
|
if (!APP.editable) {
|
||||||
|
hide.push($menu.find('a.editable'));
|
||||||
|
}
|
||||||
|
if (!isOwnDrive()) {
|
||||||
|
hide.push($menu.find('a.own'));
|
||||||
|
}
|
||||||
|
if ($element.is('.file-element')) {
|
||||||
|
hide.push($menu.find('a.newfolder'));
|
||||||
|
} else {
|
||||||
|
hide.push($menu.find('a.open_ro'));
|
||||||
|
}
|
||||||
|
if (path && path.length > 4) {
|
||||||
|
hide.push($menu.find('a.restore'));
|
||||||
|
hide.push($menu.find('a.properties'));
|
||||||
|
}
|
||||||
|
return hide;
|
||||||
|
};
|
||||||
|
|
||||||
|
var updatePathSize = function () {
|
||||||
|
var $context = $iframe.find('#contextButtonsContainer');
|
||||||
|
var l = 50;
|
||||||
|
if ($context.length) {
|
||||||
|
l += $context.width() || 0;
|
||||||
|
}
|
||||||
|
$driveToolbar.find('.path').css('max-width', 'calc(100vw - '+$tree.width()+'px - '+l+'px)');
|
||||||
};
|
};
|
||||||
|
|
||||||
var updateContextButton = function () {
|
var updateContextButton = function () {
|
||||||
|
@ -339,6 +373,7 @@ define([
|
||||||
$li = $tree.find('.element.active').closest('li');
|
$li = $tree.find('.element.active').closest('li');
|
||||||
}
|
}
|
||||||
var $button = $driveToolbar.find('#contextButton');
|
var $button = $driveToolbar.find('#contextButton');
|
||||||
|
if ($button.length) { // mobile
|
||||||
if ($li.length !== 1
|
if ($li.length !== 1
|
||||||
|| !$._data($li[0], 'events').contextmenu
|
|| !$._data($li[0], 'events').contextmenu
|
||||||
|| $._data($li[0], 'events').contextmenu.length === 0) {
|
|| $._data($li[0], 'events').contextmenu.length === 0) {
|
||||||
|
@ -354,6 +389,39 @@ define([
|
||||||
background: ''
|
background: ''
|
||||||
});
|
});
|
||||||
}, 500);
|
}, 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Non mobile
|
||||||
|
var $container = $driveToolbar.find('#contextButtonsContainer');
|
||||||
|
if (!$container.length) { return; }
|
||||||
|
$container.html('');
|
||||||
|
var $element = $li;
|
||||||
|
var $menu = $element.data('context');
|
||||||
|
var path = $element.data('path');
|
||||||
|
if (!$menu || !path) { return; }
|
||||||
|
var actions = [];
|
||||||
|
var $actions = $menu.find('a');
|
||||||
|
var toHide = filterContextMenu($menu, $element);
|
||||||
|
$actions = $actions.filter(function (i, el) {
|
||||||
|
for (var j = 0; j < toHide.length; j++) {
|
||||||
|
if ($(el).is(toHide[j])) { return false; };
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
$actions.each(function (i, el) {
|
||||||
|
var $a = $('<button>', {'class': 'element'});
|
||||||
|
if ($(el).attr('data-icon')) {
|
||||||
|
$a.addClass('fa').addClass($(el).attr('data-icon'));
|
||||||
|
$a.attr('title', $(el).text());
|
||||||
|
} else {
|
||||||
|
$a.text($(el).text());
|
||||||
|
}
|
||||||
|
$(el).data('path', path);
|
||||||
|
$(el).data('element', $element);
|
||||||
|
$container.append($a);
|
||||||
|
$a.click(function() { $(el).click(); });
|
||||||
|
});
|
||||||
|
updatePathSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the "selected" class to the "li" corresponding to the clicked element
|
// Add the "selected" class to the "li" corresponding to the clicked element
|
||||||
|
@ -384,15 +452,21 @@ define([
|
||||||
module.hideMenu();
|
module.hideMenu();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
var path = $(e.target).closest('li').data('path');
|
var $element = $(e.target).closest('li');
|
||||||
|
if (!$element.length) {
|
||||||
|
logError("Unable to locate the .element tag", e.target);
|
||||||
|
$menu.hide();
|
||||||
|
log(Messages.fm_contextMenuError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = $element.data('path');
|
||||||
if (!path) { return false; }
|
if (!path) { return false; }
|
||||||
|
|
||||||
if (!APP.editable) {
|
var toHide = filterContextMenu($menu, $element);
|
||||||
$menu.find('a.editable').parent('li').hide();
|
toHide.forEach(function ($a) {
|
||||||
}
|
$a.parent('li').hide();
|
||||||
if (!isOwnDrive()) {
|
});
|
||||||
$menu.find('a.own').parent('li').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$menu.css({
|
$menu.css({
|
||||||
display: "block",
|
display: "block",
|
||||||
|
@ -406,45 +480,27 @@ define([
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// $element should be the <li class="element">
|
|
||||||
var $element = $(e.target).closest('li');
|
|
||||||
onElementClick(undefined, $element);
|
onElementClick(undefined, $element);
|
||||||
if (!$element.length) {
|
|
||||||
logError("Unable to locate the .element tag", e.target);
|
|
||||||
$menu.hide();
|
|
||||||
log(Messages.fm_contextMenuError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$menu.find('a').data('path', path);
|
$menu.find('a').data('path', path);
|
||||||
$menu.find('a').data('element', $element);
|
$menu.find('a').data('element', $element);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var openDirectoryContextMenu = function (e) {
|
var openDirectoryContextMenu = function (e) {
|
||||||
var $element = $(e.target).closest('li');
|
|
||||||
$contextMenu.find('li').show();
|
$contextMenu.find('li').show();
|
||||||
if ($element.is('.file-element')) {
|
|
||||||
$contextMenu.find('a.newfolder').parent('li').hide();
|
|
||||||
} else {
|
|
||||||
$contextMenu.find('a.open_ro').parent('li').hide();
|
|
||||||
}
|
|
||||||
openContextMenu(e, $contextMenu);
|
openContextMenu(e, $contextMenu);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var openDefaultContextMenu = function (e) {
|
var openDefaultContextMenu = function (e) {
|
||||||
var $element = $(e.target).closest('li');
|
|
||||||
$defaultContextMenu.find('li').show();
|
$defaultContextMenu.find('li').show();
|
||||||
if ($element.is('.file-element')) {
|
|
||||||
$defaultContextMenu.find('a.newfolder').parent('li').hide();
|
|
||||||
} else {
|
|
||||||
$defaultContextMenu.find('a.open_ro').parent('li').hide();
|
|
||||||
}
|
|
||||||
openContextMenu(e, $defaultContextMenu);
|
openContextMenu(e, $defaultContextMenu);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var openTrashTreeContextMenu = function (e) {
|
var openTrashTreeContextMenu = function (e) {
|
||||||
|
$trashTreeContextMenu.find('li').show();
|
||||||
openContextMenu(e, $trashTreeContextMenu);
|
openContextMenu(e, $trashTreeContextMenu);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -453,10 +509,6 @@ define([
|
||||||
var path = $(e.target).closest('li').data('path');
|
var path = $(e.target).closest('li').data('path');
|
||||||
if (!path) { return; }
|
if (!path) { return; }
|
||||||
$trashContextMenu.find('li').show();
|
$trashContextMenu.find('li').show();
|
||||||
if (path.length > 4) {
|
|
||||||
$trashContextMenu.find('a.restore').parent('li').hide();
|
|
||||||
$trashContextMenu.find('a.properties').parent('li').hide();
|
|
||||||
}
|
|
||||||
openContextMenu(e, $trashContextMenu);
|
openContextMenu(e, $trashContextMenu);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -752,8 +804,10 @@ define([
|
||||||
});
|
});
|
||||||
if (!isTrash) {
|
if (!isTrash) {
|
||||||
$element.contextmenu(openDirectoryContextMenu);
|
$element.contextmenu(openDirectoryContextMenu);
|
||||||
|
$element.data('context', $contextMenu);
|
||||||
} else {
|
} else {
|
||||||
$element.contextmenu(openTrashContextMenu);
|
$element.contextmenu(openTrashContextMenu);
|
||||||
|
$element.data('context', $trashContextMenu);
|
||||||
}
|
}
|
||||||
var isNewFolder = module.newFolder && filesOp.comparePath(newPath, module.newFolder);
|
var isNewFolder = module.newFolder && filesOp.comparePath(newPath, module.newFolder);
|
||||||
if (isNewFolder) {
|
if (isNewFolder) {
|
||||||
|
@ -914,16 +968,11 @@ define([
|
||||||
}
|
}
|
||||||
AppConfig.availablePadTypes.forEach(function (type) {
|
AppConfig.availablePadTypes.forEach(function (type) {
|
||||||
if (type === 'drive') { return; }
|
if (type === 'drive') { return; }
|
||||||
var path = filesOp.isPathInTrash(currentPath) ? '' : '/#?path=' + encodeURIComponent(currentPath);
|
|
||||||
var attributes = {
|
var attributes = {
|
||||||
'class': 'newdoc',
|
'class': 'newdoc',
|
||||||
'data-type': type
|
'data-type': type,
|
||||||
|
'href': '#'
|
||||||
};
|
};
|
||||||
// In root, do not redirect instantly, but ask for a name first. Cf handlers below
|
|
||||||
if (!isInRoot) {
|
|
||||||
attributes.href = '/' + type + path;
|
|
||||||
attributes.target = '_blank';
|
|
||||||
}
|
|
||||||
options.push({
|
options.push({
|
||||||
tag: 'a',
|
tag: 'a',
|
||||||
attributes: attributes,
|
attributes: attributes,
|
||||||
|
@ -953,6 +1002,12 @@ define([
|
||||||
var name = Cryptpad.getDefaultName({type: type});
|
var name = Cryptpad.getDefaultName({type: type});
|
||||||
filesOp.createNewFile(currentPath, name, type, onCreated);
|
filesOp.createNewFile(currentPath, name, type, onCreated);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
$block.find('a.newdoc').click(function (e) {
|
||||||
|
var type = $(this).attr('data-type') || 'pad';
|
||||||
|
sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathInTrash(currentPath) ? '' : currentPath;
|
||||||
|
window.open('/' + type + '/');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return $block;
|
return $block;
|
||||||
|
@ -1202,6 +1257,7 @@ define([
|
||||||
onElementClick(e, $element, path);
|
onElementClick(e, $element, path);
|
||||||
});
|
});
|
||||||
$element.contextmenu(openDefaultContextMenu);
|
$element.contextmenu(openDefaultContextMenu);
|
||||||
|
$element.data('context', $defaultContextMenu);
|
||||||
if (draggable) {
|
if (draggable) {
|
||||||
addDragAndDropHandlers($element, path, false, false);
|
addDragAndDropHandlers($element, path, false, false);
|
||||||
}
|
}
|
||||||
|
@ -1231,6 +1287,7 @@ define([
|
||||||
onElementClick(e, $element);
|
onElementClick(e, $element);
|
||||||
});
|
});
|
||||||
$element.contextmenu(openDefaultContextMenu);
|
$element.contextmenu(openDefaultContextMenu);
|
||||||
|
$element.data('context', $defaultContextMenu); // TODO: hide the "delete" link in that context menu
|
||||||
$container.append($element);
|
$container.append($element);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1328,6 +1385,7 @@ define([
|
||||||
|
|
||||||
var $modeButton = createViewModeButton().appendTo($toolbar.find('.rightside'));
|
var $modeButton = createViewModeButton().appendTo($toolbar.find('.rightside'));
|
||||||
var $title = createTitle(path).appendTo($toolbar.find('.rightside'));
|
var $title = createTitle(path).appendTo($toolbar.find('.rightside'));
|
||||||
|
updatePathSize();
|
||||||
|
|
||||||
if (APP.mobile()) {
|
if (APP.mobile()) {
|
||||||
var $context = $('<button>', {'class': 'element right dropdown-bar', id: 'contextButton'});
|
var $context = $('<button>', {'class': 'element right dropdown-bar', id: 'contextButton'});
|
||||||
|
@ -1352,6 +1410,9 @@ define([
|
||||||
});
|
});
|
||||||
$li.contextmenu();
|
$li.contextmenu();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
var $contextButtons = $('<span>', {'id' : 'contextButtonsContainer'});
|
||||||
|
$contextButtons.appendTo($toolbar.find('.rightside'));
|
||||||
}
|
}
|
||||||
updateContextButton();
|
updateContextButton();
|
||||||
|
|
||||||
|
@ -1589,6 +1650,14 @@ define([
|
||||||
return base + viewHash;
|
return base + viewHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Disable middle click in the context menu to avoid opening /drive/inner.html# in new tabs
|
||||||
|
$(ifrw).click(function (e) {
|
||||||
|
if (e.which !== 3) {
|
||||||
|
e.stopPropagation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$contextMenu.on("click", "a", function(e) {
|
$contextMenu.on("click", "a", function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
var path = $(this).data('path');
|
var path = $(this).data('path');
|
||||||
|
@ -1820,6 +1889,7 @@ define([
|
||||||
if (APP.resizeTree) { return; }
|
if (APP.resizeTree) { return; }
|
||||||
APP.resizeTree = window.setInterval(function () {
|
APP.resizeTree = window.setInterval(function () {
|
||||||
$driveToolbar.find('.leftside').width($tree.width());
|
$driveToolbar.find('.leftside').width($tree.width());
|
||||||
|
updatePathSize();
|
||||||
}, 100);
|
}, 100);
|
||||||
});
|
});
|
||||||
$(ifrw).mouseup(function (e) {
|
$(ifrw).mouseup(function (e) {
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<div id="align-container">
|
<div id="align-container">
|
||||||
<div id="main-container">
|
<div id="main-container">
|
||||||
<div id="data" class="hidden">
|
<div id="data" class="hidden">
|
||||||
<p class="left" data-localization="main_p1"><!-- Zero Knowledge collaborative realtime editor. Protected from the NSA. --></p>
|
<p class="left" data-localization="main_info"><!-- Zero Knowledge collaborative realtime editor. Protected from the NSA. --></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="userForm" class="form-group hidden">
|
<div id="userForm" class="form-group hidden">
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
define(function () {
|
||||||
|
// Adds a context menu entry to open the selected link in a new tab.
|
||||||
|
// See https://github.com/xwiki-contrib/application-ckeditor/commit/755d193497bf23ed874d874b4ae92fbee887fc10
|
||||||
|
return {
|
||||||
|
addSupportForOpeningLinksInNewTab : function (Ckeditor) {
|
||||||
|
return function(event) {
|
||||||
|
var editor = event.editor;
|
||||||
|
if (!Ckeditor.plugins.link) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.addCommand( 'openLink', {
|
||||||
|
exec: function(editor) {
|
||||||
|
var anchor = getActiveLink(editor);
|
||||||
|
if (anchor) {
|
||||||
|
var href = anchor.getAttribute('href');
|
||||||
|
if (href) {
|
||||||
|
window.open(href);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (typeof editor.addMenuItem === 'function') {
|
||||||
|
editor.addMenuItem('openLink', {
|
||||||
|
label: 'Open Link in New Tab',
|
||||||
|
command: 'openLink',
|
||||||
|
group: 'link',
|
||||||
|
order: -1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (editor.contextMenu) {
|
||||||
|
editor.contextMenu.addListener(function(startElement, selection, path) {
|
||||||
|
if (startElement) {
|
||||||
|
var anchor = getActiveLink(editor);
|
||||||
|
if (anchor && anchor.getAttribute('href')) {
|
||||||
|
return {openLink: Ckeditor.TRISTATE_OFF};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editor.contextMenu._.panelDefinition.css.push('.cke_button__openLink_icon {' +
|
||||||
|
Ckeditor.skin.getIconStyle('link') + '}');
|
||||||
|
}
|
||||||
|
// Returns the DOM element of the active (currently focused) link. It has also support for linked image widgets.
|
||||||
|
// @return {CKEDITOR.dom.element}
|
||||||
|
var getActiveLink = function(editor) {
|
||||||
|
var anchor = Ckeditor.plugins.link.getSelectedLink(editor),
|
||||||
|
// We need to do some special checking against widgets availability.
|
||||||
|
activeWidget = editor.widgets && editor.widgets.focused;
|
||||||
|
// If default way of getting links didn't return anything useful..
|
||||||
|
if (!anchor && activeWidget && activeWidget.name == 'image' && activeWidget.parts.link) {
|
||||||
|
// Since CKEditor 4.4.0 image widgets may be linked.
|
||||||
|
anchor = activeWidget.parts.link;
|
||||||
|
}
|
||||||
|
return anchor;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -12,12 +12,13 @@ define([
|
||||||
'/common/cryptpad-common.js',
|
'/common/cryptpad-common.js',
|
||||||
'/common/visible.js',
|
'/common/visible.js',
|
||||||
'/common/notify.js',
|
'/common/notify.js',
|
||||||
|
'/pad/links.js',
|
||||||
'/bower_components/file-saver/FileSaver.min.js',
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
'/bower_components/diff-dom/diffDOM.js',
|
'/bower_components/diff-dom/diffDOM.js',
|
||||||
'/bower_components/jquery/dist/jquery.min.js',
|
'/bower_components/jquery/dist/jquery.min.js',
|
||||||
], function (Crypto, realtimeInput, Hyperjson,
|
], function (Crypto, realtimeInput, Hyperjson,
|
||||||
Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad,
|
Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad,
|
||||||
Visible, Notify) {
|
Visible, Notify, Links) {
|
||||||
var $ = window.jQuery;
|
var $ = window.jQuery;
|
||||||
var saveAs = window.saveAs;
|
var saveAs = window.saveAs;
|
||||||
var Messages = Cryptpad.Messages;
|
var Messages = Cryptpad.Messages;
|
||||||
|
@ -102,6 +103,7 @@ define([
|
||||||
customConfig: '/customize/ckeditor-config.js',
|
customConfig: '/customize/ckeditor-config.js',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editor.on('instanceReady', Links.addSupportForOpeningLinksInNewTab(Ckeditor));
|
||||||
editor.on('instanceReady', function (Ckeditor) {
|
editor.on('instanceReady', function (Ckeditor) {
|
||||||
var $bar = $('#pad-iframe')[0].contentWindow.$('#cke_1_toolbox');
|
var $bar = $('#pad-iframe')[0].contentWindow.$('#cke_1_toolbox');
|
||||||
var parsedHash = Cryptpad.parsePadUrl(window.location.href);
|
var parsedHash = Cryptpad.parsePadUrl(window.location.href);
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>CryptPad</li>
|
<li class="title">CryptPad</li>
|
||||||
<li><a href="/about.html" data-localization="about"></a></li>
|
<li><a href="/about.html" data-localization="about"></a></li>
|
||||||
<li><a href="/terms.html" data-localization="terms"></a></li>
|
<li><a href="/terms.html" data-localization="terms"></a></li>
|
||||||
<li><a href="/privacy.html" data-localization="privacy"></a></li>
|
<li><a href="/privacy.html" data-localization="privacy"></a></li>
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li data-localization="footer_applications"><li>
|
<li class="title" data-localization="footer_applications"><li>
|
||||||
<li><a href="/pad/" data-localization="main_richText"></a></li>
|
<li><a href="/pad/" data-localization="main_richText"></a></li>
|
||||||
<li><a href="/code/" data-localization="main_code"></a></li>
|
<li><a href="/code/" data-localization="main_code"></a></li>
|
||||||
<li><a href="/slide/" data-localization="main_slide"></a></li>
|
<li><a href="/slide/" data-localization="main_slide"></a></li>
|
||||||
|
@ -95,15 +95,15 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li data-localization="footer_aboutUs"><li>
|
<li class="title" data-localization="footer_aboutUs"><li>
|
||||||
<li><a href="https://labs.xwiki.com" target="_blank" rel="noopener noreferrer">XWiki Labs</a></li>
|
<li><a href="https://labs.xwiki.com" target="_blank" rel="noopener noreferrer">XWiki Labs</a></li>
|
||||||
<li><a href="http://www.xwiki.com" target="_blank" rel="noopener noreferrer">XWiki SAS</a></li>
|
<li><a href="http://www.xwiki.com" target="_blank" rel="noopener noreferrer">XWiki SAS</a></li>
|
||||||
<li><a href="https://www.openpass.fr/" target="_blank" rel="noopener noreferrer">OpenPaaS</a></li>
|
<li><a href="https://www.open-paas.org/" target="_blank" rel="noopener noreferrer">OpenPaaS</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li data-localization="footer_contact"><li>
|
<li class="title" data-localization="footer_contact"><li>
|
||||||
<li><a href="http://webchat.freenode.net?channels=%23cryptpad&uio=MT1mYWxzZSY5PXRydWUmMTE9Mjg3JjE1PXRydWUe7" target="_blank" rel="noopener noreferrer">IRC</a></li>
|
<li><a href="http://webchat.freenode.net?channels=%23cryptpad&uio=MT1mYWxzZSY5PXRydWUmMTE9Mjg3JjE1PXRydWUe7" target="_blank" rel="noopener noreferrer">IRC</a></li>
|
||||||
<li><a href="https://twitter.com/cryptpad" target="_blank" rel="noopener noreferrer">Twitter</a></li>
|
<li><a href="https://twitter.com/cryptpad" target="_blank" rel="noopener noreferrer">Twitter</a></li>
|
||||||
<li><a href="https://github.com/xwiki-labs/cryptpad" target="_blank" rel="noopener noreferrer">GitHub</a></li>
|
<li><a href="https://github.com/xwiki-labs/cryptpad" target="_blank" rel="noopener noreferrer">GitHub</a></li>
|
||||||
|
|
Loading…
Reference in New Issue