([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
From e613f4ebc268bb9d8a0bd1ea2f07fef73a870199 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Mon, 20 Jul 2020 17:01:39 -0400
Subject: fixed noAutoscroll functionality for creator icons
---
src/client/documents/Documents.ts | 1 +
src/client/util/CurrentUserUtils.ts | 7 +++----
src/client/util/DragManager.ts | 2 +-
src/client/views/nodes/FontIconBox.scss | 3 ++-
src/fields/ScriptField.ts | 2 +-
5 files changed, 8 insertions(+), 7 deletions(-)
(limited to 'src')
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 8e7d125b0..2d74c462d 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -69,6 +69,7 @@ export interface DocumentOptions {
_showTitle?: string; // which field to display in the title area. leave empty to have no title
_showCaption?: string; // which field to display in the caption area. leave empty to have no caption
_scrollTop?: number; // scroll location for pdfs
+ _noAutoscroll?: boolean;// whether collectoins autoscroll when this item is dragged
_chromeStatus?: string;
_viewType?: string; // sub type of a collection
_gridGap?: number; // gap between items in masonry view
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 4b8c342f1..d53a6fcdb 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -466,6 +466,7 @@ export class CurrentUserUtils {
onClick: click ? ScriptField.MakeScript(click) : undefined,
ischecked: ischecked ? ComputedField.MakeFunction(ischecked) : undefined,
activeInkPen,
+ _noAutoscroll: true,
backgroundColor,
removeDropProperties: new List(["dropAction"]),
dragFactory,
@@ -735,15 +736,13 @@ export class CurrentUserUtils {
}
static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
- ...opts,
- _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
+ ...opts, _noAutoscroll: true, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true
})) as any as Doc
static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
- ...opts,
- dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
+ ...opts, _noAutoscroll: true, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
})) as any as Doc
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 6a3108157..007336190 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -435,7 +435,7 @@ export namespace DragManager {
const complete = new DragCompleteEvent(false, dragData);
- if (target && !options?.noAutoscroll) {
+ if (target && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._noAutoscroll)) {
target.dispatchEvent(
new CustomEvent("dashDragging", {
bubbles: true,
diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss
index fe0f067ad..5b85d8b0b 100644
--- a/src/client/views/nodes/FontIconBox.scss
+++ b/src/client/views/nodes/FontIconBox.scss
@@ -11,7 +11,6 @@
.fontIconBox-label {
background: gray;
color:white;
- margin-left: -10px;
border-radius: 8px;
width:100%;
position: absolute;
@@ -19,6 +18,8 @@
font-size: 8px;
margin-top:4px;
letter-spacing: normal;
+ left: 0;
+ overflow: hidden;
}
svg {
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index ebca19430..4604a2132 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -51,7 +51,7 @@ async function deserializeScript(script: ScriptField) {
return (script as any).script = (ScriptField.DeiconifyView ?? (ScriptField.DeiconifyView = ComputedField.MakeFunction('deiconifyView(self)')))?.script;
}
if (script.script.originalScript === 'convertToButtons(dragData)') {
- return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)')))?.script;
+ return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)', { dragData: "DocumentDragData" })))?.script;
}
console.log(script.script.originalScript);
const captures: ProxyField = (script as any).captures;
--
cgit v1.2.3-70-g09d2
From 4cc4f636fdf020e001c78a58b771032f94396fa1 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Mon, 20 Jul 2020 17:19:23 -0400
Subject: fixed active flag for pdfs
---
src/client/views/pdf/PDFMenu.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx
index 00c56d73e..6592c488b 100644
--- a/src/client/views/pdf/PDFMenu.tsx
+++ b/src/client/views/pdf/PDFMenu.tsx
@@ -47,7 +47,7 @@ export default class PDFMenu extends AntimodeMenu {
public AddTag: (key: string, value: string) => boolean = returnFalse;
public PinToPres: () => void = unimplementedFunction;
public Marquee: { left: number; top: number; width: number; height: number; } | undefined;
- public get Active() { return this._opacity ? true : false; }
+ public get Active() { return this._left > 0; }
constructor(props: Readonly<{}>) {
super(props);
--
cgit v1.2.3-70-g09d2
From fa68e59c31c9ad4b4458933a246440807529794b Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Tue, 21 Jul 2020 12:15:39 +0530
Subject: more addonly fixes
---
src/client/documents/Documents.ts | 3 +++
src/client/views/DocComponent.tsx | 10 ++++++----
src/client/views/MainView.tsx | 2 +-
src/client/views/collections/CollectionSubView.tsx | 6 ++++++
4 files changed, 16 insertions(+), 5 deletions(-)
(limited to 'src')
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 8e7d125b0..c783a761a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -549,6 +549,9 @@ export namespace Docs {
const dataDoc = MakeDataDelegate(proto, protoProps, data, fieldKey);
const viewDoc = Doc.MakeDelegate(dataDoc, delegId);
+ // so that the list of annotations is already initialised, prevents issues in addonly
+ dataDoc[fieldKey + "-annotations"] = new List();
+
proto.links = ComputedField.MakeFunction("links(self)");
viewDoc.author = Doc.CurrentUserEmail;
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 8740d17c2..2519360da 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -1,4 +1,4 @@
-import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym } from '../../fields/Doc';
+import { Doc, Opt, DataSym, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym, DocListCastAsync, DocListCast } from '../../fields/Doc';
import { Touchable } from './Touchable';
import { computed, action, observable } from 'mobx';
import { Cast, BoolCast, ScriptCast } from '../../fields/Types';
@@ -126,11 +126,13 @@ export function ViewBoxAnnotatableComponent doc.annotationOn = undefined);
const targetDataDoc = this.dataDoc;
const value = DocListCast(targetDataDoc[this.annotationKey]);
- const result = value.filter(v => !docs.includes(v));
- if (result.length !== value.length) {
- targetDataDoc[this.annotationKey] = new List(result);
+ const toRemove = value.filter(v => docs.includes(v));
+ // can't assign new List(result) to this because you can't assign new values in addonly
+ if (toRemove.length !== 0) {
+ toRemove.forEach(doc => Doc.RemoveDocFromList(targetDataDoc, this.annotationKey, doc));
return true;
}
+
return false;
}
// if the moved document is already in this overlay collection nothing needs to be done.
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7184e8225..aadfdef21 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -90,7 +90,7 @@ export class MainView extends React.Component {
public isPointerDown = false;
componentDidMount() {
- DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus", "data-annotations"]); // 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');
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 3794088d4..8a3c2144e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -91,6 +91,11 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?:
// to its children which may be templates.
// If 'annotationField' is specified, then all children exist on that field of the extension document, otherwise, they exist directly on the data document under 'fieldKey'
@computed get dataField() {
+ // sets the dataDoc's data field to an empty list if the data field is undefined - prevents issues with addonly
+ // setTimeout changes it outside of the @computed section
+ setTimeout(() => {
+ if (!this.dataDoc[this.props.annotationsKey || this.props.fieldKey]) this.dataDoc[this.props.annotationsKey || this.props.fieldKey] = new List();
+ }, 1000);
return this.dataDoc[this.props.annotationsKey || this.props.fieldKey];
}
@@ -418,4 +423,5 @@ import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTex
import { CollectionView } from "./CollectionView";
import { SelectionManager } from "../../util/SelectionManager";
import { OverlayView } from "../OverlayView";
+import { setTimeout } from "timers";
--
cgit v1.2.3-70-g09d2
From c4499c610f377be4b80cf2999d25f97b619d4727 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Tue, 21 Jul 2020 17:17:47 +0530
Subject: distributing acls shifted to util.ts
---
src/client/util/SharingManager.tsx | 47 +++------------
src/client/views/DocComponent.tsx | 34 ++++++-----
src/client/views/collections/CollectionView.tsx | 76 +++++++++++++------------
src/fields/util.ts | 46 ++++++++++++++-
4 files changed, 109 insertions(+), 94 deletions(-)
(limited to 'src')
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 8b3ac2613..d3bc84770 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,4 +1,4 @@
-import { observable, runInAction, action } from "mobx";
+import { observable, runInAction, action, computed } from "mobx";
import * as React from "react";
import MainViewModal from "../views/MainViewModal";
import { Doc, Opt, DocListCastAsync, DataSym, DocListCast } from "../../fields/Doc";
@@ -20,6 +20,7 @@ import GroupMemberView from "./GroupMemberView";
import Select from "react-select";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { List } from "../../fields/List";
+import { distributeAcls } from "../../fields/util";
library.add(fa.faCopy, fa.faTimes);
@@ -131,7 +132,7 @@ export default class SharingManager extends React.Component<{}> {
// target[ACL] = permission;
// Doc.GetProto(target)[ACL] = permission;
- this.distributeAcls(ACL, permission as SharingPermissions);
+ distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!);
group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]);
@@ -174,7 +175,7 @@ export default class SharingManager extends React.Component<{}> {
const ACL = `ACL-${StrCast(group.groupName)}`;
// doc[ACL] = doc[DataSym][ACL] = "Not Shared";
- this.distributeAcls(ACL, SharingPermissions.None, doc);
+ distributeAcls(ACL, SharingPermissions.None, doc);
const members: string[] = JSON.parse(StrCast(group.members));
const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
@@ -186,6 +187,7 @@ export default class SharingManager extends React.Component<{}> {
}
}
+ // @action
setInternalSharing = (recipient: ValidatedUser, permission: string) => {
const { user, notificationDoc } = recipient;
const target = this.targetDoc!;
@@ -196,7 +198,7 @@ export default class SharingManager extends React.Component<{}> {
// target[ACL] = permission;
// Doc.GetProto(target)[ACL] = permission;
- this.distributeAcls(ACL, permission as SharingPermissions);
+ distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!);
if (permission !== SharingPermissions.None) {
DocListCastAsync(notificationDoc[storage]).then(resolved => {
@@ -210,40 +212,6 @@ export default class SharingManager extends React.Component<{}> {
}
}
- @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]);
- });
-
- }
// private setExternalSharing = (permission: string) => {
// const sharingDoc = this.sharingDoc;
@@ -344,7 +312,6 @@ export default class SharingManager extends React.Component<{}> {
}
private get sharingInterface() {
-
const groupList = GroupManager.Instance?.getAllGroups() || [];
const sortedUsers = this.users.sort(this.sortUsers)
@@ -368,7 +335,7 @@ 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 userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { // can't use async here
+ const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => {
const userKey = user.email.replace('.', '_');
const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None);
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 2519360da..655be80ef 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -150,24 +150,28 @@ 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 && !getPlaygroundMode()) {
return false;
- } else if (effectiveAcl === AclAddonly) {
- 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]);
- targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ }
+ else {
+ if (this.props.Document[AclSym]) {
+ added.forEach(d => {
+ const dataDoc = d[DataSym];
+ dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym];
+ for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
+ dataDoc[key] = d[key] = this.AclMap.get(value);
+ }
+ });
+ }
+ if (effectiveAcl === AclAddonly) {
+ 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]);
+ targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now()));
+ }
}
}
return true;
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 17567ea73..5cef6c44e 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 } from '../../../fields/util';
+import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, distributeAcls } 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,46 +142,48 @@ 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;
- } else if (effectiveAcl === AclAddonly) {
- added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc));
- } else {
- added.map(doc => {
- const context = Cast(doc.context, Doc, null);
- if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
- const pushpin = Docs.Create.FontIconDocument({
- title: "pushpin",
- icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
- _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
- });
- pushpin.isPushpin = true;
- Doc.GetProto(pushpin).annotationOn = doc.annotationOn;
- Doc.SetInPlace(doc, "annotationOn", undefined, true);
- Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin);
- const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
- doc.displayTimecode = undefined;
- }
- doc.context = this.props.Document;
- });
- added.map(add => 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()));
+ }
+ else {
+ if (this.props.Document[AclSym]) {
+ // change so it only adds if more restrictive
+ added.forEach(d => {
+ const dataDoc = d[DataSym];
+ for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
+ distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d);
+ }
+ dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym];
+ });
+ }
+
+ if (effectiveAcl === AclAddonly) {
+ added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc));
+ }
+ else {
+ added.map(doc => {
+ const context = Cast(doc.context, Doc, null);
+ if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
+ const pushpin = Docs.Create.FontIconDocument({
+ title: "pushpin",
+ icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
+ _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null)
+ });
+ pushpin.isPushpin = true;
+ Doc.GetProto(pushpin).annotationOn = doc.annotationOn;
+ Doc.SetInPlace(doc, "annotationOn", undefined, true);
+ Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin);
+ const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", "");
+ doc.displayTimecode = undefined;
+ }
+ doc.context = this.props.Document;
+ });
+ added.map(add => 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()));
+ }
}
}
return true;
diff --git a/src/fields/util.ts b/src/fields/util.ts
index ee01f6213..a714b01e3 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, fetchProto } from "./Doc";
+import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, fetchProto, DataSym, DocListCast } from "./Doc";
import { SerializationHelper } from "../client/util/SerializationHelper";
import { ProxyField, PrefetchProxy } from "./Proxy";
import { RefField } from "./RefField";
@@ -8,7 +8,8 @@ import { action, trace } from "mobx";
import { Parent, OnUpdate, Update, Id, SelfProxy, Self } from "./FieldSymbols";
import { DocServer } from "../client/DocServer";
import { ComputedField } from "./ScriptField";
-import { ScriptCast } from "./Types";
+import { ScriptCast, StrCast } from "./Types";
+import { SharingPermissions } from "../client/util/SharingManager";
function _readOnlySetter(): never {
@@ -168,6 +169,47 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number)
return AclEdit;
}
+export function distributeAcls(key: string, acl: SharingPermissions, target: Doc) {
+
+ const HierarchyMapping = new Map([
+ ["Not Shared", 0],
+ ["Can View", 1],
+ ["Can Add", 2],
+ ["Can Edit", 3]
+ ]);
+
+ const dataDoc = target[DataSym];
+
+ if (!target[key] || HierarchyMapping.get(StrCast(target[key]))! < HierarchyMapping.get(acl)!) target[key] = acl;
+
+ if (dataDoc && (!dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! < HierarchyMapping.get(acl)!)) {
+ dataDoc[key] = acl;
+
+ DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => {
+ if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) {
+ distributeAcls(key, acl, d);
+ d[key] = acl;
+ }
+ const data = d[DataSym];
+ if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) {
+ distributeAcls(key, acl, data);
+ data[key] = acl;
+ }
+ });
+
+ DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => {
+ if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) {
+ distributeAcls(key, acl, d);
+ d[key] = acl;
+ }
+ const data = d[DataSym];
+ if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) {
+ distributeAcls(key, acl, data);
+ data[key] = acl;
+ }
+ });
+ }
+}
const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox",
"chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"];
--
cgit v1.2.3-70-g09d2
From 2d0741800ed626ac3db2a8ac551904cbc0f7848e Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Tue, 21 Jul 2020 09:38:29 -0400
Subject: fixed up autoscrollin a bit. scrolls the correct collection and
waits 250ms to start scrolling.
---
src/client/documents/Documents.ts | 2 +-
src/client/util/CurrentUserUtils.ts | 5 +-
src/client/util/DragManager.ts | 96 ++++++++++++----------
.../collectionFreeForm/CollectionFreeFormView.tsx | 41 +++------
4 files changed, 65 insertions(+), 79 deletions(-)
(limited to 'src')
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2d74c462d..36c8a0d3b 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -69,7 +69,7 @@ export interface DocumentOptions {
_showTitle?: string; // which field to display in the title area. leave empty to have no title
_showCaption?: string; // which field to display in the caption area. leave empty to have no caption
_scrollTop?: number; // scroll location for pdfs
- _noAutoscroll?: boolean;// whether collectoins autoscroll when this item is dragged
+ _noAutoscroll?: boolean;// whether collections autoscroll when this item is dragged
_chromeStatus?: string;
_viewType?: string; // sub type of a collection
_gridGap?: number; // gap between items in masonry view
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index d53a6fcdb..03a75381a 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -466,7 +466,6 @@ export class CurrentUserUtils {
onClick: click ? ScriptField.MakeScript(click) : undefined,
ischecked: ischecked ? ComputedField.MakeFunction(ischecked) : undefined,
activeInkPen,
- _noAutoscroll: true,
backgroundColor,
removeDropProperties: new List(["dropAction"]),
dragFactory,
@@ -736,13 +735,13 @@ export class CurrentUserUtils {
}
static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, {
- ...opts, _noAutoscroll: true, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
+ ...opts, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true,
dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true
})) as any as Doc
static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({
- ...opts, _noAutoscroll: true, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
+ ...opts, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100
})) as any as Doc
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 007336190..4291eee9c 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -7,7 +7,7 @@ import { listSpec } from "../../fields/Schema";
import { SchemaHeaderField } from "../../fields/SchemaHeaderField";
import { ScriptField } from "../../fields/ScriptField";
import { Cast, NumCast, ScriptCast, StrCast } from "../../fields/Types";
-import { emptyFunction } from "../../Utils";
+import { emptyFunction, returnTrue } from "../../Utils";
import { Docs, DocUtils } from "../documents/Documents";
import * as globalCssVariables from "../views/globalCssVariables.scss";
import { UndoManager } from "./UndoManager";
@@ -235,7 +235,8 @@ export namespace DragManager {
e.docDragData && (e.docDragData.droppedDocuments = [bd]);
return e;
};
- options && (options.noAutoscroll = true);
+ options = options ?? {};
+ options.noAutoscroll = true; // these buttons are being dragged on the overlay layer, so scrollin the underlay is not appropriate
StartDrag(eles, new DragManager.DocumentDragData([]), downX, downY, options, finishDrag);
}
@@ -411,6 +412,8 @@ export namespace DragManager {
const yFromTop = downY - elesCont.top;
const xFromRight = elesCont.right - downX;
const yFromBottom = elesCont.bottom - downY;
+ let paused = false;
+ let scrollAwaiter: Opt;
const moveHandler = (e: PointerEvent) => {
e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
if (dragData instanceof DocumentDragData) {
@@ -433,50 +436,55 @@ export namespace DragManager {
const target = document.elementFromPoint(e.x, e.y);
- const complete = new DragCompleteEvent(false, dragData);
-
if (target && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._noAutoscroll)) {
- target.dispatchEvent(
- new CustomEvent("dashDragging", {
- bubbles: true,
- detail: {
- shiftKey: e.shiftKey,
- altKey: e.altKey,
- metaKey: e.metaKey,
- ctrlKey: e.ctrlKey,
- clientX: e.clientX,
- clientY: e.clientY,
- dataTransfer: new DataTransfer,
- button: e.button,
- buttons: e.buttons,
- getModifierState: e.getModifierState,
- movementX: e.movementX,
- movementY: e.movementY,
- pageX: e.pageX,
- pageY: e.pageY,
- relatedTarget: e.relatedTarget,
- screenX: e.screenX,
- screenY: e.screenY,
- detail: e.detail,
- view: e.view ? e.view : new Window,
- nativeEvent: new DragEvent("dashDragging"),
- currentTarget: target,
- target: target,
+ scrollAwaiter && clearTimeout(scrollAwaiter);
+ scrollAwaiter = setTimeout(() => autoScrollHandler(), 250);
+ const autoScrollHandler = () => {
+ target.dispatchEvent(
+ new CustomEvent("dashDragAutoScroll", {
bubbles: true,
- cancelable: true,
- defaultPrevented: true,
- eventPhase: e.eventPhase,
- isTrusted: true,
- preventDefault: e.preventDefault,
- isDefaultPrevented: () => true,
- stopPropagation: e.stopPropagation,
- isPropagationStopped: () => true,
- persist: emptyFunction,
- timeStamp: e.timeStamp,
- type: "dashDragging"
- }
- })
- );
+ detail: {
+ shiftKey: e.shiftKey,
+ altKey: e.altKey,
+ metaKey: e.metaKey,
+ ctrlKey: e.ctrlKey,
+ clientX: e.clientX,
+ clientY: e.clientY,
+ dataTransfer: new DataTransfer,
+ button: e.button,
+ buttons: e.buttons,
+ getModifierState: e.getModifierState,
+ movementX: e.movementX,
+ movementY: e.movementY,
+ pageX: e.pageX,
+ pageY: e.pageY,
+ relatedTarget: e.relatedTarget,
+ screenX: e.screenX,
+ screenY: e.screenY,
+ detail: e.detail,
+ view: e.view ? e.view : new Window,
+ nativeEvent: new DragEvent("dashDragAutoScroll"),
+ currentTarget: target,
+ target: target,
+ bubbles: true,
+ cancelable: true,
+ defaultPrevented: true,
+ eventPhase: e.eventPhase,
+ isTrusted: true,
+ preventDefault: () => "not implemented for this event" ? false : false,
+ isDefaultPrevented: () => "not implemented for this event" ? false : false,
+ stopPropagation: () => "not implemented for this event" ? false : false,
+ isPropagationStopped: () => "not implemented for this event" ? false : false,
+ persist: emptyFunction,
+ timeStamp: e.timeStamp,
+ type: "dashDragAutoScroll"
+ }
+ })
+ );
+
+ scrollAwaiter && clearTimeout(scrollAwaiter);
+ SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(() => autoScrollHandler(), 25));
+ }
}
const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 01b0c81d8..412f91417 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -85,8 +85,6 @@ export class CollectionFreeFormView extends CollectionSubView = new Map();
@@ -582,7 +580,6 @@ export class CollectionFreeFormView extends CollectionSubView {
- this._lastClientY = this._lastClientX = undefined;
if (InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) return;
document.removeEventListener("pointermove", this.onPointerMove);
@@ -1152,16 +1149,12 @@ export class CollectionFreeFormView extends CollectionSubView this._layoutElements = elements || [],
{ fireImmediately: true, name: "doLayout" });
- const handler = (e: any) => this.handleDragging(e, (e as CustomEvent).detail);
-
- document.addEventListener("dashDragging", handler);
+ this._marqueeRef.current?.addEventListener("dashDragAutoScroll", this.onDragAutoScroll as any);
}
componentWillUnmount() {
this._layoutComputeReaction?.();
-
- const handler = (e: any) => this.handleDragging(e, (e as CustomEvent).detail);
- document.removeEventListener("dashDragging", handler);
+ this._marqueeRef.current?.removeEventListener("dashDragAutoScroll", this.onDragAutoScroll as any);
}
@computed get views() { return this._layoutElements.filter(ele => ele.bounds && !ele.bounds.z).map(ele => ele.ele); }
@@ -1176,39 +1169,25 @@ export class CollectionFreeFormView extends CollectionSubView
@action
- handleDragging = (e: CustomEvent, de: DragEvent) => {
- if ((e as any).handlePan) return;
+ onDragAutoScroll = (e: CustomEvent) => {
+ if ((e as any).handlePan || this.props.isAnnotationOverlay) return;
(e as any).handlePan = true;
- this._lastClientY = e.detail.clientY;
- this._lastClientX = e.detail.clientX;
if (this._marqueeRef?.current) {
const dragX = e.detail.clientX;
const dragY = e.detail.clientY;
const bounds = this._marqueeRef.current?.getBoundingClientRect();
- const deltaX = dragX - bounds.left < 25 ? -2 : bounds.right - dragX < 25 ? 2 : 0;
- const deltaY = dragY - bounds.top < 25 ? -2 : bounds.bottom - dragY < 25 ? 2 : 0;
- (deltaX !== 0 || deltaY !== 0) && this.continuePan(deltaX, deltaY);
+ const deltaX = dragX - bounds.left < 25 ? -(25 + (bounds.left - dragX)) : bounds.right - dragX < 25 ? 25 - (bounds.right - dragX) : 0;
+ const deltaY = dragY - bounds.top < 25 ? -(25 + (bounds.top - dragY)) : bounds.bottom - dragY < 25 ? 25 - (bounds.bottom - dragY) : 0;
+ if (deltaX !== 0 || deltaY !== 0) {
+ this.Document._panY = NumCast(this.Document._panY) + deltaY / 2;
+ this.Document._panX = NumCast(this.Document._panX) + deltaX / 2;
+ }
}
e.stopPropagation();
}
- continuePan = (deltaX: number, deltaY: number) => {
- setTimeout(action(() => {
- const dragY = this._lastClientY;
- const dragX = this._lastClientX;
- if (dragY !== undefined && dragX !== undefined && this._marqueeRef.current) {
- const bounds = this._marqueeRef.current.getBoundingClientRect();
- this.Document._panY = NumCast(this.Document._panY) + deltaY;
- this.Document._panX = NumCast(this.Document._panX) + deltaX;
- if (dragY - bounds.top < 25 || bounds.bottom - dragY < 25 || dragX - bounds.left < 25 || bounds.right - dragX < 25) {
- this.continuePan(deltaX, deltaY);
- }
- } else this._lastClientY !== undefined && this._lastClientX !== undefined && this.continuePan(deltaX, deltaY);
- }), 50);
- }
-
promoteCollection = undoBatch(action(() => {
const childDocs = this.childDocs.slice();
childDocs.forEach(doc => {
--
cgit v1.2.3-70-g09d2
From 3d06cdd362d58dfbc8d6efdcd9dc59250ab003a4 Mon Sep 17 00:00:00 2001
From: usodhi <61431818+usodhi@users.noreply.github.com>
Date: Tue, 21 Jul 2020 23:16:49 +0530
Subject: distributeAcls only changes if container is more restrictive
---
src/client/util/SharingManager.tsx | 14 +++++---------
src/client/views/DocComponent.tsx | 2 +-
src/client/views/collections/CollectionView.tsx | 6 +++---
src/client/views/nodes/DocumentView.tsx | 5 +++--
src/fields/util.ts | 18 +++++++-----------
5 files changed, 19 insertions(+), 26 deletions(-)
(limited to 'src')
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index d3bc84770..9c857a7c0 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,7 +1,7 @@
-import { observable, runInAction, action, computed } from "mobx";
+import { observable, runInAction, action } from "mobx";
import * as React from "react";
import MainViewModal from "../views/MainViewModal";
-import { Doc, Opt, DocListCastAsync, DataSym, DocListCast } from "../../fields/Doc";
+import { Doc, Opt, DocListCastAsync } from "../../fields/Doc";
import { DocServer } from "../DocServer";
import { Cast, StrCast } from "../../fields/Types";
import * as RequestPromise from "request-promise";
@@ -41,9 +41,9 @@ interface GroupOptions {
options: UserOptions[];
}
-const SharingKey = "sharingPermissions";
-const PublicKey = "publicLinkPermissions";
-const DefaultColor = "black";
+// const SharingKey = "sharingPermissions";
+// const PublicKey = "publicLinkPermissions";
+// const DefaultColor = "black";
const groupType = "!groupType/";
const indType = "!indType/";
@@ -192,12 +192,8 @@ export default class SharingManager extends React.Component<{}> {
const { user, notificationDoc } = recipient;
const target = this.targetDoc!;
const key = user.email.replace('.', '_');
-
const ACL = `ACL-${key}`;
- // target[ACL] = permission;
- // Doc.GetProto(target)[ACL] = permission;
-
distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!);
if (permission !== SharingPermissions.None) {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 655be80ef..95c1bcda8 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -165,7 +165,7 @@ export function ViewBoxAnnotatableComponent console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)));
+ added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc));
}
else {
added.map(doc => doc.context = this.props.Document);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 5cef6c44e..9b04deff5 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -151,11 +151,11 @@ export class CollectionView extends Touchable {
- const dataDoc = d[DataSym];
+ // const dataDoc = d[DataSym];
for (const [key, value] of Object.entries(this.props.Document[AclSym])) {
- distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d);
+ distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true);
}
- dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym];
+ // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym];
});
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 803720417..0b5bd707b 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as rp from "request-promise";
-import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclPrivate, AclReadonly } from "../../../fields/Doc";
+import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclPrivate, AclEdit } from "../../../fields/Doc";
import { Document } from '../../../fields/documentSchemas';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -707,6 +707,7 @@ export class DocumentView extends DocComponent(Docu
if (data && data.author === Doc.CurrentUserEmail) data.ACL = acl;
});
}
+
@undoBatch
@action
testAcl = (acl: SharingPermissions) => {
@@ -806,7 +807,7 @@ export class DocumentView extends DocComponent(Docu
});
moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
}
- moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
+ GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" });
!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 a714b01e3..81ccbf6d9 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -137,14 +137,10 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number)
if (target[AclSym] && Object.keys(target[AclSym]).length) {
- // 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;
-
let effectiveAcl = AclPrivate;
let aclPresent = false;
@@ -169,7 +165,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number)
return AclEdit;
}
-export function distributeAcls(key: string, acl: SharingPermissions, target: Doc) {
+export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) {
const HierarchyMapping = new Map([
["Not Shared", 0],
@@ -180,30 +176,30 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
const dataDoc = target[DataSym];
- if (!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;
- if (dataDoc && (!dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! < HierarchyMapping.get(acl)!)) {
+ if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) {
dataDoc[key] = acl;
DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => {
- if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) {
+ if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) {
distributeAcls(key, acl, d);
d[key] = acl;
}
const data = d[DataSym];
- if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) {
+ if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) {
distributeAcls(key, acl, data);
data[key] = acl;
}
});
DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => {
- if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) {
+ if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) {
distributeAcls(key, acl, d);
d[key] = acl;
}
const data = d[DataSym];
- if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) {
+ if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) {
distributeAcls(key, acl, data);
data[key] = acl;
}
--
cgit v1.2.3-70-g09d2
From 12dd45618c0dc595b8e6663bf8d3635dd7161306 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Tue, 21 Jul 2020 16:02:53 -0400
Subject: fixed compile warnings
---
src/client/documents/Documents.ts | 4 +++-
src/client/util/DragManager.ts | 9 ++++-----
src/client/views/DocumentDecorations.tsx | 11 +++++------
src/client/views/MetadataEntryMenu.tsx | 4 ++--
src/client/views/collections/CollectionMenu.tsx | 6 +++---
.../collectionFreeForm/CollectionFreeFormLinkView.tsx | 10 +++++-----
6 files changed, 22 insertions(+), 22 deletions(-)
(limited to 'src')
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 657ba521b..e2569ec70 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -550,7 +550,9 @@ export namespace Docs {
const dataDoc = MakeDataDelegate(proto, protoProps, data, fieldKey);
const viewDoc = Doc.MakeDelegate(dataDoc, delegId);
- // so that the list of annotations is already initialised, prevents issues in addonly
+ // so that the list of annotations is already initialised, prevents issues in addonly.
+ // 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();
proto.links = ComputedField.MakeFunction("links(self)");
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 4291eee9c..837f0b1db 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -412,7 +412,6 @@ export namespace DragManager {
const yFromTop = downY - elesCont.top;
const xFromRight = elesCont.right - downX;
const yFromBottom = elesCont.bottom - downY;
- let paused = false;
let scrollAwaiter: Opt;
const moveHandler = (e: PointerEvent) => {
e.preventDefault(); // required or dragging text menu link item ends up dragging the link button as native drag/drop
@@ -437,8 +436,6 @@ export namespace DragManager {
const target = document.elementFromPoint(e.x, e.y);
if (target && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._noAutoscroll)) {
- scrollAwaiter && clearTimeout(scrollAwaiter);
- scrollAwaiter = setTimeout(() => autoScrollHandler(), 250);
const autoScrollHandler = () => {
target.dispatchEvent(
new CustomEvent("dashDragAutoScroll", {
@@ -483,8 +480,10 @@ export namespace DragManager {
);
scrollAwaiter && clearTimeout(scrollAwaiter);
- SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(() => autoScrollHandler(), 25));
- }
+ SnappingManager.GetIsDragging() && (scrollAwaiter = setTimeout(autoScrollHandler, 25));
+ };
+ scrollAwaiter && clearTimeout(scrollAwaiter);
+ scrollAwaiter = setTimeout(autoScrollHandler, 250);
}
const { thisX, thisY } = snapDrag(e, xFromLeft, yFromTop, xFromRight, yFromBottom);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 35c040f86..fec4ad9e0 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -293,13 +293,12 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
const doc = Document(element.rootDoc);
if (doc.type === DocumentType.INK && doc.x && doc.y && doc._width && doc._height && doc.data) {
doc.rotation = Number(doc.rotation) + Number(angle);
- const ink = Cast(doc.data, InkField)?.inkData;
- if (ink) {
-
+ const inks = Cast(doc.data, InkField)?.inkData;
+ if (inks) {
const newPoints: { X: number, Y: number }[] = [];
- for (var i = 0; i < ink.length; i++) {
- const newX = Math.cos(angle) * (ink[i].X - this._centerPoints[index].X) - Math.sin(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].X;
- const newY = Math.sin(angle) * (ink[i].X - this._centerPoints[index].X) + Math.cos(angle) * (ink[i].Y - this._centerPoints[index].Y) + this._centerPoints[index].Y;
+ for (const ink of inks) {
+ const newX = Math.cos(angle) * (ink.X - this._centerPoints[index].X) - Math.sin(angle) * (ink.Y - this._centerPoints[index].Y) + this._centerPoints[index].X;
+ const newY = Math.sin(angle) * (ink.X - this._centerPoints[index].X) + Math.cos(angle) * (ink.Y - this._centerPoints[index].Y) + this._centerPoints[index].Y;
newPoints.push({ X: newX, Y: newY });
}
doc.data = new InkField(newPoints);
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx
index ca8a6e1d7..82ec5a5b3 100644
--- a/src/client/views/MetadataEntryMenu.tsx
+++ b/src/client/views/MetadataEntryMenu.tsx
@@ -38,7 +38,7 @@ export class MetadataEntryMenu extends React.Component{
let field: Field | undefined | null = null;
let onProto: boolean = false;
let value: string | undefined = undefined;
- let docs = this.props.docs;
+ const docs = this.props.docs;
for (const doc of docs) {
const v = await doc[this._currentKey];
onProto = onProto || !Object.keys(doc).includes(this._currentKey);
@@ -110,7 +110,7 @@ export class MetadataEntryMenu extends React.Component{
getKeySuggestions = (value: string) => {
value = value.toLowerCase();
- let docs = this.props.docs;
+ const docs = this.props.docs;
const keys = new Set();
docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key)));
return Array.from(keys).filter(key => key.toLowerCase().startsWith(value));
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 2be57b6d2..e7c5ca86b 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -402,7 +402,7 @@ export class CollectionFreeFormViewChrome extends React.Component this._widthBtn = !this._widthBtn, "bars", null);
+ const widthPicker = this.toggleButton("stroke width", this._widthBtn, () => this._widthBtn = !this._widthBtn, "bars", null);
return !this._widthBtn ? widthPicker :
{widthPicker}
@@ -416,7 +416,7 @@ export class CollectionFreeFormViewChrome extends React.Component
this._colorBtn = !this._colorBtn, "pen-nib",
+ const colorPicker = this.toggleButton("stroke color", this._colorBtn, () => this._colorBtn = !this._colorBtn, "pen-nib",
);
return !this._colorBtn ? colorPicker :
@@ -431,7 +431,7 @@ export class CollectionFreeFormViewChrome extends React.Component
;
}
@computed get fillPicker() {
- var fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip",
+ const fillPicker = this.toggleButton("shape fill color", this._fillBtn, () => this._fillBtn = !this._fillBtn, "fill-drip",
);
return !this._fillBtn ? fillPicker :
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
index 6d44ac967..bfe569853 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx
@@ -26,7 +26,7 @@ export class CollectionFreeFormLinkView extends React.Component (Date.now() < this._start++ + 1000) && setTimeout(this.timeout, 25);
+ timeout = () => (Date.now() < this._start++ + 1000) && setTimeout(this.timeout, 25)
componentDidMount() {
this._anchorDisposer = reaction(() => [this.props.A.props.ScreenToLocalTransform(), this.props.B.props.ScreenToLocalTransform(), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document), this.props.A.isSelected() || Doc.IsBrushed(this.props.A.props.Document)],
action(() => {
@@ -111,10 +111,10 @@ export class CollectionFreeFormLinkView extends React.Component