From 5b4b916b2700da746c12754ba3238eb1f3bbf5f7 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:42:57 +0530 Subject: many changes to acls, aliases, sharing sidebar etc --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/SharingManager.tsx | 20 ++++++------ src/client/views/PropertiesButtons.tsx | 12 ++++--- .../collectionFreeForm/PropertiesView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 3 +- src/fields/util.ts | 37 ++++++++++++---------- 7 files changed, 42 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 42ba4d2c4..c424c2bef 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -575,7 +575,7 @@ export namespace Docs { // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. dataDoc[fieldKey + "-annotations"] = new List(); - dataDoc.aliases = new List(); + dataDoc.aliases = new List([viewDoc]); proto.links = ComputedField.MakeFunction("links(self)"); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 68d02cd94..907b42327 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -846,7 +846,7 @@ export class CurrentUserUtils { // Sharing sidebar is where shared documents are contained static setupSharingSidebar(doc: Doc) { if (doc["sidebar-sharing"] === undefined) { - doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias", system: true })); + doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias", system: true, _yMargin: 30, _showTitle: "title", ignoreClick: true, lockedPosition: true })); } } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 48a3c023f..9d79188a3 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -155,16 +155,17 @@ export default class SharingManager extends React.Component<{}> { const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); const target = targetDoc || this.targetDoc!; - const ACL = `ACL-${StrCast(group.groupName)}`; + const key = StrCast(group.groupName).replace(".", "_"); + const ACL = `ACL-${key}`; - target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); + GetEffectiveAcl(target) === AclAdmin && 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 ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List).push(target) : group.docsShared = new List([target]); - users.forEach(({ notificationDoc }) => { + users.forEach(({ user, notificationDoc }) => { if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added - else Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists }); } @@ -231,14 +232,11 @@ export default class SharingManager extends React.Component<{}> { const key = user.email.replace('.', '_'); const ACL = `ACL-${key}`; - target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); + GetEffectiveAcl(target) === AclAdmin && distributeAcls(ACL, permission as SharingPermissions, target); + + if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); - if (permission !== SharingPermissions.None) { - Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); - } - else { - Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); - } } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 35d4f7f6e..dfedc9ccc 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -3,7 +3,7 @@ import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faChec import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../fields/Doc"; +import { Doc, DataSym, AclEdit, AclAdmin } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast, BoolCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils"; @@ -30,6 +30,7 @@ import { undoBatch, UndoManager } from '../util/UndoManager'; import { DocumentType } from '../documents/DocumentTypes'; import { InkField } from '../../fields/InkField'; import { PresBox } from './nodes/PresBox'; +import { GetEffectiveAcl } from '../../fields/util'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -710,6 +711,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isCollection = this.selectedDoc.type === DocumentType.COL ? true : false; const isFreeForm = this.selectedDoc._viewType === "freeform" ? true : false; const hasContext = this.selectedDoc.context ? true : false; + const collectionAcl = GetEffectiveAcl(this.selectedDocumentView?.props.ContainingCollectionDoc?.[DataSym]); return
@@ -733,9 +735,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
{this.downloadButton}
-
- {this.deleteButton} -
+ {collectionAcl === AclAdmin || collectionAcl === AclEdit ? +
+ {this.deleteButton} +
+ : (null)}
{this.onClickButton}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 57e968aa7..b38eed495 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -403,7 +403,7 @@ export class PropertiesView extends React.Component { // }) // shifts the current user and the owner to the top of the doc. - tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]))); + tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); return
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d92dc0ec2..3986a21e8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -763,7 +763,8 @@ export class DocumentView extends DocComponent(Docu Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); } - moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); + const collectionAcl = GetEffectiveAcl(this.props.ContainingCollectionDoc?.[DataSym]); + if (collectionAcl === AclAdmin || collectionAcl === AclEdit) moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); diff --git a/src/fields/util.ts b/src/fields/util.ts index 3d832636f..561d505e3 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -154,14 +154,16 @@ export enum SharingPermissions { /** * Calculates the effective access right to a document for the current user. */ -export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { +export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number, user?: string): symbol { if (!target) return AclPrivate; if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclAdmin; if (target[AclSym] && Object.keys(target[AclSym]).length) { + const userChecked = user || Doc.CurrentUserEmail; + // if the current user is the author of the document / the current user is a member of the admin group - if (Doc.CurrentUserEmail === (target.__fields?.author || target.author) || currentUserGroups.includes("admin")) return AclAdmin; + if (userChecked === (target.__fields?.author || target.author) || 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; @@ -178,7 +180,7 @@ 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 (currentUserGroups.includes(key.substring(4).replace("_", ".")) || userChecked === key.substring(4).replace("_", ".")) { if (HierarchyMapping.get(value as symbol)! > HierarchyMapping.get(effectiveAcl)!) { effectiveAcl = value as symbol; if (effectiveAcl === AclAdmin) break; @@ -208,52 +210,53 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); - let changed = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) + let layoutDocChanged = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) + let dataDocChanged = 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; - changed = true; + layoutDocChanged = true; + } + + if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { + dataDoc[key] = acl; + dataDocChanged = true; // maps over the aliases of the document - const aliases = DocListCast(target.aliases); + const aliases = DocListCast(dataDoc.aliases); if (aliases.length) { aliases.map(alias => { alias !== target && distributeAcls(key, acl, alias, inheritingFromCollection); }); } - } - - 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 => { - if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { + if (GetEffectiveAcl(d) === AclAdmin && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(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)!)) { + if (data && GetEffectiveAcl(data) === AclAdmin && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(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)!)) { + if (GetEffectiveAcl(d) === AclAdmin && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(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)!)) { + if (data && GetEffectiveAcl(data) === AclAdmin && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, data, inheritingFromCollection); } }); } - changed && fetchProto(target); // updates target[AclSym] when changes to acls have been made + layoutDocChanged && fetchProto(target); // updates target[AclSym] when changes to acls have been made + dataDocChanged && fetchProto(dataDoc); } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", -- cgit v1.2.3-70-g09d2 From 624de3234c8daccdeb0d759c407cbd72880d3b35 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 15 Aug 2020 16:51:30 +0530 Subject: mainly ui --- src/client/views/collections/collectionFreeForm/PropertiesView.scss | 1 - src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index aee28366a..ddaca7d42 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -267,7 +267,6 @@ padding: 3px; align-items: center; border-bottom: 0.5px solid grey; - cursor: pointer; &:hover .propertiesView-sharingTable-item-name { overflow-x: unset; diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index b38eed495..5c1ec1280 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -389,7 +389,7 @@ export class PropertiesView extends React.Component { 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/* && sidebarUsersDisplayed![name] !== false*/) { + if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) { tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!)); } } @@ -402,7 +402,8 @@ export class PropertiesView extends React.Component { // } // }) - // shifts the current user and the owner to the top of the doc. + // shifts the current user, owner, public to the top of the doc. + tableEntries.unshift(this.sharingItem("Public", effectiveAcl, AclMap.get(this.selectedDoc![AclSym]["ACL-Public"])!)) tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); -- cgit v1.2.3-70-g09d2 From e7fd28e27e7389c67c22410ed1a3ff313556a153 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 15 Aug 2020 19:20:52 +0530 Subject: more alias stuff --- src/client/util/SharingManager.tsx | 4 ++-- src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 9d79188a3..30935c5dd 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -165,7 +165,7 @@ export default class SharingManager extends React.Component<{}> { users.forEach(({ user, notificationDoc }) => { if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added - else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf((target.aliasOf as Doc || target), DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, (target.aliasOf as Doc || target)); // remove the target from the list if it already exists }); } @@ -235,7 +235,7 @@ export default class SharingManager extends React.Component<{}> { GetEffectiveAcl(target) === AclAdmin && distributeAcls(ACL, permission as SharingPermissions, target); if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); - else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf((target.aliasOf as Doc || target), DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, (target.aliasOf as Doc || target)); } diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 5c1ec1280..5b58d0ef4 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -403,7 +403,7 @@ export class PropertiesView extends React.Component { // }) // shifts the current user, owner, public to the top of the doc. - tableEntries.unshift(this.sharingItem("Public", effectiveAcl, AclMap.get(this.selectedDoc![AclSym]["ACL-Public"])!)) + tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(this.selectedDoc![AclSym]?.["ACL-Public"]) || SharingPermissions.None))); tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); -- cgit v1.2.3-70-g09d2 From a248e49ddbabe1947a3883bba47e786e22e1158a Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 17 Aug 2020 16:21:12 +0530 Subject: added layoutdoc toggles --- src/client/util/SharingManager.scss | 21 +++++++++- src/client/util/SharingManager.tsx | 46 +++++++++++++--------- .../collectionFreeForm/PropertiesView.scss | 14 +++++++ .../collectionFreeForm/PropertiesView.tsx | 26 ++++++++---- 4 files changed, 79 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 7912db74d..42c300712 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -62,6 +62,7 @@ input { height: 10px; + cursor: pointer; } label { @@ -69,11 +70,29 @@ font-style: italic; } } + + .layoutDoc-acls { + display: flex; + flex-direction: column; + float: right; + margin-right: 12; + margin-top: -15; + align-items: center; + + label { + font-weight: normal; + font-style: italic; + } + + input { + cursor: pointer; + } + } } .main-container { display: flex; - margin-top: -10px; + margin-top: -25px; .individual-container, .group-container { diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 30935c5dd..5a863c813 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, AclAdmin, AclPrivate, DocListCast } from "../../fields/Doc"; +import { Doc, Opt, AclAdmin, AclPrivate, DocListCast, DataSym } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; @@ -25,7 +25,6 @@ import { library } from "@fortawesome/fontawesome-svg-core"; library.add(fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); - export interface User { email: string; userDocumentId: string; @@ -47,6 +46,8 @@ interface GroupedOptions { const indType = "!indType/"; const groupType = "!groupType/"; +const storage = "data"; + /** * A user who also has a notificationDoc. */ @@ -55,7 +56,6 @@ interface ValidatedUser { notificationDoc: Doc; } -const storage = "data"; @observer export default class SharingManager extends React.Component<{}> { @@ -75,7 +75,8 @@ export default class SharingManager extends React.Component<{}> { // if both showUserOptions and showGroupOptions are false then both are displayed @observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component) @observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component) - private populating: boolean = false; + private populating: boolean = false; // whether the list of users is populating or not + @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used // private get linkVisible() { // return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false; @@ -176,7 +177,6 @@ export default class SharingManager extends React.Component<{}> { */ shareWithAddedMember = (group: Doc, emailId: string) => { const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!; - if (group.docsShared) DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); } @@ -184,9 +184,12 @@ export default class SharingManager extends React.Component<{}> { * Called from the properties sidebar to change permissions of a user. */ 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); + if (shareWith !== "Public") { + 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); + } + else if (GetEffectiveAcl(target) === AclAdmin) distributeAcls("ACL-Public", permission, target); } /** @@ -370,8 +373,8 @@ export default class SharingManager extends React.Component<{}> { * @returns the main interface of the SharingManager. */ private get sharingInterface() { - const groupList = GroupManager.Instance?.getAllGroups() || []; + const groupList = GroupManager.Instance?.getAllGroups() || []; const sortedUsers = this.users.slice().sort(this.sortUsers) .map(({ user: { email } }) => ({ label: email, value: indType + email })); const sortedGroups = groupList.slice().sort(this.sortGroups) @@ -404,17 +407,19 @@ 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 users = this.individualSort === "ascending" ? this.users.slice().sort(this.sortUsers) : this.individualSort === "descending" ? this.users.slice().sort(this.sortUsers).reverse() : this.users; + const groups = this.groupSort === "ascending" ? groupList.slice().sort(this.sortGroups) : this.groupSort === "descending" ? groupList.slice().sort(this.sortGroups).reverse() : groupList; - const effectiveAcl = this.targetDoc ? GetEffectiveAcl(this.targetDoc) : AclPrivate; + const targetDoc = this.layoutDocAcls ? this.targetDoc : this.targetDoc?.[DataSym]; + + const effectiveAcl = targetDoc ? GetEffectiveAcl(targetDoc) : AclPrivate; // the list of users shared with const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { const userKey = user.email.replace('.', '_'); - const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`]); + const permissions = StrCast(targetDoc?.[`ACL-${userKey}`]); - return !permissions || user.email === this.targetDoc?.author ? null : ( + return !permissions || user.email === targetDoc?.author ? (null) : (
{ key={"owner"} className={"container"} > - {this.targetDoc?.author === Doc.CurrentUserEmail ? "Me" : this.targetDoc?.author} + {targetDoc?.author === Doc.CurrentUserEmail ? "Me" : targetDoc?.author}
Owner @@ -454,7 +459,7 @@ export default class SharingManager extends React.Component<{}> {
), - this.targetDoc?.author !== Doc.CurrentUserEmail ? + targetDoc?.author !== Doc.CurrentUserEmail ? (
{ Me
- {this.targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]} + {targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]}
@@ -472,7 +477,7 @@ export default class SharingManager extends React.Component<{}> { // the list of groups shared with const groupListContents = groups.map(group => { - const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`]); + const permissions = StrCast(targetDoc?.[`ACL-${StrCast(group.groupName)}`]); return !permissions ? null : (
{
*/}
-

Share {this.focusOn(StrCast(this.targetDoc?.title, "this document"))}

+

Share {this.focusOn(StrCast(targetDoc?.title, "this document"))}

@@ -569,6 +574,9 @@ export default class SharingManager extends React.Component<{}> { this.showUserOptions = !this.showUserOptions)} /> this.showGroupOptions = !this.showGroupOptions)} />
+
+ this.layoutDocAcls = !this.layoutDocAcls)} checked={this.layoutDocAcls} /> +
}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index ddaca7d42..535581f2e 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -121,6 +121,19 @@ padding: 10px; margin-left: 5px; + .propertiesView-acls-checkbox { + float: right; + height: 20px; + margin-top: -20px; + margin-right: -15; + + .propertiesView-acls-checkbox-text { + font-size: 7px; + margin-top: -10px; + margin-left: 6px; + } + } + .change-buttons { display: flex; @@ -259,6 +272,7 @@ background-color: #ececec; max-height: 130px; overflow-y: scroll; + width: 92%; .propertiesView-sharingTable-item { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 5b58d0ef4..85a1d7137 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, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync } from "../../../../fields/Doc"; +import { Doc, Field, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync, DataSym } from "../../../../fields/Doc"; import { ComputedField } from "../../../../fields/ScriptField"; import { EditableView } from "../../EditableView"; import { KeyValueBox } from "../../nodes/KeyValueBox"; @@ -73,6 +73,7 @@ export class PropertiesView extends React.Component { @observable openTransform: boolean = true; // @observable selectedUser: string = ""; // @observable addButtonPressed: boolean = false; + @observable layoutDocAcls: boolean = false; //Pres Trails booleans: @observable openPresTransitions: boolean = false; @@ -386,11 +387,12 @@ export class PropertiesView extends React.Component { const tableEntries = []; // DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => { - if (this.selectedDoc![AclSym]) { - for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) { + const target = this.layoutDocAcls ? this.selectedDoc! : this.selectedDoc![DataSym]; + if (target[AclSym]) { + for (const [key, value] of Object.entries(target[AclSym])) { const name = key.substring(4).replace("_", "."); - if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) { - tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!)); + if (name !== Doc.CurrentUserEmail && name !== target.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) { + tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value as symbol)!)); } } } @@ -403,9 +405,9 @@ export class PropertiesView extends React.Component { // }) // shifts the current user, owner, public to the top of the doc. - tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(this.selectedDoc![AclSym]?.["ACL-Public"]) || SharingPermissions.None))); - tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); - if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); + tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(target[AclSym]?.["ACL-Public"]) || SharingPermissions.None))); + tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === target.author ? "Owner" : AclMap.get(effectiveAcl)!)); + if (Doc.CurrentUserEmail !== target.author) tableEntries.unshift(this.sharingItem(StrCast(target.author), effectiveAcl, "Owner")); return
{tableEntries} @@ -867,6 +869,14 @@ export class PropertiesView extends React.Component {
{!this.openSharing ? (null) :
+
+ this.layoutDocAcls = !this.layoutDocAcls)} + checked={this.layoutDocAcls} + />; +
Layout
+
{this.sharingTable} {/*