Add a proxy manager to handle operations between shared folders

pull/1/head
yflory 7 years ago
parent 66591a3654
commit a25a72b5db

@ -1,6 +1,7 @@
define([ define([
'json.sortify', 'json.sortify',
'/common/userObject.js', '/common/userObject.js',
'/common/proxy-manager.js',
'/common/migrate-user-object.js', '/common/migrate-user-object.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-util.js', '/common/common-util.js',
@ -18,7 +19,7 @@ define([
'/bower_components/chainpad-listmap/chainpad-listmap.js', '/bower_components/chainpad-listmap/chainpad-listmap.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/bower_components/saferphore/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, CpNfWorker, NetConfig, AppConfig,
Crypto, ChainPad, Listmap, nThen, Saferphore) { Crypto, ChainPad, Listmap, nThen, Saferphore) {
var Store = {}; var Store = {};
@ -78,17 +79,10 @@ define([
if (!userChannel) { return null; } if (!userChannel) { return null; }
// Get the list of pads' channel ID in your drive // 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 // This list is filtered so that it doesn't include pad owned by other users
// not pin these pads) // It now includes channels from shared folders
var files = store.userObject.getFiles([store.userObject.FILES_DATA]);
var edPublic = store.proxy.edPublic; var edPublic = store.proxy.edPublic;
var list = files.map(function (id) { var list = store.manager.getPinList(edPublic);
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; });
// Get the avatar // Get the avatar
var profile = store.proxy.profile; var profile = store.proxy.profile;
@ -451,10 +445,16 @@ define([
if (data.expire) { pad.expire = data.expire; } if (data.expire) { pad.expire = data.expire; }
if (data.password) { pad.password = data.password; } if (data.password) { pad.password = data.password; }
if (data.channel) { pad.channel = data.channel; } 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}); } if (e) { return void cb({error: "Error while adding a template:"+ e}); }
var path = data.path || ['root']; uo.add(id, path);
store.userObject.add(id, path);
sendDriveEvent('DRIVE_CHANGE', { sendDriveEvent('DRIVE_CHANGE', {
path: ['drive', UserObject.FILES_DATA] path: ['drive', UserObject.FILES_DATA]
}, clientId); }, clientId);
@ -733,67 +733,28 @@ define([
expire = +channelData.data.expire || undefined; expire = +channelData.data.expire || undefined;
} }
var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {}; var datas = store.manager.findChannel(channel);
var isStronger; var contains = datas.length !== 0;
datas.forEach(function (obj) {
// If we don't find the new channel in our existing pads, we'll have to add the pads var pad = obj.data;
// to filesData pad.atime = +new Date();
var contains; pad.title = title;
if (owners || h.type !== "file") {
// Update all pads that use the same channel but with a weaker hash // OWNED_FILES
// Edit > Edit (present) > View > View (present) // Never remove owner for files
for (var id in allPads) { pad.owners = owners;
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;
}
} }
pad.expire = expire;
if (shouldUpdate) { if (h.mode === 'view') { return; }
contains = true;
pad.atime = +new Date(); // If we only have rohref, it means we have a stronger href
pad.title = title; if (!pad.href) {
if (owners || h.type !== "file") { // If we have a stronger url, remove the possible weaker from the trash.
// OWNED_FILES // If all of the weaker ones were in the trash, add the stronger to ROOT
// Never remove owner for files obj.userObject.restoreHref(href);
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;
} }
} pad.href = 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);
}
// Add the pad if it does not exist in our drive // Add the pad if it does not exist in our drive
if (!contains) { if (!contains) {
@ -1215,11 +1176,11 @@ define([
}; };
var rt = Listmap.create(listmapConfig); var rt = Listmap.create(listmapConfig);
store.sharedFolders[id] = rt; store.sharedFolders[id] = rt;
store.manager.addProxy(rt.proxy);
return rt; return rt;
}; };
Store.addSharedFolder = function (clientId, data, cb) { Store.addSharedFolder = function (clientId, data, cb) {
var path = data.path; var path = data.path;
var href = data.href;
var id; var id;
nThen(function (waitFor) { nThen(function (waitFor) {
// TODO // TODO
@ -1232,13 +1193,13 @@ define([
} }
id = folderId; id = folderId;
})); }));
nThen(function (waitFor) { }).nThen(function (waitFor) {
// 2a. add the shared folder to the path in our drive // 2a. add the shared folder to the path in our drive
store.userObject.add(id, path); store.userObject.add(id, path);
onSync(waitFor()); onSync(waitFor());
// 2b. load the proxy // 2b. load the proxy
var rt = loadSharedFolder(folderId, data); var rt = loadSharedFolder(id, data);
rt.on('ready', waitFor(function () { rt.on('ready', waitFor(function () {
// TODO // TODO
// "fixFiles" // "fixFiles"
@ -1267,22 +1228,7 @@ define([
}); });
cb(data2); cb(data2);
}; };
switch (cmdData.cmd) { store.manager.command(cmdData, cb2);
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();
}
}; };
// Clients management // Clients management
@ -1416,7 +1362,7 @@ define([
var onReady = function (clientId, returned, cb) { var onReady = function (clientId, returned, cb) {
var proxy = store.proxy; 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); }, pinPads: function (data, cb) { Store.pinPads(null, data, cb); },
unpinPads: function (data, cb) { Store.unpinPads(null, data, cb); }, unpinPads: function (data, cb) { Store.unpinPads(null, data, cb); },
removeOwnedChannel: function (data, cb) { Store.removeOwnedChannel(null, data, cb); }, removeOwnedChannel: function (data, cb) { Store.removeOwnedChannel(null, data, cb); },
@ -1427,6 +1373,7 @@ define([
sendDriveEvent("DRIVE_LOG", msg); sendDriveEvent("DRIVE_LOG", msg);
} }
}); });
var userObject = store.userObject = manager.user.userObject;
nThen(function (waitFor) { nThen(function (waitFor) {
postMessage(clientId, 'LOADING_DRIVE', { postMessage(clientId, 'LOADING_DRIVE', {
state: 2 state: 2
@ -1439,12 +1386,13 @@ define([
progress: progress progress: progress
}); });
}); });
}).nThen(function () { }).nThen(function (waitFor) {
postMessage(clientId, 'LOADING_DRIVE', { postMessage(clientId, 'LOADING_DRIVE', {
state: 3 state: 3
}); });
userObject.fixFiles(); userObject.fixFiles();
loadSharedFolders(waitFor);
}).nThen(function () {
var requestLogin = function () { var requestLogin = function () {
broadcast([], "REQUEST_LOGIN"); broadcast([], "REQUEST_LOGIN");
}; };

@ -22,7 +22,7 @@ define([
console.error("removeOwnedChannel was not provided"); console.error("removeOwnedChannel was not provided");
}; };
var loggedIn = config.loggedIn; var loggedIn = config.loggedIn;
var workgroup = config.workgroup; var sharedFolder = config.sharedFolder;
var edPublic = config.edPublic; var edPublic = config.edPublic;
var ROOT = exp.ROOT; var ROOT = exp.ROOT;
@ -31,6 +31,7 @@ define([
var UNSORTED = exp.UNSORTED; var UNSORTED = exp.UNSORTED;
var TRASH = exp.TRASH; var TRASH = exp.TRASH;
var TEMPLATE = exp.TEMPLATE; var TEMPLATE = exp.TEMPLATE;
var SHARED_FOLDERS = exp.SHARED_FOLDERS;
var debug = exp.debug; 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 // 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 // FILES_DATA. If there are owned pads, remove them from server too, unless the flag tells
// us they're already removed // us they're already removed
exp.checkDeletedFiles = function (isOwnPadRemoved) { exp.checkDeletedFiles = function (isOwnPadRemoved, noUnpin) {
// Nothing in FILES_DATA for workgroups if (!loggedIn && !config.testMode) { return; }
if (workgroup || (!loggedIn && !config.testMode)) { return; }
var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]); var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]);
var toClean = []; var toClean = [];
@ -107,6 +107,7 @@ define([
} }
}); });
if (!toClean.length) { return; } if (!toClean.length) { return; }
if (noUnpin) { return; }
unpinPads(toClean, function (response) { unpinPads(toClean, function (response) {
if (response && response.error) { return console.error(response.error); } if (response && response.error) { return console.error(response.error); }
// console.error(response); // console.error(response);
@ -124,7 +125,7 @@ define([
files[TRASH][obj.name].splice(idx, 1); 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 hrefPaths = paths.filter(function(x) { return exp.isPathIn(x, ['hrefArray']); });
var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); }); var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); });
var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); }); var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); });
@ -176,11 +177,66 @@ define([
deleteMultipleTrashRoot(trashRoot); deleteMultipleTrashRoot(trashRoot);
// In some cases, we want to remove pads from a location without removing them from // In some cases, we want to remove pads from a location without removing them from
// OLD_FILES_DATA (replaceHref) // FILES_DATA (replaceHref)
if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved); } if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved, noUnpin); }
}; };
// Move // 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 pushToTrash = function (name, element, path) {
var trash = files[TRASH]; var trash = files[TRASH];
if (typeof(trash[name]) === "undefined") { trash[name] = []; } if (typeof(trash[name]) === "undefined") { trash[name] = []; }
@ -449,6 +505,7 @@ define([
} }
}; };
var fixTrashRoot = function () { var fixTrashRoot = function () {
if (sharedFolder) { return; }
if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; } if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; }
var tr = files[TRASH]; var tr = files[TRASH];
var toClean; var toClean;
@ -492,6 +549,7 @@ define([
} }
}; };
var fixTemplate = function () { var fixTemplate = function () {
if (sharedFolder) { return; }
if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; } if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; }
files[TEMPLATE] = Util.deduplicateString(files[TEMPLATE].slice()); files[TEMPLATE] = Util.deduplicateString(files[TEMPLATE].slice());
var us = files[TEMPLATE]; var us = files[TEMPLATE];
@ -608,6 +666,10 @@ define([
spliceFileData(id); 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 () { var fixDrive = function () {
Object.keys(files).forEach(function (key) { Object.keys(files).forEach(function (key) {
@ -617,10 +679,9 @@ define([
fixRoot(); fixRoot();
fixTrashRoot(); fixTrashRoot();
if (!workgroup) { fixTemplate();
fixTemplate(); fixFilesData();
fixFilesData(); fixSharedFolders();
}
fixDrive(); fixDrive();
if (JSON.stringify(files) !== before) { 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.UNSORTED = UNSORTED;
exp.TRASH = TRASH; exp.TRASH = TRASH;
exp.TEMPLATE = TEMPLATE; exp.TEMPLATE = TEMPLATE;
exp.SHARED_FOLDERS = SHARED_FOLDERS;
// Logging // Logging
var logging = function () { var logging = function () {
@ -42,9 +43,6 @@ define([
console.error.apply(console, arguments); console.error.apply(console, arguments);
}; };
// TODO: workgroup
var workgroup = config.workgroup;
if (pinPads) { if (pinPads) {
// Extend "exp" with methods used only outside of the iframe (requires access to store) // Extend "exp" with methods used only outside of the iframe (requires access to store)
OuterFO.init(config, exp, files); OuterFO.init(config, exp, files);
@ -89,6 +87,9 @@ define([
if (!isFolder(element)) { return false; } if (!isFolder(element)) { return false; }
return Object.keys(element).length === 0; return Object.keys(element).length === 0;
}; };
exp.isSharedFolder = function (element) {
return Boolean(files[SHARED_FOLDERS][element]);
};
exp.hasSubfolder = function (element, trashRoot) { exp.hasSubfolder = function (element, trashRoot) {
if (!isFolder(element)) { return false; } if (!isFolder(element)) { return false; }
@ -134,7 +135,6 @@ define([
// Data from filesData // Data from filesData
var getTitle = exp.getTitle = function (file, type) { var getTitle = exp.getTitle = function (file, type) {
if (workgroup) { debug("No titles in workgroups"); return; }
var data = getFileData(file); var data = getFileData(file);
if (!file || !data || !(data.href || data.roHref)) { if (!file || !data || !(data.href || data.roHref)) {
error("getTitle called with a non-existing file id: ", file, data); error("getTitle called with a non-existing file id: ", file, data);
@ -206,7 +206,8 @@ define([
// GET FILES // GET FILES
var getFilesRecursively = function (root, arr) { var getFilesRecursively = exp.getFilesRecursively = function (root, arr) {
arr = arr || [];
for (var e in root) { for (var e in root) {
if (isFile(root[e])) { if (isFile(root[e])) {
if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); } if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); }
@ -214,6 +215,7 @@ define([
getFilesRecursively(root[e], arr); getFilesRecursively(root[e], arr);
} }
} }
return arr;
}; };
var _getFiles = {}; var _getFiles = {};
_getFiles['array'] = function (cat) { _getFiles['array'] = function (cat) {
@ -552,18 +554,19 @@ define([
// DELETE // DELETE
// Permanently delete multiple files at once using a list of paths // 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) // 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) { if (sframeChan) {
return void sframeChan.query("Q_DRIVE_USEROBJECT", { return void sframeChan.query("Q_DRIVE_USEROBJECT", {
cmd: "delete", cmd: "delete",
data: { data: {
paths: paths, paths: paths,
nocheck: nocheck, nocheck: nocheck,
noUnpin: noUnpin,
isOwnPadRemoved: isOwnPadRemoved isOwnPadRemoved: isOwnPadRemoved
} }
}, cb); }, cb);
} }
exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved); exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved, noUnpin);
if (typeof cb === "function") { cb(); } if (typeof cb === "function") { cb(); }
}; };
exp.emptyTrash = function (cb) { exp.emptyTrash = function (cb) {

@ -244,27 +244,27 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faTags, 'data-icon': faTags,
}, Messages.fc_hashtag)), }, 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', 'tabindex': '-1',
'data-icon': AppConfig.applicationsIcon.pad, 'data-icon': AppConfig.applicationsIcon.pad,
'data-type': 'pad' 'data-type': 'pad'
}, Messages.button_newpad)), }, 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', 'tabindex': '-1',
'data-icon': AppConfig.applicationsIcon.code, 'data-icon': AppConfig.applicationsIcon.code,
'data-type': 'code' 'data-type': 'code'
}, Messages.button_newcode)), }, 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', 'tabindex': '-1',
'data-icon': AppConfig.applicationsIcon.slide, 'data-icon': AppConfig.applicationsIcon.slide,
'data-type': 'slide' 'data-type': 'slide'
}, Messages.button_newslide)), }, 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', 'tabindex': '-1',
'data-icon': AppConfig.applicationsIcon.poll, 'data-icon': AppConfig.applicationsIcon.poll,
'data-type': 'poll' 'data-type': 'poll'
}, Messages.button_newpoll)), }, 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', 'tabindex': '-1',
'data-icon': AppConfig.applicationsIcon.whiteboard, 'data-icon': AppConfig.applicationsIcon.whiteboard,
'data-type': 'whiteboard' 'data-type': 'whiteboard'
@ -311,13 +311,6 @@ define([
var edPublic = priv.edPublic; var edPublic = priv.edPublic;
APP.origin = priv.origin; 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.loggedIn = APP.loggedIn;
config.sframeChan = sframeChan; config.sframeChan = sframeChan;
@ -357,11 +350,9 @@ define([
} }
// FILE MANAGER // FILE MANAGER
// _WORKGROUP_ and other people drive : display Documents as main page var currentPath = APP.currentPath = getLastOpenedFolder();
var currentPath = APP.currentPath = isOwnDrive() ? getLastOpenedFolder() : [ROOT];
// Categories dislayed in the menu // Categories dislayed in the menu
// _WORKGROUP_ : do not display unsorted
var displayedCategories = [ROOT, TRASH, SEARCH, RECENT]; var displayedCategories = [ROOT, TRASH, SEARCH, RECENT];
// PCS enabled: display owned pads // PCS enabled: display owned pads
@ -371,7 +362,6 @@ define([
// Tags used: display Tags category // Tags used: display Tags category
if (Object.keys(filesOp.getTagsList()).length) { displayedCategories.push(TAGS); } if (Object.keys(filesOp.getTagsList()).length) { displayedCategories.push(TAGS); }
if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; }
var virtualCategories = [SEARCH, RECENT, OWNED, TAGS]; var virtualCategories = [SEARCH, RECENT, OWNED, TAGS];
if (!APP.loggedIn) { if (!APP.loggedIn) {
@ -856,7 +846,6 @@ define([
show.forEach(function (className) { show.forEach(function (className) {
var $el = $contextMenu.find('.cp-app-drive-context-' + className); var $el = $contextMenu.find('.cp-app-drive-context-' + className);
if (!APP.editable && $el.is('.cp-app-drive-context-editable')) { return; } 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; } if (filter($el, className)) { return; }
$el.parent('li').show(); $el.parent('li').show();
filtered.push('.cp-app-drive-context-' + className); filtered.push('.cp-app-drive-context-' + className);
@ -1212,10 +1201,6 @@ define([
if (movedPaths && movedPaths.length) { if (movedPaths && movedPaths.length) {
moveElements(movedPaths, newPath, null, refresh); moveElements(movedPaths, newPath, null, refresh);
} }
if (importedElements && importedElements.length) {
// TODO workgroup
//filesOp.importElements(importedElements, newPath, refresh);
}
}; };
var addDragAndDropHandlers = function ($element, path, isFolder, droppable) { var addDragAndDropHandlers = function ($element, path, isFolder, droppable) {
@ -1266,7 +1251,6 @@ define([
addDragAndDropHandlers($content, null, true, true); addDragAndDropHandlers($content, null, true, true);
// In list mode, display metadata from the filesData object // 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) { var addFileData = function (element, $span) {
if (!filesOp.isFile(element)) { return; } if (!filesOp.isFile(element)) { return; }
@ -1323,10 +1307,7 @@ define([
var $cdate = $('<span>', { var $cdate = $('<span>', {
'class': 'cp-app-drive-element-ctime cp-app-drive-element-list' 'class': 'cp-app-drive-element-ctime cp-app-drive-element-list'
}).text(getDate(data.ctime)); }).text(getDate(data.ctime));
$span.append($type); $span.append($type).append($adate).append($cdate);
if (!isWorkgroup()) {
$span.append($adate).append($cdate);
}
}; };
var addFolderData = function (element, key, $span) { var addFolderData = function (element, key, $span) {
@ -1804,7 +1785,6 @@ define([
$list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon); $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 getFileListHeader = function () {
var $fihElement = $('<li>', { var $fihElement = $('<li>', {
'class': 'cp-app-drive-element-header cp-app-drive-element-list' 'class': 'cp-app-drive-element-header cp-app-drive-element-list'
@ -1827,9 +1807,7 @@ define([
}).text(Messages.fm_creation).click(onSortByClick); }).text(Messages.fm_creation).click(onSortByClick);
// If displayTitle is false, it means the "name" is the title, so do not display the "name" header // 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); $fihElement.append($fhIcon).append($fhName).append($fhState).append($fhType);
if (!isWorkgroup()) { $fihElement.append($fhAdate).append($fhCdate);
$fihElement.append($fhAdate).append($fhCdate);
}
addFileSortIcon($fihElement); addFileSortIcon($fihElement);
return $fihElement; return $fihElement;
}; };
@ -2277,7 +2255,6 @@ define([
// Display the selected directory into the content part (rightside) // Display the selected directory into the content part (rightside)
// NOTE: Elements in the trash are not using the same storage structure as the others // 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) { var _displayDirectory = function (path, force) {
APP.hideMenu(); APP.hideMenu();
if (!APP.editable) { debug("Read-only mode"); } if (!APP.editable) { debug("Read-only mode"); }
@ -2331,9 +2308,7 @@ define([
$tree.find('#cp-app-drive-tree-search-input')[0].selectionEnd = getSearchCursor(); $tree.find('#cp-app-drive-tree-search-input')[0].selectionEnd = getSearchCursor();
} }
if (!isWorkgroup()) { setLastOpenedFolder(path);
setLastOpenedFolder(path);
}
var $toolbar = createToolbar(path); var $toolbar = createToolbar(path);
var $info = createInfoBox(path); var $info = createInfoBox(path);

Loading…
Cancel
Save