aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/DropConverter.ts2
-rw-r--r--src/client/util/KeyCodes.ts2
-rw-r--r--src/client/util/SharingManager.tsx4
-rw-r--r--src/client/views/DocComponent.tsx26
-rw-r--r--src/client/views/DocumentDecorations.tsx15
-rw-r--r--src/client/views/GlobalKeyHandler.ts12
-rw-r--r--src/client/views/MainView.scss4
-rw-r--r--src/client/views/MainView.tsx14
-rw-r--r--src/client/views/PropertiesButtons.tsx13
-rw-r--r--src/client/views/collections/CollectionLinearView.tsx2
-rw-r--r--src/client/views/collections/CollectionView.tsx15
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx12
-rw-r--r--src/client/views/globalCssVariables.scss2
-rw-r--r--src/client/views/globalCssVariables.scss.d.ts1
-rw-r--r--src/client/views/nodes/DocumentView.tsx21
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx11
-rw-r--r--src/client/views/nodes/WebBox.tsx4
-rw-r--r--src/client/views/pdf/PDFViewer.tsx4
-rw-r--r--src/fields/Doc.ts3
-rw-r--r--src/fields/util.ts10
20 files changed, 71 insertions, 106 deletions
diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts
index d0acf14c3..f1848f7e5 100644
--- a/src/client/util/DropConverter.ts
+++ b/src/client/util/DropConverter.ts
@@ -58,7 +58,7 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) {
let dbox = doc;
// bcz: isButtonBar is intended to allow a collection of linear buttons to be dropped and nested into another collection of buttons... it's not being used yet, and isn't very elegant
if (doc.type === DocumentType.FONTICON || StrCast(Doc.Layout(doc).layout).includes("FontIconBox")) {
- dbox = Doc.MakeAlias(doc);
+ //dbox = Doc.MakeAlias(doc); // don't need to do anything if dropping an icon doc onto an icon bar since there should be no layout data for an icon
} else if (!doc.onDragStart && !doc.isButtonBar) {
const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc;
if (layoutDoc.type !== DocumentType.FONTICON) {
diff --git a/src/client/util/KeyCodes.ts b/src/client/util/KeyCodes.ts
index cacb72a57..de2457a5a 100644
--- a/src/client/util/KeyCodes.ts
+++ b/src/client/util/KeyCodes.ts
@@ -131,6 +131,6 @@ export class KeyCodes {
public static NUM_7: number = 55;
public static NUM_8: number = 56;
public static NUM_9: number = 57;
- public static SUBSTRACT: number = 189;
+ public static SUBTRACT: number = 189;
public static ADD: number = 187;
} \ No newline at end of file
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index d50a132f8..48a3c023f 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -179,6 +179,9 @@ export default class SharingManager extends React.Component<{}> {
if (group.docsShared) DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
}
+ /**
+ * Called from the properties sidebar to change permissions of a user.
+ */
shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => {
const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith));
if (user) this.setInternalSharing(user, permission, target);
@@ -228,7 +231,6 @@ export default class SharingManager extends React.Component<{}> {
const key = user.email.replace('.', '_');
const ACL = `ACL-${key}`;
-
target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target);
if (permission !== SharingPermissions.None) {
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index ea854c2a3..8c8bb6fde 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -122,15 +122,23 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
@action.bound
removeDocument(doc: Doc | Doc[]): boolean {
- const docs = doc instanceof Doc ? [doc] : doc;
- docs.map(doc => doc.isPushpin = doc.annotationOn = undefined);
- const targetDataDoc = this.dataDoc;
- const value = DocListCast(targetDataDoc[this.annotationKey]);
- const toRemove = value.filter(v => docs.includes(v));
- // can't assign new List<Doc>(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;
+ const effectiveAcl = GetEffectiveAcl(this.dataDoc);
+ if (effectiveAcl === AclAdmin || effectiveAcl === AclEdit) {
+ const docs = doc instanceof Doc ? [doc] : doc;
+ docs.map(doc => doc.isPushpin = doc.annotationOn = undefined);
+ const targetDataDoc = this.dataDoc;
+ const value = DocListCast(targetDataDoc[this.annotationKey]);
+ const toRemove = value.filter(v => docs.includes(v));
+
+ if (toRemove.length !== 0) {
+ const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
+ toRemove.forEach(doc => {
+ Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey + "-annotations", doc);
+ recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true);
+ doc.deleted = true;
+ });
+ return true;
+ }
}
return false;
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 552d504c0..596c5931b 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -197,17 +197,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@action
onCloseClick = async (e: React.MouseEvent | undefined) => {
if (!e?.button) {
- const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = SelectionManager.SelectedDocuments().slice();
SelectionManager.DeselectAll();
-
- selected.map(dv => {
- const effectiveAcl = GetEffectiveAcl(dv.props.Document);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete
- recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true);
- dv.props.removeDocument?.(dv.props.Document);
- }
- });
+ selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
}
}
@action
@@ -615,9 +607,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
return (null);
}
const canDelete = SelectionManager.SelectedDocuments().some(docView => {
- const docAcl = GetEffectiveAcl(docView.props.Document);
- const collectionAcl = GetEffectiveAcl(docView.props.ContainingCollectionDoc);
- return [docAcl, collectionAcl].some(acl => [AclAdmin, AclEdit].includes(acl));
+ const collectionAcl = GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]);
+ return collectionAcl === AclAdmin || collectionAcl === AclEdit;
});
const minimal = bounds.r - bounds.x < 100 ? true : false;
const maximizeIcon = minimal ? (
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index fd9b04128..be6aa6be2 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -1,6 +1,6 @@
import { action } from "mobx";
import { DateField } from "../../fields/DateField";
-import { Doc, DocListCast, AclEdit, AclAdmin } from "../../fields/Doc";
+import { Doc, DocListCast } from "../../fields/Doc";
import { Id } from "../../fields/FieldSymbols";
import { InkTool } from "../../fields/InkField";
import { List } from "../../fields/List";
@@ -23,7 +23,6 @@ import PDFMenu from "./pdf/PDFMenu";
import { ContextMenu } from "./ContextMenu";
import GroupManager from "../util/GroupManager";
import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu";
-import { GetEffectiveAcl } from "../../fields/util";
const modifiers = ["control", "meta", "shift", "alt"];
type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>;
@@ -120,16 +119,9 @@ export default class KeyManager {
}
}
- const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = SelectionManager.SelectedDocuments().slice();
UndoManager.RunInBatch(() => {
- selected.map(dv => {
- const effectiveAcl = GetEffectiveAcl(dv.props.Document);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete
- recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true);
- dv.props.removeDocument?.(dv.props.Document);
- }
- });
+ selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
}, "delete");
SelectionManager.DeselectAll();
break;
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index f3fba82bc..44c756b63 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -157,7 +157,7 @@
width: 60px;
background-color: #121721;
- height: calc(100% - 32px);
+ height: calc(100% - $searchpanel-height);
//overflow-y: scroll;
//overflow-x: hidden;
@@ -215,7 +215,7 @@
.mainView-searchPanel {
width: 100%;
- height: 32px;
+ height: $searchpanel-height;
background-color: black;
color: white;
text-align: center;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 3df6c72c7..d1c4dd4e6 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -41,7 +41,7 @@ import { ContextMenu } from './ContextMenu';
import { DictationOverlay } from './DictationOverlay';
import { DocumentDecorations } from './DocumentDecorations';
import GestureOverlay from './GestureOverlay';
-import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss';
+import { ANTIMODEMENU_HEIGHT, SEARCH_PANEL_HEIGHT } from './globalCssVariables.scss';
import KeyManager from './GlobalKeyHandler';
import { LinkMenu } from './linking/LinkMenu';
import "./MainView.scss";
@@ -50,7 +50,6 @@ import { AudioBox } from './nodes/AudioBox';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
import { DocumentView } from './nodes/DocumentView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
-import RichTextMenu from './nodes/formattedText/RichTextMenu';
import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
import { LinkDocPreview } from './nodes/LinkDocPreview';
import { RadialMenu } from './nodes/RadialMenu';
@@ -59,10 +58,10 @@ import { OverlayView } from './OverlayView';
import PDFMenu from './pdf/PDFMenu';
import { PreviewCursor } from './PreviewCursor';
import { Hypothesis } from '../util/HypothesisUtils';
-import { undoBatch } from '../util/UndoManager';
import { WebBox } from './nodes/WebBox';
import * as ReactDOM from 'react-dom';
import { SearchBox } from './search/SearchBox';
+import RichTextMenu from './nodes/formattedText/RichTextMenu';
@observer
export class MainView extends React.Component {
@@ -402,7 +401,7 @@ export class MainView extends React.Component {
TraceMobx();
const mainContainer = this.mainContainer;
const width = this.flyoutWidth + this.propertiesWidth();
- return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)`, height: `calc(100% - 32px)` }}>
+ return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)`, height: `calc(100% - ${SEARCH_PANEL_HEIGHT})` }}>
{!mainContainer ? (null) : this.mainDocView}
</div>;
}
@@ -439,15 +438,14 @@ export class MainView extends React.Component {
doc.dockingConfig ? this.openWorkspace(doc) :
CollectionDockingView.AddRightSplit(doc, libraryPath);
}
- sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
- //sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
+ sidebarScreenToLocal = () => new Transform(0, (CollectionMenu.Instance.Pinned ? -35 : 0) - Number(SEARCH_PANEL_HEIGHT.replace("px", "")), 1);
mainContainerXf = () => this.sidebarScreenToLocal().translate(-55, -this._buttonBarHeight);
@computed get closePosition() { return 55 + this.flyoutWidth; }
@computed get flyout() {
if (!this.sidebarContent) return null;
return <div className="mainView-libraryFlyout">
- <div className="mainView-contentArea" style={{ position: "relative", height: `calc(100% - 32px)`, width: "100%", overflow: "visible" }}>
+ <div className="mainView-contentArea" style={{ position: "relative", height: `calc(100% - ${SEARCH_PANEL_HEIGHT})`, width: "100%", overflow: "visible" }}>
{/* {this.flyoutWidth > 0 ? <div className="mainView-libraryFlyout-close"
onPointerDown={this.closeFlyout}>
<FontAwesomeIcon icon="times" color="black" size="lg" />
@@ -819,8 +817,8 @@ export class MainView extends React.Component {
<DocumentDecorations />
{this.search}
<CollectionMenu />
- <FormatShapePane />
<div style={{ display: "none" }}><RichTextMenu key="rich" /></div>
+ <FormatShapePane />
{LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
{DocumentLinksButton.EditLink ? <LinkMenu docView={DocumentLinksButton.EditLink} addDocTab={DocumentLinksButton.EditLink.props.addDocTab} changeFlyout={emptyFunction} /> : (null)}
{LinkDocPreview.LinkInfo ? <LinkDocPreview location={LinkDocPreview.LinkInfo.Location} backgroundColor={this.defaultBackgroundColors}
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 5e25ead87..1ddae97ce 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -3,7 +3,7 @@ import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faChec
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast, AclEdit, AclAdmin } from "../../fields/Doc";
+import { Doc } from "../../fields/Doc";
import { RichTextField } from '../../fields/RichTextField';
import { Cast, NumCast, BoolCast } from "../../fields/Types";
import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils";
@@ -30,7 +30,6 @@ import { undoBatch, UndoManager } from '../util/UndoManager';
import { DocumentType } from '../documents/DocumentTypes';
import { InkField } from '../../fields/InkField';
import { PresBox } from './nodes/PresBox';
-import { GetEffectiveAcl } from "../../fields/util";
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -432,16 +431,8 @@ export class PropertiesButtons extends React.Component<{}, {}> {
@undoBatch
@action
deleteDocument = () => {
- const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = SelectionManager.SelectedDocuments().slice();
-
- selected.map(dv => {
- const effectiveAcl = GetEffectiveAcl(dv.props.Document);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete
- recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true);
- dv.props.removeDocument?.(dv.props.Document);
- }
- });
+ selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
this.selectedDoc && (this.selectedDoc.deleted = true);
this.selectedDocumentView?.props.ContainingCollectionView?.removeDocument(this.selectedDocumentView?.props.Document);
SelectionManager.DeselectAll();
diff --git a/src/client/views/collections/CollectionLinearView.tsx b/src/client/views/collections/CollectionLinearView.tsx
index 3cf46dbed..e1b07077e 100644
--- a/src/client/views/collections/CollectionLinearView.tsx
+++ b/src/client/views/collections/CollectionLinearView.tsx
@@ -119,7 +119,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) {
// transform: this.props.Document.linearViewIsExpanded ? "" : "rotate(45deg)"
}}
onPointerDown={e => e.stopPropagation()} >
- <p>+</p>
+ <p>{BoolCast(this.props.Document.linearViewIsExpanded) ? "–" : "+"}</p>
</label>;
return <div className="collectionLinearView-outer">
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index fe30cb05a..7562d7e9c 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -142,7 +142,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
const targetDataDoc = this.props.Document[DataSym];
const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
const added = docs.filter(d => !docList.includes(d));
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
if (added.length) {
if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) {
@@ -193,16 +193,19 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
@action.bound
removeDocument = (doc: any): boolean => {
- const collectionEffectiveAcl = GetEffectiveAcl(this.props.Document);
- const docEffectiveAcl = GetEffectiveAcl(doc);
- // you can remove the document if you either have Admin/Edit access to the collection or to the specific document
- if (collectionEffectiveAcl === AclEdit || collectionEffectiveAcl === AclAdmin || docEffectiveAcl === AclAdmin || docEffectiveAcl === AclEdit) {
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
+ if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) {
const docs = doc instanceof Doc ? [doc] : doc as Doc[];
const targetDataDoc = this.props.Document[DataSym];
const value = DocListCast(targetDataDoc[this.props.fieldKey]);
const toRemove = value.filter(v => docs.includes(v));
if (toRemove.length !== 0) {
- toRemove.forEach(doc => Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc));
+ const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
+ toRemove.forEach(doc => {
+ Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc);
+ recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true);
+ doc.deleted = true;
+ });
return true;
}
}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index ddc9bf40a..54b09ab72 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -278,7 +278,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
} else {
this._downX = x;
this._downY = y;
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
if ([AclAdmin, AclEdit, AclAddonly].includes(effectiveAcl)) PreviewCursor.Show(x, y, this.onKeyPress, this.props.addLiveTextDocument, this.props.getTransform, this.props.addDocument, this.props.nudge);
this.clearSelection();
}
@@ -340,17 +340,9 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
@undoBatch
@action
delete = () => {
- const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = this.marqueeSelect(false);
SelectionManager.DeselectAll();
-
- selected.map(doc => {
- const effectiveAcl = GetEffectiveAcl(doc);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete
- recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true);
- this.props.removeDocument(doc);
- }
- });
+ selected.forEach(doc => this.props.removeDocument(doc));
this.cleanupInteractions(false);
MarqueeOptionsMenu.Instance.fadeOut(true);
diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/globalCssVariables.scss
index 4c79a7c2f..7eb07ff55 100644
--- a/src/client/views/globalCssVariables.scss
+++ b/src/client/views/globalCssVariables.scss
@@ -29,6 +29,7 @@ $search-thumnail-size: 130;
$contextMenu-zindex: 100000; // context menu shows up over everything
$radialMenu-zindex: 100000; // context menu shows up over everything
+$searchpanel-height: 32px;
$mainTextInput-zindex: 999; // then text input overlay so that it's context menu will appear over decorations, etc
$docDecorations-zindex: 998; // then doc decorations appear over everything else
$remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right?
@@ -43,4 +44,5 @@ $MAX_ROW_HEIGHT: 44px;
MAX_ROW_HEIGHT: $MAX_ROW_HEIGHT;
SEARCH_THUMBNAIL_SIZE: $search-thumnail-size;
ANTIMODEMENU_HEIGHT: $antimodemenu-height;
+ SEARCH_PANEL_HEIGHT: $searchpanel-height;
} \ No newline at end of file
diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/globalCssVariables.scss.d.ts
index a7ca4b300..fd1f60f13 100644
--- a/src/client/views/globalCssVariables.scss.d.ts
+++ b/src/client/views/globalCssVariables.scss.d.ts
@@ -6,6 +6,7 @@ interface IGlobalScss {
MAX_ROW_HEIGHT: string;
SEARCH_THUMBNAIL_SIZE: string;
ANTIMODEMENU_HEIGHT: string;
+ SEARCH_PANEL_HEIGHT: string;
}
declare const globalCssVariables: IGlobalScss;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 536f1ed68..a1c934e81 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -9,7 +9,7 @@ import { listSpec } from "../../../fields/Schema";
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Types";
-import { GetEffectiveAcl, SharingPermissions, TraceMobx } from '../../../fields/util';
+import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
import { MobileInterface } from '../../../mobile/MobileInterface';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
import { emptyFunction, emptyPath, OmitKeys, returnOne, returnTransparent, Utils } from "../../../Utils";
@@ -179,7 +179,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15);
// RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 });
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
(effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 });
// RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 });
RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 });
@@ -571,19 +571,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (Doc.UserDoc().activeWorkspace === this.props.Document) {
alert("Can't delete the active workspace");
} else {
- const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc;
const selected = SelectionManager.SelectedDocuments().slice();
SelectionManager.DeselectAll();
-
- selected.map(dv => {
- const effectiveAcl = GetEffectiveAcl(dv.props.Document);
- if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete
- recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true);
- dv.props.removeDocument?.(dv.props.Document);
- }
- });
-
- this.props.Document.deleted = true;
+ selected.map(dv => dv.props.removeDocument?.(dv.props.Document));
this.props.removeDocument?.(this.props.Document);
}
}
@@ -777,8 +767,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" });
}
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
- (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" });
+ moreItems.push({ description: "Close", event: this.deleteClicked, icon: "trash" });
!more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" });
cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!);
@@ -1003,7 +992,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
render() {
if (!(this.props.Document instanceof Doc)) return (null);
- if (GetEffectiveAcl(this.props.Document) === AclPrivate) return (null);
+ if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null);
if (this.props.Document.hidden) return (null);
const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth);
const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index ebb916307..c4481b213 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -7,21 +7,16 @@ import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, re
import { Docs } from "../../documents/Documents";
import { DocumentManager } from "../../util/DocumentManager";
import { Transform } from "../../util/Transform";
+import { ContextMenu } from '../ContextMenu';
import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
-import React = require("react");
-import { DocumentView } from './DocumentView';
-import { sortAndDeduplicateDiagnostics } from 'typescript';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { LinkManager } from '../../util/LinkManager';
import { DocumentLinksButton } from './DocumentLinksButton';
-import { ContextMenu } from '../ContextMenu';
-import { undoBatch } from '../../util/UndoManager';
+import React = require("react");
interface Props {
linkDoc?: Doc;
linkSrc?: Doc;
href?: string;
- backgroundColor: (doc: Doc) => string;
+ backgroundColor: (doc: Doc, renderDepth: number) => string;
addDocTab: (document: Doc, where: string) => boolean;
location: number[];
}
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 3283f568a..f37909e6e 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction
import { observer } from "mobx-react";
import { Dictionary } from "typescript-collections";
import * as WebRequest from 'web-request';
-import { Doc, DocListCast, Opt, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt, AclAddonly, AclEdit, AclAdmin, DataSym } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { HtmlField } from "../../../fields/HtmlField";
@@ -535,7 +535,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
@action
highlight = (color: string) => {
// creates annotation documents for current highlights
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) ? this.makeAnnotationDocument(color) : undefined;
annotationDoc && this.addDocument?.(annotationDoc);
return annotationDoc ?? undefined;
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 7c1b2f621..cca86adb5 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -4,7 +4,7 @@ const pdfjs = require('pdfjs-dist/es5/build/pdf.js');
import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
import { Dictionary } from "typescript-collections";
-import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc";
+import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin, DataSym } from "../../../fields/Doc";
import { documentSchema } from "../../../fields/documentSchemas";
import { Id } from "../../../fields/FieldSymbols";
import { InkTool } from "../../../fields/InkField";
@@ -573,7 +573,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
@action
highlight = (color: string) => {
// creates annotation documents for current highlights
- const effectiveAcl = GetEffectiveAcl(this.props.Document);
+ const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]);
const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color);
annotationDoc && this.addDocument?.(annotationDoc);
return annotationDoc as Doc ?? undefined;
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 927ff4422..ea53bc9a2 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -806,7 +806,8 @@ export namespace Doc {
target[targetKey] = new PrefetchProxy(templateDoc);
} else {
titleTarget && (Doc.GetProto(target).title = titleTarget);
- Doc.GetProto(target)[targetKey] = new PrefetchProxy(templateDoc);
+ const setDoc = [AclAdmin, AclEdit].includes(GetEffectiveAcl(Doc.GetProto(target))) ? Doc.GetProto(target) : target;
+ setDoc[targetKey] = new PrefetchProxy(templateDoc);
}
}
return target;
diff --git a/src/fields/util.ts b/src/fields/util.ts
index 4c71572db..3d832636f 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -161,8 +161,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number)
if (target[AclSym] && Object.keys(target[AclSym]).length) {
// if the current user is the author of the document / the current user is a member of the admin group
- // but not if the doc in question is an alias - the current user will be the author of their alias rather than the original author
- if ((Doc.CurrentUserEmail === (target.__fields?.author || target.author) && !(target.aliasOf || target.__fields?.aliasOf)) || currentUserGroups.includes("admin")) return AclAdmin;
+ if (Doc.CurrentUserEmail === (target.__fields?.author || target.author) || currentUserGroups.includes("admin")) return AclAdmin;
// if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified)
if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit;
@@ -218,9 +217,10 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc
changed = true;
// maps over the aliases of the document
- if (target.aliases) {
- DocListCast(target.aliases).map(alias => {
- distributeAcls(key, acl, alias, inheritingFromCollection);
+ const aliases = DocListCast(target.aliases);
+ if (aliases.length) {
+ aliases.map(alias => {
+ alias !== target && distributeAcls(key, acl, alias, inheritingFromCollection);
});
}