diff options
Diffstat (limited to 'src/client/util/SharingManager.tsx')
-rw-r--r-- | src/client/util/SharingManager.tsx | 109 |
1 files changed, 59 insertions, 50 deletions
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index d3241009a..828271270 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,4 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Colors } from 'browndash-components'; import { concat, intersection } from 'lodash'; import { action, computed, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -22,6 +23,7 @@ import { GroupManager, UserOptions } from './GroupManager'; import { GroupMemberView } from './GroupMemberView'; import { SelectionManager } from './SelectionManager'; import './SharingManager.scss'; +import { undoable } from './UndoManager'; export interface User { email: string; @@ -76,8 +78,10 @@ export class SharingManager extends React.Component<{}> { @observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component) @observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component) private populating: boolean = false; // whether the list of users is populating or not + @observable private overrideNested: boolean = false; // whether child docs in a collection/dashboard should be changed to be less private - initially selected so default is override @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used @observable private myDocAcls: boolean = false; // whether the My Docs checkbox is selected or not + @observable private _buttonDown = false; // private get linkVisible() { // return this.targetDoc ? this.targetDoc["acl-" + PublicKey] !== SharingPermissions.None : false; @@ -91,6 +95,7 @@ export class SharingManager extends React.Component<{}> { DictationOverlay.Instance.hasActiveModal = true; this.isOpen = this.targetDoc !== undefined; this.permissions = SharingPermissions.Augment; + this.overrideNested = true; }); }; @@ -149,36 +154,30 @@ export class SharingManager extends React.Component<{}> { /** * Shares the document with a user. */ - setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc: Doc | undefined) => { + setInternalSharing = undoable((recipient: ValidatedUser, permission: string, targetDoc: Doc | undefined) => { const { user, sharingDoc } = recipient; const target = targetDoc || this.targetDoc!; const acl = `acl-${normalizeEmail(user.email)}`; - const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`; const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc); docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => { - doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc, undefined, undefined); - - distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined); + distributeAcls(acl, permission as SharingPermissions, doc); if (permission !== SharingPermissions.None) Doc.AddDocToList(sharingDoc, storage, doc); else GetEffectiveAcl(doc, user.email) === AclPrivate && Doc.RemoveDocFromList(sharingDoc, storage, (doc.createdFrom as Doc) || doc); }); - }; + }, 'set Doc permissions'); /** * Sets the permission on the target for the group. * @param group * @param permission */ - setInternalGroupSharing = (group: Doc | { title: string }, permission: string, targetDoc?: Doc) => { + setInternalGroupSharing = undoable((group: Doc | { title: string }, permission: string, targetDoc?: Doc) => { const target = targetDoc || this.targetDoc!; - const key = normalizeEmail(StrCast(group.title)); - let acl = `acl-${key}`; + const acl = `acl-${normalizeEmail(StrCast(group.title))}`; const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.rootDoc); docs.map(doc => (this.layoutDocAcls ? doc : Doc.GetProto(doc))).forEach(doc => { - doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc, undefined, undefined); - - distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined); + distributeAcls(acl, permission as SharingPermissions, doc, undefined, this.overrideNested); if (group instanceof Doc) { Doc.AddDocToList(group, 'docsShared', doc); @@ -191,7 +190,7 @@ export class SharingManager extends React.Component<{}> { }); } }); - }; + }, 'set group permissions'); /** * Shares the documents shared with a group with a new user who has been added to that group. @@ -217,23 +216,23 @@ export class SharingManager extends React.Component<{}> { /** * Called from the properties sidebar to change permissions of a user. */ - shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, docs: Doc[], layout: boolean) => { + shareFromPropertiesSidebar = undoable((shareWith: string, permission: SharingPermissions, docs: Doc[], layout: boolean) => { if (layout) this.layoutDocAcls = true; if (shareWith !== 'Public' && shareWith !== 'Override') { const user = this.users.find(({ user: { email } }) => email === (shareWith === 'Me' ? Doc.CurrentUserEmail : shareWith)); docs.forEach(doc => { if (user) this.setInternalSharing(user, permission, doc); - else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, doc); + else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, doc, undefined, true); }); } else { docs.forEach(doc => { if (GetEffectiveAcl(doc) === AclAdmin) { - distributeAcls(`acl-${shareWith}`, permission, doc, undefined, undefined); + distributeAcls(`acl-${shareWith}`, permission, doc, undefined, true); } }); } this.layoutDocAcls = false; - }; + }, 'sidebar set permissions'); /** * Removes the documents shared with a user through a group when the user is removed from the group. @@ -261,7 +260,7 @@ export class SharingManager extends React.Component<{}> { if (group.docsShared) { DocListCast(group.docsShared).forEach(doc => { const acl = `acl-${StrCast(group.title)}`; - distributeAcls(acl, SharingPermissions.None, doc, undefined, undefined); + distributeAcls(acl, SharingPermissions.None, doc); const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); @@ -342,39 +341,43 @@ export class SharingManager extends React.Component<{}> { /** * Handles changes in the permission chosen to share with someone with */ - @action - handlePermissionsChange = (event: React.ChangeEvent<HTMLSelectElement>) => { - this.permissions = event.currentTarget.value as SharingPermissions; - }; + handlePermissionsChange = undoable( + action((event: React.ChangeEvent<HTMLSelectElement>) => { + this.permissions = event.currentTarget.value as SharingPermissions; + }), + 'permission change' + ); /** * Calls the relevant method for sharing, displays the popup, and resets the relevant variables. */ - @action - share = () => { - if (this.selectedUsers) { - this.selectedUsers.forEach(user => { - if (user.value.includes(indType)) { - this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions, undefined); - } else { - this.setInternalGroupSharing(GroupManager.Instance.getGroup(user.label)!, this.permissions); - } - }); - - const { left, width, top, height } = this.shareDocumentButtonRef.current!.getBoundingClientRect(); - TaskCompletionBox.popupX = left - 1.5 * width; - TaskCompletionBox.popupY = top - 1.5 * height; - TaskCompletionBox.textDisplayed = 'Document shared!'; - TaskCompletionBox.taskCompleted = true; - setTimeout( - action(() => (TaskCompletionBox.taskCompleted = false)), - 2000 - ); + share = undoable( + action(() => { + if (this.selectedUsers) { + this.selectedUsers.forEach(user => { + if (user.value.includes(indType)) { + this.setInternalSharing(this.users.find(u => u.user.email === user.label)!, this.permissions, undefined); + } else { + this.setInternalGroupSharing(GroupManager.Instance.getGroup(user.label)!, this.permissions); + } + }); + + const { left, width, top, height } = this.shareDocumentButtonRef.current!.getBoundingClientRect(); + TaskCompletionBox.popupX = left - 1.5 * width; + TaskCompletionBox.popupY = top - 1.5 * height; + TaskCompletionBox.textDisplayed = 'Document shared!'; + TaskCompletionBox.taskCompleted = true; + setTimeout( + action(() => (TaskCompletionBox.taskCompleted = false)), + 2000 + ); - this.layoutDocAcls = false; - this.selectedUsers = null; - } - }; + this.layoutDocAcls = false; + this.selectedUsers = null; + } + }), + 'share Doc' + ); /** * Sorting algorithm to sort users. @@ -542,12 +545,17 @@ export class SharingManager extends React.Component<{}> { <b>Share </b> {this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')} </p> - <button className="share-copy-link" onClick={this.copyURL}> - <FontAwesomeIcon title={'Copy Public URL'} icon={'copy'} size={'sm'} onClick={this.copyURL} /> + <button + className="share-copy-link" + style={{ background: this._buttonDown ? Colors.LIGHT_BLUE : undefined }} + onPointerDown={action(e => (this._buttonDown = true))} + onPointerUp={action(e => (this._buttonDown = false))} + onClick={this.copyURL}> + <FontAwesomeIcon title="Copy Public URL" icon="copy" size="sm" /> Copy Public URL </button> - <div className={'close-button'} onClick={this.close}> - <FontAwesomeIcon icon={'times'} color={'black'} size={'lg'} /> + <div className="close-button" onClick={this.close}> + <FontAwesomeIcon icon="times" color="black" size="lg" /> </div> {admin ? ( <div className="share-container"> @@ -585,6 +593,7 @@ export class SharingManager extends React.Component<{}> { <div className="acl-container"> {Doc.noviceMode ? null : ( <div className="layoutDoc-acls"> + <input type="checkbox" onChange={action(() => (this.overrideNested = !this.overrideNested))} checked={this.overrideNested} /> <label>Override Nested </label> <input type="checkbox" onChange={action(() => (this.layoutDocAcls = !this.layoutDocAcls))} checked={this.layoutDocAcls} /> <label>Layout</label> </div> )} |