diff options
author | bobzel <zzzman@gmail.com> | 2020-09-30 21:01:23 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-30 21:01:23 -0400 |
commit | f76fcfc24e128d0de898928b5a5b1abdee656c4f (patch) | |
tree | a4819debe1b8d874abe7f4f44cb92dc82ac790ed | |
parent | d116f51faf21351c0a40258b2ba1f9146a5ab25e (diff) | |
parent | d69eaadf58687070e3e3649747ffa0447d3e7964 (diff) |
Merge pull request #823 from browngraphicslab/acls_uv
ACL Refresh
-rw-r--r-- | src/client/util/SharingManager.scss | 27 | ||||
-rw-r--r-- | src/client/util/SharingManager.tsx | 42 | ||||
-rw-r--r-- | src/client/views/DocumentButtonBar.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PropertiesView.scss | 32 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 21 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 3 |
6 files changed, 86 insertions, 41 deletions
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 54e3f45bc..9dc57dd1e 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -72,22 +72,25 @@ } } - .layoutDoc-acls, - .myDocs-acls { + .acl-container { display: flex; - flex-direction: column; float: right; - margin-right: 12; - margin-top: -15; - align-items: center; + align-items: baseline; + margin-top: -12; - label { - font-weight: normal; - font-style: italic; - } + .layoutDoc-acls, + .myDocs-acls { + flex-direction: column; + margin-right: 12; - input { - cursor: pointer; + label { + font-weight: normal; + font-style: italic; + } + + input { + cursor: pointer; + } } } } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 2c9620b02..bcd7d4056 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -4,7 +4,7 @@ import { observer } from "mobx-react"; import * as React from "react"; import Select from "react-select"; import * as RequestPromise from "request-promise"; -import { AclAdmin, AclPrivate, DataSym, Doc, DocListCast, Opt, AclSym } from "../../fields/Doc"; +import { AclAdmin, AclPrivate, DataSym, Doc, DocListCast, Opt, AclSym, AclAddonly, AclEdit, AclReadonly } from "../../fields/Doc"; import { List } from "../../fields/List"; import { Cast, StrCast } from "../../fields/Types"; import { distributeAcls, GetEffectiveAcl, SharingPermissions, TraceMobx } from "../../fields/util"; @@ -71,6 +71,7 @@ export class SharingManager extends React.Component<{}> { @observable private individualSort: "ascending" | "descending" | "none" = "none"; // sorting options for the list of individuals @observable private groupSort: "ascending" | "descending" | "none" = "none"; // sorting options for the list of groups private shareDocumentButtonRef: React.RefObject<HTMLButtonElement> = React.createRef(); // ref for the share button, used for the position of the popup + private distributeAclsButtonRef: React.RefObject<HTMLButtonElement> = React.createRef(); // ref for the distribute button, used for the position of the popup // if both showUserOptions and showGroupOptions are false then both are displayed @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) @@ -374,6 +375,25 @@ export class SharingManager extends React.Component<{}> { } } + distributeOverCollection = (targetDoc?: Doc) => { + const AclMap = new Map<symbol, string>([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit], + [AclAdmin, SharingPermissions.Admin] + ]); + + const target = targetDoc || this.targetDoc!; + + const docs = SelectionManager.SelectedDocuments().length < 2 ? [target] : SelectionManager.SelectedDocuments().map(docView => docView.props.Document); + docs.forEach(doc => { + for (const [key, value] of Object.entries(doc[AclSym])) { + distributeAcls(key, AclMap.get(value)! as SharingPermissions, target); + } + }); + } + /** * Sorting algorithm to sort users. */ @@ -436,7 +456,7 @@ export class SharingManager extends React.Component<{}> { const commonKeys = intersection(...docs.map(doc => this.layoutDocAcls ? doc?.[AclSym] && Object.keys(doc[AclSym]) : doc?.[DataSym]?.[AclSym] && Object.keys(doc[DataSym][AclSym]))); // the list of users shared with - const userListContents: (JSX.Element | null)[] = users.filter(({ user }) => docs.length > 1 ? commonKeys.includes(`acl-${user.email.replace('.', '_')}`) : true).map(({ user, notificationDoc, userColor }) => { + const userListContents: (JSX.Element | null)[] = users.filter(({ user }) => docs.length > 1 ? commonKeys.includes(`acl-${user.email.replace('.', '_')}`) : docs[0]?.author !== user.email).map(({ user, notificationDoc, userColor }) => { const userKey = `acl-${user.email.replace('.', '_')}`; const uniform = docs.every(doc => this.layoutDocAcls ? doc?.[AclSym]?.[userKey] === docs[0]?.[AclSym]?.[userKey] : doc?.[DataSym]?.[AclSym]?.[userKey] === docs[0]?.[DataSym]?.[AclSym]?.[userKey]); const permissions = uniform ? StrCast(targetDoc?.[userKey]) : "-multiple-"; @@ -580,13 +600,19 @@ export class SharingManager extends React.Component<{}> { <input type="checkbox" onChange={action(() => this.showUserOptions = !this.showUserOptions)} /> <label style={{ marginRight: 10 }}>Individuals</label> <input type="checkbox" onChange={action(() => this.showGroupOptions = !this.showGroupOptions)} /> <label>Groups</label> </div> - <div className="myDocs-acls"> - <input type="checkbox" onChange={action(() => this.myDocAcls = !this.myDocAcls)} checked={this.myDocAcls} /> <label>My Docs</label> + + <div className="acl-container"> + <div className="myDocs-acls"> + <input type="checkbox" onChange={action(() => this.myDocAcls = !this.myDocAcls)} checked={this.myDocAcls} /> <label>My Docs</label> + </div> + {Doc.UserDoc().noviceMode ? (null) : + <div className="layoutDoc-acls"> + <input type="checkbox" onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} checked={this.layoutDocAcls} /> <label>Layout</label> + </div>} + <button className="distribute-button" onClick={() => this.distributeOverCollection()}> + Distribute + </button> </div> - {Doc.UserDoc().noviceMode ? (null) : - <div className="layoutDoc-acls"> - <input type="checkbox" onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} checked={this.layoutDocAcls} /> <label>Layout</label> - </div>} </div> } <div className="main-container"> diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index fff410267..d8c32a919 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -242,7 +242,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV get menuButton() { const targetDoc = this.view0?.props.Document; return !targetDoc ? (null) : <Tooltip title={<><div className="dash-tooltip">{`Open Context Menu`}</div></>}> - <div className="documentButtonBar-linker" style={{ color: "white", cursor: "context-menu" }} onClick={e => this.openContextMenu(e)}> + <div className="documentButtonBar-linker" style={{ color: "white", cursor: "pointer" }} onClick={e => this.openContextMenu(e)}> <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="bars" /> </div></Tooltip >; } diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 47d8aacea..9fdc8bc47 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -121,19 +121,30 @@ padding: 10px; margin-left: 5px; - .propertiesView-acls-checkbox { + .propertiesView-buttonContainer { float: right; - height: 20px; - margin-top: -20px; - margin-right: -15; - - .propertiesView-acls-checkbox-text { - font-size: 7px; - margin-top: -10px; - margin-left: 6px; + display: flex; + + button { + width: 15; + height: 15; + padding: 0; + margin-top: -5; + } + + .propertiesView-acls-checkbox { + margin-top: -20px; + + .propertiesView-acls-checkbox-text { + font-size: 7px; + margin-top: -10px; + margin-left: 6px; + } } } + + .change-buttons { display: flex; @@ -247,8 +258,7 @@ } .expansion-button { - margin-left: -22.5; - margin: 3; + margin-left: -20; .expansion-button-icon { width: 11px; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 5877c1d6d..5cab7726e 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -901,14 +901,19 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> {!this.openSharing ? (null) : <div className="propertiesView-sharing-content"> - {!novice ? (<div className="propertiesView-acls-checkbox"> - <Checkbox - color="primary" - onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} - checked={this.layoutDocAcls} - />; - <div className="propertiesView-acls-checkbox-text">Layout</div> - </div>) : (null)} + <div className="propertiesView-buttonContainer"> + {!novice ? (<div className="propertiesView-acls-checkbox"> + <Checkbox + color="primary" + onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} + checked={this.layoutDocAcls} + /> + <div className="propertiesView-acls-checkbox-text">Layout</div> + </div>) : (null)} + <button onPointerDown={() => SharingManager.Instance.distributeOverCollection(this.selectedDoc!)}> + <FontAwesomeIcon icon="redo-alt" color="white" size="1x" /> + </button> + </div> {this.sharingTable} </div>} </div> diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 8b48acf23..ddfb3cc34 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -274,7 +274,8 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp width: this.props.InMenu ? "20px" : "30px", height: this.props.InMenu ? "20px" : "30px", backgroundColor: DocumentLinksButton.StartLink ? "" : "grey", opacity: DocumentLinksButton.StartLink ? "" : "50%", - border: DocumentLinksButton.StartLink ? "" : "none" + border: DocumentLinksButton.StartLink ? "" : "none", + cursor: DocumentLinksButton.StartLink ? "pointer" : "default" }} onPointerDown={DocumentLinksButton.StartLink ? this.completeLink : emptyFunction} onClick={e => DocumentLinksButton.StartLink ? DocumentLinksButton.finishLinkClick(e.clientX, e.clientY, DocumentLinksButton.StartLink, this.props.View.props.Document, true, this.props.View) : emptyFunction} /> : (null) |