([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 a8251abdaf57a3f02de46b434126caeb83df96ec Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Mon, 20 Jul 2020 10:35:33 -0400
Subject: added standard static ScriptFields to avoid extra compiles
---
src/client/util/CurrentUserUtils.ts | 52 ++++++++++++++++++++++++-------------
src/fields/ScriptField.ts | 23 +++++++++++++++-
2 files changed, 56 insertions(+), 19 deletions(-)
(limited to 'src')
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 58d3848a3..4b8c342f1 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -4,7 +4,7 @@ import { Utils } from "../../Utils";
import { DocServer } from "../DocServer";
import { Docs, DocumentOptions, DocUtils } from "../documents/Documents";
import { UndoManager } from "./UndoManager";
-import { Doc, DocListCast, DocListCastAsync } from "../../fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, DataSym } from "../../fields/Doc";
import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
import { ScriptField, ComputedField } from "../../fields/ScriptField";
@@ -91,29 +91,29 @@ export class CurrentUserUtils {
}
if (doc["template-button-description"] === undefined) {
- const descriptionTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created
- Doc.GetProto(descriptionTemplate).layout =
+ const descriptionTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header")); // text needs to be a space to allow templateText to be created
+ descriptionTemplate[DataSym].layout =
"" +
" " +
" " +
"
";
- descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView");
+ (descriptionTemplate.proto as Doc).isTemplateDoc = makeTemplate(descriptionTemplate.proto as Doc, true, "descriptionView");
doc["template-button-description"] = CurrentUserUtils.ficon({
- onDragStart: ScriptField.MakeFunction('makeDelegate(this.dragFactory)'),
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
dragFactory: new PrefetchProxy(descriptionTemplate) as any as Doc,
removeDropProperties: new List(["dropAction"]), title: "description view", icon: "window-maximize"
});
}
if (doc["template-button-link"] === undefined) { // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to.
- const linkTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created
+ const linkTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header")); // text needs to be a space to allow templateText to be created
Doc.GetProto(linkTemplate).layout =
"" +
" " +
" " +
"
";
- linkTemplate.isTemplateDoc = makeTemplate(linkTemplate, true, "linkView");
+ (linkTemplate.proto as Doc).isTemplateDoc = makeTemplate(linkTemplate.proto as Doc, true, "linkView");
const rtf2 = {
doc: {
@@ -146,7 +146,7 @@ export class CurrentUserUtils {
linkTemplate.header = new RichTextField(JSON.stringify(rtf2), "");
doc["template-button-link"] = CurrentUserUtils.ficon({
- onDragStart: ScriptField.MakeFunction('makeDelegate(this.dragFactory)'),
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
dragFactory: new PrefetchProxy(linkTemplate) as any as Doc,
removeDropProperties: new List(["dropAction"]), title: "link view", icon: "window-maximize"
});
@@ -390,6 +390,21 @@ export class CurrentUserUtils {
if (doc.emptyScript === undefined) {
doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script" });
}
+ if (doc.emptyScreenshot === undefined) {
+ doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" });
+ }
+ if (doc.emptyAudio === undefined) {
+ doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "ready to record audio" });
+ }
+ if (doc.emptyImage === undefined) {
+ doc.emptyImage = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth: 250, title: "an image of a cat" });
+ }
+ if (doc.emptyButton === undefined) {
+ doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button" });
+ }
+ if (doc.emptySearch === undefined) {
+ doc.emptySearch = Docs.Create.QueryDocument({ _width: 200, title: "empty search" });
+ }
if (doc.emptyDocHolder === undefined) {
doc.emptyDocHolder = Docs.Create.DocumentDocument(
ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]") as any,
@@ -404,14 +419,15 @@ export class CurrentUserUtils {
return [
{ toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc },
{ toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc },
- { toolTip: "Drag a cat image", title: "Image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' },
+ { toolTip: "Drag a cat image", title: "Image", icon: "cat", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyImage as Doc },
{ toolTip: "Drag a comparison box", title: "Comp", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc },
- { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' },
+ { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScreenshot as Doc },
// { title: "Drag a webcam", title: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' },
- { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` },
- { toolTip: "Drag a button", title: "Button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' },
- { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc },
- { toolTip: "Drag a search box", title: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' },
+ { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyAudio as Doc },
+ { toolTip: "Drag a button", title: "Button", icon: "bolt", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyButton as Doc },
+
+ { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc },
+ { toolTip: "Drag a search box", title: "Query", icon: "search", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptySearch as Doc },
{ toolTip: "Drag a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc },
// { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' },
{ toolTip: "Drag a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc },
@@ -421,7 +437,7 @@ export class CurrentUserUtils {
// { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc },
// { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "pink", activeInkPen: doc },
// { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activeInkPen = this;', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "white", activeInkPen: doc },
- { toolTip: "Drag a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory,true)', dragFactory: doc.emptyDocHolder as Doc },
+ { toolTip: "Drag a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyDocHolder as Doc },
{ toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' },
];
@@ -599,7 +615,7 @@ export class CurrentUserUtils {
_width: 35, _height: 25, title: "Tools", _fontSize: "10pt",
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: toolsStack,
- onDragStart: ScriptField.MakeFunction('getAlias(this.dragFactory, true)'),
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
dragFactory: toolsStack,
removeDropProperties: new List(["lockedPosition"]),
stayInCollection: true,
@@ -664,12 +680,12 @@ export class CurrentUserUtils {
_width: 50, _height: 25, title: "Library", _fontSize: "10pt", targetDropAction: "same",
letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)",
sourcePanel: libraryStack,
- onDragStart: ScriptField.MakeFunction('getAlias(this.dragFactory, true)'),
+ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'),
dragFactory: libraryStack,
removeDropProperties: new List(["lockedPosition"]),
stayInCollection: true,
targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc,
- onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;")
+ onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel")
}));
}
return doc["tabs-button-library"] as Doc;
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 11b3b0524..ebca19430 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -3,7 +3,7 @@ import { CompiledScript, CompileScript, scriptingGlobal, ScriptOptions, CompileE
import { Copy, ToScriptString, ToString, Parent, SelfProxy } from "./FieldSymbols";
import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr";
import { Deserializable, autoObject } from "../client/util/SerializationHelper";
-import { Doc, Field } from "./Doc";
+import { Doc, Field, Opt } from "./Doc";
import { Plugins, setter } from "./util";
import { computedFn } from "mobx-utils";
import { ProxyField } from "./Proxy";
@@ -38,6 +38,22 @@ const scriptSchema = createSimpleSchema({
});
async function deserializeScript(script: ScriptField) {
+ if (script.script.originalScript === 'getCopy(this.dragFactory, true)') {
+ return (script as any).script = (ScriptField.GetCopyOfDragFactory ?? (ScriptField.GetCopyOfDragFactory = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')))?.script;
+ }
+ if (script.script.originalScript === 'links(self)') {
+ return (script as any).script = (ScriptField.LinksSelf ?? (ScriptField.LinksSelf = ComputedField.MakeFunction('links(self)')))?.script;
+ }
+ if (script.script.originalScript === 'openOnRight(getCopy(this.dragFactory, true))') {
+ return (script as any).script = (ScriptField.OpenOnRight ?? (ScriptField.OpenOnRight = ComputedField.MakeFunction('openOnRight(getCopy(this.dragFactory, true))')))?.script;
+ }
+ if (script.script.originalScript === 'deiconifyView(self)') {
+ 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;
+ }
+ console.log(script.script.originalScript);
const captures: ProxyField = (script as any).captures;
if (captures) {
const doc = (await captures.value())!;
@@ -65,6 +81,11 @@ export class ScriptField extends ObjectField {
@serializable(autoObject())
private captures?: ProxyField;
+ public static GetCopyOfDragFactory: Opt;
+ public static LinksSelf: Opt;
+ public static OpenOnRight: Opt;
+ public static DeiconifyView: Opt;
+ public static ConvertToButtons: Opt;
constructor(script: CompiledScript, setterscript?: CompiledScript) {
super();
--
cgit v1.2.3-70-g09d2
From 30b92fe6e39ffba2d55cc3f83e9d18d3d7bcf036 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Mon, 20 Jul 2020 15:36:46 -0400
Subject: fixed some performance issues with dragging invalidating stackingview
documents unnecessarily
---
src/client/util/DocumentManager.ts | 4 +-
.../CollectionStackingViewFieldColumn.tsx | 68 +++++++++++++---------
2 files changed, 43 insertions(+), 29 deletions(-)
(limited to 'src')
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index b66e7fdc4..51b50878d 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -9,6 +9,7 @@ import { LinkManager } from './LinkManager';
import { Scripting } from './Scripting';
import { SelectionManager } from './SelectionManager';
import { DocumentType } from '../documents/DocumentTypes';
+import { TraceMobx } from '../../fields/util';
export type CreateViewFunc = (doc: Doc, followLinkLocation: string, finished?: () => void) => void;
@@ -104,8 +105,9 @@ export class DocumentManager {
@computed
public get LinkedDocumentViews() {
+ TraceMobx();
const pairs = DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => {
- const linksList = LinkManager.Instance.getAllRelatedLinks(dv.props.Document);
+ const linksList = DocListCast(dv.props.Document.links);
pairs.push(...linksList.reduce((pairs, link) => {
const linkToDoc = link && LinkManager.Instance.getOppositeAnchor(link, dv.props.Document);
linkToDoc && DocumentManager.Instance.getDocumentViews(linkToDoc).map(docView1 => {
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 2f4a25bfe..76af70cd1 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -2,7 +2,7 @@ import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
import { faPalette } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, observable, runInAction } from "mobx";
+import { action, observable, runInAction, computed } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCast } from "../../../fields/Doc";
import { RichTextField } from "../../../fields/RichTextField";
@@ -279,8 +279,7 @@ export class CollectionStackingViewFieldColumn extends React.Component : (null);
for (let i = 0; i < cols; i++) templatecols += `${style.columnWidth / style.numGroupColumns}px `;
const chromeStatus = this.props.parent.props.Document._chromeStatus;
+
+ return <>
+ {this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView}
+ {
+ this.collapsed ? (null) :
+
+
+ {this.props.parent.children(this.props.docList, uniqueHeadings.length)}
+ {singleColumn ? (null) : this.props.parent.columnDragger}
+
+ {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ?
+
+
+
: null}
+
+ }
+ >;
+ }
+
+
+ render() {
+ TraceMobx();
+ const headings = this.props.headings();
+ const heading = this._heading;
+ const uniqueHeadings = headings.map((i, idx) => headings.indexOf(i) === idx);
+ const chromeStatus = this.props.parent.props.Document._chromeStatus;
return (
- {this.props.parent.Document._columnsHideIfEmpty ? (null) : headingView}
- {
- this.collapsed ? (null) :
-
-
- {this.props.parent.children(this.props.docList, uniqueHeadings.length)}
- {singleColumn ? (null) : this.props.parent.columnDragger}
-
- {(chromeStatus !== 'view-mode' && chromeStatus !== 'disabled') ?
-
-
-
: null}
-
- }
+ {this.innards}
);
}
--
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
Date: Tue, 21 Jul 2020 18:29:19 -0400
Subject: added test to force keyboard focus to stop at first freeform
collection that is hit as opposed to travelin up to the last collection --
this allows templates with nested collections to get keyboard focus.
---
src/client/views/collections/collectionFreeForm/MarqueeView.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 8aab2e6a5..de1f2c52f 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -288,7 +288,10 @@ export class MarqueeView extends React.Component
Date: Tue, 21 Jul 2020 19:36:59 -0400
Subject: from last
---
.../collections/collectionFreeForm/MarqueeView.tsx | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
(limited to 'src')
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index de1f2c52f..6db8c8992 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -189,15 +189,18 @@ export class MarqueeView extends React.Component {
this._downX = this._lastX = e.clientX;
this._downY = this._lastY = e.clientY;
- // allow marquee if right click OR alt+left click OR space bar + left click
- if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) {
- // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) {
- this.setPreviewCursor(e.clientX, e.clientY, true);
- // (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors.
- e.preventDefault();
- // }
- // bcz: do we need this? it kills the context menu on the main collection if !altKey
- // e.stopPropagation();
+ if (!(e as any).marqueeHit) {
+ (e as any).marqueeHit = true;
+ // allow marquee if right click OR alt+left click OR space bar + left click
+ if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) {
+ // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) {
+ this.setPreviewCursor(e.clientX, e.clientY, true);
+ // (!e.altKey) && e.stopPropagation(); // bcz: removed so that you can alt-click on button in a collection to switch link following behaviors.
+ e.preventDefault();
+ // }
+ // bcz: do we need this? it kills the context menu on the main collection if !altKey
+ // e.stopPropagation();
+ }
}
}
--
cgit v1.2.3-70-g09d2
From 9d530f8fc7ca9621274a38260faebe797f66dd60 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Tue, 21 Jul 2020 23:57:55 -0400
Subject: fixed problem where adding to a collection would cause a remote
synchronized collection to erase and redraw since all of its list items got
replaced. the fix was to update the 'cache' field of ProxyFields when they
are deserialized to use an existing cached value if available.
---
src/fields/Proxy.ts | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/fields/Proxy.ts b/src/fields/Proxy.ts
index 555faaad0..62734d3d2 100644
--- a/src/fields/Proxy.ts
+++ b/src/fields/Proxy.ts
@@ -9,7 +9,12 @@ import { Id, Copy, ToScriptString, ToString } from "./FieldSymbols";
import { scriptingGlobal } from "../client/util/Scripting";
import { Plugins } from "./util";
-@Deserializable("proxy")
+function deserializeProxy(field: any) {
+ if (!field.cache) {
+ field.cache = DocServer.GetCachedRefField(field.fieldId) as any;
+ }
+}
+@Deserializable("proxy", deserializeProxy)
export class ProxyField extends ObjectField {
constructor();
constructor(value: T);
@@ -17,6 +22,7 @@ export class ProxyField extends ObjectField {
constructor(value?: T | string) {
super();
if (typeof value === "string") {
+ this.cache = DocServer.GetCachedRefField(value) as any;
this.fieldId = value;
} else if (value) {
this.cache = value;
--
cgit v1.2.3-70-g09d2
From 828a28e112db3357f52d3923987070129fd64b21 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 22 Jul 2020 11:33:28 -0400
Subject: restored download document. fixed clone() to clone to be async and
handles lists properly.
---
src/client/util/CurrentUserUtils.ts | 6 +++++
src/client/util/LinkManager.ts | 12 ++-------
src/client/util/Scripting.ts | 10 +++-----
src/client/views/GlobalKeyHandler.ts | 4 +--
src/client/views/PreviewCursor.tsx | 4 +--
.../collections/collectionFreeForm/MarqueeView.tsx | 8 +++---
src/client/views/linking/LinkEditor.tsx | 4 +--
src/client/views/linking/LinkMenuItem.tsx | 3 ++-
src/client/views/nodes/DocumentView.tsx | 14 ++++------
src/client/views/nodes/LinkDocPreview.tsx | 9 +------
.../formattedText/FormattedTextBoxComment.tsx | 2 ++
.../views/nodes/formattedText/RichTextMenu.tsx | 4 ++-
src/fields/Doc.ts | 30 +++++++++++-----------
src/server/ApiManagers/DownloadManager.ts | 12 +++------
src/server/ApiManagers/UploadManager.ts | 14 +++-------
15 files changed, 56 insertions(+), 80 deletions(-)
(limited to 'src')
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 03a75381a..23b8f09de 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -22,6 +22,7 @@ import { DocumentType } from "../documents/DocumentTypes";
import { SchemaHeaderField } from "../../fields/SchemaHeaderField";
import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView";
import { LabelBox } from "../views/nodes/LabelBox";
+import { LinkManager } from "./LinkManager";
export class CurrentUserUtils {
private static curr_id: string;
@@ -888,3 +889,8 @@ export class CurrentUserUtils {
Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); },
"creates a new workspace when called");
+
+Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
+ "returns all the links to the document or its annotations", "(doc: any)");
+Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); },
+ "returns all the links directly to the document", "(doc: any)");
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 974744344..223f0e7ef 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -2,8 +2,6 @@ import { Doc, DocListCast, Opt } from "../../fields/Doc";
import { List } from "../../fields/List";
import { listSpec } from "../../fields/Schema";
import { Cast, StrCast } from "../../fields/Types";
-import { Scripting } from "./Scripting";
-import { undoBatch } from "./UndoManager";
/*
* link doc:
@@ -25,12 +23,12 @@ export class LinkManager {
private static _instance: LinkManager;
-
public static currentLink: Opt;
public static get Instance(): LinkManager {
return this._instance || (this._instance = new this());
}
+
private constructor() {
}
@@ -53,7 +51,6 @@ export class LinkManager {
return false;
}
- @undoBatch
public deleteLink(linkDoc: Doc): boolean {
if (LinkManager.Instance.LinkManagerDoc && linkDoc instanceof Doc) {
Doc.RemoveDocFromList(LinkManager.Instance.LinkManagerDoc, "data", linkDoc);
@@ -210,9 +207,4 @@ export class LinkManager {
if (Doc.AreProtosEqual(anchor, a2)) return a1;
if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc;
}
-}
-
-Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); },
- "returns all the links to the document or its annotations", "(doc: any)");
-Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); },
- "returns all the links directly to the document", "(doc: any)");
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts
index e6cf50de3..f1e6155d2 100644
--- a/src/client/util/Scripting.ts
+++ b/src/client/util/Scripting.ts
@@ -10,8 +10,6 @@ export { ts };
// @ts-ignore
import * as typescriptlib from '!!raw-loader!./type_decls.d';
import { Doc, Field } from '../../fields/Doc';
-import { Cast } from "../../fields/Types";
-import { listSpec } from "../../fields/Schema";
export interface ScriptSucccess {
success: true;
@@ -95,10 +93,10 @@ export namespace Scripting {
export function removeGlobal(name: string) {
if (getGlobals().includes(name)) {
delete _scriptingGlobals[name];
- if (_scriptingDescriptions[name]){
+ if (_scriptingDescriptions[name]) {
delete _scriptingDescriptions[name];
}
- if (_scriptingParams[name]){
+ if (_scriptingParams[name]) {
delete _scriptingParams[name];
}
return true;
@@ -123,11 +121,11 @@ export namespace Scripting {
return _scriptingGlobals;
}
- export function getDescriptions(){
+ export function getDescriptions() {
return _scriptingDescriptions;
}
- export function getParameters(){
+ export function getParameters() {
return _scriptingParams;
}
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 4dfa7aec8..b63537b5f 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -309,13 +309,13 @@ export default class KeyManager {
const targetDataDoc = Doc.GetProto(first.props.Document);
const fieldKey = Doc.LayoutFieldKey(first.props.Document);
const docList = DocListCast(targetDataDoc[fieldKey]);
- docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => {
+ docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => {
count++;
if (doc instanceof Doc) {
list.push(doc);
}
if (count === docids.length) {
- const added = list.filter(d => !docList.includes(d)).map(d => clone ? Doc.MakeClone(d) : d);
+ const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? await Doc.MakeClone(d) : d));
if (added.length) {
added.map(doc => doc.context = targetDataDoc);
undoBatch(() => {
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 6583589f3..2d51403d7 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -69,11 +69,11 @@ export class PreviewCursor extends React.Component<{}> {
const list: Doc[] = [];
let first: Doc | undefined;
- docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => {
+ docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => {
count++;
if (doc instanceof Doc) {
i === 1 && (first = doc);
- const alias = clone ? Doc.MakeClone(doc) : doc;
+ const alias = clone ? await Doc.MakeClone(doc) : doc;
const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx;
const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty;
alias.x = newPoint[0] + deltaX;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 6db8c8992..84719b2c9 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -189,8 +189,8 @@ export class MarqueeView extends React.Component {
this._downX = this._lastX = e.clientX;
this._downY = this._lastY = e.clientY;
- if (!(e as any).marqueeHit) {
- (e as any).marqueeHit = true;
+ if (!(e.nativeEvent as any).marqueeHit) {
+ (e.nativeEvent as any).marqueeHit = true;
// allow marquee if right click OR alt+left click OR space bar + left click
if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) {
// if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) {
@@ -291,8 +291,8 @@ export class MarqueeView extends React.Component {
//@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION";
+ @undoBatch
@action
deleteLink = (): void => {
LinkManager.Instance.deleteLink(this.props.linkDoc);
@@ -422,8 +424,6 @@ export class LinkEditor extends React.Component {
Editing Link to: {
destination.proto?.title ?? destination.title ?? "untitled"}
- {/* this.deleteLink()} title="Delete link">
- */}
Show more link information
>} placement="top">
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 0e847632b..d8ba39f09 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -17,6 +17,7 @@ import { DocumentLinksButton } from '../nodes/DocumentLinksButton';
import { LinkDocPreview } from '../nodes/LinkDocPreview';
import { Tooltip } from '@material-ui/core';
import { DocumentType } from '../../documents/DocumentTypes';
+import { undoBatch } from '../../util/UndoManager';
library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash);
@@ -163,10 +164,10 @@ export class LinkMenuItem extends React.Component {
}
}
+ @undoBatch
@action
deleteLink = (): void => {
LinkManager.Instance.deleteLink(this.props.linkDoc);
- //this.props.showLinks();
LinkDocPreview.LinkInfo = undefined;
DocumentLinksButton.EditLink = undefined;
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0b5bd707b..12d9890c9 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -794,16 +794,12 @@ export class DocumentView extends DocComponent(Docu
}
moreItems.push({
description: "Download document", icon: "download", event: async () => {
- const response = await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), {
- qs: { q: 'world', fq: 'NOT baseProto_b:true AND NOT deleted:true', start: '0', rows: '100', hl: true, 'hl.fl': '*' }
- });
- console.log(response ? JSON.parse(response) : undefined);
+ const a = document.createElement("a");
+ const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+ a.href = url;
+ a.download = `DocExport-${this.props.Document[Id]}.zip`;
+ a.click();
}
- // const a = document.createElement("a");
- // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
- // a.href = url;
- // a.download = `DocExport-${this.props.Document[Id]}.zip`;
- // a.click();
});
moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 1caa82380..ebb916307 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { LinkManager } from '../../util/LinkManager';
import { DocumentLinksButton } from './DocumentLinksButton';
import { ContextMenu } from '../ContextMenu';
+import { undoBatch } from '../../util/UndoManager';
interface Props {
linkDoc?: Doc;
@@ -31,14 +32,6 @@ export class LinkDocPreview extends React.Component {
@observable _toolTipText = "";
_editRef = React.createRef();
- @action
- deleteLink = (): void => {
- this.props.linkDoc ? LinkManager.Instance.deleteLink(this.props.linkDoc) : null;
- //this.props.showLinks();
- LinkDocPreview.LinkInfo = undefined;
- DocumentLinksButton.EditLink = undefined;
- }
-
@action
onContextMenu = (e: React.MouseEvent) => {
DocumentLinksButton.EditLink = undefined;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 3687d5513..6f3984f39 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -22,6 +22,7 @@ import { LinkManager } from "../../../util/LinkManager";
import { LinkDocPreview } from "../LinkDocPreview";
import { DocumentLinksButton } from "../DocumentLinksButton";
import { Tooltip } from "@material-ui/core";
+import { undoBatch } from "../../../util/UndoManager";
export let formattedTextBoxCommentPlugin = new Plugin({
view(editorView) { return new FormattedTextBoxComment(editorView); }
@@ -143,6 +144,7 @@ export class FormattedTextBoxComment {
}
}
+ @undoBatch
@action
deleteLink = () => {
FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null;
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 2e0b0e659..47a4911b8 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -23,7 +23,7 @@ import { updateBullets } from "./ProsemirrorExampleTransfer";
import "./RichTextMenu.scss";
import { schema } from "./schema_rts";
import { TraceMobx } from "../../../../fields/util";
-import { UndoManager } from "../../../util/UndoManager";
+import { UndoManager, undoBatch } from "../../../util/UndoManager";
import { Tooltip } from "@material-ui/core";
const { toggleMark } = require("prosemirror-commands");
@@ -831,6 +831,8 @@ export default class RichTextMenu extends AntimodeMenu {
((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target);
}
+ @undoBatch
+ @action
deleteLink = () => {
if (this.view) {
const link = this.view.state.selection.$from.nodeAfter?.marks.find(m => m.type === this.view!.state.schema.marks.linkAnchor);
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 2f3b7025e..16ade5912 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -483,25 +483,25 @@ export namespace Doc {
return alias;
}
-
-
- export function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[]): Doc {
+ export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[]): Promise {
if (Doc.IsBaseProto(doc)) return doc;
if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
const copy = new Doc(undefined, true);
cloneMap.set(doc[Id], copy);
if (LinkManager.Instance.getAllLinks().includes(doc) && LinkManager.Instance.getAllLinks().indexOf(copy) === -1) LinkManager.Instance.addLink(copy);
- const exclude = Cast(doc.excludeFields, listSpec("string"), []);
- Object.keys(doc).forEach(key => {
- if (exclude.includes(key)) return;
+ const filter = Cast(doc.cloneFieldFilter, listSpec("string"), exclusions);
+ Object.keys(doc).forEach(async key => {
+ if (filter.includes(key)) return;
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
const field = ProxyField.WithoutProxy(() => doc[key]);
- const copyObjectField = (field: ObjectField) => {
- const list = Cast(doc[key], listSpec(Doc));
- if (list !== undefined && !(list instanceof Promise)) {
- copy[key] = new List(list.filter(d => d instanceof Doc).map(d => Doc.makeClone(d as Doc, cloneMap, rtfs)));
+ const copyObjectField = async (field: ObjectField) => {
+ const list = await Cast(doc[key], listSpec(Doc));
+ const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
+ if (docs !== undefined && docs.length) {
+ const clones = docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions));
+ copy[key] = new List(await Promise.all(clones));
} else if (doc[key] instanceof Doc) {
- copy[key] = key.includes("layout[") ? undefined : Doc.makeClone(doc[key] as Doc, cloneMap, rtfs); // reference documents except copy documents that are expanded teplate fields
+ copy[key] = key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions); // reference documents except copy documents that are expanded teplate fields
} else {
copy[key] = ObjectField.MakeCopy(field);
if (field instanceof RichTextField) {
@@ -513,7 +513,7 @@ export namespace Doc {
};
if (key === "proto") {
if (doc[key] instanceof Doc) {
- copy[key] = Doc.makeClone(doc[key]!, cloneMap, rtfs);
+ copy[key] = await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions);
}
} else {
if (field instanceof RefField) {
@@ -535,10 +535,10 @@ export namespace Doc {
cloneMap.set(doc[Id], copy);
return copy;
}
- export function MakeClone(doc: Doc): Doc {
+ export async function MakeClone(doc: Doc): Promise {
const cloneMap = new Map();
const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = [];
- const copy = Doc.makeClone(doc, cloneMap, rtfMap);
+ const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"]);
rtfMap.map(({ copy, key, field }) => {
const replacer = (match: any, attr: string, id: string, offset: any, string: any) => {
const mapped = cloneMap.get(id);
@@ -657,7 +657,7 @@ export namespace Doc {
export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc {
const copy = new Doc(copyProtoId, true);
- const exclude = Cast(doc.excludeFields, listSpec("string"), []);
+ const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []);
Object.keys(doc).forEach(key => {
if (exclude.includes(key)) return;
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts
index c5f3ca717..0d4472fdc 100644
--- a/src/server/ApiManagers/DownloadManager.ts
+++ b/src/server/ApiManagers/DownloadManager.ts
@@ -80,20 +80,14 @@ async function getDocs(id: string) {
}
const ids: string[] = [];
for (const key in doc.fields) {
- if (!doc.fields.hasOwnProperty(key)) {
- continue;
- }
+ if (!doc.fields.hasOwnProperty(key)) { continue; }
const field = doc.fields[key];
- if (field === undefined || field === null) {
- continue;
- }
+ if (field === undefined || field === null) { continue; }
if (field.__type === "proxy" || field.__type === "prefetch_proxy") {
ids.push(field.fieldId);
} else if (field.__type === "script" || field.__type === "computed") {
- if (field.captures) {
- ids.push(field.captures.fieldId);
- }
+ field.captures && ids.push(field.captures.fieldId);
} else if (field.__type === "list") {
ids.push(...fn(field));
} else if (typeof field === "string") {
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 55ceab9fb..0b9e999ac 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -139,13 +139,9 @@ export default class UploadManager extends ApiManager {
doc.id = getId(doc.id);
}
for (const key in doc.fields) {
- if (!doc.fields.hasOwnProperty(key)) {
- continue;
- }
+ if (!doc.fields.hasOwnProperty(key)) { continue; }
const field = doc.fields[key];
- if (field === undefined || field === null) {
- continue;
- }
+ if (field === undefined || field === null) { continue; }
if (field.__type === "proxy" || field.__type === "prefetch_proxy") {
field.fieldId = getId(field.fieldId);
@@ -208,11 +204,7 @@ export default class UploadManager extends ApiManager {
} catch (e) { console.log(e); }
unlink(path_2, () => { });
}
- if (id) {
- res.send(JSON.stringify(getId(id)));
- } else {
- res.send(JSON.stringify("error"));
- }
+ res.send(JSON.stringify(id ? getId(id) : "error"));
} catch (e) { console.log(e); }
resolve();
});
--
cgit v1.2.3-70-g09d2
From 8f95d52ed2b93930716ab6ed0ba9aab5c438876c Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 22 Jul 2020 20:16:53 -0400
Subject: fixed document download/import to capture links as well.
---
package-lock.json | 56 ++++++++++++
package.json | 3 +
src/client/views/GlobalKeyHandler.ts | 2 +-
src/client/views/PreviewCursor.tsx | 2 +-
.../collectionFreeForm/CollectionFreeFormView.tsx | 7 ++
src/client/views/nodes/DocHolderBox.tsx | 2 +-
src/client/views/nodes/DocumentView.tsx | 12 +--
src/fields/Doc.ts | 101 ++++++++++++++++-----
src/server/ApiManagers/UploadManager.ts | 2 +
9 files changed, 155 insertions(+), 32 deletions(-)
(limited to 'src')
diff --git a/package-lock.json b/package-lock.json
index 1b39905cf..698bd60cc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -711,6 +711,12 @@
"express-validator": "*"
}
},
+ "@types/file-saver": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.1.tgz",
+ "integrity": "sha512-g1QUuhYVVAamfCifK7oB7G3aIl4BbOyzDOqVyUfEr4tfBKrXfeH+M+Tg7HKCXSrbzxYdhyCP7z9WbKo0R2hBCw==",
+ "dev": true
+ },
"@types/formidable": {
"version": "1.0.31",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz",
@@ -6069,6 +6075,11 @@
}
}
},
+ "file-saver": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
+ "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
+ },
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@@ -7280,6 +7291,11 @@
}
}
},
+ "immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+ },
"import-fresh": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
@@ -8160,6 +8176,33 @@
"promise": "^7.0.1"
}
},
+ "jszip": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz",
+ "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==",
+ "requires": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "set-immediate-shim": "~1.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ }
+ }
+ },
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
@@ -8300,6 +8343,14 @@
}
}
},
+ "lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "requires": {
+ "immediate": "~3.0.5"
+ }
+ },
"lines-and-columns": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
@@ -15142,6 +15193,11 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+ },
"set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
diff --git a/package.json b/package.json
index cb083020f..6c466825e 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"@types/express-flash": "0.0.0",
"@types/express-session": "^1.15.16",
"@types/express-validator": "^3.0.0",
+ "@types/file-saver": "^2.0.1",
"@types/formidable": "^1.0.31",
"@types/google-maps-react": "^2.0.5",
"@types/jquery": "^3.5.0",
@@ -154,6 +155,7 @@
"express-session": "^1.17.0",
"express-validator": "^5.3.1",
"expressjs": "^1.0.1",
+ "file-saver": "^2.0.2",
"find-in-files": "^0.5.0",
"fit-curve": "^0.1.7",
"flexlayout-react": "^0.3.11",
@@ -172,6 +174,7 @@
"image-size-stream": "^1.1.0",
"js-datepicker": "^4.6.6",
"jsonschema": "^1.2.5",
+ "jszip": "^3.5.0",
"libxmljs": "^0.19.7",
"lodash": "^4.17.15",
"material-ui": "^0.20.2",
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index b63537b5f..086085db5 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -315,7 +315,7 @@ export default class KeyManager {
list.push(doc);
}
if (count === docids.length) {
- const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? await Doc.MakeClone(d) : d));
+ const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? (await Doc.MakeClone(d)).clone : d));
if (added.length) {
added.map(doc => doc.context = targetDataDoc);
undoBatch(() => {
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 2d51403d7..b4116e980 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -73,7 +73,7 @@ export class PreviewCursor extends React.Component<{}> {
count++;
if (doc instanceof Doc) {
i === 1 && (first = doc);
- const alias = clone ? await Doc.MakeClone(doc) : doc;
+ const alias = clone ? (await Doc.MakeClone(doc)).clone : doc;
const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx;
const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty;
alias.x = newPoint[0] + deltaX;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 412f91417..bee9e7009 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -46,6 +46,8 @@ import "./CollectionFreeFormView.scss";
import MarqueeOptionsMenu from "./MarqueeOptionsMenu";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
+import { SearchUtil } from "../../../util/SearchUtil";
+import { LinkManager } from "../../../util/LinkManager";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -1276,6 +1278,11 @@ export class CollectionFreeFormView extends CollectionSubView {
+ SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => {
+ docs.docs.forEach(d => LinkManager.Instance.addLink(d));
+ })
+ }, 2000); // need to give solr some time to update so that this query will find any link docs we've added.
}
}
}
diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx
index 0cf5505cc..0c4242172 100644
--- a/src/client/views/nodes/DocHolderBox.tsx
+++ b/src/client/views/nodes/DocHolderBox.tsx
@@ -180,7 +180,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent(Docu
}
moreItems.push({
description: "Download document", icon: "download", event: async () => {
- const a = document.createElement("a");
- const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
- a.href = url;
- a.download = `DocExport-${this.props.Document[Id]}.zip`;
- a.click();
+ Doc.Zip(this.props.Document);
+ // const a = document.createElement("a");
+ // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+ // a.href = url;
+ // a.download = `DocExport-${this.props.Document[Id]}.zip`;
+ // a.click();
}
});
moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 16ade5912..917a6853c 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1,6 +1,6 @@
import { action, computed, observable, ObservableMap, runInAction, untracked } from "mobx";
import { computedFn } from "mobx-utils";
-import { alias, map, serializable } from "serializr";
+import { alias, map, serializable, list } from "serializr";
import { DocServer } from "../client/DocServer";
import { DocumentType } from "../client/documents/DocumentTypes";
import { Scripting, scriptingGlobal } from "../client/util/Scripting";
@@ -14,12 +14,16 @@ import { ObjectField } from "./ObjectField";
import { PrefetchProxy, ProxyField } from "./Proxy";
import { FieldId, RefField } from "./RefField";
import { RichTextField } from "./RichTextField";
+import { ImageField, VideoField, WebField, AudioField, PdfField } from "./URLField";
+import { DateField } from "./DateField";
import { listSpec } from "./Schema";
import { ComputedField } from "./ScriptField";
import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction, GetEffectiveAcl } from "./util";
import { LinkManager } from "../client/util/LinkManager";
import { SharingPermissions } from "../client/util/SharingManager";
+import JSZip = require("jszip");
+import { saveAs } from "file-saver";
export namespace Field {
export function toKeyValueString(doc: Doc, key: string): string {
@@ -93,6 +97,7 @@ export const WidthSym = Symbol("Width");
export const HeightSym = Symbol("Height");
export const DataSym = Symbol("Data");
export const LayoutSym = Symbol("Layout");
+export const FieldsSym = Symbol("Fields");
export const AclSym = Symbol("Acl");
export const AclPrivate = Symbol("AclOwnerOnly");
export const AclReadonly = Symbol("AclReadOnly");
@@ -180,7 +185,6 @@ export class Doc extends RefField {
}
@observable
- //{ [key: string]: Field | FieldWaiting | undefined }
private ___fields: any = {};
private [UpdatingFromServer]: boolean = false;
@@ -191,6 +195,7 @@ export class Doc extends RefField {
private [Self] = this;
private [SelfProxy]: any;
+ public [FieldsSym] = () => this.___fields;
public [AclSym]: { [key: string]: symbol };
public [WidthSym] = () => NumCast(this[SelfProxy]._width);
public [HeightSym] = () => NumCast(this[SelfProxy]._height);
@@ -483,27 +488,28 @@ export namespace Doc {
return alias;
}
- export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[]): Promise {
+ export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[], dontCreate: boolean): Promise {
if (Doc.IsBaseProto(doc)) return doc;
if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!;
- const copy = new Doc(undefined, true);
+ const copy = dontCreate ? doc : new Doc(undefined, true);
cloneMap.set(doc[Id], copy);
if (LinkManager.Instance.getAllLinks().includes(doc) && LinkManager.Instance.getAllLinks().indexOf(copy) === -1) LinkManager.Instance.addLink(copy);
const filter = Cast(doc.cloneFieldFilter, listSpec("string"), exclusions);
- Object.keys(doc).forEach(async key => {
+ await Promise.all(Object.keys(doc).map(async key => {
if (filter.includes(key)) return;
+ const assignKey = (val: any) => !dontCreate && (copy[key] = val);
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
const field = ProxyField.WithoutProxy(() => doc[key]);
const copyObjectField = async (field: ObjectField) => {
const list = await Cast(doc[key], listSpec(Doc));
const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc);
if (docs !== undefined && docs.length) {
- const clones = docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions));
- copy[key] = new List(await Promise.all(clones));
+ const clones = await Promise.all(docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions, dontCreate)));
+ !dontCreate && assignKey(new List(clones));
} else if (doc[key] instanceof Doc) {
- copy[key] = key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions); // reference documents except copy documents that are expanded teplate fields
+ assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions, dontCreate)); // reference documents except copy documents that are expanded teplate fields
} else {
- copy[key] = ObjectField.MakeCopy(field);
+ assignKey(ObjectField.MakeCopy(field));
if (field instanceof RichTextField) {
if (field.Data.includes('"docid":') || field.Data.includes('"targetId":') || field.Data.includes('"linkId":')) {
rtfs.push({ copy, key, field });
@@ -513,32 +519,34 @@ export namespace Doc {
};
if (key === "proto") {
if (doc[key] instanceof Doc) {
- copy[key] = await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions);
+ assignKey(await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions, dontCreate));
}
} else {
if (field instanceof RefField) {
- copy[key] = field;
+ assignKey(field);
} else if (cfield instanceof ComputedField) {
- copy[key] = ComputedField.MakeFunction(cfield.script.originalScript);
- (key === "links" && field instanceof ObjectField) && copyObjectField(field);
+ !dontCreate && assignKey(ComputedField.MakeFunction(cfield.script.originalScript));
+ (key === "links" && field instanceof ObjectField) && await copyObjectField(field);
} else if (field instanceof ObjectField) {
- copyObjectField(field);
+ await copyObjectField(field);
} else if (field instanceof Promise) {
debugger; //This shouldn't happend...
} else {
- copy[key] = field;
+ assignKey(field);
}
}
- });
- Doc.SetInPlace(copy, "title", "CLONE: " + doc.title, true);
- copy.cloneOf = doc;
- cloneMap.set(doc[Id], copy);
+ }));
+ if (!dontCreate) {
+ Doc.SetInPlace(copy, "title", "CLONE: " + doc.title, true);
+ copy.cloneOf = doc;
+ cloneMap.set(doc[Id], copy);
+ }
return copy;
}
- export async function MakeClone(doc: Doc): Promise {
+ export async function MakeClone(doc: Doc, dontCreate: boolean = false) {
const cloneMap = new Map();
const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = [];
- const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"]);
+ const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"], dontCreate);
rtfMap.map(({ copy, key, field }) => {
const replacer = (match: any, attr: string, id: string, offset: any, string: any) => {
const mapped = cloneMap.get(id);
@@ -552,9 +560,56 @@ export namespace Doc {
const re = new RegExp(regex, "g");
copy[key] = new RichTextField(field.Data.replace(/("docid":|"targetId":|"linkId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text);
});
- return copy;
- }
+ return { clone: copy, map: cloneMap };
+ }
+
+ export async function Zip(doc: Doc) {
+ const { clone, map } = await Doc.MakeClone(doc, true);
+ function replacer(key: any, value: any) {
+ console.log("Checkin: " + key);
+ if (["cloneOf", "context", "cursors"].includes(key)) return undefined;
+ else if (value instanceof Doc) {
+ if (key !== "field" && Number.isNaN(Number(key))) {
+ const __fields = value[FieldsSym]();
+ return { id: value[Id], __type: "Doc", fields: __fields };
+ } else {
+ return { fieldId: value[Id], __type: "proxy" };
+ }
+ }
+ else if (value instanceof RichTextField) return { Data: value.Data, Text: value.Text, __type: "RichTextField" };
+ else if (value instanceof ImageField) return { url: value.url.href, __type: "image" };
+ else if (value instanceof PdfField) return { url: value.url.href, __type: "pdf" };
+ else if (value instanceof AudioField) return { url: value.url.href, __type: "audio" };
+ else if (value instanceof VideoField) return { url: value.url.href, __type: "video" };
+ else if (value instanceof WebField) return { url: value.url.href, __type: "web" };
+ else if (value instanceof DateField) return { date: value.toString(), __type: "date" };
+ else if (value instanceof ProxyField) return { fieldId: value.fieldId, __type: "proxy" };
+ else if (value instanceof Array && key !== "fields") return { fields: value, __type: "list" };
+ else if (value instanceof ComputedField) return { script: value.script, __type: "computed" };
+ else return value;
+ }
+
+ const docs: { [id: string]: any } = {};
+ Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]);
+ const docString = JSON.stringify({ id: doc[Id], docs }, replacer);
+
+ var zip = new JSZip();
+ zip.file("doc.json", docString);
+
+ // // Generate a directory within the Zip file structure
+ // var img = zip.folder("images");
+
+ // // Add a file to the directory, in this case an image with data URI as contents
+ // img.file("smile.gif", imgData, {base64: true});
+
+ // Generate the zip file asynchronously
+ zip.generateAsync({ type: "blob" })
+ .then((content: any) => {
+ // Force down of the Zip file
+ saveAs(content, "download.zip");
+ });
+ }
//
// Determines whether the layout needs to be expanded (as a template).
// template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index 0b9e999ac..4455d11eb 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -16,6 +16,7 @@ const imageDataUri = require('image-data-uri');
import { isWebUri } from "valid-url";
import { launch } from "puppeteer";
import { Opt } from "../../fields/Doc";
+import { SolrManager } from "./SearchManager";
export enum Directory {
parsed_files = "parsed_files",
@@ -204,6 +205,7 @@ export default class UploadManager extends ApiManager {
} catch (e) { console.log(e); }
unlink(path_2, () => { });
}
+ SolrManager.update();
res.send(JSON.stringify(id ? getId(id) : "error"));
} catch (e) { console.log(e); }
resolve();
--
cgit v1.2.3-70-g09d2
From 49e1dccee78af835ef48723bb708f1c2b47c9228 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 22 Jul 2020 21:09:20 -0400
Subject: fixed highlighting of text based on author. made download /import
document novice menu items.
---
.../collectionFreeForm/CollectionFreeFormView.tsx | 69 +++++++++++-----------
src/client/views/nodes/DocumentView.tsx | 20 +++----
.../views/nodes/formattedText/FormattedTextBox.tsx | 15 ++---
src/client/views/nodes/formattedText/marks_rts.ts | 10 ++--
4 files changed, 58 insertions(+), 56 deletions(-)
(limited to 'src')
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index bee9e7009..dc32ecb07 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1258,41 +1258,44 @@ export class CollectionFreeFormView extends CollectionSubView this.Document._freeformLOD = !this.Document._freeformLOD, icon: "table" });
- optionItems.push({
- description: "Import document", icon: "upload", event: ({ x, y }) => {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = ".zip";
- input.onchange = async _e => {
- const upload = Utils.prepend("/uploadDoc");
- const formData = new FormData();
- const file = input.files && input.files[0];
- if (file) {
- formData.append('file', file);
- formData.append('remap', "true");
- const response = await fetch(upload, { method: "POST", body: formData });
- const json = await response.json();
- if (json !== "error") {
- const doc = await DocServer.GetRefField(json);
- if (doc instanceof Doc) {
- const [xx, yy] = this.props.ScreenToLocalTransform().transformPoint(x, y);
- doc.x = xx, doc.y = yy;
- this.props.addDocument?.(doc);
- setTimeout(() => {
- SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => {
- docs.docs.forEach(d => LinkManager.Instance.addLink(d));
- })
- }, 2000); // need to give solr some time to update so that this query will find any link docs we've added.
- }
- }
- }
- };
- input.click();
- }
- });
+
}
!options && ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
-
+ const mores = ContextMenu.Instance.findByDescription("More...");
+ const moreItems = mores && "subitems" in mores ? mores.subitems : [];
+ moreItems.push({
+ description: "Import document", icon: "upload", event: ({ x, y }) => {
+ const input = document.createElement("input");
+ input.type = "file";
+ input.accept = ".zip";
+ input.onchange = async _e => {
+ const upload = Utils.prepend("/uploadDoc");
+ const formData = new FormData();
+ const file = input.files && input.files[0];
+ if (file) {
+ formData.append('file', file);
+ formData.append('remap', "true");
+ const response = await fetch(upload, { method: "POST", body: formData });
+ const json = await response.json();
+ if (json !== "error") {
+ const doc = await DocServer.GetRefField(json);
+ if (doc instanceof Doc) {
+ const [xx, yy] = this.props.ScreenToLocalTransform().transformPoint(x, y);
+ doc.x = xx, doc.y = yy;
+ this.props.addDocument?.(doc);
+ setTimeout(() => {
+ SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => {
+ docs.docs.forEach(d => LinkManager.Instance.addLink(d));
+ })
+ }, 2000); // need to give solr some time to update so that this query will find any link docs we've added.
+ }
+ }
+ }
+ };
+ input.click();
+ }
+ });
+ !mores && ContextMenu.Instance.addItem({ description: "More...", subitems: moreItems, icon: "eye" });
}
@observable showTimeline = false;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3b46b70ea..748938699 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -782,6 +782,16 @@ export class DocumentView extends DocComponent(Docu
const more = cm.findByDescription("More...");
const moreItems = more && "subitems" in more ? more.subitems : [];
+ moreItems.push({
+ description: "Download document", icon: "download", event: async () => {
+ Doc.Zip(this.props.Document);
+ // const a = document.createElement("a");
+ // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+ // a.href = url;
+ // a.download = `DocExport-${this.props.Document[Id]}.zip`;
+ // a.click();
+ }
+ });
if (!Doc.UserDoc().noviceMode) {
moreItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: "concierge-bell" });
moreItems.push({ description: `${this.Document._chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document._chromeStatus = (this.Document._chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
@@ -791,16 +801,6 @@ export class DocumentView extends DocComponent(Docu
moreItems.push({ description: "Tag Child Images via Google Photos", event: () => GooglePhotos.Query.TagChildImages(this.props.Document), icon: "caret-square-right" });
moreItems.push({ description: "Write Back Link to Album", event: () => GooglePhotos.Transactions.AddTextEnrichment(this.props.Document), icon: "caret-square-right" });
}
- moreItems.push({
- description: "Download document", icon: "download", event: async () => {
- Doc.Zip(this.props.Document);
- // const a = document.createElement("a");
- // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
- // a.href = url;
- // a.download = `DocExport-${this.props.Document[Id]}.zip`;
- // a.click();
- }
- });
moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" });
}
GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 7906e2533..e703a81e2 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -425,16 +425,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
addStyleSheetRule(FormattedTextBox._userStyleSheet, "UM-" + Doc.CurrentUserEmail.replace(".", "").replace("@", ""), { background: "moccasin" });
}
if (FormattedTextBox._highlights.indexOf("Todo Items") !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, "userTag-" + "todo", { outline: "black solid 1px" });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, "UT-" + "todo", { outline: "black solid 1px" });
}
if (FormattedTextBox._highlights.indexOf("Important Items") !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, "userTag-" + "important", { "font-size": "larger" });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, "UT-" + "important", { "font-size": "larger" });
}
if (FormattedTextBox._highlights.indexOf("Disagree Items") !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, "userTag-" + "disagree", { "text-decoration": "line-through" });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, "UT-" + "disagree", { "text-decoration": "line-through" });
}
if (FormattedTextBox._highlights.indexOf("Ignore Items") !== -1) {
- addStyleSheetRule(FormattedTextBox._userStyleSheet, "userTag-" + "ignore", { "font-size": "1" });
+ addStyleSheetRule(FormattedTextBox._userStyleSheet, "UT-" + "ignore", { "font-size": "1" });
}
if (FormattedTextBox._highlights.indexOf("By Recent Minute") !== -1) {
addStyleSheetRule(FormattedTextBox._userStyleSheet, "UM-" + Doc.CurrentUserEmail.replace(".", "").replace("@", ""), { opacity: "0.1" });
@@ -1303,9 +1303,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (e.key === "Tab" || e.key === "Enter") {
e.preventDefault();
}
- const mark = e.key !== " " && this._lastTimedMark ? this._lastTimedMark : schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
- this._lastTimedMark = mark;
- // this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(mark));
+ if (e.key === " " || this._lastTimedMark?.attrs.userid !== Doc.CurrentUserEmail) {
+ const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
+ this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(mark));
+ }
if (!this._undoTyping) {
this.startUndoTypingBatch();
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 3d7d71b14..f95f46104 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -258,9 +258,7 @@ export const marks: { [index: string]: MarkSpec } = {
},
parseDOM: [{ style: 'background: yellow' }],
toDOM(node: any) {
- return ['span', {
- style: `background: ${node.attrs.selected ? "orange" : "yellow"}`
- }];
+ return ['span', { style: `background: ${node.attrs.selected ? "orange" : "yellow"}` }];
}
},
@@ -277,8 +275,8 @@ export const marks: { [index: string]: MarkSpec } = {
const min = Math.round(node.attrs.modified / 12);
const hr = Math.round(min / 60);
const day = Math.round(hr / 60 / 24);
- const remote = node.attrs.userid !== Doc.CurrentUserEmail ? " userMark-remote" : "";
- return ['span', { class: "userMark-" + uid + remote + " userMark-min-" + min + " userMark-hr-" + hr + " userMark-day-" + day }, 0];
+ const remote = node.attrs.userid !== Doc.CurrentUserEmail ? " UM-remote" : "";
+ return ['span', { class: "UM-" + uid + remote + " UM-min-" + min + " UM-hr-" + hr + " UM-day-" + day }, 0];
}
},
// the id of the user who entered the text
@@ -292,7 +290,7 @@ export const marks: { [index: string]: MarkSpec } = {
inclusive: false,
toDOM(node: any) {
const uid = node.attrs.userid.replace(".", "").replace("@", "");
- return ['span', { class: "userTag-" + uid + " userTag-" + node.attrs.tag }, 0];
+ return ['span', { class: "UT-" + uid + " UT-" + node.attrs.tag }, 0];
}
},
--
cgit v1.2.3-70-g09d2
From c9703063f1bc4a2007833164bee19c3b0ffb0792 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik
Date: Wed, 22 Jul 2020 23:17:58 -0400
Subject: simplified changing columnHeaders in StackingView
---
src/client/views/collections/CollectionStackingView.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'src')
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index bf7c51f2c..dd4c34885 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -123,7 +123,7 @@ export class CollectionStackingView extends CollectionSubView(StackingDocument)
changed = true;
});
}
- changed && setTimeout(action(() => { if (this.columnHeaders) { this.columnHeaders.length = 0; this.columnHeaders.push(...columnHeaders); } }), 0);
+ changed && setTimeout(action(() => this.columnHeaders?.splice(0, this.columnHeaders.length, ...columnHeaders)), 0);
return fields;
}
--
cgit v1.2.3-70-g09d2