From 1410392575b411f49601ce039787b6052542b711 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 3 Jul 2020 21:50:56 +0530 Subject: can now exit modal by clicking outside it --- src/client/util/SettingsManager.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client/util/SettingsManager.tsx') diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 9888cce48..fa2b20095 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -134,6 +134,7 @@ export default class SettingsManager extends React.Component<{}> { interactive={true} dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} overlayDisplayedOpacity={this.overlayOpacity} + closeOnExternalClick={this.close} /> ); } -- cgit v1.2.3-70-g09d2 From 6f985b10f71ace2303b669d4e2a1165ff3a29eda Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 10 Jul 2020 18:24:32 +0530 Subject: added _chromeStatus to playground fields --- src/client/util/SettingsManager.tsx | 2 ++ src/client/views/MainView.tsx | 5 +---- src/client/views/collections/CollectionView.tsx | 2 +- src/fields/util.ts | 2 -- 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src/client/util/SettingsManager.tsx') diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index fa2b20095..ecc17eec1 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -11,6 +11,7 @@ import { Networking } from "../Network"; import { CurrentUserUtils } from "./CurrentUserUtils"; import { Utils } from "../../Utils"; import { Doc } from "../../fields/Doc"; +import GroupManager from "./GroupManager"; library.add(fa.faWindowClose); @@ -100,6 +101,7 @@ export default class SettingsManager extends React.Component<{}> { + {this.settingsContent === "password" ?
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 81195b550..1bda9e9c2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -88,7 +88,7 @@ export class MainView extends React.Component { public isPointerDown = false; componentDidMount() { - DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType"]); // can play with these fields on someone else's + DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's const tag = document.createElement('script'); @@ -454,9 +454,6 @@ export class MainView extends React.Component { -
{this.docButtons} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 34d67905e..47b6dc058 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -136,7 +136,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); } else { added.map(doc => { diff --git a/src/fields/util.ts b/src/fields/util.ts index 77855887e..ebfc3933a 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -81,12 +81,10 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number } //if (typeof value === "object" && !(value instanceof ObjectField)) debugger; - // remove below lines to prevent saving changes to server if (writeToServer) { if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } }); else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); } else { - console.log("not writing to server") DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue); } UndoManager.AddEvent({ -- cgit v1.2.3-70-g09d2 From 7543ca061700fda8286e6dd3f4374a877ccf929c Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 16 Jul 2020 13:00:12 +0530 Subject: can't change acl field to non-acl (through kvp) now + added playground mode button to settings --- src/client/util/SettingsManager.scss | 2 ++ src/client/util/SettingsManager.tsx | 13 +++++++++++-- src/client/util/SharingManager.tsx | 2 -- src/client/views/nodes/DocumentView.tsx | 2 +- src/fields/util.ts | 3 +++ 5 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src/client/util/SettingsManager.tsx') diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 6d394a38d..c1627e69f 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -52,6 +52,7 @@ .settings-body { display: flex; justify-content: space-between; + margin-top: -10; .settings-type { display: flex; @@ -105,6 +106,7 @@ text-transform: uppercase; letter-spacing: 2px; font-size: 120%; + margin-top: 0; } .container { diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index d54a39943..9d91568cf 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -14,8 +14,9 @@ import { Doc } from "../../fields/Doc"; import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; +import { togglePlaygroundMode } from "../../fields/util"; -library.add(fa.faWindowClose); +library.add(fa.faTimes); @observer export default class SettingsManager extends React.Component<{}> { @@ -26,6 +27,7 @@ export default class SettingsManager extends React.Component<{}> { @observable private settingsContent = "password"; @observable private errorText = ""; @observable private successText = ""; + @observable private playgroundMode = false; private curr_password_ref = React.createRef(); private new_password_ref = React.createRef(); private new_confirm_ref = React.createRef(); @@ -95,19 +97,26 @@ export default class SettingsManager extends React.Component<{}> { HypothesisAuthenticationManager.Instance.fetchAccessToken(true) } + @action + togglePlaygroundMode = () => { + togglePlaygroundMode(); + this.playgroundMode = !this.playgroundMode; + } + private get settingsInterface() { return (

settings

- +
+ + -
{this.settingsContent === "password" ?
@@ -155,8 +155,6 @@ export default class SettingsManager extends React.Component<{}> { contents={this.settingsInterface} isDisplayed={this.isOpen} interactive={true} - dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} - overlayDisplayedOpacity={this.overlayOpacity} closeOnExternalClick={this.close} /> ); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index fe7324d5c..8b3ac2613 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,13 +1,12 @@ 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, DataSym, DocListCast } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; import { Utils } from "../../Utils"; import "./SharingManager.scss"; -import { Id } from "../../fields/FieldSymbols"; import { observer } from "mobx-react"; import { library } from '@fortawesome/fontawesome-svg-core'; import * as fa from '@fortawesome/free-solid-svg-icons'; @@ -82,6 +81,7 @@ export default class SharingManager extends React.Component<{}> { this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; + this.permissions = SharingPermissions.Edit; })); } @@ -127,9 +127,11 @@ export default class SharingManager extends React.Component<{}> { const target = this.targetDoc!; const ACL = `ACL-${StrCast(group.groupName)}`; + // fix this - not needed (here and setinternalsharing and removegroup) + // target[ACL] = permission; + // Doc.GetProto(target)[ACL] = permission; - target[ACL] = permission; - Doc.GetProto(target)[ACL] = permission; + this.distributeAcls(ACL, permission as SharingPermissions); group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); @@ -170,7 +172,9 @@ export default class SharingManager extends React.Component<{}> { DocListCastAsync(group.docsShared).then(resolved => { resolved?.forEach(doc => { const ACL = `ACL-${StrCast(group.groupName)}`; - doc[ACL] = "Not Shared"; + // doc[ACL] = doc[DataSym][ACL] = "Not Shared"; + + this.distributeAcls(ACL, SharingPermissions.None, doc); const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); @@ -189,8 +193,10 @@ export default class SharingManager extends React.Component<{}> { const ACL = `ACL-${key}`; - target[ACL] = permission; - Doc.GetProto(target)[ACL] = permission; + // target[ACL] = permission; + // Doc.GetProto(target)[ACL] = permission; + + this.distributeAcls(ACL, permission as SharingPermissions); if (permission !== SharingPermissions.None) { DocListCastAsync(notificationDoc[storage]).then(resolved => { @@ -202,6 +208,40 @@ export default class SharingManager extends React.Component<{}> { Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); }); } + } + + @action + distributeAcls = (key: string, acl: SharingPermissions, doc?: Doc) => { + const target = doc ? doc : this.targetDoc!; + const dataDoc = target[DataSym]; + target[key] = acl; + if (dataDoc) dataDoc[key] = acl; + // dataDoc[key] = target[key] = acl; + // next line distributes the acl to all children of the target + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { + if (d.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, data); + data[key] = acl; + } + }); + + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { + if (d.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, data); + data[key] = acl; + } + console.log(d, d[DataSym]); + }); } @@ -308,9 +348,9 @@ export default class SharingManager extends React.Component<{}> { const groupList = GroupManager.Instance?.getAllGroups() || []; const sortedUsers = this.users.sort(this.sortUsers) - .map(({ user: { email } }) => ({ label: email, value: "!indType/" + email })); + .map(({ user: { email } }) => ({ label: email, value: indType + email })); const sortedGroups = groupList.sort(this.sortGroups) - .map(({ groupName }) => ({ label: StrCast(groupName), value: "!groupType/" + StrCast(groupName) })); + .map(({ groupName }) => ({ label: StrCast(groupName), value: groupType + StrCast(groupName) })); const options: GroupOptions[] = GroupManager.Instance ? [ diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index eb58d8a3e..8740d17c2 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly } from '../../fields/Doc'; +import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym } from '../../fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast, BoolCast, ScriptCast } from '../../fields/Types'; @@ -7,7 +7,8 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl } from '../../fields/util'; +import { GetEffectiveAcl, getPlaygroundMode } from '../../fields/util'; +import { SharingPermissions } from '../util/SharingManager'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -92,6 +93,13 @@ export function ViewBoxAnnotatableComponent

([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit] + ]); + lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result; styleFromLayoutString = (scale: number) => { @@ -139,11 +147,21 @@ export function ViewBoxAnnotatableComponent

!docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.dataDoc); + + 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 (added.length) { - if (effectiveAcl === AclReadonly) { + if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; } else if (effectiveAcl === AclAddonly) { - added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); + added.map(doc => console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc))); } else { added.map(doc => doc.context = this.props.Document); targetDataDoc[this.annotationKey] = new List([...docList, ...added]); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5c6781f4c..61d2246db 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -91,7 +91,7 @@ export class MainView extends React.Component { public isPointerDown = false; componentDidMount() { - DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's + DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus", "data-annotations"]); // can play with these fields on someone else's const tag = document.createElement('script'); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 50d66c567..17567ea73 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -8,7 +8,7 @@ import * as React from 'react'; import Lightbox from 'react-image-lightbox-with-rotate'; import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app import { DateField } from '../../../fields/DateField'; -import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit } from '../../../fields/Doc'; +import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit, AclSym, AclPrivate } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; @@ -48,6 +48,7 @@ import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from "./CollectionTreeView"; import './CollectionView.scss'; import CollectionMenu from './CollectionMenu'; +import { SharingPermissions } from '../../util/SharingManager'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -106,6 +107,13 @@ export class CollectionView extends Touchable([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit] + ]); + get collectionViewType(): CollectionViewType | undefined { const viewField = StrCast(this.props.Document._viewType); if (CollectionView._safeMode) { @@ -128,11 +136,26 @@ export class CollectionView extends Touchable !docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.props.Document); + if (this.props.Document[AclSym]) { + // change so it only adds if more restrictive + added.forEach(d => { + console.log(d[Id]); + const dataDoc = d[DataSym]; + console.log(dataDoc[Id]); + for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + dataDoc[key] = d[key] = this.AclMap.get(value); + } + dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + + }); + } + if (added.length) { if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5dfc14a4a..ef57171bf 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -109,15 +109,15 @@ const AclMap = new Map([ ]); export function fetchProto(doc: Doc) { - if (doc.author !== Doc.CurrentUserEmail) { - untracked(() => { - const permissions: { [key: string]: symbol } = {}; + // if (doc.author !== Doc.CurrentUserEmail) { + untracked(() => { + const permissions: { [key: string]: symbol } = {}; - Object.keys(doc).filter(key => key.startsWith("ACL")).forEach(key => permissions[key] = AclMap.get(StrCast(doc[key]))!); + Object.keys(doc).filter(key => key.startsWith("ACL")).forEach(key => permissions[key] = AclMap.get(StrCast(doc[key]))!); - if (Object.keys(permissions).length) doc[AclSym] = permissions; - }); - } + if (Object.keys(permissions).length) doc[AclSym] = permissions; + }); + // } if (doc.proto instanceof Promise) { doc.proto.then(fetchProto); diff --git a/src/fields/util.ts b/src/fields/util.ts index 6d2d715bd..ee01f6213 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -129,28 +129,31 @@ export function setGroups(groups: string[]) { export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclEdit; - const HierarchyMapping = new Map([ - [AclPrivate, 0], - [AclReadonly, 1], - [AclAddonly, 2], - [AclEdit, 3] - ]); - if (!target[AclSym] && target instanceof Doc) { fetchProto(target); } + if (target[AclSym] && Object.keys(target[AclSym]).length) { - if (target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; + // console.log(target[AclSym]); + + if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; - if (target[AclSym].ACL) return target[AclSym].ACL; + // if (target[AclSym].ACL) return target[AclSym].ACL; let effectiveAcl = AclPrivate; let aclPresent = false; + const HierarchyMapping = new Map([ + [AclPrivate, 0], + [AclReadonly, 1], + [AclAddonly, 2], + [AclEdit, 3] + ]); + for (const [key, value] of Object.entries(target[AclSym])) { if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) { if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) { -- cgit v1.2.3-70-g09d2