Add Team app
This commit is contained in:
parent
e9785c7ef6
commit
1a8f47d558
@ -93,6 +93,10 @@
|
|||||||
@colortheme_drive-color: #fff;
|
@colortheme_drive-color: #fff;
|
||||||
@colortheme_drive-warn: #cd2532;
|
@colortheme_drive-warn: #cd2532;
|
||||||
|
|
||||||
|
@colortheme_team-bg: #0b0061;
|
||||||
|
@colortheme_team-color: #fff;
|
||||||
|
@colortheme_team-warn: #cd2532;
|
||||||
|
|
||||||
@colortheme_file-bg: #cd2532;
|
@colortheme_file-bg: #cd2532;
|
||||||
@colortheme_file-color: #fff;
|
@colortheme_file-color: #fff;
|
||||||
@colortheme_file-warn: #ffae00;
|
@colortheme_file-warn: #ffae00;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ define(function() {
|
|||||||
* redirected to the drive.
|
* redirected to the drive.
|
||||||
* You should never remove the drive from this list.
|
* You should never remove the drive from this list.
|
||||||
*/
|
*/
|
||||||
config.availablePadTypes = ['drive', 'pad', 'sheet', 'code', 'slide', 'poll', 'kanban', 'whiteboard',
|
config.availablePadTypes = ['drive', 'team', 'pad', 'sheet', 'code', 'slide', 'poll', 'kanban', 'whiteboard',
|
||||||
/*'oodoc', 'ooslide',*/ 'file', 'todo', 'contacts'];
|
/*'oodoc', 'ooslide',*/ 'file', 'todo', 'contacts'];
|
||||||
/* The registered only types are apps restricted to registered users.
|
/* The registered only types are apps restricted to registered users.
|
||||||
* You should never remove apps from this list unless you know what you're doing. The apps
|
* You should never remove apps from this list unless you know what you're doing. The apps
|
||||||
@ -20,7 +20,7 @@ define(function() {
|
|||||||
* users and these users will be redirected to the login page if they still try to access
|
* users and these users will be redirected to the login page if they still try to access
|
||||||
* the app
|
* the app
|
||||||
*/
|
*/
|
||||||
config.registeredOnlyTypes = ['file', 'contacts', 'oodoc', 'ooslide', 'sheet', 'notifications'];
|
config.registeredOnlyTypes = ['team', 'file', 'contacts', 'oodoc', 'ooslide', 'sheet', 'notifications'];
|
||||||
|
|
||||||
/* CryptPad is available is multiple languages, but only English and French are maintained
|
/* CryptPad is available is multiple languages, but only English and French are maintained
|
||||||
* by the developers. The other languages may be outdated, and any missing string for a langauge
|
* by the developers. The other languages may be outdated, and any missing string for a langauge
|
||||||
|
|||||||
@ -2473,6 +2473,7 @@ define([
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
var types = AppConfig.availablePadTypes.filter(function (p) {
|
var types = AppConfig.availablePadTypes.filter(function (p) {
|
||||||
if (p === 'drive') { return; }
|
if (p === 'drive') { return; }
|
||||||
|
if (p === 'team') { return; }
|
||||||
if (p === 'contacts') { return; }
|
if (p === 'contacts') { return; }
|
||||||
if (p === 'todo') { return; }
|
if (p === 'todo') { return; }
|
||||||
if (p === 'file') { return; }
|
if (p === 'file') { return; }
|
||||||
|
|||||||
@ -922,6 +922,7 @@ MessengerUI, Messages) {
|
|||||||
var pads_options = [];
|
var pads_options = [];
|
||||||
Config.availablePadTypes.forEach(function (p) {
|
Config.availablePadTypes.forEach(function (p) {
|
||||||
if (p === 'drive') { return; }
|
if (p === 'drive') { return; }
|
||||||
|
if (p === 'team') { return; }
|
||||||
if (!Common.isLoggedIn() && Config.registeredOnlyTypes &&
|
if (!Common.isLoggedIn() && Config.registeredOnlyTypes &&
|
||||||
Config.registeredOnlyTypes.indexOf(p) !== -1) { return; }
|
Config.registeredOnlyTypes.indexOf(p) !== -1) { return; }
|
||||||
pads_options.push({
|
pads_options.push({
|
||||||
|
|||||||
13
www/team/app-team.less
Normal file
13
www/team/app-team.less
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@import (reference) '../../customize/src/less2/include/framework.less';
|
||||||
|
@import (reference) '../../customize/src/less2/include/drive.less';
|
||||||
|
|
||||||
|
&.cp-app-team {
|
||||||
|
.framework_min_main(
|
||||||
|
@bg-color: @colortheme_team-bg,
|
||||||
|
@warn-color: @colortheme_team-warn,
|
||||||
|
@color: @colortheme_team-color
|
||||||
|
);
|
||||||
|
|
||||||
|
.drive_main();
|
||||||
|
}
|
||||||
|
|
||||||
12
www/team/index.html
Normal file
12
www/team/index.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CryptPad</title>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="referrer" content="no-referrer" />
|
||||||
|
<script async data-bootload="main.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<link href="/customize/src/outer.css" rel="stylesheet" type="text/css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="sbox-iframe">
|
||||||
24
www/team/inner.html
Normal file
24
www/team/inner.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="cp-app-noscroll">
|
||||||
|
<head>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<script async data-bootload="/team/inner.js" data-main="/common/sframe-boot.js?ver=1.6" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<style>
|
||||||
|
.loading-hidden { display: none; }
|
||||||
|
#editor1 { display: none; }
|
||||||
|
.cp-contextmenu { display: none; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="cp-app-team cp-body-drive">
|
||||||
|
<div id="cp-toolbar" class="cp-toolbar-container"></div>
|
||||||
|
<div class="cp-app-drive-container" tabindex="0">
|
||||||
|
<div id="cp-app-drive-tree">
|
||||||
|
</div>
|
||||||
|
<div id="cp-app-drive-content-container">
|
||||||
|
<div id="cp-app-drive-toolbar"></div>
|
||||||
|
<div id="cp-app-drive-content" tabindex="2"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
256
www/team/inner.js
Normal file
256
www/team/inner.js
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
define([
|
||||||
|
'jquery',
|
||||||
|
'/common/toolbar3.js',
|
||||||
|
'/common/drive-ui.js',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-feedback.js',
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/common/sframe-common.js',
|
||||||
|
'/common/proxy-manager.js',
|
||||||
|
'/customize/application_config.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
|
||||||
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
|
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
|
'less!/team/app-team.less',
|
||||||
|
], function (
|
||||||
|
$,
|
||||||
|
Toolbar,
|
||||||
|
DriveUI,
|
||||||
|
Util,
|
||||||
|
UI,
|
||||||
|
Feedback,
|
||||||
|
nThen,
|
||||||
|
SFCommon,
|
||||||
|
ProxyManager,
|
||||||
|
AppConfig,
|
||||||
|
Messages)
|
||||||
|
{
|
||||||
|
var APP = {};
|
||||||
|
var SHARED_FOLDER_NAME = Messages.fm_sharedFolderName;
|
||||||
|
|
||||||
|
var copyObjectValue = function (objRef, objToCopy) {
|
||||||
|
for (var k in objRef) { delete objRef[k]; }
|
||||||
|
$.extend(true, objRef, objToCopy);
|
||||||
|
};
|
||||||
|
var updateSharedFolders = function (sframeChan, manager, drive, folders, cb) {
|
||||||
|
if (!drive || !drive.sharedFolders) {
|
||||||
|
return void cb();
|
||||||
|
}
|
||||||
|
var oldIds = Object.keys(folders);
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
Object.keys(drive.sharedFolders).forEach(function (fId) {
|
||||||
|
sframeChan.query('Q_DRIVE_GETOBJECT', {
|
||||||
|
sharedFolder: fId
|
||||||
|
}, waitFor(function (err, newObj) {
|
||||||
|
folders[fId] = folders[fId] || {};
|
||||||
|
copyObjectValue(folders[fId], newObj);
|
||||||
|
if (manager && oldIds.indexOf(fId) === -1) {
|
||||||
|
manager.addProxy(fId, folders[fId]);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}).nThen(function () {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var updateObject = function (sframeChan, obj, cb) {
|
||||||
|
sframeChan.query('Q_DRIVE_GETOBJECT', null, function (err, newObj) {
|
||||||
|
copyObjectValue(obj, newObj);
|
||||||
|
if (!APP.loggedIn && APP.newSharedFolder) {
|
||||||
|
obj.drive.sharedFolders = obj.drive.sharedFolders || {};
|
||||||
|
obj.drive.sharedFolders[APP.newSharedFolder] = {};
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var history = {
|
||||||
|
isHistoryMode: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var setEditable = DriveUI.setEditable;
|
||||||
|
|
||||||
|
var setHistory = function (bool, update) {
|
||||||
|
history.isHistoryMode = bool;
|
||||||
|
setEditable(!bool);
|
||||||
|
if (!bool && update) {
|
||||||
|
history.onLeaveHistory();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var main = function () {
|
||||||
|
var common;
|
||||||
|
var proxy = {};
|
||||||
|
var folders = {};
|
||||||
|
var readOnly;
|
||||||
|
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
$(waitFor(function () {
|
||||||
|
UI.addLoadingScreen();
|
||||||
|
}));
|
||||||
|
window.cryptpadStore.getAll(waitFor(function (val) {
|
||||||
|
APP.store = JSON.parse(JSON.stringify(val));
|
||||||
|
}));
|
||||||
|
SFCommon.create(waitFor(function (c) { common = c; }));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
var privReady = Util.once(waitFor());
|
||||||
|
var metadataMgr = common.getMetadataMgr();
|
||||||
|
if (JSON.stringify(metadataMgr.getPrivateData()) !== '{}') {
|
||||||
|
privReady();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
metadataMgr.onChange(function () {
|
||||||
|
if (typeof(metadataMgr.getPrivateData().readOnly) === 'boolean') {
|
||||||
|
readOnly = APP.readOnly = metadataMgr.getPrivateData().readOnly;
|
||||||
|
privReady();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
APP.loggedIn = common.isLoggedIn();
|
||||||
|
if (!APP.loggedIn) { Feedback.send('ANONYMOUS_DRIVE'); }
|
||||||
|
APP.$body = $('body');
|
||||||
|
APP.$bar = $('#cp-toolbar');
|
||||||
|
|
||||||
|
common.setTabTitle(Messages.type.drive);
|
||||||
|
|
||||||
|
var metadataMgr = common.getMetadataMgr();
|
||||||
|
var privateData = metadataMgr.getPrivateData();
|
||||||
|
if (privateData.newSharedFolder) {
|
||||||
|
APP.newSharedFolder = privateData.newSharedFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sframeChan = common.getSframeChannel();
|
||||||
|
updateObject(sframeChan, proxy, waitFor(function () {
|
||||||
|
updateSharedFolders(sframeChan, null, proxy.drive, folders, waitFor());
|
||||||
|
}));
|
||||||
|
}).nThen(function () {
|
||||||
|
var sframeChan = common.getSframeChannel();
|
||||||
|
var metadataMgr = common.getMetadataMgr();
|
||||||
|
var privateData = metadataMgr.getPrivateData();
|
||||||
|
|
||||||
|
APP.disableSF = !privateData.enableSF && AppConfig.disableSharedFolders;
|
||||||
|
if (APP.newSharedFolder && !APP.loggedIn) {
|
||||||
|
readOnly = APP.readOnly = true;
|
||||||
|
var data = folders[APP.newSharedFolder];
|
||||||
|
if (data) {
|
||||||
|
sframeChan.query('Q_SET_PAD_TITLE_IN_DRIVE', {
|
||||||
|
title: data.metadata && data.metadata.title,
|
||||||
|
}, function () {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ANON_SHARED_FOLDER
|
||||||
|
var pageTitle = (!APP.loggedIn && APP.newSharedFolder) ? SHARED_FOLDER_NAME : Messages.type.drive;
|
||||||
|
|
||||||
|
var configTb = {
|
||||||
|
displayed: ['useradmin', 'pageTitle', 'newpad', 'limit', 'notifications'],
|
||||||
|
pageTitle: pageTitle,
|
||||||
|
metadataMgr: metadataMgr,
|
||||||
|
readOnly: privateData.readOnly,
|
||||||
|
sfCommon: common,
|
||||||
|
$container: APP.$bar
|
||||||
|
};
|
||||||
|
var toolbar = APP.toolbar = Toolbar.create(configTb);
|
||||||
|
|
||||||
|
var $rightside = toolbar.$rightside;
|
||||||
|
$rightside.html(''); // Remove the drawer if we don't use it to hide the toolbar
|
||||||
|
APP.$displayName = APP.$bar.find('.' + Toolbar.constants.username);
|
||||||
|
|
||||||
|
/* add the usage */
|
||||||
|
if (APP.loggedIn) {
|
||||||
|
common.createUsageBar(function (err, $limitContainer) {
|
||||||
|
if (err) { return void DriveUI.logError(err); }
|
||||||
|
APP.$limit = $limitContainer;
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add a history button */
|
||||||
|
APP.histConfig = {
|
||||||
|
onLocal: function () {
|
||||||
|
UI.addLoadingScreen({ loadingText: Messages.fm_restoreDrive });
|
||||||
|
var data = {};
|
||||||
|
if (history.sfId) {
|
||||||
|
copyObjectValue(folders[history.sfId], history.currentObj);
|
||||||
|
data.sfId = history.sfId;
|
||||||
|
data.drive = history.currentObj;
|
||||||
|
} else {
|
||||||
|
proxy.drive = history.currentObj.drive;
|
||||||
|
data.drive = history.currentObj.drive;
|
||||||
|
}
|
||||||
|
sframeChan.query("Q_DRIVE_RESTORE", data, function () {
|
||||||
|
UI.removeLoadingScreen();
|
||||||
|
}, {
|
||||||
|
timeout: 5 * 60 * 1000
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onOpen: function () {},
|
||||||
|
onRemote: function () {},
|
||||||
|
setHistory: setHistory,
|
||||||
|
applyVal: function (val) {
|
||||||
|
var obj = JSON.parse(val || '{}');
|
||||||
|
history.currentObj = obj;
|
||||||
|
history.onEnterHistory(obj);
|
||||||
|
},
|
||||||
|
$toolbar: APP.$bar,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a "Burn this drive" button
|
||||||
|
if (!APP.loggedIn) {
|
||||||
|
APP.$burnThisDrive = common.createButton(null, true).click(function () {
|
||||||
|
UI.confirm(Messages.fm_burnThisDrive, function (yes) {
|
||||||
|
if (!yes) { return; }
|
||||||
|
common.getSframeChannel().event('EV_BURN_ANON_DRIVE');
|
||||||
|
}, null, true);
|
||||||
|
}).attr('title', Messages.fm_burnThisDriveButton)
|
||||||
|
.removeClass('fa-question')
|
||||||
|
.addClass('fa-ban');
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataMgr.onChange(function () {
|
||||||
|
var name = metadataMgr.getUserData().name || Messages.anonymous;
|
||||||
|
APP.$displayName.text(name);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').css('display', '');
|
||||||
|
if (!proxy.drive || typeof(proxy.drive) !== 'object') {
|
||||||
|
throw new Error("Corrupted drive");
|
||||||
|
}
|
||||||
|
DriveUI.create(common, {
|
||||||
|
proxy: proxy,
|
||||||
|
folders: folders,
|
||||||
|
updateObject: updateObject,
|
||||||
|
updateSharedFolders: updateSharedFolders,
|
||||||
|
history: history,
|
||||||
|
APP: APP
|
||||||
|
});
|
||||||
|
|
||||||
|
var onDisconnect = function (noAlert) {
|
||||||
|
setEditable(false);
|
||||||
|
if (APP.refresh) { APP.refresh(); }
|
||||||
|
APP.toolbar.failed();
|
||||||
|
if (!noAlert) { UI.alert(Messages.common_connectionLost, undefined, true); }
|
||||||
|
};
|
||||||
|
var onReconnect = function (info) {
|
||||||
|
setEditable(true);
|
||||||
|
if (APP.refresh) { APP.refresh(); }
|
||||||
|
APP.toolbar.reconnecting(info.myId);
|
||||||
|
UI.findOKButton().click();
|
||||||
|
};
|
||||||
|
|
||||||
|
sframeChan.on('EV_DRIVE_LOG', function (msg) {
|
||||||
|
UI.log(msg);
|
||||||
|
});
|
||||||
|
sframeChan.on('EV_NETWORK_DISCONNECT', function () {
|
||||||
|
onDisconnect();
|
||||||
|
});
|
||||||
|
sframeChan.on('EV_NETWORK_RECONNECT', function (data) {
|
||||||
|
// data.myId;
|
||||||
|
onReconnect(data);
|
||||||
|
});
|
||||||
|
common.onLogout(function () { setEditable(false); });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
main();
|
||||||
|
});
|
||||||
117
www/team/main.js
Normal file
117
www/team/main.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
||||||
|
define([
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/api/config',
|
||||||
|
'/common/dom-ready.js',
|
||||||
|
'/common/requireconfig.js',
|
||||||
|
'/common/sframe-common-outer.js',
|
||||||
|
], function (nThen, ApiConfig, DomReady, RequireConfig, SFCommonO) {
|
||||||
|
var requireConfig = RequireConfig();
|
||||||
|
|
||||||
|
// Loaded in load #2
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
DomReady.onReady(waitFor());
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
var req = {
|
||||||
|
cfg: requireConfig,
|
||||||
|
req: [ '/common/loading.js' ],
|
||||||
|
pfx: window.location.origin
|
||||||
|
};
|
||||||
|
window.rc = requireConfig;
|
||||||
|
window.apiconf = ApiConfig;
|
||||||
|
document.getElementById('sbox-iframe').setAttribute('src',
|
||||||
|
ApiConfig.httpSafeOrigin + '/team/inner.html?' + requireConfig.urlArgs +
|
||||||
|
'#' + encodeURIComponent(JSON.stringify(req)));
|
||||||
|
|
||||||
|
// This is a cheap trick to avoid loading sframe-channel in parallel with the
|
||||||
|
// loading screen setup.
|
||||||
|
var done = waitFor();
|
||||||
|
var onMsg = function (msg) {
|
||||||
|
var data = JSON.parse(msg.data);
|
||||||
|
if (data.q !== 'READY') { return; }
|
||||||
|
window.removeEventListener('message', onMsg);
|
||||||
|
var _done = done;
|
||||||
|
done = function () { };
|
||||||
|
_done();
|
||||||
|
};
|
||||||
|
window.addEventListener('message', onMsg);
|
||||||
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
var afterSecrets = function (Cryptpad, Utils, secret, cb) {
|
||||||
|
var hash = window.location.hash.slice(1);
|
||||||
|
if (hash && Utils.LocalStore.isLoggedIn()) {
|
||||||
|
// Add a shared folder!
|
||||||
|
Cryptpad.addSharedFolder(secret, function (id) {
|
||||||
|
window.CryptPad_newSharedFolder = id;
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
} else if (hash) {
|
||||||
|
var id = Utils.Util.createRandomInteger();
|
||||||
|
window.CryptPad_newSharedFolder = id;
|
||||||
|
var data = {
|
||||||
|
href: Utils.Hash.getRelativeHref(window.location.href),
|
||||||
|
password: secret.password
|
||||||
|
};
|
||||||
|
return void Cryptpad.loadSharedFolder(id, data, cb);
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
var addRpc = function (sframeChan, Cryptpad, Utils) {
|
||||||
|
sframeChan.on('EV_BURN_ANON_DRIVE', function () {
|
||||||
|
if (Utils.LocalStore.isLoggedIn()) { return; }
|
||||||
|
Utils.LocalStore.setFSHash('');
|
||||||
|
Utils.LocalStore.clearThumbnail();
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
sframeChan.on('Q_DRIVE_USEROBJECT', function (data, cb) {
|
||||||
|
Cryptpad.userObjectCommand(data, cb);
|
||||||
|
});
|
||||||
|
sframeChan.on('Q_DRIVE_RESTORE', function (data, cb) {
|
||||||
|
Cryptpad.restoreDrive(data, cb);
|
||||||
|
});
|
||||||
|
sframeChan.on('Q_DRIVE_GETOBJECT', function (data, cb) {
|
||||||
|
if (data && data.sharedFolder) {
|
||||||
|
Cryptpad.getSharedFolder(data.sharedFolder, function (obj) {
|
||||||
|
cb(obj);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Cryptpad.getUserObject(function (obj) {
|
||||||
|
cb(obj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
sframeChan.on('EV_DRIVE_SET_HASH', function (hash) {
|
||||||
|
// Update the hash in the address bar
|
||||||
|
if (!Utils.LocalStore.isLoggedIn()) { return; }
|
||||||
|
var ohc = window.onhashchange;
|
||||||
|
window.onhashchange = function () {};
|
||||||
|
window.location.hash = hash || '';
|
||||||
|
window.onhashchange = ohc;
|
||||||
|
ohc({reset:true});
|
||||||
|
});
|
||||||
|
Cryptpad.onNetworkDisconnect.reg(function () {
|
||||||
|
sframeChan.event('EV_NETWORK_DISCONNECT');
|
||||||
|
});
|
||||||
|
Cryptpad.onNetworkReconnect.reg(function (data) {
|
||||||
|
sframeChan.event('EV_NETWORK_RECONNECT', data);
|
||||||
|
});
|
||||||
|
Cryptpad.drive.onLog.reg(function (msg) {
|
||||||
|
sframeChan.event('EV_DRIVE_LOG', msg);
|
||||||
|
});
|
||||||
|
Cryptpad.drive.onChange.reg(function (data) {
|
||||||
|
sframeChan.event('EV_DRIVE_CHANGE', data);
|
||||||
|
});
|
||||||
|
Cryptpad.drive.onRemove.reg(function (data) {
|
||||||
|
sframeChan.event('EV_DRIVE_REMOVE', data);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
SFCommonO.start({
|
||||||
|
afterSecrets: afterSecrets,
|
||||||
|
noHash: true,
|
||||||
|
noRealtime: true,
|
||||||
|
driveEvents: true,
|
||||||
|
addRpc: addRpc,
|
||||||
|
isDrive: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
418
www/team/tests.js
Normal file
418
www/team/tests.js
Normal file
@ -0,0 +1,418 @@
|
|||||||
|
define([
|
||||||
|
'/common/cryptpad-common.js',
|
||||||
|
'/common/userObject.js',
|
||||||
|
],function (Cryptpad, FO) {
|
||||||
|
var module = {};
|
||||||
|
|
||||||
|
var href1 = "/pad/#/1/edit/a798u+miu2tg5b-QaP9SvA/UIPoGUPewZscBUFhNIi+eBBM/";
|
||||||
|
var href2 = "/poll/#/1/edit/uFJTXjQUEwV2bl-y3cKVpP/LJ-4qPnpR5iY0HVdwLcnjLsx/";
|
||||||
|
var href3 = "/code/#/1/view/eRS+YPTTASNqjRbgrznAdQ/2OyNsvfYw7ZwLg6wkJuCaGBzOZvxNLra9n7GN848Zic/";
|
||||||
|
var href4 = "/slide/#/1/edit/R2bZC1mY9khSsrLCyJT+CA/mlQrCxbTiqQJ4HyUxbFBnmG8/";
|
||||||
|
var href5 = "/whiteboard/#/1/edit/k8bZC1mY9khSsrLCyJT+CA/moQrCxbTiqQJ4HyUxbFBnmG8/";
|
||||||
|
|
||||||
|
var id1 = 1000000000001;
|
||||||
|
var id2 = 1000000000002;
|
||||||
|
var id3 = 1000000000003;
|
||||||
|
var id4 = 1000000000004;
|
||||||
|
var example = {
|
||||||
|
"root": {
|
||||||
|
"Folder": {
|
||||||
|
"Sub": {}
|
||||||
|
},
|
||||||
|
"Folder2": {
|
||||||
|
"rdmStrFile1": id1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": [id2],
|
||||||
|
"trash": {
|
||||||
|
"DeletedF": [{
|
||||||
|
"path": ["root"],
|
||||||
|
"element": {}
|
||||||
|
},{
|
||||||
|
"path": ["root"],
|
||||||
|
"element": {
|
||||||
|
"rdmStrFile3": id3
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"Title4": [{
|
||||||
|
"path": ["root", "Folder"],
|
||||||
|
"element": id4
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"filesData": {
|
||||||
|
"1000000000004": {
|
||||||
|
"atime": 23456783489,
|
||||||
|
"ctime": 12345678999,
|
||||||
|
"href": href4,
|
||||||
|
"title": "Title4"
|
||||||
|
},
|
||||||
|
"1000000000003": {
|
||||||
|
"atime": 23456783456,
|
||||||
|
"ctime": 12345678901,
|
||||||
|
"href": href3,
|
||||||
|
"title": "Title3"
|
||||||
|
},
|
||||||
|
"1000000000002": {
|
||||||
|
"atime": 23456789012,
|
||||||
|
"ctime": 12345789235,
|
||||||
|
"href": href2,
|
||||||
|
"title": "Title2"
|
||||||
|
},
|
||||||
|
"1000000000001": {
|
||||||
|
"atime": 23456789012,
|
||||||
|
"ctime": 12345789235,
|
||||||
|
"href": href1,
|
||||||
|
"title": "Title1",
|
||||||
|
"filename": "FileName1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.test = function (assert) {
|
||||||
|
var config = {
|
||||||
|
outer: true,
|
||||||
|
workgroup: false,
|
||||||
|
testMode: true,
|
||||||
|
loggedIn: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// MIGRATION FROM HREF TO ID
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START DRIVE1');
|
||||||
|
var files = {
|
||||||
|
"root": {
|
||||||
|
"Folder": {},
|
||||||
|
"Folder2": {
|
||||||
|
"FileName": href1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": [href3],
|
||||||
|
"trash": {
|
||||||
|
"DeletedF": [{
|
||||||
|
"path": ["root"],
|
||||||
|
"element": {}
|
||||||
|
}, {
|
||||||
|
"path": ["root", "Folder"],
|
||||||
|
"element": href2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"CryptPad_RECENTPADS": [{
|
||||||
|
"atime": 23456783456,
|
||||||
|
"ctime": 12345678901,
|
||||||
|
"href": href3,
|
||||||
|
"title": "pewcode"
|
||||||
|
}, {
|
||||||
|
"atime": 23456789012,
|
||||||
|
"ctime": 12345789235,
|
||||||
|
"href": href2,
|
||||||
|
"title": "pewpoll"
|
||||||
|
}, {
|
||||||
|
"atime": 23456789012,
|
||||||
|
"ctime": 12345789235,
|
||||||
|
"href": href1,
|
||||||
|
"title": "pewpad"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
var todo = function () {
|
||||||
|
fo.fixFiles();
|
||||||
|
if (files['CryptPad_RECENTPADS'] || !files.filesData) {
|
||||||
|
console.log("DRIVE1: migration from RECENTPADS to filesData failed");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
var fileKey = Object.keys(files.root.Folder2)[0];
|
||||||
|
if (!fileKey) { return cb(); }
|
||||||
|
var fileId = files.root.Folder2[fileKey];
|
||||||
|
var res = typeof fileId === "number"
|
||||||
|
&& typeof files.filesData[fileId] === "object"
|
||||||
|
&& files.filesData[fileId].filename === "FileName"
|
||||||
|
&& typeof files.trash.DeletedF[1].element === "number"
|
||||||
|
&& typeof files.filesData[files.trash.DeletedF[1].element] === "object"
|
||||||
|
&& files.filesData[files.trash.DeletedF[1].element].filename === "DeletedF"
|
||||||
|
&& typeof files.template[0] === "number"
|
||||||
|
&& typeof files.filesData[files.template[0]] === "object"
|
||||||
|
&& !files.filesData[files.template[0]].filename;
|
||||||
|
return cb(res);
|
||||||
|
};
|
||||||
|
fo.migrate(todo);
|
||||||
|
}, "DRIVE1: migration and fixFiles without unsorted");
|
||||||
|
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START DRIVE2');
|
||||||
|
var files = {
|
||||||
|
"root": {
|
||||||
|
"Folder": {},
|
||||||
|
"Folder2": {
|
||||||
|
"FileName": "/pad/#/1/edit/a798u+miu2tg5b-QaP9SvA/UIPoGUPewZscBUFhNIi+eBBM/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unsorted": ["/code/#/1/edit/R1kZC1mY9khSsrLCyJT+CA/jtQrCxbTiqQJ4HyUxbFBnmG8/"],
|
||||||
|
"trash": {},
|
||||||
|
"CryptPad_RECENTPADS": [{
|
||||||
|
"atime": 23456783456,
|
||||||
|
"ctime": 12345678901,
|
||||||
|
"href": "/code/#/1/edit/R1kZC1mY9khSsrLCyJT+CA/jtQrCxbTiqQJ4HyUxbFBnmG8/",
|
||||||
|
"title": "pewcode"
|
||||||
|
}, {
|
||||||
|
"atime": 23456789012,
|
||||||
|
"ctime": 12345789235,
|
||||||
|
"href": "/pad/#/1/edit/a798u+miu2tg5b-QaP9SvA/UIPoGUPewZscBUFhNIi+eBBM/",
|
||||||
|
"title": "pewpad"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
var todo = function () {
|
||||||
|
fo.fixFiles();
|
||||||
|
if (files['CryptPad_RECENTPADS'] || !files.filesData) {
|
||||||
|
console.log("DRIVE2: migration from RECENTPADS to filesData failed");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (!files.template) {
|
||||||
|
console.log("DRIVE2: template is missing");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (files.unsorted) {
|
||||||
|
console.log("DRIVE2: unsorted not removed");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
var fileKey = Object.keys(files.root.Folder2)[0];
|
||||||
|
var fileKey2 = Object.keys(files.root).filter(function (x) {
|
||||||
|
return typeof files.root[x] === "number";
|
||||||
|
})[0];
|
||||||
|
if (!fileKey || !fileKey2) { return cb(); }
|
||||||
|
var fileId = files.root.Folder2[fileKey];
|
||||||
|
var fileId2 = files.root[fileKey2];
|
||||||
|
var res = typeof fileId === "number"
|
||||||
|
&& typeof files.filesData[fileId] === "object"
|
||||||
|
&& files.filesData[fileId].filename === "FileName"
|
||||||
|
&& typeof fileId2 === "number"
|
||||||
|
&& typeof files.filesData[fileId2] === "object"
|
||||||
|
&& !files.filesData[fileId2].filename;
|
||||||
|
return cb(res);
|
||||||
|
};
|
||||||
|
fo.migrate(todo);
|
||||||
|
}, "DRIVE2: migration and fixFiles with unsorted");
|
||||||
|
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START DRIVE3');
|
||||||
|
var files = {
|
||||||
|
"root": {
|
||||||
|
"Folder": {},
|
||||||
|
"Folder2": {
|
||||||
|
"FileName": href1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": [href3],
|
||||||
|
"trash": {
|
||||||
|
"DeletedF": [{
|
||||||
|
"path": ["root"],
|
||||||
|
"element": { "Trash": href4 }
|
||||||
|
}, {
|
||||||
|
"path": ["root", "Folder"],
|
||||||
|
"element": href2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"CryptPad_RECENTPADS": []
|
||||||
|
};
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
var todo = function () {
|
||||||
|
fo.fixFiles();
|
||||||
|
if (files['CryptPad_RECENTPADS'] || !files.filesData) {
|
||||||
|
console.log("DRIVE2: migration from RECENTPADS to filesData failed");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
var fileKey = Object.keys(files.root.Folder2)[0];
|
||||||
|
var fileKey2 = Object.keys(files.trash.DeletedF[0].element)[0];
|
||||||
|
if (!fileKey || !fileKey2) { return cb(); }
|
||||||
|
var fileId = files.root.Folder2[fileKey];
|
||||||
|
var fileId2 = files.trash.DeletedF[0].element[fileKey2];
|
||||||
|
var res = typeof fileId === "number"
|
||||||
|
&& typeof files.filesData[fileId] === "object"
|
||||||
|
&& files.filesData[fileId].filename === "FileName"
|
||||||
|
&& files.filesData[fileId].href === href1
|
||||||
|
&& typeof files.trash.DeletedF[1].element === "number"
|
||||||
|
&& typeof files.filesData[files.trash.DeletedF[1].element] === "object"
|
||||||
|
&& files.filesData[files.trash.DeletedF[1].element].filename === "DeletedF"
|
||||||
|
&& files.filesData[files.trash.DeletedF[1].element].href === href2
|
||||||
|
&& typeof files.template[0] === "number"
|
||||||
|
&& typeof files.filesData[files.template[0]] === "object"
|
||||||
|
&& !files.filesData[files.template[0]].filename
|
||||||
|
&& !files.filesData[files.template[0]].href
|
||||||
|
&& files.filesData[files.template[0]].roHref === href3
|
||||||
|
&& typeof fileId2 === "number"
|
||||||
|
&& typeof files.filesData[fileId2] === "object"
|
||||||
|
&& files.filesData[fileId2].filename === "Trash"
|
||||||
|
&& files.filesData[fileId2].href === href4;
|
||||||
|
return cb(res);
|
||||||
|
};
|
||||||
|
fo.migrate(todo);
|
||||||
|
}, "DRIVE4: migration and fixFiles with a pad in trash not root");
|
||||||
|
|
||||||
|
// Pad attributes migration
|
||||||
|
/*
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START PAD ATTRIBUTES');
|
||||||
|
var files = JSON.parse(JSON.stringify(example));
|
||||||
|
files[href1.slice(6) + '.userid'] = 'value';
|
||||||
|
files[href1.slice(6) + '.previewMode'] = true;
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
fo.fixFiles();
|
||||||
|
return cb(files.filesData[id1].userid === 'value'
|
||||||
|
&& files.filesData[id1].previewMode);
|
||||||
|
}, "PAD ATTRIBUTES");
|
||||||
|
*/
|
||||||
|
|
||||||
|
// userObject Tests
|
||||||
|
|
||||||
|
// UTILS
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START DRIVE utils');
|
||||||
|
var files = JSON.parse(JSON.stringify(example));
|
||||||
|
|
||||||
|
var href6 = "/pad/#67a9385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyGbj7LNy/";
|
||||||
|
var id6 = 1000000000006;
|
||||||
|
var data = {
|
||||||
|
href: href6,
|
||||||
|
title: 'Title6',
|
||||||
|
atime: +new Date(),
|
||||||
|
ctime: +new Date()
|
||||||
|
};
|
||||||
|
files.filesData[id6] = data;
|
||||||
|
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
fo.fixFiles();
|
||||||
|
|
||||||
|
|
||||||
|
if (fo.isFile({}) || fo.isFile(href1) || !fo.isFile(href1, true) || !fo.isFile(id1)) {
|
||||||
|
console.log("DRIVE utils: isFile returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.isReadOnlyFile(id1)) {
|
||||||
|
console.log("DRIVE utils: isReadOnlyFile returns true for an 'edit' file");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (!fo.isReadOnlyFile(id3)) {
|
||||||
|
console.log("DRIVE utils: isReadOnlyFile returns false for a 'view' file");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (typeof fo.isReadOnlyFile(id6) !== "undefined") {
|
||||||
|
console.log("DRIVE utils: isReadOnlyFile should return undefined for a v0 hash");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (!fo.hasSubfolder(files.root.Folder) || fo.hasSubfolder(files.root.Folder2)) {
|
||||||
|
console.log("DRIVE utils: hasSubfolder returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.hasFile(files.root.Folder) || !fo.hasFile(files.root.Folder2)) {
|
||||||
|
console.log("DRIVE utils: hasFile returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (JSON.stringify(fo.getFileData(id1)) !== JSON.stringify(files.filesData[id1])) {
|
||||||
|
console.log("DRIVE utils: getFileData returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.getTitle(id4) !== "Title4" || fo.getTitle(id1) !== "FileName1") {
|
||||||
|
console.log("DRIVE utils: getTitle returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.find(["root", "Folder2", "rdmStrFile1"]) !== id1) {
|
||||||
|
console.log("DRIVE utils: 'find' returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.getFiles().length !== 5 || fo.getFiles(['trash']).length !== 2) {
|
||||||
|
console.log("DRIVE utils: getFiles returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.findFile(id4).length !== 1 || fo.findFile(id4)[0].length !== 4) {
|
||||||
|
console.log("DRIVE utils: findFile returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (fo.search('tle2').length !== 1 || fo.search('tle2')[0].data.href !== href2 || fo.search('tle2')[0].paths[0][0] !== 'template') {
|
||||||
|
console.log("DRIVE utils: search returns an incorrect value");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(true);
|
||||||
|
}, "DRIVE utils");
|
||||||
|
|
||||||
|
// OPERATIONS
|
||||||
|
assert(function (cb) {
|
||||||
|
console.log('START DRIVE operations');
|
||||||
|
var files = JSON.parse(JSON.stringify(example));
|
||||||
|
var fo = FO.init(files, config);
|
||||||
|
fo.fixFiles();
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
href: href5,
|
||||||
|
title: 'Title5',
|
||||||
|
atime: +new Date(),
|
||||||
|
ctime: +new Date()
|
||||||
|
};
|
||||||
|
var res;
|
||||||
|
var id5;
|
||||||
|
// pushData is synchronous in test mode (no pinning)
|
||||||
|
fo.pushData(data, function (e, id) {
|
||||||
|
fo.add(id, ["root", "Folder"]);
|
||||||
|
id5 = id;
|
||||||
|
res = JSON.stringify(data) === JSON.stringify(fo.getFileData(id)) &&
|
||||||
|
fo.getFiles(["root"]).indexOf(id) !== -1;
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
console.log("DRIVE operations: pushData");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.move([["root", "Folder"], ["template", 0]], ["trash"]);
|
||||||
|
if (fo.getFiles(["template"]).indexOf(id2) !== -1 ||
|
||||||
|
fo.getFiles(["trash"]).indexOf(id5) === -1) {
|
||||||
|
console.log("DRIVE operations: move");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.restore(["trash", "Title2", 0, "element"]);
|
||||||
|
if (files["template"][0] !== id2 || fo.getFiles(['trash']).indexOf(id2) !== -1) {
|
||||||
|
console.log("DRIVE operations: restore");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
files["template"] = [];
|
||||||
|
fo.add(id2, ["template"]);
|
||||||
|
if (fo.getFiles(['template']).indexOf(id2) === -1) {
|
||||||
|
console.log("DRIVE operations");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
var path;
|
||||||
|
fo.addFolder(["root", "Folder2"], "subsub", function (o) { path = o.newPath; });
|
||||||
|
if (!files.root.Folder2.subsub || path.length !== 3) {
|
||||||
|
console.log("DRIVE operations: add folder");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.forget(href2);
|
||||||
|
if (files["template"].length !== 0 || fo.getFiles(['trash']).indexOf(id2) === -1) {
|
||||||
|
console.log("DRIVE operations: forget");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.restore(["trash", "Title2", 0, "element"]);
|
||||||
|
fo.delete([["root", "Folder2", "subsub"],["template",0]]);
|
||||||
|
if (files.root.Folder2.subsub || fo.getFiles().indexOf(id2) !== -1) {
|
||||||
|
console.log("DRIVE operations: delete");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.emptyTrash();
|
||||||
|
if (JSON.stringify(files.trash) !== "{}" || fo.getFiles().indexOf(id5) !== -1 ||
|
||||||
|
files.filesData[id5]) {
|
||||||
|
console.log("DRIVE operations: emptyTrash");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
fo.rename(["root", "Folder2"], "FolderNew");
|
||||||
|
fo.rename(["root", "FolderNew", "rdmStrFile1"], "NewFileName1");
|
||||||
|
if (files.root.Folder2 || !files.root.FolderNew ||
|
||||||
|
fo.getFileData(id1).filename !== "NewFileName1" ||
|
||||||
|
fo.getTitle(id1) !== "NewFileName1") {
|
||||||
|
console.log("DRIVE operations: rename");
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(true);
|
||||||
|
}, "DRIVE operations");
|
||||||
|
};
|
||||||
|
|
||||||
|
return module;
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user