From 306fc6cdb94638b2d812eb5ab1dee6392d1ea268 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 12 Sep 2019 17:54:50 +0200 Subject: [PATCH] Create and store pads in a team --- .../src/less2/include/creation.less | 12 ++++ www/common/common-constants.js | 1 + www/common/common-ui-elements.js | 69 ++++++++++++++++++- www/common/cryptpad-common.js | 15 ++++ www/common/drive-ui.js | 14 +++- www/common/outer/async-store.js | 4 +- www/common/outer/team.js | 10 +++ www/common/sframe-common-outer.js | 15 +++- www/common/sframe-common.js | 1 + www/team/inner.js | 11 +-- 10 files changed, 139 insertions(+), 13 deletions(-) diff --git a/customize.dist/src/less2/include/creation.less b/customize.dist/src/less2/include/creation.less index e5c71a3db..281e15e44 100644 --- a/customize.dist/src/less2/include/creation.less +++ b/customize.dist/src/less2/include/creation.less @@ -175,6 +175,18 @@ color: @colortheme_form-color; } + .cp-creation-team { + .cp-dropdown-container { + flex: 1; + min-width: 0; + margin-left: 10px; + margin-right: 10px; + button, .cp-dropdown-content { + width: 100%; + } + } + } + .cp-creation-expire { .cp-creation-expire-picker { text-align: center; diff --git a/www/common/common-constants.js b/www/common/common-constants.js index ac51dfbca..752298841 100644 --- a/www/common/common-constants.js +++ b/www/common/common-constants.js @@ -7,6 +7,7 @@ define(function () { fileHashKey: 'FS_hash', // sessionStorage newPadPathKey: "newPadPath", + newPadTeamKey: "newPadTeam", newPadFileData: "newPadFileData", // Store displayNameKey: 'cryptpad.username', diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 13783c67b..0e5fd4a46 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2652,7 +2652,6 @@ define([ var type = metadataMgr.getMetadataLazy().type; var fromFileData = privateData.fromFileData; - var $body = $('body'); var $creationContainer = $('
', { id: 'cp-creation-container' }).appendTo($body); var urlArgs = (Config.requireConf && Config.requireConf.urlArgs) || ''; @@ -2685,6 +2684,64 @@ define([ return q; }; + // Team pad + var team; + var teamExists = privateData.teams && Object.keys(privateData.teams).length; + var $teamBlock; + // storeInTeam can be + // * a team ID ==> store in the team drive, and the team will be the owner + // * -1 ==> store in the user drive, and the user will be the owner + // * undefined ==> ask + if (teamExists) { + var teamOptions = Object.keys(privateData.teams).map(function (teamId) { + var t = privateData.teams[teamId]; + return { + tag: 'a', + attributes: { + 'data-value': teamId, + 'href': '#' + }, + content: 'TEAM: ' + t.name + '' // XXX + }; + }); + teamOptions.unshift({ + tag: 'a', + attributes: { + 'data-value': '-1', + 'href': '#' + }, + content: Messages.settings_cat_drive + }); + teamOptions.unshift({ + tag: 'a', + attributes: { + 'data-value': '', + 'href': '#' + }, + content: ' ' + }); + var teamDropdownConfig = { + text: " ", // Button initial text + options: teamOptions, // Entries displayed in the menu + isSelect: true, + common: common + }; + $teamBlock = UIElements.createDropdown(teamDropdownConfig); + $teamBlock.find('a').click(function () { + var id = $(this).attr('data-value'); + $teamBlock.setValue(id); + }); + team = h('div.cp-creation-team', [ + 'Store in', // XXX + $teamBlock[0], + createHelper('#', "The pad will be stored in your team's drive. If this is an owned pad, it will be owned by the team.") // XXX + ]); + if (privateData.storeInTeam) { + $teamBlock.setValue(privateData.storeInTeam); + } + } + + // Owned pads // Default is Owned pad var owned = h('div.cp-creation-owned', [ @@ -2749,6 +2806,7 @@ define([ var $create = $(createDiv); $(h('div#cp-creation-form', [ + team, owned, expire, password, @@ -2954,12 +3012,19 @@ define([ var $template = $creation.find('.cp-creation-template-selected'); var templateId = $template.data('id') || undefined; + // Team + var team; + if ($teamBlock && $teamBlock.getValue()) { + team = privateData.teams[$teamBlock.getValue()] || {}; + team.id = Number($teamBlock.getValue()); + } return { owned: ownedVal, password: passwordVal, expire: expireVal, - templateId: templateId + templateId: templateId, + team: team }; }; var create = function () { diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index dab1b37f4..09b18f707 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -660,6 +660,16 @@ define([ if (typeof (data.title) !== "string") { return cb('Missing title'); } + if (common.initialTeam) { + // If the value is -1, it means the user drive was selected from the pad creation screen + // If the value is a positive Integer, force save in the team with the selected ID + if (common.initialTeam !== -1) { + // Team selected from the PCS or pad created from a team drive + data.teamId = common.initialTeam; + } + data.forceSave = 1; + delete common.initialTeam; + } if (common.initialPath) { if (!data.path) { data.path = Array.isArray(common.initialPath) ? common.initialPath @@ -1410,6 +1420,11 @@ define([ delete sessionStorage[Constants.newPadPathKey]; } + if (sessionStorage[Constants.newPadTeamKey]) { + common.initialTeam = sessionStorage[Constants.newPadTeamKey]; + delete sessionStorage[Constants.newPadTeamKey]; + } + var channelIsReady = waitFor(); var msgEv = Util.mkEvent(); diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index c4f69d27a..0d852c76a 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -2243,6 +2243,7 @@ define([ var arr = []; AppConfig.availablePadTypes.forEach(function (type) { if (type === 'drive') { return; } + if (type === 'team') { return; } if (type === 'contacts') { return; } if (type === 'todo') { return; } if (type === 'file') { return; } @@ -2392,7 +2393,10 @@ define([ .click(function () { var type = $(this).attr('data-type') || 'pad'; var path = manager.isPathIn(currentPath, [TRASH]) ? '' : currentPath; - common.sessionStorage.put(Constants.newPadPathKey, path, function () { + nThen(function (waitFor) { + common.sessionStorage.put(Constants.newPadPathKey, path, waitFor()); + common.sessionStorage.put(Constants.newPadTeamKey, APP.team, waitFor()); + }).nThen(function () { common.openURL('/' + type + '/'); }); }); @@ -3830,6 +3834,7 @@ define([ nThen(function (waitFor) { common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(simpleData), waitFor()); common.sessionStorage.put(Constants.newPadPathKey, currentPath, waitFor()); + common.sessionStorage.put(Constants.newPadTeamKey, APP.team, waitFor()); }).nThen(function () { common.openURL('/code/'); }); @@ -4020,7 +4025,10 @@ define([ else if ($this.hasClass("cp-app-drive-context-newdoc")) { var ntype = $this.data('type') || 'pad'; var path2 = manager.isPathIn(currentPath, [TRASH]) ? '' : currentPath; - common.sessionStorage.put(Constants.newPadPathKey, path2, function () { + nThen(function (waitFor) { + common.sessionStorage.put(Constants.newPadPathKey, path2, waitFor()); + common.sessionStorage.put(Constants.newPadTeamKey, APP.team, waitFor()); + }).nThen(function () { common.openURL('/' + ntype + '/'); }); } @@ -4312,7 +4320,7 @@ define([ refresh(); UI.removeLoadingScreen(); - if (!APP.isTeam) { + if (!APP.team) { sframeChan.query('Q_DRIVE_GETDELETED', null, function (err, data) { var ids = manager.findChannels(data); var titles = []; diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index e9a86fca5..03b263319 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -523,6 +523,7 @@ define([ // Get the metadata for sframe-common-outer Store.getMetadata = function (clientId, data, cb) { var disableThumbnails = Util.find(store.proxy, ['settings', 'general', 'disableThumbnails']); + var teams = store.modules['team'] && store.modules['team'].getTeamsData(); var metadata = { // "user" is shared with everybody via the userlist user: { @@ -544,7 +545,8 @@ define([ isDriveOwned: Boolean(Util.find(store, ['driveMetadata', 'owners'])), support: Util.find(store.proxy, ['mailboxes', 'support', 'channel']), pendingFriends: store.proxy.friends_pending || {}, - supportPrivateKey: Util.find(store.proxy, ['mailboxes', 'supportadmin', 'keys', 'curvePrivate']) + supportPrivateKey: Util.find(store.proxy, ['mailboxes', 'supportadmin', 'keys', 'curvePrivate']), + teams: teams } }; cb(JSON.parse(JSON.stringify(metadata))); diff --git a/www/common/outer/team.js b/www/common/outer/team.js index bcaa8ee1b..a683e9aaa 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -431,6 +431,16 @@ define([ team.getTeam = function (id) { return ctx.teams[id]; }; + team.getTeamsData = function () { + var t = {}; + Object.keys(teams).forEach(function (id) { + t[id] = { + name: teams[id].name, + edPublic: Util.find(teams[id], ['keys', 'edPublic']) + }; + }); + return t; + }; team.getTeams = function () { return Object.keys(ctx.teams); }; diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index ade5dcb72..7faa736d3 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -326,6 +326,7 @@ define([ fromFileData: Cryptpad.fromFileData ? { title: Cryptpad.fromFileData.title } : undefined, + storeInTeam: Cryptpad.initialTeam || (Cryptpad.initialPath ? -1 : undefined) }; if (window.CryptPad_newSharedFolder) { additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder; @@ -682,7 +683,11 @@ define([ }); sframeChan.on('Q_SESSIONSTORAGE_PUT', function (data, cb) { - sessionStorage[data.key] = data.value; + if (typeof (data.value) === "undefined") { + delete sessionStorage[data.key]; + } else { + sessionStorage[data.key] = data.value; + } cb(); }); @@ -1201,7 +1206,13 @@ define([ var rtConfig = { metadata: {} }; - if (data.owned) { + if (data.team) { + Cryptpad.initialTeam = data.team.id; + } + if (data.owned && data.team && data.team.edPublic) { + rtConfig.metadata.owners = [data.team.edPublic]; + // XXX Teams mailbox + } else if (data.owned) { rtConfig.metadata.owners = [edPublic]; rtConfig.metadata.mailbox = {}; rtConfig.metadata.mailbox[edPublic] = Utils.crypto.encrypt(JSON.stringify({ diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 2ac9bb07f..57571b6b0 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -297,6 +297,7 @@ define([ owned: cfg.owned, expire: cfg.expire, password: cfg.password, + team: cfg.team, template: cfg.template, templateId: cfg.templateId }, cb); diff --git a/www/team/inner.js b/www/team/inner.js index a5acee042..d39bc2fc7 100644 --- a/www/team/inner.js +++ b/www/team/inner.js @@ -30,9 +30,7 @@ define([ Messages) { var APP = {}; - var driveAPP = { - isTeam: true - }; + var driveAPP = {}; //var SHARED_FOLDER_NAME = Messages.fm_sharedFolderName; var copyObjectValue = function (objRef, objToCopy) { @@ -91,6 +89,7 @@ define([ APP.module.execCommand('SUBSCRIBE', null, function () { sframeChan.query('Q_SET_TEAM', null, function (err) { if (err) { return void console.error(err); } + APP.team = null; APP.buildUI(common); }); }); @@ -184,7 +183,7 @@ define([ // Team APP - var loadTeam = function (common, firstLoad) { + var loadTeam = function (common, id, firstLoad) { var sframeChan = common.getSframeChannel(); var proxy = {}; var folders = {}; @@ -199,6 +198,7 @@ define([ if (!proxy.drive || typeof(proxy.drive) !== 'object') { throw new Error("Corrupted drive"); } + driveAPP.team = id; var drive = DriveUI.create(common, { proxy: proxy, folders: folders, @@ -255,6 +255,7 @@ define([ APP.module.execCommand('SUBSCRIBE', id, function () { sframeChan.query('Q_SET_TEAM', id, function (err) { if (err) { return void console.error(err); } + APP.team = id; buildUI(common, true); }); }); @@ -322,7 +323,7 @@ define([ ]; UI.addLoadingScreen(); cb(content); - loadTeam(common, false); + loadTeam(common, APP.team, false); });