Add a proxy manager to handle operations between shared folders
parent
66591a3654
commit
a25a72b5db
|
@ -1,6 +1,7 @@
|
|||
define([
|
||||
'json.sortify',
|
||||
'/common/userObject.js',
|
||||
'/common/proxy-manager.js',
|
||||
'/common/migrate-user-object.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-util.js',
|
||||
|
@ -18,7 +19,7 @@ define([
|
|||
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
'/bower_components/saferphore/index.js',
|
||||
], function (Sortify, UserObject, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger,
|
||||
], function (Sortify, UserObject, ProxyManager, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger,
|
||||
CpNfWorker, NetConfig, AppConfig,
|
||||
Crypto, ChainPad, Listmap, nThen, Saferphore) {
|
||||
var Store = {};
|
||||
|
@ -78,17 +79,10 @@ define([
|
|||
if (!userChannel) { return null; }
|
||||
|
||||
// Get the list of pads' channel ID in your drive
|
||||
// This list is filtered so that it doesn't include pad owned by other users (you should
|
||||
// not pin these pads)
|
||||
var files = store.userObject.getFiles([store.userObject.FILES_DATA]);
|
||||
// This list is filtered so that it doesn't include pad owned by other users
|
||||
// It now includes channels from shared folders
|
||||
var edPublic = store.proxy.edPublic;
|
||||
var list = files.map(function (id) {
|
||||
var d = store.userObject.getFileData(id);
|
||||
if (d.owners && d.owners.length && edPublic &&
|
||||
d.owners.indexOf(edPublic) === -1) { return; }
|
||||
return d.channel;
|
||||
})
|
||||
.filter(function (x) { return x; });
|
||||
var list = store.manager.getPinList(edPublic);
|
||||
|
||||
// Get the avatar
|
||||
var profile = store.proxy.profile;
|
||||
|
@ -451,10 +445,16 @@ define([
|
|||
if (data.expire) { pad.expire = data.expire; }
|
||||
if (data.password) { pad.password = data.password; }
|
||||
if (data.channel) { pad.channel = data.channel; }
|
||||
store.userObject.pushData(pad, function (e, id) {
|
||||
var uo = store.userObject;
|
||||
var path = ['root'];
|
||||
if (data.path) {
|
||||
var resolved = store.manager.resolvePath(path);
|
||||
uo = resolved.userObject;
|
||||
path = resolved.path;
|
||||
}
|
||||
uo.pushData(pad, function (e, id) {
|
||||
if (e) { return void cb({error: "Error while adding a template:"+ e}); }
|
||||
var path = data.path || ['root'];
|
||||
store.userObject.add(id, path);
|
||||
uo.add(id, path);
|
||||
sendDriveEvent('DRIVE_CHANGE', {
|
||||
path: ['drive', UserObject.FILES_DATA]
|
||||
}, clientId);
|
||||
|
@ -733,67 +733,28 @@ define([
|
|||
expire = +channelData.data.expire || undefined;
|
||||
}
|
||||
|
||||
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {};
|
||||
var isStronger;
|
||||
|
||||
// If we don't find the new channel in our existing pads, we'll have to add the pads
|
||||
// to filesData
|
||||
var contains;
|
||||
|
||||
// Update all pads that use the same channel but with a weaker hash
|
||||
// Edit > Edit (present) > View > View (present)
|
||||
for (var id in allPads) {
|
||||
var pad = allPads[id];
|
||||
if (!pad.href && !pad.roHref) { continue; }
|
||||
|
||||
var p2 = Hash.parsePadUrl(pad.href || pad.roHref);
|
||||
var h2 = p2.hashData;
|
||||
|
||||
// Different types, proceed to the next one
|
||||
// No hash data: corrupted pad?
|
||||
if (p.type !== p2.type || !h2) { continue; }
|
||||
// Different channel: continue
|
||||
if (pad.channel !== channel) { continue; }
|
||||
|
||||
var shouldUpdate = p.hash.replace(/\/$/, '') === p2.hash.replace(/\/$/, '');
|
||||
|
||||
// If the hash is different but represents the same channel, check if weaker or stronger
|
||||
if (!shouldUpdate && h.version !== 0) {
|
||||
// We had view & now we have edit, update
|
||||
if (h2.mode === 'view' && h.mode === 'edit') { shouldUpdate = true; }
|
||||
// Same mode and we had present URL, update
|
||||
else if (h.mode === h2.mode && h2.present) { shouldUpdate = true; }
|
||||
// If we're here it means we have a weaker URL:
|
||||
// update the date but keep the existing hash
|
||||
else {
|
||||
pad.atime = +new Date();
|
||||
contains = true;
|
||||
continue;
|
||||
}
|
||||
var datas = store.manager.findChannel(channel);
|
||||
var contains = datas.length !== 0;
|
||||
datas.forEach(function (obj) {
|
||||
var pad = obj.data;
|
||||
pad.atime = +new Date();
|
||||
pad.title = title;
|
||||
if (owners || h.type !== "file") {
|
||||
// OWNED_FILES
|
||||
// Never remove owner for files
|
||||
pad.owners = owners;
|
||||
}
|
||||
pad.expire = expire;
|
||||
if (h.mode === 'view') { return; }
|
||||
|
||||
if (shouldUpdate) {
|
||||
contains = true;
|
||||
pad.atime = +new Date();
|
||||
pad.title = title;
|
||||
if (owners || h.type !== "file") {
|
||||
// OWNED_FILES
|
||||
// Never remove owner for files
|
||||
pad.owners = owners;
|
||||
}
|
||||
pad.expire = expire;
|
||||
|
||||
// If the href is different, it means we have a stronger one
|
||||
if (href !== pad.href) { isStronger = true; }
|
||||
pad.href = href;
|
||||
// If we only have rohref, it means we have a stronger href
|
||||
if (!pad.href) {
|
||||
// If we have a stronger url, remove the possible weaker from the trash.
|
||||
// If all of the weaker ones were in the trash, add the stronger to ROOT
|
||||
obj.userObject.restoreHref(href);
|
||||
}
|
||||
}
|
||||
|
||||
if (isStronger) {
|
||||
// If we have a stronger url, remove the possible weaker from the trash.
|
||||
// If all of the weaker ones were in the trash, add the stronger to ROOT
|
||||
store.userObject.restoreHref(href);
|
||||
}
|
||||
pad.href = href;
|
||||
});
|
||||
|
||||
// Add the pad if it does not exist in our drive
|
||||
if (!contains) {
|
||||
|
@ -1215,11 +1176,11 @@ define([
|
|||
};
|
||||
var rt = Listmap.create(listmapConfig);
|
||||
store.sharedFolders[id] = rt;
|
||||
store.manager.addProxy(rt.proxy);
|
||||
return rt;
|
||||
};
|
||||
Store.addSharedFolder = function (clientId, data, cb) {
|
||||
var path = data.path;
|
||||
var href = data.href;
|
||||
var id;
|
||||
nThen(function (waitFor) {
|
||||
// TODO
|
||||
|
@ -1232,13 +1193,13 @@ define([
|
|||
}
|
||||
id = folderId;
|
||||
}));
|
||||
nThen(function (waitFor) {
|
||||
}).nThen(function (waitFor) {
|
||||
// 2a. add the shared folder to the path in our drive
|
||||
store.userObject.add(id, path);
|
||||
onSync(waitFor());
|
||||
|
||||
// 2b. load the proxy
|
||||
var rt = loadSharedFolder(folderId, data);
|
||||
var rt = loadSharedFolder(id, data);
|
||||
rt.on('ready', waitFor(function () {
|
||||
// TODO
|
||||
// "fixFiles"
|
||||
|
@ -1267,22 +1228,7 @@ define([
|
|||
});
|
||||
cb(data2);
|
||||
};
|
||||
switch (cmdData.cmd) {
|
||||
case 'move':
|
||||
store.userObject.move(data.paths, data.newPath, cb2); break;
|
||||
case 'restore':
|
||||
store.userObject.restore(data.path, cb2); break;
|
||||
case 'addFolder':
|
||||
store.userObject.addFolder(data.path, data.name, cb2); break;
|
||||
case 'delete':
|
||||
store.userObject.delete(data.paths, cb2, data.nocheck, data.isOwnPadRemoved); break;
|
||||
case 'emptyTrash':
|
||||
store.userObject.emptyTrash(cb2); break;
|
||||
case 'rename':
|
||||
store.userObject.rename(data.path, data.newName, cb2); break;
|
||||
default:
|
||||
cb();
|
||||
}
|
||||
store.manager.command(cmdData, cb2);
|
||||
};
|
||||
|
||||
// Clients management
|
||||
|
@ -1416,7 +1362,7 @@ define([
|
|||
|
||||
var onReady = function (clientId, returned, cb) {
|
||||
var proxy = store.proxy;
|
||||
var userObject = store.userObject = UserObject.init(proxy.drive, {
|
||||
var manager = store.manager = ProxyManager.create(proxy.drive, proxy.edPublic, {
|
||||
pinPads: function (data, cb) { Store.pinPads(null, data, cb); },
|
||||
unpinPads: function (data, cb) { Store.unpinPads(null, data, cb); },
|
||||
removeOwnedChannel: function (data, cb) { Store.removeOwnedChannel(null, data, cb); },
|
||||
|
@ -1427,6 +1373,7 @@ define([
|
|||
sendDriveEvent("DRIVE_LOG", msg);
|
||||
}
|
||||
});
|
||||
var userObject = store.userObject = manager.user.userObject;
|
||||
nThen(function (waitFor) {
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
state: 2
|
||||
|
@ -1439,12 +1386,13 @@ define([
|
|||
progress: progress
|
||||
});
|
||||
});
|
||||
}).nThen(function () {
|
||||
}).nThen(function (waitFor) {
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
state: 3
|
||||
});
|
||||
userObject.fixFiles();
|
||||
|
||||
loadSharedFolders(waitFor);
|
||||
}).nThen(function () {
|
||||
var requestLogin = function () {
|
||||
broadcast([], "REQUEST_LOGIN");
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ define([
|
|||
console.error("removeOwnedChannel was not provided");
|
||||
};
|
||||
var loggedIn = config.loggedIn;
|
||||
var workgroup = config.workgroup;
|
||||
var sharedFolder = config.sharedFolder;
|
||||
var edPublic = config.edPublic;
|
||||
|
||||
var ROOT = exp.ROOT;
|
||||
|
@ -31,6 +31,7 @@ define([
|
|||
var UNSORTED = exp.UNSORTED;
|
||||
var TRASH = exp.TRASH;
|
||||
var TEMPLATE = exp.TEMPLATE;
|
||||
var SHARED_FOLDERS = exp.SHARED_FOLDERS;
|
||||
|
||||
var debug = exp.debug;
|
||||
|
||||
|
@ -76,9 +77,8 @@ define([
|
|||
// Find files in FILES_DATA that are not anymore in the drive, and remove them from
|
||||
// FILES_DATA. If there are owned pads, remove them from server too, unless the flag tells
|
||||
// us they're already removed
|
||||
exp.checkDeletedFiles = function (isOwnPadRemoved) {
|
||||
// Nothing in FILES_DATA for workgroups
|
||||
if (workgroup || (!loggedIn && !config.testMode)) { return; }
|
||||
exp.checkDeletedFiles = function (isOwnPadRemoved, noUnpin) {
|
||||
if (!loggedIn && !config.testMode) { return; }
|
||||
|
||||
var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]);
|
||||
var toClean = [];
|
||||
|
@ -107,6 +107,7 @@ define([
|
|||
}
|
||||
});
|
||||
if (!toClean.length) { return; }
|
||||
if (noUnpin) { return; }
|
||||
unpinPads(toClean, function (response) {
|
||||
if (response && response.error) { return console.error(response.error); }
|
||||
// console.error(response);
|
||||
|
@ -124,7 +125,7 @@ define([
|
|||
files[TRASH][obj.name].splice(idx, 1);
|
||||
});
|
||||
};
|
||||
exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved) {
|
||||
exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved, noUnpin) {
|
||||
var hrefPaths = paths.filter(function(x) { return exp.isPathIn(x, ['hrefArray']); });
|
||||
var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); });
|
||||
var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); });
|
||||
|
@ -176,11 +177,66 @@ define([
|
|||
deleteMultipleTrashRoot(trashRoot);
|
||||
|
||||
// In some cases, we want to remove pads from a location without removing them from
|
||||
// OLD_FILES_DATA (replaceHref)
|
||||
if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved); }
|
||||
// FILES_DATA (replaceHref)
|
||||
if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved, noUnpin); }
|
||||
};
|
||||
|
||||
// Move
|
||||
|
||||
// From another drive
|
||||
exp.copyFromOtherDrive = function (path, element, data) {
|
||||
// Copy files data
|
||||
// We have to remove pads that are already in the current proxy to make sure
|
||||
// we won't create duplicates
|
||||
|
||||
var toRemove = [];
|
||||
Object.keys(data).forEach(function (id) {
|
||||
// Find and maybe update existing pads with the same channel id
|
||||
var d = data[id];
|
||||
var found = false;
|
||||
for (var i in files[FILES_DATA]) {
|
||||
if (files[FILES_DATA][i].channel === d.channel) {
|
||||
// Update href?
|
||||
if (!files[FILES_DATA][i].href) { files[FILES_DATA][i].href = d.href; }
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
toRemove.push(id);
|
||||
return;
|
||||
}
|
||||
files[FILES_DATA][id] = data[id];
|
||||
});
|
||||
|
||||
// Remove existing pads from the "element" variable
|
||||
if (exp.isFile(element) && toRemove.indexOf(element) !== -1) {
|
||||
// XXX display error in the UI
|
||||
return;
|
||||
} else if (exp.isFolder(element)) {
|
||||
var _removeExisting = function (root) {
|
||||
for (var k in root) {
|
||||
if (exp.isFile(root[k])) {
|
||||
if (toRemove.indexOf(root[k]) !== -1) {
|
||||
// XXX display message in UI
|
||||
delete root[k];
|
||||
}
|
||||
} else if (exp.isFolder(root[k])) {
|
||||
_removeExisting(root[k]);
|
||||
}
|
||||
}
|
||||
};
|
||||
_removeExisting(element);
|
||||
}
|
||||
|
||||
|
||||
// Copy file or folder
|
||||
var newParent = exp.find(path);
|
||||
var newName = exp.getAvailableName(newParent, Hash.createChannelId());
|
||||
newParent[newName] = element;
|
||||
};
|
||||
|
||||
// From the same drive
|
||||
var pushToTrash = function (name, element, path) {
|
||||
var trash = files[TRASH];
|
||||
if (typeof(trash[name]) === "undefined") { trash[name] = []; }
|
||||
|
@ -449,6 +505,7 @@ define([
|
|||
}
|
||||
};
|
||||
var fixTrashRoot = function () {
|
||||
if (sharedFolder) { return; }
|
||||
if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; }
|
||||
var tr = files[TRASH];
|
||||
var toClean;
|
||||
|
@ -492,6 +549,7 @@ define([
|
|||
}
|
||||
};
|
||||
var fixTemplate = function () {
|
||||
if (sharedFolder) { return; }
|
||||
if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; }
|
||||
files[TEMPLATE] = Util.deduplicateString(files[TEMPLATE].slice());
|
||||
var us = files[TEMPLATE];
|
||||
|
@ -608,6 +666,10 @@ define([
|
|||
spliceFileData(id);
|
||||
});
|
||||
};
|
||||
var fixSharedFolders = function () {
|
||||
if (sharedFolder) { return; }
|
||||
if (typeof(files[SHARED_FOLDERS]) !== "object") { debug("SHARED_FOLDER was not an object"); files[SHARED_FOLDERS] = {}; }
|
||||
};
|
||||
|
||||
var fixDrive = function () {
|
||||
Object.keys(files).forEach(function (key) {
|
||||
|
@ -617,10 +679,9 @@ define([
|
|||
|
||||
fixRoot();
|
||||
fixTrashRoot();
|
||||
if (!workgroup) {
|
||||
fixTemplate();
|
||||
fixFilesData();
|
||||
}
|
||||
fixTemplate();
|
||||
fixFilesData();
|
||||
fixSharedFolders();
|
||||
fixDrive();
|
||||
|
||||
if (JSON.stringify(files) !== before) {
|
||||
|
|
|
@ -0,0 +1,338 @@
|
|||
define([
|
||||
'/common/userObject.js',
|
||||
'/common/common-util.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
], function (UserObject, Util, nThen) {
|
||||
|
||||
|
||||
var getConfig = function (Env) {
|
||||
var cfg = {};
|
||||
for (var k in Env.cfg) { cfg[k] = Env[k]; }
|
||||
return cfg;
|
||||
};
|
||||
|
||||
// Add a shared folder to the list
|
||||
var addProxy = function (Env, id, proxy, leave) {
|
||||
var cfg = getConfig();
|
||||
cfg.sharedFolder = true;
|
||||
cfg.id = id;
|
||||
var userObject = UserObject.init(proxy, Env.cfg);
|
||||
userObject.fixFiles();
|
||||
Env.folders[id] = {
|
||||
proxy: proxy,
|
||||
userObject: userObject,
|
||||
leave: leave
|
||||
};
|
||||
return userObject;
|
||||
};
|
||||
|
||||
// TODO: Remove a shared folder from the list
|
||||
var removeProxy = function (Env, id) {
|
||||
var f = Env.folders[id];
|
||||
if (!f) { return; }
|
||||
f.leave();
|
||||
delete Env.folders[id];
|
||||
};
|
||||
|
||||
/*
|
||||
Paths
|
||||
*/
|
||||
|
||||
// Transform an absolute path into a path relative to the correct shared folder
|
||||
var _resolvePath = function (Env, path) {
|
||||
var res = {
|
||||
id: null,
|
||||
userObject: Env.user.userObject,
|
||||
path: path
|
||||
};
|
||||
if (!Array.isArray(path) || path.length <= 1) {
|
||||
return res;
|
||||
}
|
||||
var current;
|
||||
var uo = Env.user.userObject;
|
||||
for (var i=2; i<=path.length; i++) {
|
||||
current = uo.find(path.slice(0,i));
|
||||
if (uo.isSharedFolder(current)) {
|
||||
res = {
|
||||
id: current,
|
||||
userObject: Env.folders[current].userObject,
|
||||
path: path.slice(i)
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
var _resolvePaths = function (Env, paths) {
|
||||
var main = [];
|
||||
var folders = {};
|
||||
paths.forEach(function (path) {
|
||||
var r = _resolvePath(Env, path);
|
||||
if (r.id) {
|
||||
if (!folders[r.id]) {
|
||||
folders[r.id] = [r.path];
|
||||
} else {
|
||||
folders[r.id].push(r.path);
|
||||
}
|
||||
} else {
|
||||
main.push(r.path);
|
||||
}
|
||||
});
|
||||
return {
|
||||
main: main,
|
||||
folders: folders
|
||||
};
|
||||
};
|
||||
|
||||
// Get a copy of the elements located in the given paths, with their files data
|
||||
var _getCopyFromPaths = function (paths, userObject) {
|
||||
var data = [];
|
||||
paths.forEach(function (path) {
|
||||
var el = userObject.find(path);
|
||||
var files = [];
|
||||
|
||||
// Get the files ID from the current path (file or folder)
|
||||
if (userObject.isFile(el)) {
|
||||
files.push(el);
|
||||
} else {
|
||||
userObject.getFilesRecursively(el, files);
|
||||
}
|
||||
|
||||
// Remove the shared folder from this list of files ID
|
||||
files.filter(function (f) { return !userObject.isSharedFolder(f); });
|
||||
// Deduplicate
|
||||
Util.deduplicateString(files);
|
||||
|
||||
// Get the files data associated to these files
|
||||
var filesData = {};
|
||||
files.forEach(function (f) {
|
||||
filesData[f] = userObject.getFileData(f);
|
||||
});
|
||||
|
||||
// TODO RO
|
||||
// Encrypt or decrypt edit link here
|
||||
// filesData.forEach(function (d) { d.href = encrypt(d.href); });
|
||||
|
||||
|
||||
data.push({
|
||||
el: el,
|
||||
data: filesData
|
||||
});
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
/*
|
||||
RPC commands
|
||||
*/
|
||||
|
||||
// Move files or folders in the drive
|
||||
var _move = function (Env, data, cb) {
|
||||
var resolved = _resolvePaths(Env, data.paths);
|
||||
var newResolved = _resolvePath(Env, data.newPath);
|
||||
|
||||
if (!newResolved.userObject.isFolder(newResolved.path)) { return void cb(); } // XXX
|
||||
|
||||
nThen(function (waitFor) {
|
||||
if (resolved.main.length) {
|
||||
// Move from the main drive
|
||||
if (!newResolved.id) {
|
||||
// Move from the main drive to the main drive
|
||||
Env.user.userObject.move(resolved.main, newResolved.path, waitFor());
|
||||
} else {
|
||||
// Move from the main drive to a shared folder
|
||||
|
||||
// Copy the elements to the new location
|
||||
var toCopy = _getCopyFromPaths(resolved.main, Env.user.userObject);
|
||||
var newUserObject = newResolved.userObject;
|
||||
newUserObject.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data);
|
||||
|
||||
// Filter owned pads so that we won't remove them from our drive
|
||||
var toRemove = resolved.main.slice();
|
||||
toRemove.filter(function (id) {
|
||||
var owners = Env.user.userObject.getFileData(id).owners;
|
||||
return !Array.isArray(owners) || owners.indexOf(Env.edPublic) === -1;
|
||||
});
|
||||
|
||||
// Remove the elements from the old location (without unpinning)
|
||||
Env.user.userObject.delete(resolved.main, waitFor(), false, false, true);
|
||||
}
|
||||
}
|
||||
var folderIds = Object.keys(resolved.folders);
|
||||
if (folderIds.length) {
|
||||
// Move from a shared folder
|
||||
folderIds.forEach(function (fIdStr) {
|
||||
var fId = Number(fIdStr);
|
||||
var paths = resolved.folders[fId];
|
||||
if (newResolved.id === fId) {
|
||||
// Move to the same shared folder
|
||||
newResolved.userObject.move(paths, newResolved.path, waitFor());
|
||||
} else {
|
||||
// Move to a different shared folder or to main drive
|
||||
var uoFrom = Env.folders[fId].userObject;
|
||||
var uoTo = newResolved.userObject;
|
||||
|
||||
// Copy the elements to the new location
|
||||
var toCopy = _getCopyFromPaths(paths, uoFrom);
|
||||
uoTo.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data);
|
||||
|
||||
// Remove the elements from the old location (without unpinning)
|
||||
uoFrom.delete(paths, waitFor(), false, false, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).nThen(function () {
|
||||
cb();
|
||||
});
|
||||
};
|
||||
// Restore from the trash (main drive only)
|
||||
var _restore = function (Env, data, cb) {
|
||||
var userObject = Env.user.userObject;
|
||||
data = data || {};
|
||||
userObject.restore(data.path, cb);
|
||||
};
|
||||
// Add a folder/subfolder
|
||||
var _addFolder = function (Env, data, cb) {
|
||||
data = data || {};
|
||||
var resolved = _resolvePath(Env, data.path);
|
||||
if (!resolved || !resolved.userObject) { return void cb({error: 'E_NOTFOUND'}); }
|
||||
resolved.userObject.addFolder(resolved.path, data.name, cb);
|
||||
};
|
||||
// Delete permanently some pads or folders
|
||||
var _delete = function (Env, data, cb) {
|
||||
data = data || {};
|
||||
var resolved = _resolvePaths(Env, data.paths);
|
||||
if (!resolved.main.length && !Object.keys(resolved.folders).length) {
|
||||
return void cb({error: 'E_NOTFOUND'});
|
||||
}
|
||||
nThen(function (waitFor) {
|
||||
if (resolved.main.length) {
|
||||
Env.user.userObject.delete(resolved.main, waitFor(), data.nocheck,
|
||||
data.isOwnPadRemoved);
|
||||
}
|
||||
Object.keys(resolved.folders).forEach(function (id) {
|
||||
Env.folders[id].userObject.delete(resolved.folders[id], waitFor(), data.nocheck,
|
||||
data.isOwnPadRemoved);
|
||||
});
|
||||
}).nThen(function () {
|
||||
cb();
|
||||
});
|
||||
};
|
||||
// Empty the trash (main drive only)
|
||||
var _emptyTrash = function (Env, data, cb) {
|
||||
Env.user.userObject.emptyTrash(cb);
|
||||
};
|
||||
// Rename files or folders
|
||||
var _rename = function (Env, data, cb) {
|
||||
data = data || {};
|
||||
var resolved = _resolvePath(Env, data.path);
|
||||
if (!resolved || !resolved.userObject) { return void cb({error: 'E_NOTFOUND'}); }
|
||||
resolved.userObject.rename(resolved.path, data.newName, cb);
|
||||
};
|
||||
var onCommand = function (Env, cmdData, cb) {
|
||||
var cmd = cmdData.cmd;
|
||||
var data = cmdData.data || {};
|
||||
switch (cmd) {
|
||||
case 'move':
|
||||
_move(Env, data, cb); break;
|
||||
//store.userObject.move(data.paths, data.newPath, cb2); break;
|
||||
case 'restore':
|
||||
_restore(Env, data, cb); break;
|
||||
case 'addFolder':
|
||||
_addFolder(Env, data, cb); break;
|
||||
case 'delete':
|
||||
_delete(Env, data, cb); break;
|
||||
case 'emptyTrash':
|
||||
_emptyTrash(Env, data, cb); break;
|
||||
case 'rename':
|
||||
_rename(Env, data, cb); break;
|
||||
default:
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
// Return files data objects associated to a channel for setPadTitle
|
||||
// All occurences are returned, in drive or shared folders
|
||||
var findChannel = function (Env, channel) {
|
||||
var ret = [];
|
||||
Env.user.userObject.findChannels([channel]).forEach(function (id) {
|
||||
ret.push({
|
||||
data: Env.user.userObject.getFileData(id),
|
||||
userObject: Env.user.userObject
|
||||
});
|
||||
});
|
||||
Object.keys(Env.folders).forEach(function (fId) {
|
||||
Env.folders[fId].userObject.findChannels([channel]).forEach(function (id) {
|
||||
ret.push({
|
||||
data: Env.folders[fId].userObject.getFileData(id),
|
||||
userObject: Env.folders[fId].userObject
|
||||
});
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Get the list of channels that should be pinned
|
||||
var getPinList = function (Env, edPublic) {
|
||||
if (!edPublic) { return; }
|
||||
var toPin = [];
|
||||
var addChannel = function (userObject) {
|
||||
return function (fileId) {
|
||||
var data = userObject.getFileData(fileId);
|
||||
// Don't pin pads owned by someone else
|
||||
if (Array.isArray(data.owners) && data.owners.length &&
|
||||
data.owners.indexOf(edPublic) === -1) { return; }
|
||||
// Don't push duplicates
|
||||
if (toPin.indexOf(data.channel) === -1) {
|
||||
toPin.push(data.channel);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Get the list of user objects
|
||||
var userObjects = [Env.user.userObject];
|
||||
var foldersUO = Object.keys(Env.folders).map(function (k) {
|
||||
return Env.folders[k].userObject;
|
||||
});
|
||||
Array.prototype.push.apply(userObjects, foldersUO);
|
||||
|
||||
userObjects.forEach(function (uo) {
|
||||
var files = uo.getFiles([UserObject.FILES_DATA]);
|
||||
files.forEach(addChannel(uo));
|
||||
});
|
||||
};
|
||||
|
||||
var create = function (proxy, edPublic, uoConfig) {
|
||||
var Env = {
|
||||
cfg: uoConfig,
|
||||
edPublic: edPublic,
|
||||
user: {
|
||||
proxy: proxy,
|
||||
userObject: UserObject.init(proxy, uoConfig)
|
||||
},
|
||||
folders: {}
|
||||
};
|
||||
|
||||
var callWithEnv = function (f) {
|
||||
return function () {
|
||||
[].unshift.call(arguments, Env);
|
||||
return f.apply(null, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
addProxy: callWithEnv(addProxy),
|
||||
removeProxy: callWithEnv(removeProxy),
|
||||
command: callWithEnv(onCommand),
|
||||
findChannel: callWithEnv(findChannel),
|
||||
getPinList: callWithEnv(getPinList),
|
||||
resolvePath: callWithEnv(_resolvePath),
|
||||
user: Env.user,
|
||||
folders: Env.folders
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
create: create
|
||||
};
|
||||
});
|
|
@ -29,6 +29,7 @@ define([
|
|||
exp.UNSORTED = UNSORTED;
|
||||
exp.TRASH = TRASH;
|
||||
exp.TEMPLATE = TEMPLATE;
|
||||
exp.SHARED_FOLDERS = SHARED_FOLDERS;
|
||||
|
||||
// Logging
|
||||
var logging = function () {
|
||||
|
@ -42,9 +43,6 @@ define([
|
|||
console.error.apply(console, arguments);
|
||||
};
|
||||
|
||||
// TODO: workgroup
|
||||
var workgroup = config.workgroup;
|
||||
|
||||
if (pinPads) {
|
||||
// Extend "exp" with methods used only outside of the iframe (requires access to store)
|
||||
OuterFO.init(config, exp, files);
|
||||
|
@ -89,6 +87,9 @@ define([
|
|||
if (!isFolder(element)) { return false; }
|
||||
return Object.keys(element).length === 0;
|
||||
};
|
||||
exp.isSharedFolder = function (element) {
|
||||
return Boolean(files[SHARED_FOLDERS][element]);
|
||||
};
|
||||
|
||||
exp.hasSubfolder = function (element, trashRoot) {
|
||||
if (!isFolder(element)) { return false; }
|
||||
|
@ -134,7 +135,6 @@ define([
|
|||
|
||||
// Data from filesData
|
||||
var getTitle = exp.getTitle = function (file, type) {
|
||||
if (workgroup) { debug("No titles in workgroups"); return; }
|
||||
var data = getFileData(file);
|
||||
if (!file || !data || !(data.href || data.roHref)) {
|
||||
error("getTitle called with a non-existing file id: ", file, data);
|
||||
|
@ -206,7 +206,8 @@ define([
|
|||
|
||||
// GET FILES
|
||||
|
||||
var getFilesRecursively = function (root, arr) {
|
||||
var getFilesRecursively = exp.getFilesRecursively = function (root, arr) {
|
||||
arr = arr || [];
|
||||
for (var e in root) {
|
||||
if (isFile(root[e])) {
|
||||
if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); }
|
||||
|
@ -214,6 +215,7 @@ define([
|
|||
getFilesRecursively(root[e], arr);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
var _getFiles = {};
|
||||
_getFiles['array'] = function (cat) {
|
||||
|
@ -552,18 +554,19 @@ define([
|
|||
// DELETE
|
||||
// Permanently delete multiple files at once using a list of paths
|
||||
// NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template)
|
||||
exp.delete = function (paths, cb, nocheck, isOwnPadRemoved) {
|
||||
exp.delete = function (paths, cb, nocheck, isOwnPadRemoved, noUnpin) {
|
||||
if (sframeChan) {
|
||||
return void sframeChan.query("Q_DRIVE_USEROBJECT", {
|
||||
cmd: "delete",
|
||||
data: {
|
||||
paths: paths,
|
||||
nocheck: nocheck,
|
||||
noUnpin: noUnpin,
|
||||
isOwnPadRemoved: isOwnPadRemoved
|
||||
}
|
||||
}, cb);
|
||||
}
|
||||
exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved);
|
||||
exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved, noUnpin);
|
||||
if (typeof cb === "function") { cb(); }
|
||||
};
|
||||
exp.emptyTrash = function (cb) {
|
||||
|
|
|
@ -244,27 +244,27 @@ define([
|
|||
'tabindex': '-1',
|
||||
'data-icon': faTags,
|
||||
}, Messages.fc_hashtag)),
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', {
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
|
||||
'tabindex': '-1',
|
||||
'data-icon': AppConfig.applicationsIcon.pad,
|
||||
'data-type': 'pad'
|
||||
}, Messages.button_newpad)),
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', {
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
|
||||
'tabindex': '-1',
|
||||
'data-icon': AppConfig.applicationsIcon.code,
|
||||
'data-type': 'code'
|
||||
}, Messages.button_newcode)),
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', {
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
|
||||
'tabindex': '-1',
|
||||
'data-icon': AppConfig.applicationsIcon.slide,
|
||||
'data-type': 'slide'
|
||||
}, Messages.button_newslide)),
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', {
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
|
||||
'tabindex': '-1',
|
||||
'data-icon': AppConfig.applicationsIcon.poll,
|
||||
'data-type': 'poll'
|
||||
}, Messages.button_newpoll)),
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', {
|
||||
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
|
||||
'tabindex': '-1',
|
||||
'data-icon': AppConfig.applicationsIcon.whiteboard,
|
||||
'data-type': 'whiteboard'
|
||||
|
@ -311,13 +311,6 @@ define([
|
|||
var edPublic = priv.edPublic;
|
||||
|
||||
APP.origin = priv.origin;
|
||||
var isOwnDrive = function () {
|
||||
return true; // TODO
|
||||
};
|
||||
var isWorkgroup = function () {
|
||||
return files.workgroup === 1;
|
||||
};
|
||||
config.workgroup = isWorkgroup();
|
||||
config.loggedIn = APP.loggedIn;
|
||||
config.sframeChan = sframeChan;
|
||||
|
||||
|
@ -357,11 +350,9 @@ define([
|
|||
}
|
||||
|
||||
// FILE MANAGER
|
||||
// _WORKGROUP_ and other people drive : display Documents as main page
|
||||
var currentPath = APP.currentPath = isOwnDrive() ? getLastOpenedFolder() : [ROOT];
|
||||
var currentPath = APP.currentPath = getLastOpenedFolder();
|
||||
|
||||
// Categories dislayed in the menu
|
||||
// _WORKGROUP_ : do not display unsorted
|
||||
var displayedCategories = [ROOT, TRASH, SEARCH, RECENT];
|
||||
|
||||
// PCS enabled: display owned pads
|
||||
|
@ -371,7 +362,6 @@ define([
|
|||
// Tags used: display Tags category
|
||||
if (Object.keys(filesOp.getTagsList()).length) { displayedCategories.push(TAGS); }
|
||||
|
||||
if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; }
|
||||
var virtualCategories = [SEARCH, RECENT, OWNED, TAGS];
|
||||
|
||||
if (!APP.loggedIn) {
|
||||
|
@ -856,7 +846,6 @@ define([
|
|||
show.forEach(function (className) {
|
||||
var $el = $contextMenu.find('.cp-app-drive-context-' + className);
|
||||
if (!APP.editable && $el.is('.cp-app-drive-context-editable')) { return; }
|
||||
if (!isOwnDrive && $el.is('.cp-app-drive-context-own')) { return; }
|
||||
if (filter($el, className)) { return; }
|
||||
$el.parent('li').show();
|
||||
filtered.push('.cp-app-drive-context-' + className);
|
||||
|
@ -1212,10 +1201,6 @@ define([
|
|||
if (movedPaths && movedPaths.length) {
|
||||
moveElements(movedPaths, newPath, null, refresh);
|
||||
}
|
||||
if (importedElements && importedElements.length) {
|
||||
// TODO workgroup
|
||||
//filesOp.importElements(importedElements, newPath, refresh);
|
||||
}
|
||||
};
|
||||
|
||||
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
|
||||
|
@ -1266,7 +1251,6 @@ define([
|
|||
addDragAndDropHandlers($content, null, true, true);
|
||||
|
||||
// In list mode, display metadata from the filesData object
|
||||
// _WORKGROUP_ : Do not display title, atime and ctime columns since we don't have files data
|
||||
var addFileData = function (element, $span) {
|
||||
if (!filesOp.isFile(element)) { return; }
|
||||
|
||||
|
@ -1323,10 +1307,7 @@ define([
|
|||
var $cdate = $('<span>', {
|
||||
'class': 'cp-app-drive-element-ctime cp-app-drive-element-list'
|
||||
}).text(getDate(data.ctime));
|
||||
$span.append($type);
|
||||
if (!isWorkgroup()) {
|
||||
$span.append($adate).append($cdate);
|
||||
}
|
||||
$span.append($type).append($adate).append($cdate);
|
||||
};
|
||||
|
||||
var addFolderData = function (element, key, $span) {
|
||||
|
@ -1804,7 +1785,6 @@ define([
|
|||
$list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon);
|
||||
}
|
||||
};
|
||||
// _WORKGROUP_ : do not display title, atime and ctime in workgroups since we don't have files data
|
||||
var getFileListHeader = function () {
|
||||
var $fihElement = $('<li>', {
|
||||
'class': 'cp-app-drive-element-header cp-app-drive-element-list'
|
||||
|
@ -1827,9 +1807,7 @@ define([
|
|||
}).text(Messages.fm_creation).click(onSortByClick);
|
||||
// If displayTitle is false, it means the "name" is the title, so do not display the "name" header
|
||||
$fihElement.append($fhIcon).append($fhName).append($fhState).append($fhType);
|
||||
if (!isWorkgroup()) {
|
||||
$fihElement.append($fhAdate).append($fhCdate);
|
||||
}
|
||||
$fihElement.append($fhAdate).append($fhCdate);
|
||||
addFileSortIcon($fihElement);
|
||||
return $fihElement;
|
||||
};
|
||||
|
@ -2277,7 +2255,6 @@ define([
|
|||
|
||||
// Display the selected directory into the content part (rightside)
|
||||
// NOTE: Elements in the trash are not using the same storage structure as the others
|
||||
// _WORKGROUP_ : do not change the lastOpenedFolder value in localStorage
|
||||
var _displayDirectory = function (path, force) {
|
||||
APP.hideMenu();
|
||||
if (!APP.editable) { debug("Read-only mode"); }
|
||||
|
@ -2331,9 +2308,7 @@ define([
|
|||
$tree.find('#cp-app-drive-tree-search-input')[0].selectionEnd = getSearchCursor();
|
||||
}
|
||||
|
||||
if (!isWorkgroup()) {
|
||||
setLastOpenedFolder(path);
|
||||
}
|
||||
setLastOpenedFolder(path);
|
||||
|
||||
var $toolbar = createToolbar(path);
|
||||
var $info = createInfoBox(path);
|
||||
|
|
Loading…
Reference in New Issue