From c041b8f619957d4058c42cca894409418fde54f6 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 27 Jul 2020 11:43:38 +0530 Subject: css changes --- src/client/util/GroupMemberView.scss | 3 ++- src/client/util/GroupMemberView.tsx | 11 +++++++++-- src/client/util/SharingManager.scss | 2 +- src/client/util/SharingManager.tsx | 7 ++++++- 4 files changed, 18 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss index c609c5c7b..2fc27ed03 100644 --- a/src/client/util/GroupMemberView.scss +++ b/src/client/util/GroupMemberView.scss @@ -41,6 +41,7 @@ margin-top: -5; height: 20; text-overflow: ellipsis; + background: none; &:hover { text-overflow: visible; @@ -72,7 +73,7 @@ .editing-contents { overflow-y: auto; - height: 65%; + height: 62%; width: 100%; color: black; margin-top: -15px; diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index f20670c4e..531ef988a 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -29,13 +29,17 @@ export default class GroupMemberView extends React.Component !(JSON.parse(StrCast(this.props.group.members)) as string[]).includes(option.value)) : []; + const hasEditAccess = GroupManager.Instance.hasEditAccess(this.props.group); + return (!this.props.group ? null :
this.props.group.groupName = e.currentTarget.value} + disabled={!hasEditAccess} >
@@ -65,12 +69,15 @@ export default class GroupMemberView extends React.Component this.memberSort = this.memberSort === "ascending" ? "descending" : this.memberSort === "descending" ? "none" : "ascending")}> Emails {this.memberSort === "ascending" ? "↑" : this.memberSort === "descending" ? "↓" : ""} {/* → */}

