aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2020-10-12 01:05:13 -0400
committerbobzel <zzzman@gmail.com>2020-10-12 01:05:13 -0400
commit27635402ad810b910557eb1a86c7e85fa281aaee (patch)
tree766e936bccad6d939c47075f112bfb0dd9da65e8 /src
parent3256d0f42401b8dd8745e7f32c25033e118b444b (diff)
switched fonticonbox and colelctionsubview to test GetEffectiveAcl to determine if document is available (instead of hack of testing 'author'). made GetEffectiveAcl a computedFn. No longer create a pushpin when an annotation that's linked to text is dragged off a PDF. fixed undo of pushpin navigation (used to call finish() twice). fixed pushpin navigation to conistenly pan & sensibly toggle target
Diffstat (limited to 'src')
-rw-r--r--src/client/util/DocumentManager.ts9
-rw-r--r--src/client/views/collections/CollectionSubView.tsx5
-rw-r--r--src/client/views/collections/CollectionView.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx21
-rw-r--r--src/client/views/nodes/FontIconBox.tsx5
-rw-r--r--src/client/views/pdf/Annotation.tsx2
-rw-r--r--src/client/views/pdf/PDFViewer.tsx2
-rw-r--r--src/fields/util.ts14
8 files changed, 39 insertions, 22 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 178daf5f0..b37181e57 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -164,13 +164,14 @@ export class DocumentManager {
const sameContext = annotatedDoc && annotatedDoc === originatingDoc?.context;
if (originatingDoc?.isPushpin) {
const hide = !docView.props.Document.hidden;
- (!hide || !sameContext) && (docView.props.Document.hidden = !docView.props.Document.hidden);
- docView.props.focus(docView.props.Document, willZoom, undefined, (notfocused: boolean) => { // bcz: Argh! TODO: Need to add a notFocused argument to the after finish callback function that indicates whether the window had to scroll to show the target
- notfocused && hide && (docView.props.Document.hidden = true);
+ docView.props.focus(docView.props.Document, willZoom, undefined, (notfocused: boolean) => { // bcz: Argh! TODO: Need to add a notFocused argument to the after finish callback function that indicates whether the window had to scroll to show the target
+ if (notfocused || docView.props.Document.hidden) {
+ docView.props.Document.hidden = !docView.props.Document.hidden;
+ }
return focusAndFinish();
// @ts-ignore bcz: Argh TODO: Need to add a parameter to focus() everywhere for whether focus should center the target's container in the view or not. // here we don't want to focus the container if the source and target are in the same container
}, sameContext);
- finished?.();
+ //finished?.();
}
else {
docView.select(false);
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 493018093..b282d1e27 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -103,7 +103,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
const { Document, DataDoc } = this.props;
const validPairs = this.childDocs.map(doc => Doc.GetLayoutDataDocPair(Document, !this.props.annotationsKey ? DataDoc : undefined, doc)).
filter(pair => { // filter out any documents that have a proto that we don't have permissions to (which we determine by not having any keys
- return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && Object.keys(pair.layout.proto).length));
+ return pair.layout && (!pair.layout.proto || (pair.layout.proto instanceof Doc && GetEffectiveAcl(pair.layout.proto) !== AclPrivate));// Object.keys(pair.layout.proto).length));
});
return validPairs.map(({ data, layout }) => ({ data: data as Doc, layout: layout! })); // this mapping is a bit of a hack to coerce types
}
@@ -134,7 +134,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?:
rawdocs = rootDoc && !this.props.annotationsKey ? [Doc.GetProto(rootDoc)] : [];
}
- const docs = rawdocs.filter(d => !(d instanceof Promise) && Object.keys(d).length).map(d => d as Doc);
+ const docs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(d) !== AclPrivate).map(d => d as Doc);
const viewSpecScript = Cast(this.props.Document.viewSpecScript, ScriptField);
const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs;
@@ -502,4 +502,5 @@ import { SelectionManager } from "../../util/SelectionManager";
import { OverlayView } from "../OverlayView";
import { setTimeout } from "timers";
import { Hypothesis } from "../../util/HypothesisUtils";
+import { GetEffectiveAcl } from "../../../fields/util";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 80e9b41ad..cfd24545b 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -159,7 +159,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
else {
added.filter(doc => [AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))).map(doc => { // only make a pushpin if we have acl's to edit the document
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 hasContextAnchor = DocListCast(doc.links).some(l => (l.anchor2 === doc && Cast(l.anchor1, Doc, null)?.annotationOn === context) || (l.anchor1 === doc && Cast(l.anchor2, Doc, null)?.annotationOn === context));
+ if (context && !hasContextAnchor && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) {
const pushpin = Docs.Create.FontIconDocument({
title: "pushpin", label: "",
icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7",
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 4d9906f93..4df90e8ea 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -893,21 +893,24 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
afterFocus && setTimeout(afterFocus, delay);
} else {
const contextHgt = Doc.AreProtosEqual(annotOn, this.props.Document) && this.props.VisibleHeight ? this.props.VisibleHeight() : NumCast(annotOn._height);
- const offset = annotOn && (contextHgt / 2);
const curScroll = NumCast(this.props.Document._scrollTop);
let scrollTo = curScroll;
if (curScroll + contextHgt < NumCast(doc.y)) {
- scrollTo = NumCast(doc.y) + Math.max(NumCast(doc._height), 50) - contextHgt;
+ scrollTo = NumCast(doc.y) + Math.max(NumCast(doc._height), 100) - contextHgt;
} else if (curScroll > NumCast(doc.y)) {
- scrollTo = NumCast(doc.y);
+ scrollTo = Math.max(0, NumCast(doc.y) - 50);
}
- if (curScroll !== scrollTo) {
+ if (curScroll !== scrollTo || this.props.Document._viewTransition) {
this.props.Document._scrollPY = this.props.Document._scrollY = scrollTo;
delay = Math.abs(scrollTo - curScroll) > 5 ? 1000 : 0;
- !dontCenter && delay && this.props.focus(this.props.Document);
+ !dontCenter && this.props.focus(this.props.Document);
afterFocus && setTimeout(afterFocus, delay);
+ } else {
+ !dontCenter && delay && this.props.focus(this.props.Document);
// @ts-ignore
- } else afterFocus(true); // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
+ afterFocus(true); // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
+
+ }
}
} else {
@@ -929,14 +932,16 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
willZoom && this.setScaleToZoom(layoutdoc, scale);
Doc.linkFollowHighlight(doc);
+ const notFocused = newPanX === savedState.px && newPanY === savedState.py;
afterFocus && setTimeout(() => {
- if (afterFocus?.()) {
+ // @ts-ignore
+ if (afterFocus?.(notFocused)) { // bcz: TODO Aragh -- need to add a parameter to afterFocus() functions to indicate whether the focus function didn't need to scroll
this.Document._panX = savedState.px;
this.Document._panY = savedState.py;
this.Document[this.scaleFieldKey] = savedState.s;
this.Document._viewTransition = savedState.pt;
}
- }, 500);
+ }, notFocused ? 0 : 500);
}
}
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index 156256fe5..276c66bb1 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -8,11 +8,12 @@ import { FieldView, FieldViewProps } from './FieldView';
import { StrCast, Cast, ScriptCast } from '../../../fields/Types';
import { Utils, setupMoveUpEvents, returnFalse, emptyFunction } from "../../../Utils";
import { runInAction, observable, reaction, IReactionDisposer } from 'mobx';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, AclPrivate } from '../../../fields/Doc';
import { ContextMenu } from '../ContextMenu';
import { ScriptField } from '../../../fields/ScriptField';
import { Tooltip } from '@material-ui/core';
import { DragManager } from '../../util/DragManager';
+import { GetEffectiveAcl } from '../../../fields/util';
const FontIconSchema = createSchema({
icon: "string",
});
@@ -105,7 +106,7 @@ export class FontIconBadge extends React.Component<FontIconBadgeProps> {
render() {
if (!(this.props.collection instanceof Doc)) return (null);
- const length = DocListCast(this.props.collection.data).filter(d => Object.keys(d).length).length; // filter out any documents that we can't read
+ const length = DocListCast(this.props.collection.data).filter(d => GetEffectiveAcl(d) !== AclPrivate).length; // Object.keys(d).length).length; // filter out any documents that we can't read
return <div className="fontIconBadge-container" style={{ width: 15, height: 15, top: 12 }} ref={this._notifsRef}>
<div className="fontIconBadge" style={length > 0 ? { "display": "initial" } : { "display": "none" }}
onPointerDown={this.onPointerDown} >
diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx
index e7f901091..a071abd21 100644
--- a/src/client/views/pdf/Annotation.tsx
+++ b/src/client/views/pdf/Annotation.tsx
@@ -71,6 +71,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
this._reactionDisposer && this._reactionDisposer();
}
+ @undoBatch
deleteAnnotation = () => {
const annotation = DocListCast(this.props.dataDoc[this.props.fieldKey + "-annotations"]);
const group = FieldValue(Cast(this.props.document.group, Doc));
@@ -86,6 +87,7 @@ class RegionAnnotation extends React.Component<IRegionAnnotationProps> {
PDFMenu.Instance.fadeOut(true);
}
+ @undoBatch
pinToPres = () => {
const group = FieldValue(Cast(this.props.document.group, Doc));
const isPinned = group && Doc.isDocPinned(group) ? true : false;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 78b95b385..d8be3defd 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -194,7 +194,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
if (scrollY !== undefined) {
(this._showCover || this._showWaiting) && this.setupPdfJsViewer();
if (this.props.renderDepth === -1 && scrollY >= 0) {
- if (!this._mainCont.current) setTimeout(() => smoothScroll(1000, this._mainCont.current!, scrollY || 0));
+ if (!this._mainCont.current) setTimeout(() => this._mainCont.current && smoothScroll(1000, this._mainCont.current, scrollY || 0));
else smoothScroll(1000, this._mainCont.current, scrollY || 0);
this.Document._scrollPY = undefined;
}
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 881f301f3..b68d961b1 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -13,6 +13,7 @@ import { returnZero } from "../Utils";
import CursorField from "./CursorField";
import { List } from "./List";
import { SnappingManager } from "../client/util/SnappingManager";
+import { computedFn } from "mobx-utils";
function _readOnlySetter(): never {
throw new Error("Documents can't be modified in read-only mode");
@@ -139,7 +140,7 @@ export function denormalizeEmail(email: string) {
*
* Edit: a user with edit access to a document can remove/edit that document, add/remove/edit annotations (depending on permissions), but not change any access rights to that document.
*
- * Add: a user with add access to a document can add documents/annotations to that document but cannot edit or delete anything.
+ * Add: a user with add access to a document can augment documents/annotations to that document but cannot edit or delete anything.
*
* View: a user with view access to a document can only view it - they cannot add/remove/edit anything.
*
@@ -148,7 +149,7 @@ export function denormalizeEmail(email: string) {
export enum SharingPermissions {
Admin = "Admin",
Edit = "Can Edit",
- Add = "Can Add",
+ Add = "Can Augment",
View = "Can View",
None = "Not Shared"
}
@@ -157,6 +158,11 @@ export enum SharingPermissions {
* Calculates the effective access right to a document for the current user.
*/
export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number, user?: string): symbol {
+ return computedFn(function (target: any, in_prop?: string | symbol | number, user?: string) {
+ return getEffectiveAcl(target, in_prop, user);
+ }, true)(target, in_prop, user);
+}
+function getEffectiveAcl(target: any, in_prop?: string | symbol | number, user?: string): symbol {
if (!target) return AclPrivate;
// all changes received fromt the server must be processed as Admin
@@ -219,7 +225,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
const HierarchyMapping = new Map<string, number>([
["Not Shared", 0],
["Can View", 1],
- ["Can Add", 2],
+ ["Can Augment", 2],
["Can Edit", 3],
["Admin", 4]
]);
@@ -281,7 +287,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
// if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't
if (typeof prop === "string" && prop.startsWith("acl") && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined, "None"].includes(value))) return true;
- // if (typeof prop === "string" && prop.startsWith("acl") && !["Can Edit", "Can Add", "Can View", "Not Shared", undefined].includes(value)) return true;
+ // if (typeof prop === "string" && prop.startsWith("acl") && !["Can Edit", "Can Augment", "Can View", "Not Shared", undefined].includes(value)) return true;
if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) {
if (!prop.startsWith("_")) {