diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index d1b360bdf..e337bd386 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -3245,6 +3245,11 @@ define([ if (!isVirtual && typeof(root) === "undefined") { log(Messages.fm_unknownFolderError); debug("Unable to locate the selected directory: ", path); + if (path.length === 1 && path[0] === ROOT) { + // Somehow we can't display ROOT. We should abort now because we'll + // end up in an infinite loop + return void UI.warn(Messages.fm_error_cantPin); // Internal server error, please reload... + } var parentPath = path.slice(); parentPath.pop(); _displayDirectory(parentPath, true); diff --git a/www/common/outer/team.js b/www/common/outer/team.js index c5f053266..af232d01d 100644 --- a/www/common/outer/team.js +++ b/www/common/outer/team.js @@ -38,7 +38,9 @@ define([ // Also pin the onlyoffice channels if they exist if (n.rtChannel) { toPin.push(n.rtChannel); } if (n.lastVersion) { toPin.push(n.lastVersion); } - team.pin(toPin, function (obj) { console.error(obj); }); + team.pin(toPin, function (obj) { + if (obj && obj.error) { console.error(obj.error); } + }); } // Unpin the deleted pads (deleted <=> changed to undefined) if (p[0] === UserObject.FILES_DATA && typeof(o) === "object" && o.channel && !n) { @@ -51,7 +53,9 @@ define([ // Also unpin the onlyoffice channels if they exist if (o.rtChannel) { toUnpin.push(o.rtChannel); } if (o.lastVersion) { toUnpin.push(o.lastVersion); } - team.unpin(toUnpin, function (obj) { console.error(obj); }); + team.unpin(toUnpin, function (obj) { + if (obj && obj.error) { console.error(obj); } + }); } } } @@ -692,7 +696,7 @@ define([ return true; } }); - if ((!member || member.role !== 'OWNER') && teamData.owner) { + if (!member && teamData.owner) { var removeOwnership = function (chan) { ctx.Store.setPadMetadata(null, { channel: chan, @@ -764,6 +768,7 @@ define([ var onError = function (res) { var err = res && res.error; if (err) { + console.error(err); waitFor.abort(); return void cb({error:err}); } @@ -822,6 +827,7 @@ define([ var onError = function (res) { var err = res && res.error; if (err) { + console.error(err); waitFor.abort(); return void cb(err); } diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index dbbadd86b..d585d6e02 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -1212,5 +1212,8 @@ "team_deleteTitle": "Suppression de l'équipe", "team_deleteHint": "Supprimer l'équipe et tous les documents dont elle est exclusivement propriétaire.", "team_deleteButton": "Supprimer", - "team_deleteConfirm": "Vous êtes sur le point de supprimer les données d'une équipe entière. Cette action peut impacter l'accès à leur données pour d'autres membres de l'équipe. La suppression est irréversible. Êtes-vous sûr de vouloir continuer ?" + "team_deleteConfirm": "Vous êtes sur le point de supprimer les données d'une équipe entière. Cette action peut impacter l'accès à leur données pour d'autres membres de l'équipe. La suppression est irréversible. Êtes-vous sûr de vouloir continuer ?", + "team_pendingOwner": "(en attente)", + "team_pendingOwnerTitle": "Cet administrateur n'a pas encore accepté l'offre de devenir propriétaire de l'équipe.", + "team_demoteMeConfirm": "Vous êtes sur le point de renoncer à vos droits. Vous ne serez pas en mesure d'annuler cette action. Continuer ?" } diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index 20525bc13..feab1a206 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1212,5 +1212,8 @@ "team_deleteTitle": "Team deletion", "team_deleteHint": "Delete the team and all documents owned exclusively by the team.", "team_deleteButton": "Delete", - "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?" + "team_deleteConfirm": "You are about to delete all of an entire team's data. This may impact other team members access to their data. This cannot be undone. Are you sure you want to proceed?", + "team_pendingOwner": "(pending)", + "team_pendingOwnerTitle": "This administrator has not accepted the ownership offer yet.", + "team_demoteMeConfirm": "You are about to give up your rights. You will not be able to undo this action. Are you sure?" } diff --git a/www/teams/inner.js b/www/teams/inner.js index d5c02741b..f1691ec4d 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -155,7 +155,6 @@ define([ if (obj && obj.error) { return void UI.warn(Messages.error); } - var val = obj.avatar; common.displayAvatar($avatar, obj.avatar, obj.name); $category.append($avatar); $avatar.append(obj.name); @@ -444,15 +443,23 @@ define([ redrawRoster(common); }); }; - var makeMember = function (common, data, me) { + var makeMember = function (common, data, me, roster) { if (!data.curvePublic) { return; } + + var otherOwners = Object.keys(roster || {}).some(function (key) { + var user = roster[key]; + return user.role === "OWNER" && user.curvePublic !== me.curvePublic && !user.pendingOwner; + }); + // Avatar var avatar = h('span.cp-avatar.cp-team-member-avatar'); common.displayAvatar($(avatar), data.avatar, data.displayName); // Name var name = h('span.cp-team-member-name', data.displayName); if (data.pendingOwner) { - $(name).append(h('em', " PENDING")); + $(name).append(h('em', { + title: Messages.team_pendingOwnerTitle + }, ' ' + Messages.team_pendingOwner)); } // Status var status = h('span.cp-team-member-status'+(data.online ? '.online' : '')); @@ -468,9 +475,9 @@ define([ title: Messages.team_rosterPromoteOwner }); $(promoteOwner).click(function () { - $(promoteOwner).hide(); UI.confirm(Messages.team_ownerConfirm, function (yes) { if (!yes) { return; } + $(promoteOwner).hide(); APP.module.execCommand('OFFER_OWNERSHIP', { teamId: APP.team, curvePublic: data.curvePublic @@ -500,18 +507,29 @@ define([ } // If I'm not a member and I have an equal or higher role than them, I can demote them // (if they're not already a MEMBER) - if (!isMe && myRole >= theirRole && theirRole > 0 && !data.pending) { + if (myRole >= theirRole && theirRole > 0 && !data.pending) { var demote = h('span.fa.fa-angle-double-down', { title: Messages.team_rosterDemote }); $(demote).click(function () { - var role = ROLES[theirRole - 1] || 'MEMBER'; - $(demote).hide(); - describeUser(common, data.curvePublic, { - role: role - }, promote); + var todo = function () { + var role = ROLES[theirRole - 1] || 'MEMBER'; + $(demote).hide(); + describeUser(common, data.curvePublic, { + role: role + }, promote); + }; + if (isMe) { + return void UI.confirm(Messages.team_demoteMeConfirm, function (yes) { + if (!yes) { return; } + todo(); + }); + } + todo(); }); - $actions.append(demote); + if (!(isMe && myRole === 2 && !otherOwners)) { + $actions.append(demote); + } } // If I'm not a member and I have an equal or higher role than them, I can remove them // Note: we can't remove owners, we have to demote them first @@ -567,7 +585,7 @@ define([ if (roster[k].pending) { return; } return roster[k].role === "OWNER" || roster[k].pendingOwner; }).map(function (k) { - return makeMember(common, roster[k], me); + return makeMember(common, roster[k], me, roster); }); var admins = Object.keys(roster).filter(function (k) { if (roster[k].pending) { return; }