Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging

pull/1/head
ClemDee 6 years ago
commit 3635d1305a

@ -21,7 +21,7 @@ www/pad/mediatag-plugin-dialog.js
www/pad/disable-base64.js www/pad/disable-base64.js
www/kanban/jkanban.js www/kanban/jkanban.js
www/kanban/jscolor.js www/common/jscolor.js
www/common/media-tag-nacl.min.js www/common/media-tag-nacl.min.js

@ -1651,6 +1651,7 @@ define([
}; };
if (!proxy.settings) { proxy.settings = {}; } if (!proxy.settings) { proxy.settings = {}; }
var manager = store.manager = ProxyManager.create(proxy.drive, { var manager = store.manager = ProxyManager.create(proxy.drive, {
onSync: onSync,
edPublic: proxy.edPublic, edPublic: proxy.edPublic,
pin: pin, pin: pin,
unpin: unpin, unpin: unpin,

@ -375,6 +375,19 @@ define([
} }
}; };
exp.setFolderData = function (path, key, value, cb) {
var folder = exp.find(path);
if (!exp.isFolder(folder) || exp.isSharedFolder(folder)) { return; }
if (!exp.hasFolderData(folder)) {
var hashKey = "000" + Hash.createChannelId().slice(0, -3);
folder[hashKey] = {
metadata: true
};
}
exp.getFolderData(folder)[key] = value;
cb();
};
/** /**
* INTEGRITY CHECK * INTEGRITY CHECK
*/ */
@ -493,7 +506,16 @@ define([
var fixRoot = function (elem) { var fixRoot = function (elem) {
if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; } if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; }
var element = elem || files[ROOT]; var element = elem || files[ROOT];
var nbMetadataFolders = 0;
for (var el in element) { for (var el in element) {
if (exp.isFolderData(element[el])) {
if (nbMetadataFolders !== 0) {
debug("Multiple metadata files in folder");
delete element[el];
}
nbMetadataFolders++;
continue;
}
if (!exp.isFile(element[el], true) && !exp.isFolder(element[el])) { if (!exp.isFile(element[el], true) && !exp.isFolder(element[el])) {
debug("An element in ROOT was not a folder nor a file. ", element[el]); debug("An element in ROOT was not a folder nor a file. ", element[el]);
delete element[el]; delete element[el];

@ -567,6 +567,22 @@ define([
} }
resolved.userObject.rename(resolved.path, data.newName, cb); resolved.userObject.rename(resolved.path, data.newName, cb);
}; };
var _setFolderData = function (Env, data, cb) {
data = data || {};
var resolved = _resolvePath(Env, data.path);
if (!resolved || !resolved.userObject) { return void cb({error: 'E_NOTFOUND'}); }
if (!resolved.id) {
var el = Env.user.userObject.find(resolved.path);
if (Env.user.userObject.isSharedFolder(el) && Env.folders[el]) {
Env.user.proxy[UserObject.SHARED_FOLDERS][el][data.key] = data.value;
return void Env.onSync(cb);
}
}
resolved.userObject.setFolderData(resolved.path, data.key, data.value, function () {
Env.onSync(cb);
});
};
var onCommand = function (Env, cmdData, cb) { var onCommand = function (Env, cmdData, cb) {
var cmd = cmdData.cmd; var cmd = cmdData.cmd;
var data = cmdData.data || {}; var data = cmdData.data || {};
@ -585,6 +601,8 @@ define([
_emptyTrash(Env, data, cb); break; _emptyTrash(Env, data, cb); break;
case 'rename': case 'rename':
_rename(Env, data, cb); break; _rename(Env, data, cb); break;
case 'setFolderData':
_setFolderData(Env, data, cb); break;
default: default:
cb(); cb();
} }
@ -799,6 +817,7 @@ define([
var Env = { var Env = {
pinPads: data.pin, pinPads: data.pin,
unpinPads: data.unpin, unpinPads: data.unpin,
onSync: data.onSync,
loadSharedFolder: data.loadSharedFolder, loadSharedFolder: data.loadSharedFolder,
cfg: uoConfig, cfg: uoConfig,
edPublic: data.edPublic, edPublic: data.edPublic,
@ -905,6 +924,12 @@ define([
} }
}, cb); }, cb);
}; };
var setFolderDataInner = function (Env, data, cb) {
return void Env.sframeChan.query("Q_DRIVE_USEROBJECT", {
cmd: "setFolderData",
data: data
}, cb);
};
/* Tools */ /* Tools */
@ -989,6 +1014,19 @@ define([
return obj; return obj;
}; };
var getFolderData = function (Env, path) {
var resolved = _resolvePath(Env, path);
if (!resolved || !resolved.userObject) { return {}; }
if (!resolved.id) {
var el = Env.user.userObject.find(resolved.path);
if (Env.user.userObject.isSharedFolder(el)) {
return getSharedFolderData(Env, el);
}
}
var folder = resolved.userObject.find(resolved.path);
return resolved.userObject.getFolderData(folder);
};
var isInSharedFolder = _isInSharedFolder; var isInSharedFolder = _isInSharedFolder;
/* Generic: doesn't need access to a proxy */ /* Generic: doesn't need access to a proxy */
@ -1068,6 +1106,7 @@ define([
addSharedFolder: callWithEnv(addSharedFolderInner), addSharedFolder: callWithEnv(addSharedFolderInner),
delete: callWithEnv(deleteInner), delete: callWithEnv(deleteInner),
restore: callWithEnv(restoreInner), restore: callWithEnv(restoreInner),
setFolderData: callWithEnv(setFolderDataInner),
// Tools // Tools
getFileData: callWithEnv(getFileData), getFileData: callWithEnv(getFileData),
find: callWithEnv(find), find: callWithEnv(find),
@ -1081,6 +1120,7 @@ define([
findFile: callWithEnv(findFile), findFile: callWithEnv(findFile),
findChannels: callWithEnv(findChannels), findChannels: callWithEnv(findChannels),
getSharedFolderData: callWithEnv(getSharedFolderData), getSharedFolderData: callWithEnv(getSharedFolderData),
getFolderData: callWithEnv(getFolderData),
isInSharedFolder: callWithEnv(isInSharedFolder), isInSharedFolder: callWithEnv(isInSharedFolder),
getUserObjectPath: callWithEnv(getUserObjectPath), getUserObjectPath: callWithEnv(getUserObjectPath),
isDuplicateOwned: callWithEnv(isDuplicateOwned), isDuplicateOwned: callWithEnv(isDuplicateOwned),

@ -380,6 +380,7 @@
"fc_newfolder": "New folder", "fc_newfolder": "New folder",
"fc_newsharedfolder": "New shared folder", "fc_newsharedfolder": "New shared folder",
"fc_rename": "Rename", "fc_rename": "Rename",
"fc_color": "Change color",
"fc_open": "Open", "fc_open": "Open",
"fc_open_ro": "Open (read-only)", "fc_open_ro": "Open (read-only)",
"fc_expandAll": "Expand All", "fc_expandAll": "Expand All",

@ -91,6 +91,9 @@ define([
((typeof(files[OLD_FILES_DATA]) !== "undefined" || allowStr) ((typeof(files[OLD_FILES_DATA]) !== "undefined" || allowStr)
&& typeof(element) === "string"); && typeof(element) === "string");
}; };
var isFolderData = exp.isFolderData = function (element) {
return typeof(element) === "object" && element.metadata === true;
};
exp.isReadOnlyFile = function (element) { exp.isReadOnlyFile = function (element) {
if (!isFile(element)) { return false; } if (!isFile(element)) { return false; }
@ -101,6 +104,7 @@ define([
}; };
var isFolder = exp.isFolder = function (element) { var isFolder = exp.isFolder = function (element) {
if (isFolderData(element)) { return false; }
return typeof(element) === "object" || isSharedFolder(element); return typeof(element) === "object" || isSharedFolder(element);
}; };
exp.isFolderEmpty = function (element) { exp.isFolderEmpty = function (element) {
@ -144,12 +148,29 @@ define([
return file; return file;
}; };
exp.hasFolderData = function (folder) {
for (var el in folder) {
if(isFolderData(folder[el])) {
return true;
}
}
};
// Get data from AllFiles (Cryptpad_RECENTPADS) // Get data from AllFiles (Cryptpad_RECENTPADS)
var getFileData = exp.getFileData = function (file) { var getFileData = exp.getFileData = function (file) {
if (!file) { return; } if (!file) { return; }
return files[FILES_DATA][file] || {}; return files[FILES_DATA][file] || {};
}; };
exp.getFolderData = function (folder) {
for (var el in folder) {
if(isFolderData(folder[el])) {
return folder[el];
}
}
return {};
};
// Data from filesData // Data from filesData
var getTitle = exp.getTitle = function (file, type) { var getTitle = exp.getTitle = function (file, type) {
if (isSharedFolder(file)) { if (isSharedFolder(file)) {
@ -231,7 +252,7 @@ define([
for (var e in root) { for (var e in root) {
if (isFile(root[e]) || isSharedFolder(root[e])) { if (isFile(root[e]) || isSharedFolder(root[e])) {
if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); } if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); }
} else { } else if (!isFolderData(root[e])) {
getFilesRecursively(root[e], arr); getFilesRecursively(root[e], arr);
} }
} }

@ -179,6 +179,68 @@
} }
} }
.cp-app-drive-color-picker {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
.cp-app-drive-color-picker-color {
position: relative;
width: 50px;
height: 50px;
margin: 5px;
display: inline-block;
cursor: pointer;
&.cp-app-drive-no-color {
position: relative;
width: 40px;
height: 40px;
margin: 10px;
border: 1px solid #444;
border-radius: 2px;
background-color: white;
overflow: hidden;
&::before {
content: "";
position: absolute;
top: -1px; left: 0;
width: 200%;
border: 1px solid #bbb;
transform-origin: top left;
-ms-transform-origin: top left;
transform: rotate(45deg);
-ms-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
}
&.cp-app-drive-current-color > .fa-check {
top: 35%; left: 35%;
color: black;
}
}
.cp-app-drive-icon-folder {
position: absolute;
font-size: 50px;
}
.fa-check {
position: absolute;
top: 40%; left: 35%;
color: transparent;
}
&.cp-app-drive-current-color > .fa-check {
color: white;
}
}
}
/* TREE */ /* TREE */
@ -873,7 +935,7 @@
text-align: left; text-align: left;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
.cp-app-drive-path-inner { .cp-app-drive-path-inner {
display: flex; display: flex;
flex-flow: row-reverse; flex-flow: row-reverse;
@ -894,19 +956,19 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
transition: all 0.15s; transition: all 0.15s;
&:first-child { &:first-child {
flex-shrink: 1; flex-shrink: 1;
} }
&.cp-app-drive-path-separator { &.cp-app-drive-path-separator {
color: #ccc; color: #ccc;
} }
&.cp-app-drive-path-collapse { &.cp-app-drive-path-collapse {
position: relative; position: relative;
} }
&:hover { &:hover {
&:not(.cp-app-drive-path-separator) { &:not(.cp-app-drive-path-separator) {
background-color: darken(@colortheme_drive-bg, 15%); background-color: darken(@colortheme_drive-bg, 15%);

@ -17,6 +17,8 @@ define([
'/bower_components/chainpad-listmap/chainpad-listmap.js', '/bower_components/chainpad-listmap/chainpad-listmap.js',
'/customize/messages.js', '/customize/messages.js',
'/common/jscolor.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/drive/app-drive.less', 'less!/drive/app-drive.less',
@ -78,6 +80,7 @@ define([
var faShared = 'fa-shhare-alt'; var faShared = 'fa-shhare-alt';
var faReadOnly = 'fa-eye'; var faReadOnly = 'fa-eye';
var faRename = 'fa-pencil'; var faRename = 'fa-pencil';
var faColor = 'cptools-palette';
var faTrash = 'fa-trash'; var faTrash = 'fa-trash';
var faDelete = 'fa-eraser'; var faDelete = 'fa-eraser';
var faProperties = 'fa-database'; var faProperties = 'fa-database';
@ -316,6 +319,10 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': "collapseAll", 'data-icon': "collapseAll",
}, Messages.fc_collapseAll)), }, Messages.fc_collapseAll)),
h('li', h('a.cp-app-drive-context-color.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faColor,
}, Messages.fc_color)),
h('li', h('a.cp-app-drive-context-download.dropdown-item', { h('li', h('a.cp-app-drive-context-download.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faDownload, 'data-icon': faDownload,
@ -875,6 +882,69 @@ define([
},0); },0);
}; };
var pickFolderColor = function ($element, currentColor, cb) {
var colors = ["none", "#f23c38", "#ff0073", "#da0eba", "#9d00ac", "#6c19b3", "#4a42b1", "#3d8af0", "#30a0f1", "#1fb9d1", "#009686", "#45b354", "#84c750", "#c6e144", "#faf147", "#fbc423", "#fc9819", "#fd5227", "#775549", "#9c9c9c", "#607a89"];
var colorsElements = [];
var currentElement = null;
colors.forEach(function (color, i) {
var element;
if (i === 0) {
element = h("span.cp-app-drive-color-picker-color.cp-app-drive-no-color", [
h("span.fa.fa-check")
]);
if (currentColor === "") {
currentElement = element;
$(element).addClass("cp-app-drive-current-color");
}
$(element).on("click", function () {
$(currentElement).removeClass("cp-app-drive-current-color");
currentElement = element;
$(element).addClass("cp-app-drive-current-color");
cb("");
});
colorsElements.push(element);
}
else {
element = h("span.cp-app-drive-color-picker-color", [
h("span.cptools-folder.cptools.cp-app-drive-icon-folder.cp-app-drive-content-icon"),
h("span.fa.fa-check")
]);
$(element).css("color", colors[i]);
if (colors[i] === currentColor) {
currentElement = element;
$(element).addClass("cp-app-drive-current-color");
}
$(element).on("click", function () {
$(currentElement).removeClass("cp-app-drive-current-color");
currentElement = element;
$(element).addClass("cp-app-drive-current-color");
cb(color);
});
colorsElements.push(element);
}
});
var content = h("div.cp-app-drive-color-picker", colorsElements);
UI.alert(content);
};
var getFolderColor = function (path) {
if (path.length === 0) { return; }
return manager.getFolderData(path).color || "";
};
var setFolderColor = function ($element, path, color) {
if ($element.length === 0) { return; }
$element.find(".cp-app-drive-icon-folder").css("color", color);
manager.setFolderData({
path: path,
key: "color",
value: color
}, function () {});
};
var filterContextMenu = function (type, paths) { var filterContextMenu = function (type, paths) {
if (!paths || paths.length === 0) { logError('no paths'); } if (!paths || paths.length === 0) { logError('no paths'); }
@ -909,6 +979,7 @@ define([
// Can't rename or delete root elements // Can't rename or delete root elements
hide.push('delete'); hide.push('delete');
hide.push('rename'); hide.push('rename');
hide.push('color');
} }
if (!$element.is('.cp-app-drive-element-owned')) { if (!$element.is('.cp-app-drive-element-owned')) {
hide.push('deleteowned'); hide.push('deleteowned');
@ -925,6 +996,7 @@ define([
} }
if ($element.is('.cp-app-drive-element-file')) { if ($element.is('.cp-app-drive-element-file')) {
// No folder in files // No folder in files
hide.push('color');
hide.push('newfolder'); hide.push('newfolder');
if ($element.is('.cp-app-drive-element-readonly')) { if ($element.is('.cp-app-drive-element-readonly')) {
hide.push('open'); // Remove open 'edit' mode hide.push('open'); // Remove open 'edit' mode
@ -1001,7 +1073,7 @@ define([
show = ['newfolder', 'newsharedfolder', 'newdoc']; show = ['newfolder', 'newsharedfolder', 'newdoc'];
break; break;
case 'tree': case 'tree':
show = ['open', 'openro', 'expandall', 'collapseall', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', show = ['open', 'openro', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf',
'newfolder', 'properties', 'hashtag']; 'newfolder', 'properties', 'hashtag'];
break; break;
case 'default': case 'default':
@ -1619,9 +1691,11 @@ define([
if (isSharedFolder) { if (isSharedFolder) {
liClass = 'cp-app-drive-element-folder cp-app-drive-element'; liClass = 'cp-app-drive-element-folder cp-app-drive-element';
$icon = $sharedFolderIcon.clone(); $icon = $sharedFolderIcon.clone();
$icon.css("color", getFolderColor(path.concat(elPath)));
} else if (isFolder) { } else if (isFolder) {
liClass = 'cp-app-drive-element-folder cp-app-drive-element'; liClass = 'cp-app-drive-element-folder cp-app-drive-element';
$icon = manager.isFolderEmpty(root[key]) ? $folderEmptyIcon.clone() : $folderIcon.clone(); $icon = manager.isFolderEmpty(root[key]) ? $folderEmptyIcon.clone() : $folderIcon.clone();
$icon.css("color", getFolderColor(path.concat(elPath)));
} }
var $element = $('<li>', { var $element = $('<li>', {
draggable: true, draggable: true,
@ -2994,6 +3068,7 @@ define([
var createTreeElement = function (name, $icon, path, draggable, droppable, collapsable, active, isSharedFolder) { var createTreeElement = function (name, $icon, path, draggable, droppable, collapsable, active, isSharedFolder) {
var $name = $('<span>', { 'class': 'cp-app-drive-element' }).text(name); var $name = $('<span>', { 'class': 'cp-app-drive-element' }).text(name);
$icon.css("color", isSharedFolder ? getFolderColor(path.slice(0, -1)) : getFolderColor(path));
var $collapse; var $collapse;
if (collapsable) { if (collapsable) {
$collapse = $expandIcon.clone(); $collapse = $expandIcon.clone();
@ -3352,6 +3427,15 @@ define([
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
displayRenameInput(paths[0].element, paths[0].path); displayRenameInput(paths[0].element, paths[0].path);
} }
if ($(this).hasClass("cp-app-drive-context-color")) {
var currentColor = getFolderColor(paths[0].path);
pickFolderColor(paths[0].element, currentColor, function (color) {
paths.forEach(function (p) {
setFolderColor(p.element, p.path, color);
});
refresh();
});
}
else if($(this).hasClass("cp-app-drive-context-delete")) { else if($(this).hasClass("cp-app-drive-context-delete")) {
if (!APP.loggedIn) { if (!APP.loggedIn) {
return void deletePaths(paths); return void deletePaths(paths);

@ -10,7 +10,7 @@ define([
'/common/modes.js', '/common/modes.js',
'/customize/messages.js', '/customize/messages.js',
'/kanban/jkanban.js', '/kanban/jkanban.js',
'/kanban/jscolor.js', '/common/jscolor.js',
'css!/kanban/jkanban.css', 'css!/kanban/jkanban.css',
'less!/kanban/app-kanban.less' 'less!/kanban/app-kanban.less'
@ -281,7 +281,7 @@ define([
//return; //return;
} }
kanban.inEditMode = true; kanban.inEditMode = true;
// create a form to enter element // create a form to enter element
var boardId = $(el.parentNode.parentNode).attr("data-id"); var boardId = $(el.parentNode.parentNode).attr("data-id");
var $item = $('<div>', {'class': 'kanban-item'}); var $item = $('<div>', {'class': 'kanban-item'});
var $input = getInput().val(name).appendTo($item); var $input = getInput().val(name).appendTo($item);

Loading…
Cancel
Save