-
+
{members.map(member => (
{member}
- {GroupManager.Instance.hasEditAccess(this.props.group) ? + {hasEditAccess ?
GroupManager.Instance.removeMemberFromGroup(this.props.group, member)}>
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 130785672..d71ff0cf6 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -1,6 +1,6 @@ .sharing-interface { width: 600px; - height: 360px; + // height: 360px; .overlay { transform: translate(-20px, -20px); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 452a58d21..9fbdfa8e5 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -294,7 +294,7 @@ export default class SharingManager extends React.Component<{}> { const { left, width, top, height } = this.shareDocumentButtonRef.current!.getBoundingClientRect(); TaskCompletionBox.popupX = left - 1.5 * width; - TaskCompletionBox.popupY = top - height; + TaskCompletionBox.popupY = top - 1.5 * height; TaskCompletionBox.textDisplayed = "Document shared!"; TaskCompletionBox.taskCompleted = true; setTimeout(action(() => TaskCompletionBox.taskCompleted = false), 2000); @@ -460,6 +460,11 @@ export default class SharingManager extends React.Component<{}> { options={options} onChange={this.handleUsersChange} value={this.selectedUsers} + styles={{ + indicatorSeparator: () => ({ + visibility: "hidden" + }) + }} /> ({ - visibility: "hidden" - }) - }} - /> - - +
+
+ this.showUserOptions = !this.showUserOptions)} /> + this.showGroupOptions = !this.showGroupOptions)} /> +
}
@@ -481,17 +528,8 @@ export default class SharingManager extends React.Component<{}> { onClick={action(() => this.individualSort = this.individualSort === "ascending" ? "descending" : this.individualSort === "descending" ? "none" : "ascending")}> Individuals {this.individualSort === "ascending" ? "↑" : this.individualSort === "descending" ? "↓" : ""} {/* → */}
-
{/*200*/} - { - !displayUserList ? -
- There are no users this document has been shared with. -
- : - userListContents - } +
{/*200*/} + {userListContents}
diff --git a/src/fields/util.ts b/src/fields/util.ts index a62795e64..cf8e730fd 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -115,6 +115,7 @@ export function OVERRIDE_ACL(val: boolean) { _overrideAcl = val; } +// playground mode allows the user to add/delete documents or make layout changes without them saving to the server let playgroundMode = false; export function togglePlaygroundMode() { @@ -125,12 +126,27 @@ export function getPlaygroundMode() { return playgroundMode; } +// the list of groups that the current user is a member of let currentUserGroups: string[] = []; +// called from GroupManager once the groups have been fetched from the server export function setGroups(groups: string[]) { currentUserGroups = groups; } +/** + * These are the various levels of access a user can have to a document. + * + * Admin: a user with admin access to a document can remove/edit that document, add/remove/edit annotations (depending on permissions), as well as change others' access rights to that document. + * + * Edit: a user with edit access to a document can remove/edit that document, add/remove/edit annotations (depending on permissions), but not change any access rights to that document. + * + * Add: a user with add access to a document can add documents/annotations to that document but cannot edit or delete anything. + * + * View: a user with view access to a document can only view it - they cannot add/remove/edit anything. + * + * None: the document is not shared with that user. + */ export enum SharingPermissions { Admin = "Admin", Edit = "Can Edit", @@ -139,18 +155,21 @@ export enum SharingPermissions { None = "Not Shared" } +/** + * Calculates the effective access right to a document for the current user. + */ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclAdmin; if (target[AclSym] && Object.keys(target[AclSym]).length) { + // if the current user is the author of the document / the current user is a member of the admin group if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclAdmin; + // if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified) if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; let effectiveAcl = AclPrivate; - let aclPresent = false; - const HierarchyMapping = new Map([ [AclPrivate, 0], [AclReadonly, 1], @@ -160,19 +179,26 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) ]); for (const [key, value] of Object.entries(target[AclSym])) { + // there are issues with storing fields with . in the name, so they are replaced with _ during creation + // as a result we need to restore them again during this comparison. if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) { - if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) { - aclPresent = true; + if (HierarchyMapping.get(value as symbol)! > HierarchyMapping.get(effectiveAcl)!) { effectiveAcl = value as symbol; - if (effectiveAcl === AclEdit) break; + if (effectiveAcl === AclAdmin) break; } } } - return aclPresent ? effectiveAcl : AclEdit; + return effectiveAcl; } return AclAdmin; } - +/** + * Recursively distributes the access right for a user across the children of a document and its annotations. + * @param key the key storing the access right (e.g. ACL-groupname) + * @param acl the access right being stored (e.g. "Can Edit") + * @param target the document on which this access right is being set + * @param inheritingFromCollection whether the target is being assigned rights after being dragged into a collection (and so is inheriting the ACLs from the collection) + */ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { const HierarchyMapping = new Map([ @@ -185,32 +211,31 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc const dataDoc = target[DataSym]; + // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl; if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { dataDoc[key] = acl; + // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, d); - d[key] = acl; + distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, data); - data[key] = acl; + distributeAcls(key, acl, data, inheritingFromCollection); } }); + // maps over the annotations of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, d); - d[key] = acl; + distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { - distributeAcls(key, acl, data); - data[key] = acl; + distributeAcls(key, acl, data, inheritingFromCollection); } }); } -- cgit v1.2.3-70-g09d2 From 2fb042f575626cc6f938eec57c8e71e45ff6b1d5 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 29 Jul 2020 23:30:20 +0530 Subject: anyone can share without setting acls + fixed some inheriting stuff + deleting stuff + some cleanup --- src/client/util/SharingManager.scss | 2 +- src/client/util/SharingManager.tsx | 63 ++++++++------- src/client/views/DocComponent.tsx | 18 ++--- src/client/views/DocumentDecorations.tsx | 27 ++++--- src/client/views/collections/CollectionView.tsx | 34 ++++---- src/client/views/nodes/DocumentView.tsx | 100 ------------------------ src/client/views/nodes/TaskCompletedBox.tsx | 2 - 7 files changed, 76 insertions(+), 170 deletions(-) (limited to 'src') 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).push(target)) : group.docsShared = new List([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 : (
{
- {this.targetDoc?.author !== Doc.CurrentUserEmail ? null - : -
-
- - {this.sharingOptions} - - -
-
- this.showUserOptions = !this.showUserOptions)} /> - this.showGroupOptions = !this.showGroupOptions)} /> -
+
+ this.showUserOptions = !this.showUserOptions)} /> + this.showGroupOptions = !this.showGroupOptions)} /> +
+
}
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

