From 31685e36d1f7e6a95fd5d65c55562f51bfe723e1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 30 Jul 2020 01:31:32 -0400 Subject: fixed leftsidebar menu buttons --- src/client/util/CurrentUserUtils.ts | 49 ++++------ src/client/views/MainView.tsx | 103 +++++++-------------- .../views/collections/CollectionStackingView.tsx | 1 + .../CollectionStackingViewFieldColumn.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 3 + src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/MenuIconBox.tsx | 22 ++--- 8 files changed, 69 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 442be98d2..34e732500 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -48,8 +48,6 @@ export class CurrentUserUtils { @observable public static closedStack: any | undefined; @observable public static searchStack: any | undefined; - @observable public static panelContent: string = "none"; - // sets up the default User Templates - slideView, queryView, descriptionView static setupUserTemplateButtons(doc: Doc) { if (doc["template-button-query"] === undefined) { @@ -508,46 +506,39 @@ export class CurrentUserUtils { title: string, icon: string, click: string, }[] { return [ - { title: "Workspace", icon: "desktop", click: 'scriptContext.selectMenu("workspace")' }, - { title: "Catalog", icon: "file", click: 'scriptContext.selectMenu("catalog")' }, + { title: "Workspace", icon: "desktop", click: 'scriptContext.selectMenu("Workspace")' }, + { title: "Catalog", icon: "file", click: 'scriptContext.selectMenu("Catalog")' }, { title: "Archive", icon: "archive", click: 'scriptContext.selectMenu("deleted")' }, - { title: "Import", icon: "upload", click: 'scriptContext.selectMenu("upload")' }, + { title: "Import", icon: "upload", click: 'scriptContext.selectMenu("Import")' }, { title: "Sharing", icon: "users", click: 'GroupManager.Instance.open()' }, - { title: "Tools", icon: "wrench", click: 'scriptContext.selectMenu("tools")' }, - { title: "Help", icon: "question-circle", click: 'scriptContext.selectMenu("help")' }, + { title: "Tools", icon: "wrench", click: 'scriptContext.selectMenu("Tools")' }, + { title: "Help", icon: "question-circle", click: 'scriptContext.selectMenu("Help")' }, { title: "Settings", icon: "cog", click: 'SettingsManager.Instance.open()' }, ]; } - static setupMenuButtons(doc: Doc) { - if (doc.menuStackBtns === undefined) { + static setupMenuPanel(doc: Doc) { + if (doc.menuStack === undefined) { const buttons = CurrentUserUtils.menuBtnDescriptions(); const menuBtns = buttons.map(({ title, icon, click }) => Docs.Create.MenuIconDocument({ icon, title, + _backgroundColor: "black", stayInCollection: true, _width: 60, - _height: 70, - onClick: ScriptField.MakeScript(click), + _height: 60, + onClick: ScriptField.MakeScript(click, { scriptContext: "any" }), })); - doc.menuStackBtns = new PrefetchProxy(Docs.Create.MasonryDocument(menuBtns, { - _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, lockedPosition: true, _chromeStatus: "disabled", + doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument(menuBtns, { + title: "menuItemPanel", + _backgroundColor: "black", + _gridGap: 0, + _yMargin: 0, + _yPadding: 0, _xMargin: 0, _autoHeight: false, _width: 60, _columnWidth: 60, lockedPosition: true, _chromeStatus: "disabled", })); } - return doc.menuStackBtns as Doc; - } - - static setupMenuPanel(doc: Doc) { - doc.menuStack = undefined; - if (doc.menuStack === undefined) { - const menuBtns = CurrentUserUtils.setupMenuButtons(doc); - doc.menuStack = new PrefetchProxy(Docs.Create.StackingDocument([menuBtns], { - _yMargin: 0, _autoHeight: true, _xMargin: 0, - _width: 60, lockedPosition: true, _chromeStatus: "disabled", - })) as any as Doc; - } - return doc.menuStack; + return doc.menuStack as Doc; } @@ -696,9 +687,9 @@ export class CurrentUserUtils { onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel"), })); } - (doc["tabs-button-tools"] as Doc).sourcePanel; // prefetch sourcePanel + (doc["tabs-button-tools"] as any as Doc).sourcePanel; // prefetch sourcePanel - return doc["tabs-button-tools"] as Doc; + return doc["tabs-button-tools"] as any as Doc; } static setupWorkspaces(doc: Doc) { @@ -808,7 +799,7 @@ export class CurrentUserUtils { })); CurrentUserUtils.searchStack = new PrefetchProxy(Docs.Create.QueryDocument({ title: "search stack", })) as any as Doc; } - return doc["tabs-button-search"] as Doc; + return doc["tabs-button-search"] as any as Doc; } static setupSidebarContainer(doc: Doc) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5f7f7ca03..27d1da389 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,7 +1,6 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faHireAHelper } from '@fortawesome/free-brands-svg-icons'; import * as fa from '@fortawesome/free-solid-svg-icons'; -import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -12,57 +11,54 @@ import { Doc, DocListCast, Field, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; -import { BoolCast, Cast, FieldValue, StrCast, NumCast } from '../../fields/Types'; +import { ScriptField } from '../../fields/ScriptField'; +import { BoolCast, Cast, FieldValue, StrCast } from '../../fields/Types'; import { TraceMobx } from '../../fields/util'; -import { CurrentUserUtils } from '../util/CurrentUserUtils'; -import { emptyFunction, emptyPath, returnFalse, returnOne, returnZero, returnTrue, Utils, returnEmptyFilter, setupMoveUpEvents } from '../../Utils'; +import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnTrue, returnZero, setupMoveUpEvents, Utils } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; +import { CurrentUserUtils } from '../util/CurrentUserUtils'; +import { DocumentManager } from '../util/DocumentManager'; +import GroupManager from '../util/GroupManager'; import { HistoryUtil } from '../util/History'; -import RichTextMenu from './nodes/formattedText/RichTextMenu'; import { Scripting } from '../util/Scripting'; +import { SelectionManager } from '../util/SelectionManager'; import SettingsManager from '../util/SettingsManager'; -import GroupManager from '../util/GroupManager'; import SharingManager from '../util/SharingManager'; +import { SnappingManager } from '../util/SnappingManager'; import { Transform } from '../util/Transform'; +import { TimelineMenu } from './animationtimeline/TimelineMenu'; import { CollectionDockingView } from './collections/CollectionDockingView'; +import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane"; import MarqueeOptionsMenu from './collections/collectionFreeForm/MarqueeOptionsMenu'; +import { PropertiesView } from './collections/collectionFreeForm/PropertiesView'; import { CollectionLinearView } from './collections/CollectionLinearView'; +import CollectionMenu from './collections/CollectionMenu'; import { CollectionView, CollectionViewType } from './collections/CollectionView'; import { ContextMenu } from './ContextMenu'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import GestureOverlay from './GestureOverlay'; +import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import KeyManager from './GlobalKeyHandler'; +import { LinkMenu } from './linking/LinkMenu'; import "./MainView.scss"; import { MainViewNotifs } from './MainViewNotifs'; import { AudioBox } from './nodes/AudioBox'; +import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { DocumentView } from './nodes/DocumentView'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import RichTextMenu from './nodes/formattedText/RichTextMenu'; +import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; +import { LinkDocPreview } from './nodes/LinkDocPreview'; import { RadialMenu } from './nodes/RadialMenu'; +import { TaskCompletionBox } from './nodes/TaskCompletedBox'; import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; -import { ScriptField, ComputedField } from '../../fields/ScriptField'; -import { TimelineMenu } from './animationtimeline/TimelineMenu'; -import { SnappingManager } from '../util/SnappingManager'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; -import { DocumentManager } from '../util/DocumentManager'; -import { DocumentLinksButton } from './nodes/DocumentLinksButton'; -import { LinkMenu } from './linking/LinkMenu'; -import { LinkDocPreview } from './nodes/LinkDocPreview'; -import { TaskCompletionBox } from './nodes/TaskCompletedBox'; -import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup'; -import FormatShapePane from "./collections/collectionFreeForm/FormatShapePane"; -import HypothesisAuthenticationManager from '../apis/HypothesisAuthenticationManager'; -import CollectionMenu from './collections/CollectionMenu'; -import { Tooltip, AccordionActions } from '@material-ui/core'; -import { PropertiesView } from './collections/collectionFreeForm/PropertiesView'; -import { SelectionManager } from '../util/SelectionManager'; -import { PrefetchProxy } from '../../fields/Proxy'; -import { DragManager } from '../util/DragManager'; -import { discovery_v1, dialogflow_v2beta1 } from 'googleapis'; @observer export class MainView extends React.Component { @@ -311,9 +307,11 @@ export class MainView extends React.Component { getPHeight = () => this._panelHeight; getContentsHeight = () => this._panelHeight - this._buttonBarHeight; - defaultBackgroundColors = (doc: Doc) => { + defaultBackgroundColors = (doc: Opt) => { + if (this.panelContent === doc?.title) return "lightgrey"; if (this.darkScheme) { switch (doc?.type) { + case DocumentType.MENUICON: return "white"; case DocumentType.RTF || DocumentType.LABEL || DocumentType.BUTTON: return "#2d2d2d"; case DocumentType.LINK: case DocumentType.COL: { @@ -323,6 +321,7 @@ export class MainView extends React.Component { } } else { switch (doc?.type) { + case DocumentType.MENUICON: return "black"; case DocumentType.RTF: return "#f1efeb"; case DocumentType.BUTTON: case DocumentType.LABEL: return "lightgray"; @@ -381,7 +380,6 @@ export class MainView extends React.Component { onPointerDown = (e: React.PointerEvent) => { if (this._flyoutTranslate) { this.panelContent = "none"; - CurrentUserUtils.panelContent = "none"; this._canClick = true; this._flyoutSizeOnDown = e.clientX; document.removeEventListener("pointermove", this.onPointerMove); @@ -427,9 +425,7 @@ export class MainView extends React.Component { mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight); @computed get flyout() { - if (!(this.sidebarContent instanceof Doc)) { - return (null); - } + if (!this.sidebarContent) return null; return
{ + selectMenu = (str: string) => { if (this.panelContent === str && this.flyoutWidth !== 0) { this.panelContent = "none"; this.flyoutWidth = 0; } else { this.panelContent = str; - MainView.expandFlyout(); - if (str === "tools") { - CurrentUserUtils.toolsBtn; - this.sidebarContent.proto = CurrentUserUtils.toolsStack; - } else if (str === "workspace") { - this.sidebarContent.proto = CurrentUserUtils.workspaceStack; - } else if (str === "catalog") { - this.sidebarContent.proto = CurrentUserUtils.catalogStack; - } else if (str === "deleted") { - this.sidebarContent.proto = CurrentUserUtils.closedStack; - } else if (str === "search") { - this.sidebarContent.proto = CurrentUserUtils.searchStack; + switch (this.panelContent) { + case "Tools": this.sidebarContent.proto = CurrentUserUtils.toolsStack; break; + case "Workspace": this.sidebarContent.proto = CurrentUserUtils.workspaceStack; break; + case "Catalog": this.sidebarContent.proto = CurrentUserUtils.catalogStack; break; + case "deleted": this.sidebarContent.proto = CurrentUserUtils.closedStack; break; + case "Search": this.sidebarContent.proto = CurrentUserUtils.searchStack; break; } - } - return true; - } - - @action - selectMenu = (str: string) => { - if (CurrentUserUtils.panelContent === str && this.flyoutWidth !== 0) { - CurrentUserUtils.panelContent = "none"; - this.flyoutWidth = 0; - } else { - CurrentUserUtils.panelContent = str; MainView.expandFlyout(); - if (str === "tools") { - CurrentUserUtils.toolsBtn; - this.sidebarContent.proto = CurrentUserUtils.toolsStack; - } else if (str === "workspace") { - this.sidebarContent.proto = CurrentUserUtils.workspaceStack; - } else if (str === "catalog") { - this.sidebarContent.proto = CurrentUserUtils.catalogStack; - } else if (str === "deleted") { - this.sidebarContent.proto = CurrentUserUtils.closedStack; - } else if (str === "search") { - this.sidebarContent.proto = CurrentUserUtils.searchStack; - } } return true; } @@ -660,7 +627,7 @@ export class MainView extends React.Component { const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`; const rightFlyout = this.selectedDocumentView ? this._propertiesWidth - 1 : this.propertiesWidth() > 10 ? 151.5 : 0; - return !this.userDoc || !(this.sidebarContent instanceof Doc) ? (null) : ( + return !this.userDoc ? (null) : (
{this.flyoutWidth !== 0 ?
+ style={{ backgroundColor: this.defaultBackgroundColors(undefined) }}> ; } diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 76af70cd1..59a87b450 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -355,7 +355,7 @@ export class CollectionStackingViewFieldColumn extends React.Component +
0.001 ? "auto" : this.props.PanelWidth(), height: Math.abs(this.centeringOffset) > 0.0001 ? "auto" : this.props.PanelHeight(), diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 856eb7246..a221dcfdb 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -843,6 +843,7 @@ export class DocumentView extends DocComponent(Docu ChromeHeight={this.chromeHeight} isSelected={this.isSelected} select={this.select} + scriptContext={this.props.scriptContext} onClick={this.onClickFunc} layoutKey={this.finalLayoutKey} /> {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 48e1f6ce3..23ae48108 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -60,6 +60,7 @@ export interface FieldViewProps { color?: string; xMargin?: number; yMargin?: number; + scriptContext?: any; } @observer diff --git a/src/client/views/nodes/MenuIconBox.tsx b/src/client/views/nodes/MenuIconBox.tsx index e1656fcba..0aa7b327e 100644 --- a/src/client/views/nodes/MenuIconBox.tsx +++ b/src/client/views/nodes/MenuIconBox.tsx @@ -2,15 +2,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { observer } from 'mobx-react'; import * as React from 'react'; import { createSchema, makeInterface } from '../../../fields/Schema'; +import { StrCast } from '../../../fields/Types'; import { DocComponent } from '../DocComponent'; -import './MenuIconBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; -import { StrCast, Cast, NumCast } from '../../../fields/Types'; -import { Utils } from "../../../Utils"; -import { runInAction, observable, reaction, IReactionDisposer } from 'mobx'; -import { Doc } from '../../../fields/Doc'; -import { ScriptField } from '../../../fields/ScriptField'; -import { CurrentUserUtils } from '../../util/CurrentUserUtils'; +import './MenuIconBox.scss'; const MenuIconSchema = createSchema({ icon: "string" }); @@ -24,15 +19,12 @@ export class MenuIconBox extends DocComponent( render() { - const menuBTN =
+ const color = this.props.backgroundColor?.(this.props.Document) === "lightgrey" ? "black" : "white"; + const menuBTN =
- -
{this.dataDoc.title}
+ style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }} > + +
{this.dataDoc.title}
; -- cgit v1.2.3-70-g09d2 From 611f848ff4f7b958dc913d33dd1b760ca9474c44 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:33:19 +0530 Subject: permissions from the properties panel should work now --- src/client/util/GroupManager.tsx | 2 +- src/client/util/SharingManager.tsx | 29 +++++++---- .../collectionFreeForm/PropertiesView.scss | 2 + .../collectionFreeForm/PropertiesView.tsx | 56 ++++++++++++++-------- src/fields/util.ts | 12 ++++- 5 files changed, 67 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 72fba5c1b..dee0f105f 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -101,7 +101,7 @@ export default class GroupManager extends React.Component<{}> { */ @action open = () => { - SelectionManager.DeselectAll(); + // SelectionManager.DeselectAll(); this.isOpen = true; this.populateUsers(); this.populateGroups(); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 0d8b33fbe..9222f10c5 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -62,14 +62,12 @@ export default class SharingManager extends React.Component<{}> { @observable private groupSort: "ascending" | "descending" | "none" = "none"; private shareDocumentButtonRef: React.RefObject = React.createRef(); - - // private get linkVisible() { // return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false; // } public open = (target: DocumentView) => { - SelectionManager.DeselectAll(); + // SelectionManager.DeselectAll(); this.populateUsers().then(action(() => { this.targetDocView = target; this.targetDoc = target.props.Document; @@ -82,7 +80,7 @@ export default class SharingManager extends React.Component<{}> { public close = action(() => { this.isOpen = false; - this.users = []; + // this.users = []; this.selectedUsers = null; setTimeout(action(() => { @@ -97,7 +95,12 @@ export default class SharingManager extends React.Component<{}> { SharingManager.Instance = this; } + componentDidMount() { + this.populateUsers(); + } + populateUsers = async () => { + runInAction(() => this.users = []); const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { @@ -117,17 +120,17 @@ export default class SharingManager extends React.Component<{}> { return Promise.all(evaluating); } - setInternalGroupSharing = (group: Doc, permission: string) => { + setInternalGroupSharing = (group: Doc, permission: string, targetDoc?: Doc) => { const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); - const target = this.targetDoc!; + const target = targetDoc || this.targetDoc!; const ACL = `ACL-${StrCast(group.groupName)}`; // fix this - not needed (here and setinternalsharing and removegroup) // target[ACL] = permission; // Doc.GetProto(target)[ACL] = permission; - distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); + distributeAcls(ACL, permission as SharingPermissions, target); group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); @@ -182,14 +185,20 @@ export default class SharingManager extends React.Component<{}> { } } + shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => { + const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith)); + if (user) this.setInternalSharing(user, permission, target); + else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, target); + } + // @action - setInternalSharing = (recipient: ValidatedUser, permission: string) => { + setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => { const { user, notificationDoc } = recipient; - const target = this.targetDoc!; + const target = targetDoc || this.targetDoc!; const key = user.email.replace('.', '_'); const ACL = `ACL-${key}`; - distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); + distributeAcls(ACL, permission as SharingPermissions, target); if (permission !== SharingPermissions.None) { DocListCastAsync(notificationDoc[storage]).then(resolved => { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index cb4b7375b..4ccc0950b 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -159,6 +159,8 @@ border-radius: 6px; width: 170px; background-color: #ececec; + max-height: 130px; + overflow-y: scroll; .propertiesView-sharingTable-item { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index d5317efcb..b33b37f4b 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { observer } from "mobx-react"; import "./PropertiesView.scss"; import { observable, action, computed, runInAction } from "mobx"; -import { Doc, Field, DocListCast, WidthSym, HeightSym } from "../../../../fields/Doc"; +import { Doc, Field, DocListCast, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin } from "../../../../fields/Doc"; import { DocumentView } from "../../nodes/DocumentView"; import { ComputedField } from "../../../../fields/ScriptField"; import { EditableView } from "../../EditableView"; @@ -18,6 +18,7 @@ import { SelectionManager } from "../../../util/SelectionManager"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip, Checkbox } from "@material-ui/core"; import SharingManager from "../../../util/SharingManager"; +import { SharingPermissions, GetEffectiveAcl } from "../../../../fields/util"; interface PropertiesViewProps { @@ -249,20 +250,15 @@ export class PropertiesView extends React.Component { } } - @computed get permissionsSelect() { - return SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, this.selectedDoc!)}> + {Object.values(SharingPermissions).map(permission => { + return ( + ); + })} ; } @@ -286,23 +282,41 @@ export class PropertiesView extends React.Component { ; } - sharingItem(name: string, notify: boolean, editable: boolean, permission?: string) { + sharingItem(name: string, notify: boolean, effectiveAcl: symbol, permission?: string) { return
{name}
{notify ? this.notifyIcon : null}
- {editable ? this.permissionsSelect : permission} + {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission} {permission === "Owner" ? this.expansionIcon : null}
; } @computed get sharingTable() { + const AclMap = new Map([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit], + [AclAdmin, SharingPermissions.Admin] + ]); + + const effectiveAcl = GetEffectiveAcl(this.selectedDoc!); + const tableEntries = []; + + if (this.selectedDoc![AclSym]) { + for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) { + const name = key.substring(4).replace("_", "."); + if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author) tableEntries.push(this.sharingItem(name, false, effectiveAcl, AclMap.get(value)!)); + } + } + + tableEntries.unshift(this.sharingItem("Me", false, effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]))); + if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), false, effectiveAcl, "Owner")); + return
- {this.sharingItem("Me", false, false, "Owner")} - {this.sharingItem("Public", false, true)} - {this.sharingItem("Group 1", true, true)} - {this.sharingItem("Group 2", true, true)} + {tableEntries}
; } diff --git a/src/fields/util.ts b/src/fields/util.ts index a62795e64..267da70b4 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -1,5 +1,5 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym } from "./Doc"; +import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, CachedUpdates, DataSym, DocListCast, AclAdmin, FieldsSym, HeightSym, WidthSym, fetchProto } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; @@ -183,12 +183,18 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); + let changed = false; + const dataDoc = target[DataSym]; - if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl; + if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) { + target[key] = acl; + changed = true; + } if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { dataDoc[key] = acl; + changed = true; DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { @@ -214,6 +220,8 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc } }); } + + changed && fetchProto(target); } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", -- cgit v1.2.3-70-g09d2