Export team drive content

pull/1/head
yflory 4 years ago
parent 5c4e2bbfb4
commit 5bd09fe5d2

@ -0,0 +1,89 @@
.export_main() {
#cp-export-container {
font-size: 16px;
display: flex;
flex: 1;
min-height: 0;
align-items: center;
justify-content: center;
.cp-export-block {
width: 800px;
max-width: 90vw;
.cp-export-progress-bar-container {
height: 24px;
background: white;
border: 1px solid #DDD;
width: 80%;
margin: auto;
position: relative;
.cp-export-progress-bar {
height: 100%;
background: #5cb85c; // Same color as loading screen bar
width: 0%;
display: inline-block;
}
.cp-export-progress-text {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
text-align: center;
font-weight: bold;
}
}
& > p {
color: #777;
}
.cp-export-progress {
margin-bottom: 1rem;
p {
margin-bottom: 0;
display: flex;
align-items: center;
padding: 5px 0;
.fa {
width: 25px;
}
}
}
.cp-export-actions {
display: flex;
flex-flow: row-reverse;
.btn-default, .btn-primary {
margin-left: 20px;
}
}
.cp-export-errors {
display: none;
overflow-x: auto;
max-height: 300px;
background: #ededed;
border: 1px solid #777;
padding: 5px 20px;
margin-top: 1rem;
& > p {
margin: 0;
}
.cp-export-errors-list {
& > div {
padding: 5px 10px;
margin: 5px 0;
background: #dedede;
.title {
font-weight: bold;
}
.link {
padding: 0 20px;
font-size: 14px;
}
.reason {
padding: 0 20px;
color: #777;
}
}
}
}
}
}
}