{ - 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 ? (

Show context menu
} placement="top">
-
) : ( -
Delete
} placement="top"> -
- {/* 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*/} - -
); +
) : canDelete ? ( +
Delete
} placement="top"> +
+ {/* 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*/} + +
) : 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 { - // 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 { - 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(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(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 => { // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 @@ -791,11 +762,6 @@ export class DocumentView extends DocComponent(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(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"; -- cgit v1.2.3-70-g09d2 From 12b6b8150ab5e737e18b6029ba243677cdc6a90e Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 30 Jul 2020 18:37:18 +0530 Subject: added fetchproto to distributeAcls --- src/fields/util.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/fields/util.ts b/src/fields/util.ts index cf8e730fd..048b66b53 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"; @@ -209,13 +209,18 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); + let changed = false; const dataDoc = target[DataSym]; // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive - 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; // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { @@ -239,6 +244,8 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc } }); } + + changed && fetchProto(target); // updates aclsym when changes to acls have been made } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", -- cgit v1.2.3-70-g09d2 From 626c7b04dcfff293a2a30ed059e661100143199b Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 30 Jul 2020 22:11:39 +0530 Subject: some playground mode stuff + minor sharingmanager changes --- src/client/util/GroupManager.tsx | 2 +- src/client/util/SharingManager.tsx | 41 ++++++++++++++++--------- src/client/views/DocComponent.tsx | 6 ++-- src/client/views/collections/CollectionView.tsx | 7 +++-- 4 files changed, 35 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 551216fa4..a0db9a421 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -102,7 +102,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 00d0691f2..7ede584c2 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, AclAdmin, DataSym } from "../../fields/Doc"; +import { Doc, Opt, DocListCastAsync, AclAdmin, DataSym, AclPrivate } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; @@ -19,7 +19,7 @@ import GroupMemberView from "./GroupMemberView"; import Select from "react-select"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../fields/List"; -import { distributeAcls, SharingPermissions } from "../../fields/util"; +import { distributeAcls, SharingPermissions, GetEffectiveAcl } from "../../fields/util"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; export interface User { @@ -80,7 +80,7 @@ export default class SharingManager extends React.Component<{}> { public open = (target: DocumentView) => { runInAction(() => this.users = []); - SelectionManager.DeselectAll(); + // SelectionManager.DeselectAll(); this.populateUsers().then(action(() => { this.targetDocView = target; this.targetDoc = target.props.Document; @@ -93,8 +93,8 @@ export default class SharingManager extends React.Component<{}> { public close = action(() => { this.isOpen = false; - this.users = []; // resets the list of users and seleected users (in the react-select component) - this.selectedUsers = null; + this.users = []; + this.selectedUsers = null; // resets the list of users and seleected users (in the react-select component) setTimeout(action(() => { // this.copied = false; @@ -108,10 +108,15 @@ export default class SharingManager extends React.Component<{}> { SharingManager.Instance = this; } + componentDidMount() { + this.populateUsers(); + } + /** * Populates the list of validated users (this.users) by adding registered users which have a rightSidebarCollection. */ 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 => { @@ -379,24 +384,32 @@ export default class SharingManager extends React.Component<{}> { const users = this.individualSort === "ascending" ? this.users.sort(this.sortUsers) : this.individualSort === "descending" ? this.users.sort(this.sortUsers).reverse() : this.users; const groups = this.groupSort === "ascending" ? groupList.sort(this.sortGroups) : this.groupSort === "descending" ? groupList.sort(this.sortGroups).reverse() : groupList; + const effectiveAcl = this.targetDoc ? GetEffectiveAcl(this.targetDoc) : AclPrivate; + const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { const userKey = user.email.replace('.', '_'); - const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None); + const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`]); - return user.email === this.targetDoc?.author ? null : ( + return !permissions || user.email === this.targetDoc?.author ? null : (
{user.email}
- + {effectiveAcl === AclAdmin ? ( + + ) : ( +
+ {this.sharingOptions} +
+ )}
); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 777fb5323..3bcf4b922 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -163,13 +163,13 @@ export function ViewBoxAnnotatableComponent

Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } else { added.map(doc => doc.context = this.props.Document); - targetDataDoc[this.annotationKey] = new List([...docList, ...added]); - targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + (targetDataDoc[this.annotationKey] as List).push(...added); + if (!getPlaygroundMode()) targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 25a832994..5262c8b46 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -157,7 +157,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); } else { @@ -179,8 +179,9 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); - targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); - targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + // targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); + (targetDataDoc[this.props.fieldKey] as List).push(...added); + if (!getPlaygroundMode()) targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } -- cgit v1.2.3-70-g09d2 From 583b13be95734e22dcae558306ca94ff8ef8c7b4 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 12:07:45 +0530 Subject: fixed acls re highlights --- src/client/util/SharingManager.tsx | 21 +++++++++------------ src/client/views/nodes/WebBox.tsx | 14 +++++++++----- src/client/views/pdf/PDFMenu.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 14 +++++++++----- 4 files changed, 28 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 7ede584c2..4ab4a3c42 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -120,17 +120,14 @@ export default class SharingManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - const isCandidate = user.email !== Doc.CurrentUserEmail; - if (isCandidate) { - const userDocument = await DocServer.GetRefField(user.userDocumentId); - if (userDocument instanceof Doc) { - const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); - runInAction(() => { - if (notificationDoc instanceof Doc) { - this.users.push({ user, notificationDoc }); - } - }); - } + const userDocument = await DocServer.GetRefField(user.userDocumentId); + if (userDocument instanceof Doc) { + const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); + runInAction(() => { + if (notificationDoc instanceof Doc) { + this.users.push({ user, notificationDoc }); + } + }); } }); return Promise.all(evaluating); @@ -407,7 +404,7 @@ export default class SharingManager extends React.Component<{}> { ) : (

