diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-07-29 23:30:20 +0530 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-07-29 23:30:20 +0530 |
commit | 2fb042f575626cc6f938eec57c8e71e45ff6b1d5 (patch) | |
tree | 13b07de7e2f2e20e65e71caac4f1a03ce1cc8fb9 | |
parent | 716751fa420eda3a3f8322f579255a6532ddc7f5 (diff) |
anyone can share without setting acls + fixed some inheriting stuff + deleting stuff + some cleanup
-rw-r--r-- | src/client/util/SharingManager.scss | 2 | ||||
-rw-r--r-- | src/client/util/SharingManager.tsx | 63 | ||||
-rw-r--r-- | src/client/views/DocComponent.tsx | 18 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 27 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 34 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 100 | ||||
-rw-r--r-- | src/client/views/nodes/TaskCompletedBox.tsx | 2 |
7 files changed, 76 insertions, 170 deletions
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 2ce9f232c..8da80ef52 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -50,7 +50,7 @@ .share-button { height: 105%; margin-left: 2%; - background-color: #979797; + background-color: black; } } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index ec04bdd81..83524f062 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,7 +1,7 @@ import { observable, runInAction, action } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; -import { Doc, Opt, DocListCastAsync } from "../../fields/Doc"; +import { Doc, Opt, DocListCastAsync, AclAdmin, DataSym } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; @@ -82,6 +82,7 @@ export default class SharingManager extends React.Component<{}> { // } public open = (target: DocumentView) => { + runInAction(() => this.users = []); SelectionManager.DeselectAll(); this.populateUsers().then(action(() => { this.targetDocView = target; @@ -145,7 +146,7 @@ export default class SharingManager extends React.Component<{}> { const target = this.targetDoc!; const ACL = `ACL-${StrCast(group.groupName)}`; - distributeAcls(ACL, permission as SharingPermissions, target); + target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); // if documents have been shared, add the target to that list if it doesn't already exist, otherwise create a new list with the target group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List<Doc>).push(target)) : group.docsShared = new List<Doc>([target]); @@ -220,7 +221,7 @@ export default class SharingManager extends React.Component<{}> { const key = user.email.replace('.', '_'); const ACL = `ACL-${key}`; - distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); + target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); if (permission !== SharingPermissions.None) { DocListCastAsync(notificationDoc[storage]).then(resolved => { @@ -385,7 +386,7 @@ export default class SharingManager extends React.Component<{}> { const userKey = user.email.replace('.', '_'); const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None); - return permissions === SharingPermissions.None || user.email === this.targetDoc?.author ? null : ( + return user.email === this.targetDoc?.author ? null : ( <div key={userKey} className={"container"} @@ -490,36 +491,34 @@ export default class SharingManager extends React.Component<{}> { <div className={"close-button"} onClick={this.close}> <FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} /> </div> - {this.targetDoc?.author !== Doc.CurrentUserEmail ? null - : - <div className="share-container"> - <div className="share-setup"> - <Select - className={"user-search"} - placeholder={"Enter user or group name..."} - isMulti - closeMenuOnSelect={false} - options={options} - onChange={this.handleUsersChange} - value={this.selectedUsers} - styles={{ - indicatorSeparator: () => ({ - visibility: "hidden" - }) - }} - /> - <select className="permissions-select" onChange={this.handlePermissionsChange}> - {this.sharingOptions} - </select> - <button ref={this.shareDocumentButtonRef} className="share-button" onClick={this.share}> - Share + {<div className="share-container"> + <div className="share-setup"> + <Select + className={"user-search"} + placeholder={"Enter user or group name..."} + isMulti + closeMenuOnSelect={false} + options={options} + onChange={this.handleUsersChange} + value={this.selectedUsers} + styles={{ + indicatorSeparator: () => ({ + visibility: "hidden" + }) + }} + /> + <select className="permissions-select" onChange={this.handlePermissionsChange}> + {this.sharingOptions} + </select> + <button ref={this.shareDocumentButtonRef} className="share-button" onClick={this.share}> + Share </button> - </div> - <div className="sort-checkboxes"> - <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> + <div className="sort-checkboxes"> + <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> } <div className="main-container"> <div className={"individual-container"}> diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 9fd406407..ae180a78b 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -154,15 +154,15 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T return false; } else { - if (this.props.Document[AclSym]) { - added.forEach(d => { - const dataDoc = d[DataSym]; - dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - dataDoc[key] = d[key] = this.AclMap.get(value); - } - }); - } + // if (this.props.Document[AclSym]) { + // added.forEach(d => { + // const dataDoc = d[DataSym]; + // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + // for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + // dataDoc[key] = d[key] = this.AclMap.get(value); + // } + // }); + // } if (effectiveAcl === AclAddonly) { added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8d63537e7..655f330e3 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,9 +1,9 @@ import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, reaction, runInAction } from "mobx"; +import { action, computed, observable, reaction, runInAction, get } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DataSym, Field, WidthSym, HeightSym } from "../../fields/Doc"; +import { Doc, DataSym, Field, WidthSym, HeightSym, AclEdit, AclAdmin } from "../../fields/Doc"; import { Document } from '../../fields/documentSchemas'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, StrCast, NumCast } from "../../fields/Types"; @@ -23,6 +23,9 @@ import { SnappingManager } from '../util/SnappingManager'; import { HtmlField } from '../../fields/HtmlField'; import { InkData, InkField, InkTool } from "../../fields/InkField"; import { Tooltip } from '@material-ui/core'; +import { GetEffectiveAcl } from '../../fields/util'; +import { DocumentIcon } from './nodes/DocumentIcon'; +import { render } from 'react-dom'; library.add(faCaretUp); library.add(faObjectGroup); @@ -193,8 +196,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.DeselectAll(); selected.map(dv => { - recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true); - dv.props.removeDocument?.(dv.props.Document); + const effectiveAcl = GetEffectiveAcl(dv.props.Document); + if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete + recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true); + dv.props.removeDocument?.(dv.props.Document); + } }); } } @@ -545,17 +551,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } + const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.Document)).some(permission => permission === AclAdmin || permission === AclEdit); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? ( <Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top"> <div className="documentDecorations-contextMenu" onPointerDown={this.onSettingsDown}> <FontAwesomeIcon size="lg" icon="cog" /> - </div></Tooltip>) : ( - <Tooltip title={<><div className="dash-tooltip">Delete</div></>} placement="top"> - <div className="documentDecorations-closeButton" onClick={this.onCloseClick}> - {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} - <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" /> - </div></Tooltip>); + </div></Tooltip>) : canDelete ? ( + <Tooltip title={<><div className="dash-tooltip">Delete</div></>} placement="top"> + <div className="documentDecorations-closeButton" onClick={this.onCloseClick}> + {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} + <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" /> + </div></Tooltip>) : null; const titleArea = this._edtingTitle ? <> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a82c91383..3bb1022e0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, distributeAcls, SharingPermissions } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../../fields/util'; import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -149,16 +149,16 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus return false; } else { - if (this.props.Document[AclSym]) { - // change so it only adds if more restrictive - added.forEach(d => { - // const dataDoc = d[DataSym]; - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); - } - // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - }); - } + // if (this.props.Document[AclSym]) { + // // change so it only adds if more restrictive + // added.forEach(d => { + // // const dataDoc = d[DataSym]; + // for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + // // key.substring(4).replace("_", ".") !== Doc.CurrentUserEmail && distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); + // distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); + // } + // }); + // } if (effectiveAcl === AclAddonly) { added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); @@ -192,14 +192,16 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus @action.bound removeDocument = (doc: any): boolean => { - const effectiveAcl = GetEffectiveAcl(this.props.Document); - if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin || getPlaygroundMode()) { + const collectionEffectiveAcl = GetEffectiveAcl(this.props.Document); + const docEffectiveAcl = GetEffectiveAcl(doc); + // you can remove the document if you either have Admin/Edit access to the collection or to the specific document + if (collectionEffectiveAcl === AclEdit || collectionEffectiveAcl === AclAdmin || docEffectiveAcl === AclAdmin || docEffectiveAcl === AclEdit || getPlaygroundMode()) { const docs = doc instanceof Doc ? [doc] : doc as Doc[]; const targetDataDoc = this.props.Document[DataSym]; const value = DocListCast(targetDataDoc[this.props.fieldKey]); - const result = value.filter(v => !docs.includes(v)); - if (result.length !== value.length) { - targetDataDoc[this.props.fieldKey] = new List<Doc>(result); + const toRemove = value.filter(v => docs.includes(v)); + if (toRemove.length !== 0) { + toRemove.forEach(doc => Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc)); return true; } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b59875a7e..1d89f3d24 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -697,35 +697,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true; } - @undoBatch - @action - setAcl = (acl: SharingPermissions) => { - this.dataDoc.ACL = this.props.Document.ACL = acl; - DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail) d.ACL = acl; - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) data.ACL = acl; - }); - } - - @undoBatch - @action - testAcl = (acl: SharingPermissions) => { - this.dataDoc.author = this.props.Document.author = "ADMIN"; - this.dataDoc.ACL = this.props.Document.ACL = acl; - DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail) { - d.author = "ADMIN"; - d.ACL = acl; - } - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) { - data.author = "ADMIN"; - data.ACL = acl; - } - }); - } - @action onContextMenu = async (e: React.MouseEvent | Touch): Promise<void> => { // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 @@ -791,11 +762,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu moreItems.push({ description: "Download document", icon: "download", event: async () => { Doc.Zip(this.props.Document); - // const a = document.createElement("a"); - // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); - // a.href = url; - // a.download = `DocExport-${this.props.Document[Id]}.zip`; - // a.click(); } }); if (!Doc.UserDoc().noviceMode) { @@ -822,72 +788,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); - // const existingAcls = cm.findByDescription("Privacy..."); - // const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : []; - // aclItems.push({ description: "Make Add Only", event: () => this.setAcl(SharingPermissions.Add), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Read Only", event: () => this.setAcl(SharingPermissions.View), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Private", event: () => this.setAcl(SharingPermissions.None), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Editable", event: () => this.setAcl(SharingPermissions.Edit), icon: "concierge-bell" }); - // aclItems.push({ description: "Test Private", event: () => this.testAcl(SharingPermissions.None), icon: "concierge-bell" }); - // aclItems.push({ description: "Test Readonly", event: () => this.testAcl(SharingPermissions.View), icon: "concierge-bell" }); - // !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" }); - - // cm.addItem({ description: `${getPlaygroundMode() ? "Disable" : "Enable"} playground mode`, event: togglePlaygroundMode, icon: "concierge-bell" }); - - // const recommender_subitems: ContextMenuProps[] = []; - - // recommender_subitems.push({ - // description: "Internal recommendations", - // event: () => this.recommender(), - // icon: "brain" - // }); - - // const ext_recommender_subitems: ContextMenuProps[] = []; - - // ext_recommender_subitems.push({ - // description: "arXiv", - // event: () => this.externalRecommendation("arxiv"), - // icon: "brain" - // }); - // ext_recommender_subitems.push({ - // description: "Bing", - // event: () => this.externalRecommendation("bing"), - // icon: "brain" - // }); - - // recommender_subitems.push({ - // description: "External recommendations", - // subitems: ext_recommender_subitems, - // icon: "brain" - // }); - - - //moreItems.push({ description: "Recommender System", subitems: recommender_subitems, icon: "brain" }); - //moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); - //moreItems.push({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" }); - - // runInAction(() => { - // const setWriteMode = (mode: DocServer.WriteMode) => { - // DocServer.AclsMode = mode; - // const mode1 = mode; - // const mode2 = mode === DocServer.WriteMode.Default ? mode : DocServer.WriteMode.Playground; - // DocServer.setFieldWriteMode("x", mode1); - // DocServer.setFieldWriteMode("y", mode1); - // DocServer.setFieldWriteMode("_width", mode1); - // DocServer.setFieldWriteMode("_height", mode1); - - // DocServer.setFieldWriteMode("_panX", mode2); - // DocServer.setFieldWriteMode("_panY", mode2); - // DocServer.setFieldWriteMode("scale", mode2); - // DocServer.setFieldWriteMode("_viewType", mode2); - // }; - // const aclsMenu: ContextMenuProps[] = []; - // aclsMenu.push({ description: "Default (write/read all)", event: () => setWriteMode(DocServer.WriteMode.Default), icon: DocServer.AclsMode === DocServer.WriteMode.Default ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Playground (write own/no read)", event: () => setWriteMode(DocServer.WriteMode.Playground), icon: DocServer.AclsMode === DocServer.WriteMode.Playground ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Live Playground (write own/read others)", event: () => setWriteMode(DocServer.WriteMode.LivePlayground), icon: DocServer.AclsMode === DocServer.WriteMode.LivePlayground ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Live Readonly (no write/read others)", event: () => setWriteMode(DocServer.WriteMode.LiveReadonly), icon: DocServer.AclsMode === DocServer.WriteMode.LiveReadonly ? "check" : "exclamation" }); - // cm.addItem({ description: "Collaboration ...", subitems: aclsMenu, icon: "share" }); - // }); runInAction(() => { if (!this.topMost && !(e instanceof Touch)) { // DocumentViews should stop propagation of this event diff --git a/src/client/views/nodes/TaskCompletedBox.tsx b/src/client/views/nodes/TaskCompletedBox.tsx index 89602f219..2a3dd8d2d 100644 --- a/src/client/views/nodes/TaskCompletedBox.tsx +++ b/src/client/views/nodes/TaskCompletedBox.tsx @@ -1,7 +1,5 @@ import React = require("react"); import { observer } from "mobx-react"; -import { documentSchema } from "../../../fields/documentSchemas"; -import { makeInterface } from "../../../fields/Schema"; import "./TaskCompletedBox.scss"; import { observable, action } from "mobx"; import { Fade } from "@material-ui/core"; |