@ -1,13 +1,17 @@
define([ define([
'jquery',
'/common/cryptget.js', '/common/cryptget.js',
'/file/file-crypto.js', '/file/file-crypto.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-interface.js',
'/common/hyperscript.js',
'/common/common-feedback.js',
'/customize/messages.js', '/customize/messages.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/bower_components/saferphore/index.js', '/bower_components/saferphore/index.js',
'/bower_components/jszip/dist/jszip.min.js', '/bower_components/jszip/dist/jszip.min.js',
], function (Crypt, FileCrypto, Hash, Util, Messages, nThen, Saferphore, JsZip) { ], function ($, Crypt, FileCrypto, Hash, Util, UI, h, Feedback, Messages, nThen, Saferphore, JsZip) {
var saveAs = window.saveAs; var saveAs = window.saveAs;
var sanitize = function (str) { var sanitize = function (str) {
@ -257,7 +261,7 @@ define([
} }
if (ctx.data.sharedFolders[el]) { // if shared folder if (ctx.data.sharedFolders[el]) { // if shared folder
var sfData = ctx.sf[el].metadata; var sfData = ctx.sf[el].metadata;
var sfName = getUnique(sanitize(sfData.title || 'Folder'), '', existingNames); var sfName = getUnique(sanitize((sfData && sfData.title) || 'Folder'), '', existingNames);
existingNames.push(sfName.toLowerCase()); existingNames.push(sfName.toLowerCase());
return void makeFolder(ctx, ctx.sf[el].root, zip.folder(sfName), ctx.sf[el].filesData); return void makeFolder(ctx, ctx.sf[el].root, zip.folder(sfName), ctx.sf[el].filesData);
} }
@ -334,9 +338,149 @@ define([
}); });
}; };
var createExportUI = function (origin) {
var progress = h('div.cp-export-progress');
var actions = h('div.cp-export-actions');
var errors = h('div.cp-export-errors', [
h('p', Messages.settings_exportErrorDescription)
]);
var exportUI = h('div#cp-export-container', [
h('div.cp-export-block', [
h('h3', Messages.settings_exportTitle),
h('p', [
Messages.settings_exportDescription,
h('br'),
Messages.settings_exportFailed,
h('br'),
h('strong', Messages.settings_exportWarning),
]),
progress,
actions,
errors
])
]);
$('body').append(exportUI);
$('#cp-sidebarlayout-container').hide();
var close = function() {
$(exportUI).remove();
$('#cp-sidebarlayout-container').show();
};
var _onCancel = [];
var onCancel = function(h) {
if (typeof(h) !== "function") { return; }
_onCancel.push(h);
};
var cancel = h('button.btn.btn-default', Messages.cancel);
$(cancel).click(function() {
UI.confirm(Messages.settings_exportCancel, function(yes) {
if (!yes) { return; }
Feedback.send('FULL_DRIVE_EXPORT_CANCEL');
_onCancel.forEach(function(h) { h(); });
});
}).appendTo(actions);
var error = h('button.btn.btn-danger', Messages.settings_exportError);
var translateErrors = function(err) {
if (err === 'EEMPTY') {
return Messages.settings_exportErrorEmpty;
}
if (['E404', 'EEXPIRED', 'EDELETED'].indexOf(err) !== -1) {
return Messages.settings_exportErrorMissing;
}
return Messages._getKey('settings_exportErrorOther', [err]);
};
var addErrors = function(errs) {
if (!errs.length) { return; }
var onClick = function() {
console.error('clicked?');
$(errors).toggle();
};
$(error).click(onClick).appendTo(actions);
var list = h('div.cp-export-errors-list');
$(list).appendTo(errors);
errs.forEach(function(err) {
if (!err.data) { return; }
var href = (err.data.href && err.data.href.indexOf('#') !== -1) ? err.data.href : err.data.roHref;
$(h('div', [
h('div.title', err.data.filename || err.data.title),
h('div.link', [
h('a', {
href: href,
target: '_blank'
}, origin + href)
]),
h('div.reason', translateErrors(err.error))
])).appendTo(list);
});
};
var download = h('button.btn.btn-primary', Messages.download_mt_button);
var completed = false;
var complete = function(h, err) {
if (completed) { return; }
completed = true;
$(progress).find('.fa-square-o').removeClass('fa-square-o')
.addClass('fa-check-square-o');
$(cancel).text(Messages.filePicker_close).off('click').click(function() {
_onCancel.forEach(function(h) { h(); });
});
$(download).click(h).appendTo(actions);
addErrors(err);
};
var done = {};
var update = function(step, state) {
console.log(step, state);
console.log(done[step]);
if (done[step] && done[step] === -1) { return; }
// New step
if (!done[step]) {
$(progress).find('.fa-square-o').removeClass('fa-square-o')
.addClass('fa-check-square-o');
$(progress).append(h('p', [
h('span.fa.fa-square-o'),
h('span.text', Messages['settings_export_' + step] || step)
]));
done[step] = state; // -1 if no bar, object otherwise
if (state !== -1) {
var bar = h('div.cp-export-progress-bar');
$(progress).append(h('div.cp-export-progress-bar-container', [
bar
]));
done[step] = { bar: bar };
}
return;
}
// Updating existing step
if (typeof state !== "object") { return; }
var b = done[step].bar;
var w = (state.current / state.max) * 100;
$(b).css('width', w + '%');
if (!done[step].text) {
done[step].text = h('div.cp-export-progress-text');
$(done[step].text).appendTo(b);
}
$(done[step].text).text(state.current + ' / ' + state.max);
if (state.current === state.max) { done[step] = -1; }
};
return {
close: close,
update: update,
complete: complete,
onCancel: onCancel
};
};
return { return {
create: create, create: create,
createExportUI: createExportUI,
downloadFile: _downloadFile, downloadFile: _downloadFile,
downloadPad: _downloadPad, downloadPad: _downloadPad,
downloadFolder: _downloadFolder, downloadFolder: _downloadFolder,

@ -2,6 +2,7 @@
@import (reference) "../../customize/src/less2/include/limit-bar.less"; @import (reference) "../../customize/src/less2/include/limit-bar.less";
@import (reference) "../../customize/src/less2/include/creation.less"; @import (reference) "../../customize/src/less2/include/creation.less";
@import (reference) '../../customize/src/less2/include/framework.less'; @import (reference) '../../customize/src/less2/include/framework.less';
@import (reference) '../../customize/src/less2/include/export.less';
&.cp-app-settings { &.cp-app-settings {
.framework_min_main( .framework_min_main(
@ -26,93 +27,7 @@
padding: 10px; padding: 10px;
} }
#cp-export-container { .export_main();
font-size: 16px;
display: flex;
flex: 1;
min-height: 0;
align-items: center;
justify-content: center;
.cp-export-block {
width: 800px;
max-width: 90vw;
.cp-export-progress-bar-container {
height: 24px;
background: white;
border: 1px solid #DDD;
width: 80%;
margin: auto;
position: relative;
.cp-export-progress-bar {
height: 100%;
background: #5cb85c; // Same color as loading screen bar
width: 0%;
display: inline-block;
}
.cp-export-progress-text {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
text-align: center;
font-weight: bold;
}
}
& > p {
color: #777;
}
.cp-export-progress {
margin-bottom: 1rem;
p {
margin-bottom: 0;
display: flex;
align-items: center;
padding: 5px 0;
.fa {
width: 25px;
}
}
}
.cp-export-actions {
display: flex;
flex-flow: row-reverse;
.btn-default, .btn-primary {
margin-left: 20px;
}
}
.cp-export-errors {
display: none;
overflow-x: auto;
max-height: 300px;
background: #ededed;
border: 1px solid #777;
padding: 5px 20px;
margin-top: 1rem;
& > p {
margin: 0;
}
.cp-export-errors-list {
& > div {
padding: 5px 10px;
margin: 5px 0;
background: #dedede;
.title {
font-weight: bold;
}
.link {
padding: 0 20px;
font-size: 14px;
}
.reason {
padding: 0 20px;
color: #777;
}
}
}
}
}
}
#cp-sidebarlayout-container { #cp-sidebarlayout-container {
#cp-sidebarlayout-rightside { #cp-sidebarlayout-rightside {

@ -717,145 +717,6 @@ define([
}; };
var createExportUI = function() {
var progress = h('div.cp-export-progress');
var actions = h('div.cp-export-actions');
var errors = h('div.cp-export-errors', [
h('p', Messages.settings_exportErrorDescription)
]);
var exportUI = h('div#cp-export-container', [
h('div.cp-export-block', [
h('h3', Messages.settings_exportTitle),
h('p', [
Messages.settings_exportDescription,
h('br'),
Messages.settings_exportFailed,
h('br'),
h('strong', Messages.settings_exportWarning),
]),
progress,
actions,
errors
])
]);
$('body').append(exportUI);
$('#cp-sidebarlayout-container').hide();
var close = function() {
$(exportUI).remove();
$('#cp-sidebarlayout-container').show();
};
var _onCancel = [];
var onCancel = function(h) {
if (typeof(h) !== "function") { return; }
_onCancel.push(h);
};
var cancel = h('button.btn.btn-default', Messages.cancel);
$(cancel).click(function() {
UI.confirm(Messages.settings_exportCancel, function(yes) {
if (!yes) { return; }
Feedback.send('FULL_DRIVE_EXPORT_CANCEL');
_onCancel.forEach(function(h) { h(); });
});
}).appendTo(actions);
var error = h('button.btn.btn-danger', Messages.settings_exportError);
var translateErrors = function(err) {
if (err === 'EEMPTY') {
return Messages.settings_exportErrorEmpty;
}
if (['E404', 'EEXPIRED', 'EDELETED'].indexOf(err) !== -1) {
return Messages.settings_exportErrorMissing;
}
return Messages._getKey('settings_exportErrorOther', [err]);
};
var addErrors = function(errs) {
if (!errs.length) { return; }
var onClick = function() {
console.error('clicked?');
$(errors).toggle();
};
$(error).click(onClick).appendTo(actions);
var list = h('div.cp-export-errors-list');
$(list).appendTo(errors);
errs.forEach(function(err) {
if (!err.data) { return; }
var href = (err.data.href && err.data.href.indexOf('#') !== -1) ? err.data.href : err.data.roHref;
$(h('div', [
h('div.title', err.data.filename || err.data.title),
h('div.link', [
h('a', {
href: href,
target: '_blank'
}, privateData.origin + href)
]),
h('div.reason', translateErrors(err.error))
])).appendTo(list);
});
};
var download = h('button.btn.btn-primary', Messages.download_mt_button);
var completed = false;
var complete = function(h, err) {
if (completed) { return; }
completed = true;
$(progress).find('.fa-square-o').removeClass('fa-square-o')
.addClass('fa-check-square-o');
$(cancel).text(Messages.filePicker_close).off('click').click(function() {
_onCancel.forEach(function(h) { h(); });
});
$(download).click(h).appendTo(actions);
addErrors(err);
};
var done = {};
var update = function(step, state) {
console.log(step, state);
console.log(done[step]);
if (done[step] && done[step] === -1) { return; }
// New step
if (!done[step]) {
$(progress).find('.fa-square-o').removeClass('fa-square-o')
.addClass('fa-check-square-o');
$(progress).append(h('p', [
h('span.fa.fa-square-o'),
h('span.text', Messages['settings_export_' + step] || step)
]));
done[step] = state; // -1 if no bar, object otherwise
if (state !== -1) {
var bar = h('div.cp-export-progress-bar');
$(progress).append(h('div.cp-export-progress-bar-container', [
bar
]));
done[step] = { bar: bar };
}
return;
}
// Updating existing step
if (typeof state !== "object") { return; }
var b = done[step].bar;
var w = (state.current / state.max) * 100;
$(b).css('width', w + '%');
if (!done[step].text) {
done[step].text = h('div.cp-export-progress-text');
$(done[step].text).appendTo(b);
}
$(done[step].text).text(state.current + ' / ' + state.max);
if (state.current === state.max) { done[step] = -1; }
};
return {
close: close,
update: update,
complete: complete,
onCancel: onCancel
};
};
create['drive-backup'] = function() { create['drive-backup'] = function() {
var $div = $('<div>', { 'class': 'cp-settings-drive-backup cp-sidebarlayout-element' }); var $div = $('<div>', { 'class': 'cp-settings-drive-backup cp-sidebarlayout-element' });
@ -907,7 +768,7 @@ define([
var exportDrive = function() { var exportDrive = function() {
Feedback.send('FULL_DRIVE_EXPORT_START'); Feedback.send('FULL_DRIVE_EXPORT_START');
var todo = function(data, filename) { var todo = function(data, filename) {
var ui = createExportUI(); var ui = Backup.createExportUI(privateData.origin);
var bu = Backup.create(data, common.getPad, privateData.fileHost, function(blob, errors) { var bu = Backup.create(data, common.getPad, privateData.fileHost, function(blob, errors) {
saveAs(blob, filename); saveAs(blob, filename);

@ -4,6 +4,7 @@
@import (reference) '../../customize/src/less2/include/sidebar-layout.less'; @import (reference) '../../customize/src/less2/include/sidebar-layout.less';
@import (reference) "../../customize/src/less2/include/tools.less"; @import (reference) "../../customize/src/less2/include/tools.less";
@import (reference) "../../customize/src/less2/include/colortheme.less"; @import (reference) "../../customize/src/less2/include/colortheme.less";
@import (reference) '../../customize/src/less2/include/export.less';
&.cp-app-team { &.cp-app-team {
@ -19,6 +20,8 @@
@roster-bg-color: #efefef; @roster-bg-color: #efefef;
.export_main();
#cp-sidebarlayout-container { #cp-sidebarlayout-container {
@media screen and (max-width: 900px) { @media screen and (max-width: 900px) {
.cp-app-drive-toolbar-leftside { .cp-app-drive-toolbar-leftside {

@ -17,8 +17,10 @@ define([
'/customize/application_config.js', '/customize/application_config.js',
'/common/messenger-ui.js', '/common/messenger-ui.js',
'/common/inner/invitation.js', '/common/inner/invitation.js',
'/common/make-backup.js',
'/customize/messages.js', '/customize/messages.js',
'/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/teams/app-team.less', 'less!/teams/app-team.less',
@ -41,10 +43,12 @@ define([
AppConfig, AppConfig,
MessengerUI, MessengerUI,
InviteInner, InviteInner,
Backup,
Messages) Messages)
{ {
var APP = {}; var APP = {};
var driveAPP = {}; var driveAPP = {};
var saveAs = window.saveAs;
//var SHARED_FOLDER_NAME = Messages.fm_sharedFolderName; //var SHARED_FOLDER_NAME = Messages.fm_sharedFolderName;
var copyObjectValue = function (objRef, objToCopy) { var copyObjectValue = function (objRef, objToCopy) {
@ -169,6 +173,7 @@ define([
'cp-team-edpublic', 'cp-team-edpublic',
'cp-team-name', 'cp-team-name',
'cp-team-avatar', 'cp-team-avatar',
'cp-team-export',
'cp-team-delete', 'cp-team-delete',
], ],
}; };
@ -1026,6 +1031,51 @@ define([
}); });
}, true); }, true);
Messages.team_exportTitle = "Download team drive";
Messages.team_exportHint = "Download all the pads frm this team's drive in a readable format (when available).";
Messages.team_exportButton = "Download";
makeBlock('export', function (common, cb) {
// Backup all the pads
var sframeChan = common.getSframeChannel();
var privateData = common.getMetadataMgr().getPrivateData();
var team = privateData.teams[APP.team] || {};
var teamName = team.name || Messages.anonymous;
var exportDrive = function() {
Feedback.send('FULL_TEAMDRIVE_EXPORT_START');
var todo = function(data, filename) {
var ui = Backup.createExportUI(privateData.origin);
var bu = Backup.create(data, common.getPad, privateData.fileHost, function(blob, errors) {
saveAs(blob, filename);
sframeChan.event('EV_CRYPTGET_DISCONNECT');
ui.complete(function() {
Feedback.send('FULL_TEAMDRIVE_EXPORT_COMPLETE');
saveAs(blob, filename);
}, errors);
}, ui.update);
ui.onCancel(function() {
ui.close();
bu.stop();
});
};
sframeChan.query("Q_SETTINGS_DRIVE_GET", "full", function(err, data) {
if (err) { return void console.error(err); }
if (data.error) { return void console.error(data.error); }
var filename = teamName + '-' + new Date().toDateString() + '.zip';
todo(data, filename);
});
};
var button = h('button.btn.btn-primary', Messages.team_exportButton);
UI.confirmButton(button, {
classes: 'btn-primary',
multiple: true
}, function () {
exportDrive();
});
cb(button);
}, true);
makeBlock('delete', function (common, cb) { makeBlock('delete', function (common, cb) {
var deleteTeam = h('button.btn.btn-danger', Messages.team_deleteButton); var deleteTeam = h('button.btn.btn-danger', Messages.team_deleteButton);
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide(); var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide();

@ -46,7 +46,7 @@ define([
window.addEventListener('message', onMsg); window.addEventListener('message', onMsg);
}).nThen(function (/*waitFor*/) { }).nThen(function (/*waitFor*/) {
var teamId; var teamId;
var addRpc = function (sframeChan, Cryptpad) { var addRpc = function (sframeChan, Cryptpad, Utils) {
sframeChan.on('Q_SET_TEAM', function (data, cb) { sframeChan.on('Q_SET_TEAM', function (data, cb) {
teamId = data; teamId = data;
cb(); cb();
@ -91,6 +91,35 @@ define([
sframeChan.event('EV_NETWORK_DISCONNECT'); sframeChan.event('EV_NETWORK_DISCONNECT');
} }
}); });
sframeChan.on('Q_SETTINGS_DRIVE_GET', function (d, cb) {
Cryptpad.getUserObject(teamId, function (obj) {
if (obj.error) { return void cb(obj); }
if (d === "full") {
// We want shared folders too
var result = {
uo: obj,
sf: {}
};
if (!obj.drive || !obj.drive.sharedFolders) { return void cb(result); }
Utils.nThen(function (waitFor) {
Object.keys(obj.drive.sharedFolders).forEach(function (id) {
Cryptpad.getSharedFolder({
id: id,
teamId: teamId
}, waitFor(function (obj) {
result.sf[id] = obj;
}));
});
}).nThen(function () {
cb(result);
});
return;
}
// We want only the user object
cb(obj);
});
});
}; };
var getSecrets = function (Cryptpad, Utils, cb) { var getSecrets = function (Cryptpad, Utils, cb) {
var Hash = Utils.Hash; var Hash = Utils.Hash;

Loading…
Cancel
Save