- {this.sharingOptions} + {permissions}
)}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index d30f1499e..cb82a76f1 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import { Dictionary } from "typescript-collections"; import * as WebRequest from 'web-request'; -import { Doc, DocListCast, Opt } from "../../../fields/Doc"; +import { Doc, DocListCast, Opt, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { HtmlField } from "../../../fields/HtmlField"; @@ -13,7 +13,7 @@ import { List } from "../../../fields/List"; import { listSpec, makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { WebField } from "../../../fields/URLField"; -import { TraceMobx } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; import { addStyleSheet, clearStyleSheetRules, emptyFunction, returnOne, returnZero, Utils, returnTrue } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; @@ -535,9 +535,13 @@ export class WebBox extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); - return annotationDoc; + const effectiveAcl = GetEffectiveAcl(this.props.Document); + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + const annotationDoc = this.makeAnnotationDocument(color); + annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); + return annotationDoc; + } + return undefined; } /** * This is temporary for creating annotations from highlights. It will diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index c3e1ae22f..7bea8d01b 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -93,7 +93,7 @@ export default class PDFMenu extends AntimodeMenu { @computed get highlighter() { const button = - ; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c792df882..954b62332 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -4,7 +4,7 @@ const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; import { Dictionary } from "typescript-collections"; -import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; @@ -13,7 +13,7 @@ import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -565,9 +565,13 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && this.props.addDocument?.(annotationDoc); - return annotationDoc; + const effectiveAcl = GetEffectiveAcl(this.props.Document); + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + const annotationDoc = this.makeAnnotationDocument(color); + annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); + return annotationDoc; + } + return undefined; } /** -- cgit v1.2.3-70-g09d2 From 19c0ca86ed6ff8d8644125fa119270fc79e0afc9 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 13:59:04 +0530 Subject: integrated playgroundmode into geteffectiveacl, still some issues with deleting docs --- src/client/views/DocComponent.tsx | 8 ++++---- src/client/views/collections/CollectionView.tsx | 10 +++++----- .../views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- src/client/views/nodes/WebBox.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 4 ++-- src/fields/util.ts | 6 +----- 6 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 3bcf4b922..804c7a8d4 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -7,7 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../fields/util'; +import { GetEffectiveAcl, SharingPermissions } from '../../fields/util'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -150,7 +150,7 @@ export function ViewBoxAnnotatableComponent

Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } else { added.map(doc => doc.context = this.props.Document); (targetDataDoc[this.annotationKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5262c8b46..7e7ea6786 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, SharingPermissions } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, 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'; @@ -142,7 +142,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); } else { @@ -181,7 +181,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); // targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); (targetDataDoc[this.props.fieldKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } @@ -193,7 +193,7 @@ export class CollectionView extends Touchable { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 954b62332..59fa6b08c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -13,7 +13,7 @@ import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -566,7 +566,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/fields/util.ts b/src/fields/util.ts index 048b66b53..500daf0c7 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -122,10 +122,6 @@ export function togglePlaygroundMode() { playgroundMode = !playgroundMode; } -export function getPlaygroundMode() { - return playgroundMode; -} - // the list of groups that the current user is a member of let currentUserGroups: string[] = []; @@ -188,7 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } - return effectiveAcl; + return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; } -- cgit v1.2.3-70-g09d2 From 5d50404b127560d525cab4645fcd3b07367ef5a2 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 16:19:46 +0530 Subject: comments --- src/client/util/GroupManager.tsx | 37 +++++++++++++------------------------ src/client/util/SharingManager.tsx | 8 ++++++-- src/client/views/MainViewModal.tsx | 2 +- src/fields/util.ts | 7 +++++-- 4 files changed, 25 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index a0db9a421..5215ea35f 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -38,8 +38,8 @@ export default class GroupManager extends React.Component<{}> { @observable currentGroup: Opt; // the currently selected group. @observable private createGroupModalOpen: boolean = false; private inputRef: React.RefObject = React.createRef(); // the ref for the input box. - private createGroupButtonRef: React.RefObject = React.createRef(); - private currentUserGroups: string[] = []; + private createGroupButtonRef: React.RefObject = React.createRef(); // the ref for the group creation button + private currentUserGroups: string[] = []; // the list of groups the current user is a member of @observable private buttonColour: "#979797" | "black" = "#979797"; @observable private groupSort: "ascending" | "descending" | "none" = "none"; @@ -50,6 +50,9 @@ export default class GroupManager extends React.Component<{}> { GroupManager.Instance = this; } + /** + * Populates the list of users and groups. + */ componentDidMount() { this.populateUsers(); this.populateGroups(); @@ -63,8 +66,6 @@ export default class GroupManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - // const isCandidate = user.email !== Doc.CurrentUserEmail; - // if (isCandidate) { const userDocument = await DocServer.GetRefField(user.userDocumentId); if (userDocument instanceof Doc) { const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); @@ -74,11 +75,13 @@ export default class GroupManager extends React.Component<{}> { } }); } - // } }); return Promise.all(evaluating); } + /** + * Populates the list of groups the current user is a member of and sets this list to be used in the GetEffectiveAcl in util.ts + */ populateGroups = () => { DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { groups?.forEach(group => { @@ -146,25 +149,8 @@ export default class GroupManager extends React.Component<{}> { } /** - * @returns a readonly copy of a single group document + * Returns an array of the list of members of a given group. */ - getGroupCopy(groupName: string): Doc | undefined { - const groupDoc = this.getGroup(groupName); - if (groupDoc) { - const { members, owners } = groupDoc; - return Doc.assign(new Doc, { groupName, members: StrCast(members), owners: StrCast(owners) }); - } - return undefined; - } - /** - * @returns a readonly copy of the list of group documents - */ - getAllGroupsCopy(): Doc[] { - return this.getAllGroups().map(({ groupName, owners, members }) => - Doc.assign(new Doc, { groupName: (StrCast(groupName)), owners: (StrCast(owners)), members: (StrCast(members)) }) - ); - } - getGroupMembers(group: string | Doc): string[] { if (group instanceof Doc) return JSON.parse(StrCast(group.members)) as string[]; else return JSON.parse(StrCast(this.getGroup(group)!.members)) as string[]; @@ -317,6 +303,9 @@ export default class GroupManager extends React.Component<{}> { } + /** + * @returns the MainViewModal which allows the user to create groups. + */ private get groupCreationModal() { const contents = (

@@ -416,7 +405,7 @@ export default class GroupManager extends React.Component<{}> {
this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""} {/* → */} + Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""}
{groups.map(group => diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 4ab4a3c42..64dc491ed 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -81,13 +81,14 @@ export default class SharingManager extends React.Component<{}> { public open = (target: DocumentView) => { runInAction(() => this.users = []); // SelectionManager.DeselectAll(); - this.populateUsers().then(action(() => { + this.populateUsers(); + runInAction(() => { this.targetDocView = target; this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; this.permissions = SharingPermissions.Edit; - })); + }); } @@ -108,6 +109,9 @@ export default class SharingManager extends React.Component<{}> { SharingManager.Instance = this; } + /** + * Populates the list of users. + */ componentDidMount() { this.populateUsers(); } diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 249715511..66ea2dbf8 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -10,7 +10,7 @@ export interface MainViewOverlayProps { overlayStyle?: React.CSSProperties; dialogueBoxDisplayedOpacity?: number; overlayDisplayedOpacity?: number; - closeOnExternalClick?: () => void; + closeOnExternalClick?: () => void; // the close method of a MainViewModal, triggered if there is a click on the overlay (closing the modal) } @observer diff --git a/src/fields/util.ts b/src/fields/util.ts index 500daf0c7..16517f25f 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -184,6 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } + // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; @@ -194,6 +195,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) * @param acl the access right being stored (e.g. "Can Edit") * @param target the document on which this access right is being set * @param inheritingFromCollection whether the target is being assigned rights after being dragged into a collection (and so is inheriting the ACLs from the collection) + * inheritingFromCollection is not currently being used but could be used if ACL assignment defaults change */ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { @@ -205,7 +207,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); - let changed = false; + let changed = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) const dataDoc = target[DataSym]; // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive @@ -241,7 +243,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc }); } - changed && fetchProto(target); // updates aclsym when changes to acls have been made + changed && fetchProto(target); // updates target[AclSym] when changes to acls have been made } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", @@ -251,6 +253,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an const effectiveAcl = GetEffectiveAcl(target, in_prop); if (effectiveAcl !== AclEdit && effectiveAcl !== AclAdmin) return true; + // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === "string" && prop.startsWith("ACL") && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true; // if (typeof prop === "string" && prop.startsWith("ACL") && !["Can Edit", "Can Add", "Can View", "Not Shared", undefined].includes(value)) return true; -- cgit v1.2.3-70-g09d2 From 38cfa8e547c1ffb7344f83ebb5dd9798d0dd0d0c Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 22:47:36 +0530 Subject: added alias list to docs + sharingmanager ui changes --- src/client/util/SharingManager.tsx | 37 +++++++++++++++++++++++++++---------- src/fields/Doc.ts | 4 ++++ src/fields/util.ts | 11 ++++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 64dc491ed..196182b77 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -124,14 +124,17 @@ export default class SharingManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - const userDocument = await DocServer.GetRefField(user.userDocumentId); - if (userDocument instanceof Doc) { - const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); - runInAction(() => { - if (notificationDoc instanceof Doc) { - this.users.push({ user, notificationDoc }); - } - }); + const isCandidate = user.email !== Doc.CurrentUserEmail; + if (isCandidate) { + const userDocument = await DocServer.GetRefField(user.userDocumentId); + if (userDocument instanceof Doc) { + const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); + runInAction(() => { + if (notificationDoc instanceof Doc) { + this.users.push({ user, notificationDoc }); + } + }); + } } }); return Promise.all(evaluating); @@ -422,14 +425,28 @@ export default class SharingManager extends React.Component<{}> { key={"owner"} className={"container"} > - {this.targetDoc?.author} + {this.targetDoc?.author === Doc.CurrentUserEmail ? "Me" : this.targetDoc?.author}
Owner
- ) + ), + this.targetDoc?.author !== Doc.CurrentUserEmail ? + ( +
+ Me +
+
+ {this.targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]} +
+
+
+ ) : null ); const groupListContents = groups.map(group => { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 267defa4b..a1acc7060 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -508,6 +508,10 @@ export namespace Doc { alias.aliasOf = doc; alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`); alias.author = Doc.CurrentUserEmail; + + if (!doc.aliases) doc.aliases = new List([alias]); + else Doc.AddDocToList(doc, "aliases", alias); + return alias; } diff --git a/src/fields/util.ts b/src/fields/util.ts index 16517f25f..608ef506c 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -160,7 +160,8 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) if (target[AclSym] && Object.keys(target[AclSym]).length) { // if the current user is the author of the document / the current user is a member of the admin group - if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclAdmin; + // but not if the doc in question is an alias - the current user will be the author of their alias rather than the original author + if ((Doc.CurrentUserEmail === (target.__fields?.author || target.author) && !(target.aliasOf || target.__fields?.aliasOf)) || currentUserGroups.includes("admin")) return AclAdmin; // if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified) if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; @@ -214,6 +215,14 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) { target[key] = acl; changed = true; + + // maps over the aliases of the document + if (target.aliases) { + DocListCast(target.aliases).map(alias => { + distributeAcls(key, acl, alias); + }); + } + } if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { -- cgit v1.2.3-70-g09d2 From 10f6686e0ed4a5d7a975fdf2f3453b069fa0ae04 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 1 Aug 2020 00:42:01 +0530 Subject: playground mode changes --- src/client/DocServer.ts | 3 +-- src/client/util/SettingsManager.tsx | 2 -- src/fields/util.ts | 12 ++++++------ 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index f5ee6da3c..6fa8cf909 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -9,7 +9,6 @@ import GestureOverlay from './views/GestureOverlay'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { runInAction } from 'mobx'; import { ObjectField } from '../fields/ObjectField'; -import { getPlaygroundMode } from '../fields/util'; /** * This class encapsulates the transfer and cross-client synchronization of @@ -452,7 +451,7 @@ export namespace DocServer { } function _UpdateFieldImpl(id: string, diff: any) { - (!getPlaygroundMode()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + (!DocServer.Control.isReadOnly()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); } let _UpdateField: (id: string, diff: any) => void = errorFunc; diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index fbdceb43e..207c78964 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -14,7 +14,6 @@ import { Doc } from "../../fields/Doc"; import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; -import { togglePlaygroundMode } from "../../fields/util"; import { DocServer } from "../DocServer"; library.add(fa.faTimes); @@ -101,7 +100,6 @@ export default class SettingsManager extends React.Component<{}> { @action togglePlaygroundMode = () => { - //togglePlaygroundMode(); this.playgroundMode = !this.playgroundMode; if (this.playgroundMode) DocServer.Control.makeReadOnly(); else DocServer.Control.makeEditable(); diff --git a/src/fields/util.ts b/src/fields/util.ts index 608ef506c..d6d9718f2 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -74,7 +74,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number const fromServer = target[UpdatingFromServer]; const sameAuthor = fromServer || (receiver.author === Doc.CurrentUserEmail); const writeToDoc = sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || (writeMode !== DocServer.WriteMode.LiveReadonly); - const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || writeMode === DocServer.WriteMode.Default) && !playgroundMode; + const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAdmin || writeMode === DocServer.WriteMode.Default) && !DocServer.Control.isReadOnly();// && !playgroundMode; if (writeToDoc) { if (value === undefined) { @@ -116,11 +116,11 @@ export function OVERRIDE_ACL(val: boolean) { } // playground mode allows the user to add/delete documents or make layout changes without them saving to the server -let playgroundMode = false; +// let playgroundMode = false; -export function togglePlaygroundMode() { - playgroundMode = !playgroundMode; -} +// export function togglePlaygroundMode() { +// playgroundMode = !playgroundMode; +// } // the list of groups that the current user is a member of let currentUserGroups: string[] = []; @@ -186,7 +186,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) - return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; + return DocServer?.Control?.isReadOnly?.() && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; } -- cgit v1.2.3-70-g09d2 From 6d02ae9f9c09c27fa8da87afbd1307240dcb9289 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sun, 2 Aug 2020 17:42:56 +0530 Subject: minor changes --- src/client/util/SharingManager.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 196182b77..892fb6d6d 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -94,7 +94,6 @@ export default class SharingManager extends React.Component<{}> { public close = action(() => { this.isOpen = false; - this.users = []; this.selectedUsers = null; // resets the list of users and seleected users (in the react-select component) setTimeout(action(() => { @@ -450,9 +449,9 @@ export default class SharingManager extends React.Component<{}> { ); const groupListContents = groups.map(group => { - const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`], SharingPermissions.None); + const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`]); - return permissions === SharingPermissions.None ? null : ( + return !permissions ? null : (
Date: Sun, 2 Aug 2020 08:57:35 -0400 Subject: changed highlight() calls in PdfViewer and WebBox --- src/client/views/nodes/WebBox.tsx | 9 +++------ src/client/views/pdf/PDFViewer.tsx | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 3fbebe3e6..646a94aa7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -536,12 +536,9 @@ export class WebBox extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); - return annotationDoc; - } - return undefined; + const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); + annotationDoc && this.addDocument?.(annotationDoc); + return annotationDoc ?? undefined; } /** * This is temporary for creating annotations from highlights. It will diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 59fa6b08c..b81baf417 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -566,12 +566,9 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); - return annotationDoc; - } - return undefined; + const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); + annotationDoc && this.addDocument?.(annotationDoc); + return annotationDoc ?? undefined; } /** -- cgit v1.2.3-70-g09d2 From 63fd10d0940331d68a9ce58b4b77734b11e393f5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 2 Aug 2020 09:22:38 -0400 Subject: fixed hiding of close button based on permsisions. --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/util.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6e6ffc893..7fc4a5c99 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -586,7 +586,7 @@ 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 canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.ContainingCollectionDoc)).some(permission => permission === AclAdmin || permission === AclEdit); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? (
Show context menu
} placement="top"> @@ -597,7 +597,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{/* 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*/} -
) : null; +
) : (null); const titleArea = this._edtingTitle ? <> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index b81baf417..5a43a076b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -568,7 +568,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent Date: Sun, 2 Aug 2020 11:40:24 -0400 Subject: fixed runtime warnings. fixed color of title text of stacking and masonry views --- src/client/util/SharingManager.tsx | 4 ++-- src/client/views/EditableView.tsx | 2 +- src/client/views/collections/CollectionMasonryViewFieldRow.tsx | 2 -- src/client/views/collections/CollectionStackingView.tsx | 2 +- .../views/collections/CollectionStackingViewFieldColumn.tsx | 10 +++------- 5 files changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 892fb6d6d..5896bdf92 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -352,9 +352,9 @@ export default class SharingManager extends React.Component<{}> { private get sharingInterface() { const groupList = GroupManager.Instance?.getAllGroups() || []; - const sortedUsers = this.users.sort(this.sortUsers) + const sortedUsers = this.users.slice().sort(this.sortUsers) .map(({ user: { email } }) => ({ label: email, value: indType + email })); - const sortedGroups = groupList.sort(this.sortGroups) + const sortedGroups = groupList.slice().sort(this.sortGroups) .map(({ groupName }) => ({ label: StrCast(groupName), value: groupType + StrCast(groupName) })); const options: GroupedOptions[] = []; diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index ad61d3f91..c7b149842 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -187,7 +187,7 @@ export class EditableView extends React.Component { {this.renderEditor()}
: this.renderEditor(); } else { - this.props.autosuggestProps?.resetValue(); + setTimeout(() => this.props.autosuggestProps?.resetValue(), 0); return (this.props.contents instanceof ObjectField ? (null) :
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 0332b4bf2..312dd92f0 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -481,7 +481,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument) })} onDrop={this.onExternalDrop.bind(this)} onContextMenu={this.onContextMenu} - onWheel={e => this.props.active() && e.stopPropagation()} > + onWheel={e => this.props.active(true) && e.stopPropagation()} > {this.renderedSections} {!this.showAddAGroup ? (null) :
"", @@ -306,7 +305,6 @@ export class CollectionStackingViewFieldColumn extends React.Component } - {evContents === `NO ${key.toUpperCase()} VALUE` ? - (null) : - } + {} {evContents === `NO ${key.toUpperCase()} VALUE` ? (null) :
-- cgit v1.2.3-70-g09d2