diff options
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 2 | ||||
-rw-r--r-- | src/client/views/MarqueeAnnotator.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaHeaders.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 13 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.scss | 20 | ||||
-rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 93 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 28 | ||||
-rw-r--r-- | src/client/views/pdf/AnchorMenu.tsx | 3 | ||||
-rw-r--r-- | src/client/views/pdf/PDFViewer.tsx | 7 | ||||
-rw-r--r-- | src/fields/Doc.ts | 21 |
13 files changed, 148 insertions, 56 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c263c5cf5..2dfd1e23c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -458,7 +458,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight, }}> {!canDelete ? <div /> : topBtn("close", "times", this.onCloseClick, "Close")} - {seldoc.props.Document.type === DocumentType.EQUATION ? (null) : titleArea} + {seldoc.props.hideTitle || seldoc.props.Document.type === DocumentType.EQUATION ? (null) : titleArea} {seldoc.props.hideResizeHandles || seldoc.props.Document.type === DocumentType.EQUATION ? (null) : <> {SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) : diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 63439586c..503c284aa 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -29,6 +29,7 @@ export interface MarqueeAnnotatorProps { addDocument: (doc: Doc) => boolean; getPageFromScroll?: (top: number) => number; finishMarquee: () => void; + anchorMenuClick?: (anchor: Doc) => void; } @observer export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> { @@ -59,6 +60,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> { document.addEventListener("pointermove", this.onSelectMove); document.addEventListener("pointerup", this.onSelectEnd); + AnchorMenu.Instance.OnClick = (e: PointerEvent) => this.props.anchorMenuClick?.(this.highlight("rgba(173, 216, 230, 0.75)", true)); AnchorMenu.Instance.Highlight = this.highlight; /** * This function is used by the AnchorMenu to create an anchor highlight and a new linked text annotation. diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index f50da0134..3b52e6408 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -283,11 +283,11 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { const colpos = this._searchTerm.indexOf(":"); const temp = this._searchTerm.slice(colpos + 1, this._searchTerm.length); if (temp === "") { - Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined); + Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove"); this.updateFilter(); } else { - Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined); + Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove"); this.tempfilter = temp; Doc.setDocFilter(this.props.Document, this._key, temp, "check"); this.props.col.setColor("green"); @@ -295,7 +295,7 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { } } else { - Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, undefined); + Doc.setDocFilter(this.props.Document, this._key, this.tempfilter, "remove"); this.updateFilter(); if (this.showKeys.length) { this.onSelect(this.showKeys[0]); @@ -421,10 +421,10 @@ export class KeysDropdown extends React.Component<KeysDropdownProps> { onPointerDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()} onChange={(e) => { - e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, undefined); + e.target.checked === true ? Doc.setDocFilter(this.props.Document, this._key, key, "check") : Doc.setDocFilter(this.props.Document, this._key, key, "remove"); e.target.checked === true ? this.closeResultsVisibility = "contents" : console.log(""); e.target.checked === true ? this.props.col.setColor("green") : this.updateFilter(); - e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, undefined); + e.target.checked === true && SearchBox.Instance.filter === true ? Doc.setDocFilter(docs[0], this._key, key, "check") : Doc.setDocFilter(docs[0], this._key, key, "remove"); }} checked={bool} /> diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 10494e3e2..cf3722a6c 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -233,6 +233,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, ScreenToLocalTransform={stackedDocTransform} focus={this.focusDocument} docFilters={this.docFilters} + hideTitle={this.props.childHideTitle?.()} docRangeFilters={this.docRangeFilters} searchFilterDocs={this.searchFilterDocs} ContainingCollectionDoc={this.props.CollectionView?.props.Document} @@ -517,6 +518,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, height: `${1 / this.scaling * 100}%`, width: `${1 / this.scaling * 100}%`, transformOrigin: "top left", + background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor), pointerEvents: this.backgroundEvents ? "all" : undefined }} onScroll={action(e => this._scroll = e.currentTarget.scrollTop)} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 857982782..f903128d7 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -72,6 +72,7 @@ export interface CollectionViewProps extends FieldViewProps { children?: never | (() => JSX.Element[]) | React.ReactNode; childDocuments?: Doc[]; // used to override the documents shown by the sub collection to an explicit list (see LinkBox) childOpacity?: () => number; + childHideTitle?: () => boolean; // whether to hide the documentdecorations title for children childLayoutTemplate?: () => (Doc | undefined);// specify a layout Doc template to use for children of the collection childLayoutString?: string; childFreezeDimensions?: boolean; // used by TimeView to coerce documents to treat their width height as their native width/height diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 03210d768..1d851e775 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -433,7 +433,7 @@ export class TreeView extends React.Component<TreeViewProps> { this.onCheckedClick?.script.run({ this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, heading: this.props.containingCollection.title, - checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check", + checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? "remove" : "check", containingTreeView: this.props.treeView.props.Document, }, console.log); } else { diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 6f102213b..56130ef55 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -232,7 +232,18 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp } @computed get filteredLinks() { - return DocUtils.FilterDocs(Array.from(new Set<Doc>(this.props.links)), this.props.View.props.docFilters(), []); + const results = [] as Doc[]; + Array.from(new Set<Doc>(this.props.links)).forEach(link => { + if (!DocUtils.FilterDocs([link], this.props.View.props.docFilters(), []).length) { + if (DocUtils.FilterDocs([link.anchor2 as Doc], this.props.View.props.docFilters(), []).length) { + results.push(link); + } + if (DocUtils.FilterDocs([link.anchor1 as Doc], this.props.View.props.docFilters(), []).length) { + results.push(link); + } + } else results.push(link); + }) + return results; } @computed get linkButtonInner() { diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 16cc9d27e..74b331ae1 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -176,6 +176,26 @@ } } + .pdfBox-tagList { + display: flex; + flex-direction: row; + overflow: auto; + flex-flow: row; + flex-wrap: wrap; + .pdfBox-filterTag, .pdfBox-filterTag-active { + font-weight: bold; + padding-left: 6; + padding-right: 6; + box-shadow: black 1px 1px 4px; + border-radius: 5; + margin: 2; + height: 20; + background-color: lightgrey; + } + .pdfBox-filterTag-active { + background-color: white; + } + } .pdfBox-title-outer { width: 100%; height: 100%; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index a3b5eea0c..d356c4b6e 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -3,13 +3,13 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Doc, Opt, WidthSym, HeightSym } from "../../../fields/Doc"; +import { Doc, Opt, WidthSym, HeightSym, DocListCast, StrListCast } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; import { makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { PdfField } from "../../../fields/URLField"; import { TraceMobx } from '../../../fields/util'; -import { Utils, returnOne, OmitKeys, emptyFunction, returnZero } from '../../../Utils'; +import { Utils, returnOne, OmitKeys, emptyFunction, returnZero, returnTrue } from '../../../Utils'; import { KeyCodes } from '../../util/KeyCodes'; import { undoBatch } from '../../util/UndoManager'; import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView'; @@ -23,9 +23,13 @@ import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); import { DocAfterFocusFunc } from './DocumentView'; -import { Docs } from '../../documents/Documents'; +import { Docs, DocUtils } from '../../documents/Documents'; import { CollectionStackingView } from '../collections/CollectionStackingView'; import { StyleProp } from '../StyleProvider'; +import { SearchBox } from '../search/SearchBox'; +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; +import { Id } from '../../../fields/FieldSymbols'; +import { FormattedTextBox } from './formattedText/FormattedTextBox'; type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>; const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema); @@ -118,43 +122,61 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum !this.Document._fitWidth && (this.Document._height = this.Document[WidthSym]() * (nh / nw)); } sidebarKey = () => this.fieldKey + "-sidebar"; + sidebarFiltersHeight = () => 50; sidebarTransform = () => this.props.ScreenToLocalTransform().translate(Doc.NativeWidth(this.dataDoc), 0).scale(this.props.scaling?.() || 1); sidebarWidth = () => !this.layoutDoc._showSidebar ? 0 : (NumCast(this.layoutDoc.nativeWidth) - Doc.NativeWidth(this.dataDoc)) * this.props.PanelWidth() / NumCast(this.layoutDoc.nativeWidth); + sidebarHeight = () => this.props.PanelHeight() - this.sidebarFiltersHeight() - 20; sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.sidebarKey()); sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.sidebarKey()); sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.sidebarKey()); + @computed get allTags() { + const keys = new Set<string>(); + DocListCast(this.rootDoc[this.sidebarKey()]).forEach(doc => SearchBox.documentKeys(doc).filter(key => keys.add(key))); + return Array.from(keys.keys()).filter(key => key[0]).filter(key => !key.startsWith("_") && (key[0] === "#" || key[0] === key[0].toUpperCase())).sort(); + } + renderTag = (tag: string) => { + const active = StrListCast(this.rootDoc.docFilters).includes(`${tag}:${tag}:check`); + return <div className={`pdfbox-filterTag${active ? "-active" : ""}`} + onClick={e => Doc.setDocFilter(this.rootDoc, tag, tag, "check", true)}> + {tag} + </div>; + } @computed get sidebarOverlay() { return !this.layoutDoc._showSidebar ? (null) : <div style={{ position: "absolute", pointerEvents: this.active() ? "all" : undefined, top: 0, right: 0, - background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor), + background: this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.WidgetColor), width: `${this.sidebarWidth()}px`, height: "100%" }}> - <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} - NativeWidth={returnZero} - NativeHeight={returnZero} - PanelHeight={this.props.PanelHeight} - PanelWidth={this.sidebarWidth} - xMargin={0} - yMargin={0} - chromeStatus={"enabled"} - scaleField={this.sidebarKey() + "-scale"} - isAnnotationOverlay={false} - select={emptyFunction} - active={this.annotationsActive} - scaling={returnOne} - whenActiveChanged={this.whenActiveChanged} - childPointerEvents={true} - removeDocument={this.sidebarRemDocument} - moveDocument={this.sidebarMoveDocument} - addDocument={this.sidebarAddDocument} - CollectionView={undefined} - ScreenToLocalTransform={this.sidebarTransform} - renderDepth={this.props.renderDepth + 1} - fieldKey={this.sidebarKey()} - pointerEvents={"all"} - /> + <div className="pdfBox-tagList" style={{ height: this.sidebarFiltersHeight(), width: this.sidebarWidth() }}> + {this.allTags.map(tag => this.renderTag(tag))} + </div> + <div style={{ width: "100%", height: this.sidebarHeight(), position: "relative" }}> + <CollectionStackingView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} + NativeWidth={returnZero} + NativeHeight={returnZero} + PanelHeight={this.sidebarHeight} + PanelWidth={this.sidebarWidth} + xMargin={0} + yMargin={0} + chromeStatus={"enabled"} + scaleField={this.sidebarKey() + "-scale"} + isAnnotationOverlay={false} + select={emptyFunction} + active={this.annotationsActive} + scaling={returnOne} + whenActiveChanged={this.whenActiveChanged} + childHideTitle={returnTrue} + removeDocument={this.sidebarRemDocument} + moveDocument={this.sidebarMoveDocument} + addDocument={this.sidebarAddDocument} + CollectionView={undefined} + ScreenToLocalTransform={this.sidebarTransform} + renderDepth={this.props.renderDepth + 1} + fieldKey={this.sidebarKey()} + pointerEvents={"all"} + /></div> </div>; } @@ -252,6 +274,20 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" }); } + anchorMenuClick = (anchor: Doc) => { + const startup = StrListCast(this.rootDoc.docFilters).map(filter => filter.split(":")[0]).join(" "); + const target = Docs.Create.TextDocument(startup, { + title: "anno", + annotationOn: this.rootDoc, _width: 200, _height: 50, _fitWidth: true, _autoHeight: true, _fontSize: StrCast(Doc.UserDoc().fontSize), + _fontFamily: StrCast(Doc.UserDoc().fontFamily) + }); + FormattedTextBox.SelectOnLoad = target[Id]; + FormattedTextBox.DontSelectInitialText = true; + this.allTags.map(tag => target[tag] = tag); + DocUtils.MakeLink({ doc: anchor }, { doc: target }, "inline markup", "annotation"); + this.sidebarAddDocument(target); + } + @computed get renderTitleBox() { const classname = "pdfBox" + (this.active() ? "-interactive" : ""); return <div className={classname} > @@ -271,6 +307,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum <PDFViewer {...this.props} pdf={this._pdf!} url={pdfUrl!.url.pathname} + anchorMenuClick={this.anchorMenuClick} loaded={!Doc.NativeAspect(this.dataDoc) ? this.loaded : undefined} setPdfViewer={this.setPdfViewer} addDocument={this.addDocument} diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 9c620e729..03997713c 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -150,6 +150,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp public static FocusedBox: FormattedTextBox | undefined; public static PasteOnLoad: ClipboardEvent | undefined; public static SelectOnLoad = ""; + public static DontSelectInitialText = false; // whether initial text should be selected or not public static SelectOnLoadChar = ""; public static IsFragment(html: string) { return html.indexOf("data-pm-slice") !== -1; } public static GetHref(html: string): string { @@ -1081,10 +1082,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const tr = this._editorView.state.tr.setStoredMarks(storedMarks).insertText(FormattedTextBox.SelectOnLoadChar, this._editorView.state.doc.content.size - 1, this._editorView.state.doc.content.size).setStoredMarks(storedMarks); this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(tr.doc.content.size)))); FormattedTextBox.SelectOnLoadChar = ""; - } else if (curText?.Text) { + } else if (curText?.Text && !FormattedTextBox.DontSelectInitialText) { selectAll(this._editorView!.state, this._editorView?.dispatch); this.startUndoTypingBatch(); } + FormattedTextBox.DontSelectInitialText = false; } selectOnLoad && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. @@ -1153,6 +1155,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (!this._editorView?.state.selection.empty && FormattedTextBox._canAnnotate) this.setupAnchorMenu(); if (!this._downEvent) return; this._downEvent = false; + if ((e.nativeEvent as any).formattedHandled) { + console.log("handled"); + } if (!(e.nativeEvent as any).formattedHandled && this.active(true)) { const editor = this._editorView!; const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY }); @@ -1242,7 +1247,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._editorView!.dispatch(this._editorView!.state.tr.setSelection(NodeSelection.create(this._editorView!.state.doc, pcords.pos))); } } - if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; } + if ((e.nativeEvent as any).formattedHandled) { + e.stopPropagation(); + return; + } this.props.isSelected(true) && ((e.nativeEvent as any).formattedHandled = true); if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events @@ -1295,8 +1303,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const originalUpHandler = view.mouseDown.up; view.root.removeEventListener("mouseup", originalUpHandler); view.mouseDown.up = (e: MouseEvent) => { - !(e as any).formattedHandled && originalUpHandler(e); - (e as any).formattedHandled = true; + if (!(e as any).formattedHandled) { + originalUpHandler(e); + (e as any).formattedHandled = true; + } else { + console.log("prehandled"); + } }; view.root.addEventListener("mouseup", view.mouseDown.up); } @@ -1394,7 +1406,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp fitToBox = () => this.props.Document._fitToBox; sidebarContentScaling = () => (this.props.scaling?.() || 1) * NumCast(this.layoutDoc._viewScale, 1); sidebarAddDocument = (doc: Doc | Doc[]) => this.addDocument(doc, this.SidebarKey); - sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey); + sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey); sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey); setSidebarHeight = (height: number) => this.rootDoc[this.SidebarKey + "-height"] = height; sidebarWidth = () => Number(this.sidebarWidthPercent.substring(0, this.sidebarWidthPercent.length - 1)) / 100 * this.props.PanelWidth(); @@ -1417,7 +1429,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const renderComponent = (tag: string) => { const ComponentTag = tag === "freeform" ? CollectionFreeFormView : tag === "translation" ? FormattedTextBox : CollectionStackingView; return <ComponentTag - {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} + {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit} NativeWidth={returnZero} NativeHeight={returnZero} PanelHeight={this.props.PanelHeight} @@ -1427,8 +1439,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp chromeStatus={"enabled"} scaleField={this.SidebarKey + "-scale"} isAnnotationOverlay={false} - setHeight={this.setSidebarHeight} - fitContentsToDoc={this.fitToBox} select={emptyFunction} active={this.annotationsActive} scaling={this.sidebarContentScaling} @@ -1439,6 +1449,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp CollectionView={undefined} ScreenToLocalTransform={this.sidebarScreenToLocal} renderDepth={this.props.renderDepth + 1} + setHeight={this.setSidebarHeight} + fitContentsToDoc={this.fitToBox} noSidebar={true} fieldKey={this.layoutDoc.sidebarViewType === "translation" ? `${this.fieldKey}-translation` : this.SidebarKey} />; }; diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index e3d14d620..5a3c2103e 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -42,6 +42,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { @observable public Highlighting: boolean = false; @observable public Status: "marquee" | "annotation" | "" = ""; + public OnClick: (e: PointerEvent) => void = unimplementedFunction; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string, isPushpin: boolean) => Opt<Doc> = (color: string, isPushpin: boolean) => undefined; public Delete: () => void = unimplementedFunction; @@ -71,7 +72,7 @@ export class AnchorMenu extends AntimodeMenu<AntimodeMenuProps> { setupMoveUpEvents(this, e, (e: PointerEvent) => { this.StartDrag(e, this._commentCont.current!); return true; - }, returnFalse, returnFalse); + }, returnFalse, e => this.OnClick?.(e)); } @action diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d2fa1089e..18e167b7a 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -55,6 +55,7 @@ interface IViewerProps extends FieldViewProps { setPdfViewer: (view: PDFViewer) => void; ContentScaling?: () => number; sidebarWidth: () => number; + anchorMenuClick: (anchor: Doc) => void; } /** @@ -567,7 +568,11 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu {this.overlayInfo} {this.standinViews} {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) : - <MarqueeAnnotator rootDoc={this.rootDoc} scrollTop={0} down={this._marqueeing} addDocument={this.addDocument} finishMarquee={this.finishMarquee} getPageFromScroll={this.getPageFromScroll} savedAnnotations={this._savedAnnotations} annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} />} + <MarqueeAnnotator rootDoc={this.rootDoc} scrollTop={0} down={this._marqueeing} + anchorMenuClick={this.props.anchorMenuClick} + addDocument={this.addDocument} finishMarquee={this.finishMarquee} + getPageFromScroll={this.getPageFromScroll} savedAnnotations={this._savedAnnotations} + annotationLayer={this._annotationLayer.current} mainCont={this._mainCont.current} />} </div>; } }
\ No newline at end of file diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 041d9ce7f..d590695d0 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1066,26 +1066,27 @@ export namespace Doc { // filters document in a container collection: // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined - export function setDocFilter(target: Opt<Doc>, key: string, value: any, modifiers?: "remove" | "match" | "check" | "x" | undefined) { + export function setDocFilter(target: Opt<Doc>, key: string, value: any, modifiers: "remove" | "match" | "check" | "x", toggle?: boolean) { const container = target ?? CollectionDockingView.Instance.props.Document; const docFilters = Cast(container._docFilters, listSpec("string"), []); runInAction(() => { for (let i = 0; i < docFilters.length; i++) { const fields = docFilters[i].split(":"); // split key:value:modifier if (fields[0] === key && (fields[1] === value || modifiers === "match" || modifiers === "remove")) { - if (fields[2] === modifiers && modifiers && fields[1] === value) return; + if (fields[2] === modifiers && modifiers && fields[1] === value) { + if (toggle) modifiers = "remove"; + else return; + } docFilters.splice(i, 1); container._docFilters = new List<string>(docFilters); break; } } - if (typeof modifiers === "string") { - if (!docFilters.length && modifiers === "match" && value === undefined) { - container._docFilters = undefined; - } else if (modifiers !== "remove") { - docFilters.push(key + ":" + value + ":" + modifiers); - container._docFilters = new List<string>(docFilters); - } + if (!docFilters.length && modifiers === "match" && value === undefined) { + container._docFilters = undefined; + } else if (modifiers !== "remove") { + docFilters.push(key + ":" + value + ":" + modifiers); + container._docFilters = new List<string>(docFilters); } }); } @@ -1336,5 +1337,5 @@ Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: bo (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))); return docs.length ? new List(docs) : prevValue; }); -Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); }); +Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers: "match" | "check" | "x" | "remove") { Doc.setDocFilter(container, key, value, modifiers); }); Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); }); |