From fb9f08295c10c35c11b647d00a3c830867dc3f7d Mon Sep 17 00:00:00 2001 From: Stanley Yip Date: Tue, 3 Dec 2019 18:54:41 -0500 Subject: nothing new, infrastructure stuffs --- src/client/documents/Documents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c5bf109a1..8c6aa2006 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -422,7 +422,7 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); } - export function InkDocument(color: string, tool: number, strokeWidth: number, points: { x: number, y: number }[], options: DocumentOptions = {}) { + export function InkDocument(color: string, tool: number, strokeWidth: number, points: { X: number, Y: number }[], options: DocumentOptions = {}) { let doc = InstanceFromProto(Prototypes.get(DocumentType.INK), new InkField(points), options); doc.color = color; doc.strokeWidth = strokeWidth; -- cgit v1.2.3-70-g09d2 From 968d678e8aeb6f57cc892e3fe789067a8246c5fe Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 4 Dec 2019 17:47:28 -0500 Subject: started to add paths --- src/client/documents/Documents.ts | 5 +-- src/client/util/RichTextSchema.tsx | 3 +- src/client/views/CollectionLinearView.tsx | 1 + src/client/views/MainView.tsx | 11 ++++--- src/client/views/OverlayView.tsx | 1 + .../views/collections/CollectionDockingView.tsx | 38 +++++++++++++--------- .../views/collections/CollectionSchemaView.tsx | 1 + .../views/collections/CollectionStackingView.tsx | 1 + .../views/collections/CollectionTreeView.tsx | 36 +++++++++++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 1 + .../views/nodes/ContentFittingDocumentView.tsx | 4 ++- src/client/views/nodes/DocumentView.tsx | 12 ++++--- src/client/views/nodes/FieldView.tsx | 1 + src/client/views/nodes/FormattedTextBoxComment.tsx | 3 +- .../views/presentationview/PresElementBox.tsx | 3 +- src/client/views/search/SearchItem.tsx | 3 +- 16 files changed, 78 insertions(+), 46 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e0f2858ba..5d5bdfcbd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -534,7 +534,8 @@ export namespace Docs { export type DocConfig = { doc: Doc, - initialWidth?: number + initialWidth?: number, + path?: Doc[] }; export function StandardCollectionDockingDocument(configs: Array, options: DocumentOptions, id?: string, type: string = "row") { @@ -543,7 +544,7 @@ export namespace Docs { { type: type, content: [ - ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth)) + ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth, config.path)) ] } ] diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 3b786e61d..4612f2885 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -761,8 +761,9 @@ export class DashDocView { this._dashSpan.style.width = this._outer.style.width = dashDoc[WidthSym]() + "px"; }); ReactDOM.render( this.openWorkspace(mainDoc), 0); @@ -271,6 +270,7 @@ export class MainView extends React.Component { {!mainContainer ? (null) : this.flyoutWidth; - addDocTabFunc = (doc: Doc, data: Opt, where: string) => { + addDocTabFunc = (doc: Doc, data: Opt, where: string, libraryPath?: Doc[]) => { if (where === "close") { return CollectionDockingView.CloseRightSplit(doc); } @@ -346,7 +346,7 @@ export class MainView extends React.Component { this.openWorkspace(doc); return true; } else { - return CollectionDockingView.AddRightSplit(doc, undefined); + return CollectionDockingView.AddRightSplit(doc, undefined, undefined, libraryPath); } } mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); @@ -363,6 +363,7 @@ export class MainView extends React.Component { { @observable public static Instances: CollectionDockingView[] = []; @computed public static get Instance() { return CollectionDockingView.Instances[0]; } - public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number) { + public static makeDocumentConfig(document: Doc, dataDoc: Doc | undefined, width?: number, libraryPath?: Doc[]) { return { type: 'react-component', component: 'DocumentFrameRenderer', @@ -47,7 +47,8 @@ export class CollectionDockingView extends React.Component d[Id]) : [] //collectionDockingView: CollectionDockingView.Instance } }; @@ -95,12 +96,12 @@ export class CollectionDockingView extends React.Component { + public AddTab = (stack: any, document: Doc, dataDocument: Doc | undefined, libraryPath?: Doc[]) => { Doc.GetProto(document).lastOpened = new DateField; - const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument); + const docContentConfig = CollectionDockingView.makeDocumentConfig(document, dataDocument, undefined, libraryPath); if (stack === undefined) { let stack: any = this._goldenLayout.root; while (!stack.isStack) { @@ -427,10 +428,6 @@ export class CollectionDockingView extends React.Component, dragSpan); ReactDOM.render(, gearSpan); - // ReactDOM.render( { - // where === "onRight" ? CollectionDockingView.AddRightSplit(doc, dataDoc) : CollectionDockingView.Instance.AddTab(stack, doc, dataDoc); - // return true; - // }} />, upDiv); tab.reactComponents = [dragSpan, gearSpan, upDiv]; tab.element.append(dragSpan); tab.element.append(gearSpan); @@ -532,11 +529,13 @@ interface DockedFrameProps { documentId: FieldId; dataDocumentId: FieldId; glContainer: any; + libraryPath: (FieldId[]) //collectionDockingView: CollectionDockingView } @observer export class DockedFrameRenderer extends React.Component { _mainCont: HTMLDivElement | null = null; + @observable private _libraryPath: Doc[] = []; @observable private _panelWidth = 0; @observable private _panelHeight = 0; @observable private _document: Opt; @@ -554,6 +553,14 @@ export class DockedFrameRenderer extends React.Component { DocServer.GetRefField(this.props.dataDocumentId).then(action((f: Opt) => this._dataDoc = f as Doc)); } })); + this.props.libraryPath && this.setupLibraryPath(); + } + + async setupLibraryPath() { + Promise.all(this.props.libraryPath.map(async docid => { + let d = await DocServer.GetRefField(docid); + return d instanceof Doc ? d : undefined + })).then(action((list: (Doc | undefined)[]) => this._libraryPath = list.filter(d => d).map(d => d as Doc))); } /** @@ -640,17 +647,17 @@ export class DockedFrameRenderer extends React.Component { get previewPanelCenteringOffset() { return this.nativeWidth() && !this.layoutDoc!.ignoreAspect ? (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2 : 0; } get widthpercent() { return this.nativeWidth() && !this.layoutDoc!.ignoreAspect ? `${(this.nativeWidth() * this.contentScaling()) / this.panelWidth() * 100}%` : undefined; } - addDocTab = (doc: Doc, dataDoc: Opt, location: string) => { + addDocTab = (doc: Doc, dataDoc: Opt, location: string, libraryPath?: Doc[]) => { SelectionManager.DeselectAll(); if (doc.dockingConfig) { MainView.Instance.openWorkspace(doc); return true; } else if (location === "onRight") { - return CollectionDockingView.AddRightSplit(doc, dataDoc); + return CollectionDockingView.AddRightSplit(doc, dataDoc, undefined, libraryPath); } else if (location === "close") { return CollectionDockingView.CloseRightSplit(doc); } else { - return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc); + return CollectionDockingView.Instance.AddTab(this._stack, doc, dataDoc, libraryPath); } } @@ -659,6 +666,7 @@ export class DockedFrameRenderer extends React.Component { const document = this._document; const resolvedDataDoc = document.layout instanceof Doc ? document : this._dataDoc; return doc) { doc) { return boolean; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; panelWidth: () => number; panelHeight: () => number; @@ -95,8 +96,8 @@ class TreeView extends React.Component { @computed get MAX_EMBED_HEIGHT() { return NumCast(this.props.document.maxEmbedHeight, 300); } @computed get dataDoc() { return this.templateDataDoc ? this.templateDataDoc : this.props.document; } @computed get fieldKey() { - const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\""); - return splits.length > 1 ? splits[1].split("\"")[0] : "data"; + const splits = StrCast(Doc.LayoutField(this.props.document)).split("fieldKey={\'"); + return splits.length > 1 ? splits[1].split("\'")[0] : "data"; } childDocList(field: string) { const layout = Doc.LayoutField(this.props.document) instanceof Doc ? Doc.LayoutField(this.props.document) as Doc : undefined; @@ -120,7 +121,7 @@ class TreeView extends React.Component { } @undoBatch delete = () => this.props.deleteDoc(this.props.document); - @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight"); + @undoBatch openRight = () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath); @undoBatch indent = () => this.props.addDocument(this.props.document) && this.delete(); @undoBatch move = (doc: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => { return this.props.document !== target && this.props.deleteDoc(doc) && addDoc(doc); @@ -194,8 +195,8 @@ class TreeView extends React.Component { ContextMenu.Instance.addItem({ description: "Clear All", event: () => Doc.GetProto(CurrentUserUtils.UserDocument.recentlyClosed as Doc).data = new List(), icon: "plus" }); } else if (this.props.document !== CurrentUserUtils.UserDocument.workspaces) { ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" }); - ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab"), icon: "folder" }); - ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight"), icon: "caret-square-right" }); + ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "inTab", this.props.libraryPath), icon: "folder" }); + ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.templateDataDoc, "onRight", this.props.libraryPath), icon: "caret-square-right" }); if (DocumentManager.Instance.getDocumentViews(this.dataDoc).length) { ContextMenu.Instance.addItem({ description: "Focus", event: () => (view => view && view.props.focus(this.props.document, true))(DocumentManager.Instance.getFirstDocumentView(this.dataDoc)), icon: "camera" }); } @@ -286,7 +287,7 @@ class TreeView extends React.Component { DocListCast(contents), this.props.treeViewId, doc, undefined, key, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.hideHeaderFields, this.props.preventTreeViewOpen, - [...this.props.renderedIds, doc[Id]]); + [...this.props.renderedIds, doc[Id]], this.props.libraryPath); } else { contentElement = { this.templateDataDoc, expandKey, this.props.containingCollection, this.props.prevSibling, addDoc, remDoc, this.move, this.props.dropAction, this.props.addDocTab, this.props.pinToPres, this.props.ScreenToLocalTransform, this.props.outerXf, this.props.active, this.props.panelWidth, this.props.ChromeHeight, this.props.renderDepth, this.props.hideHeaderFields, this.props.preventTreeViewOpen, - [...this.props.renderedIds, this.props.document[Id]])} + [...this.props.renderedIds, this.props.document[Id]], this.props.libraryPath)} ; } else if (this.treeViewExpandedView === "fields") { return
    @@ -343,6 +344,7 @@ class TreeView extends React.Component { { renderDepth: number, hideHeaderFields: () => boolean, preventTreeViewOpen: boolean, - renderedIds: string[] + renderedIds: string[], + libraryPath: Doc[] | undefined ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); if (viewSpecScript) { @@ -499,9 +502,9 @@ class TreeView extends React.Component { } const indent = i === 0 ? undefined : () => { - if (StrCast(docs[i - 1].layout).indexOf("fieldKey") !== -1) { - const fieldKeysub = StrCast(docs[i - 1].layout).split("fieldKey")[1]; - const fieldKey = fieldKeysub.split("\"")[1]; + if (StrCast(docs[i - 1].layout).indexOf('fieldKey') !== -1) { + const fieldKeysub = StrCast(docs[i - 1].layout).split('fieldKey')[1]; + const fieldKey = fieldKeysub.split("\'")[1]; if (fieldKey && Cast(docs[i - 1][fieldKey], listSpec(Doc)) !== undefined) { Doc.AddDocToList(docs[i - 1], fieldKey, child); docs[i - 1].treeViewOpen = true; @@ -510,9 +513,9 @@ class TreeView extends React.Component { } }; const outdent = !parentCollectionDoc ? undefined : () => { - if (StrCast(parentCollectionDoc.layout).indexOf("fieldKey") !== -1) { - const fieldKeysub = StrCast(parentCollectionDoc.layout).split("fieldKey")[1]; - const fieldKey = fieldKeysub.split("\"")[1]; + if (StrCast(parentCollectionDoc.layout).indexOf('fieldKey') !== -1) { + const fieldKeysub = StrCast(parentCollectionDoc.layout).split('fieldKey')[1]; + const fieldKey = fieldKeysub.split("\'")[1]; Doc.AddDocToList(parentCollectionDoc, fieldKey, child, parentPrevSibling, false); parentCollectionDoc.treeViewOpen = true; remove(child); @@ -529,6 +532,7 @@ class TreeView extends React.Component { return !(child instanceof Doc) ? (null) : BoolCast(this.props.Document.hideHeaderFields), - BoolCast(this.props.Document.preventTreeViewOpen), []) + BoolCast(this.props.Document.preventTreeViewOpen), [], this.props.LibraryPath) }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index c69b264c4..c3e064da5 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -627,6 +627,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { ...this.props, DataDoc: childData, Document: childLayout, + LibraryPath: this.props.LibraryPath ? [...this.props.LibraryPath, this.props.Document] : [], layoutKey: undefined, ruleProvider: this.Document.isRuleProvider && childLayout.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider, //bcz: hack! - currently ruleProviders apply to documents in nested colleciton, not direct children of themselves onClick: undefined, // this.props.onClick, // bcz: check this out -- I don't think we want to inherit click handlers, or we at least need a way to ignore them diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index efc907f9b..86fab0ba0 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -17,6 +17,7 @@ import { CollectionView } from "../collections/CollectionView"; interface ContentFittingDocumentViewProps { Document?: Doc; DataDocument?: Doc; + LibraryPath: Doc[]; childDocs?: Doc[]; renderDepth: number; fitToBox?: boolean; @@ -85,8 +86,9 @@ export class ContentFittingDocumentView extends React.Component ; Document: Doc; DataDoc?: Doc; + LibraryPath: Doc[]; fitToBox?: boolean; onClick?: ScriptField; addDocument?: (doc: Doc) => boolean; @@ -70,7 +71,7 @@ export interface DocumentViewProps { parentActive: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; bringToFront: (doc: Doc, sendToBack?: boolean) => void; - addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean; + addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string, libraryPath?: Doc[]) => boolean; pinToPres: (document: Doc) => void; zoomToScale: (scale: number) => void; backgroundColor: (doc: Doc) => string | undefined; @@ -401,9 +402,9 @@ export class DocumentView extends DocComponent(Docu const cm = ContextMenu.Instance; const subitems: ContextMenuProps[] = []; - subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this), icon: "desktop" }); - subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"), icon: "folder" }); - subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight"), icon: "caret-square-right" }); + subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this, this.props.LibraryPath), icon: "desktop" }); + subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab", this.props.LibraryPath), icon: "folder" }); + subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight", this.props.LibraryPath), icon: "caret-square-right" }); subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" }); subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" }); subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" }); @@ -527,6 +528,8 @@ export class DocumentView extends DocComponent(Docu SelectionManager.SelectDoc(this, false); } }); + let path = this.props.LibraryPath.reduce((p: string, d: Doc) => p + "/" + (Doc.AreProtosEqual(d, (Doc.UserDoc().LibraryBtn as Doc).sourcePanel as Doc) ? "" : d.title), ""); + cm.addItem({ description: `path: ${path}`, event: () => { }, icon: "check" }) } // does Document set a layout prop @@ -552,6 +555,7 @@ export class DocumentView extends DocComponent(Docu ContainingCollectionDoc={this.props.ContainingCollectionDoc} Document={this.props.Document} fitToBox={this.props.fitToBox} + LibraryPath={this.props.LibraryPath} addDocument={this.props.addDocument} removeDocument={this.props.removeDocument} moveDocument={this.props.moveDocument} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 048960c5e..ce1c468ad 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -30,6 +30,7 @@ export interface FieldViewProps { ruleProvider: Doc | undefined; Document: Doc; DataDoc?: Doc; + LibraryPath: Doc[]; onClick?: ScriptField; isSelected: (outsideReaction?: boolean) => boolean; select: (isCtrlPressed: boolean) => void; diff --git a/src/client/views/nodes/FormattedTextBoxComment.tsx b/src/client/views/nodes/FormattedTextBoxComment.tsx index 2ec30e3b3..9f1dd4aec 100644 --- a/src/client/views/nodes/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/FormattedTextBoxComment.tsx @@ -177,8 +177,9 @@ export class FormattedTextBoxComment { } catch (e) { } if (target) { ReactDOM.render((P width: propDocWidth === 0 ? "auto" : propDocWidth * scale(), }}> { onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} onPointerLeave={action(() => this._displayDim = 50)} > Date: Thu, 12 Dec 2019 21:00:36 -0500 Subject: fixed warnings. Limited the size of pasted text boxes --- src/client/documents/Documents.ts | 1 + src/client/util/DragManager.ts | 14 ++++++------- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/PreviewCursor.tsx | 32 +++++++++++------------------ src/client/views/ScriptBox.tsx | 2 +- src/client/views/linking/LinkMenuGroup.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 11 +++++++--- 7 files changed, 30 insertions(+), 34 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5d5bdfcbd..7df08c7e6 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -112,6 +112,7 @@ export interface DocumentOptions { dropConverter?: ScriptField; // script to run when documents are dropped on this Document. strokeWidth?: number; color?: string; + limitHeight?:number; // maximum height for newly created (eg, from pasting) text documents // [key: string]: Opt; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 95529311a..326262895 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -101,10 +101,10 @@ export namespace DragManager { export class DragCompleteEvent { constructor(aborted: boolean, dragData: { [id: string]: any }) { this.aborted = aborted; - this.docDragData = dragData instanceof DocumentDragData ? dragData as DocumentDragData : undefined; - this.annoDragData = dragData instanceof PdfAnnoDragData ? dragData as PdfAnnoDragData : undefined; - this.linkDragData = dragData instanceof LinkDragData ? dragData as LinkDragData : undefined; - this.columnDragData = dragData instanceof ColumnDragData ? dragData as ColumnDragData : undefined; + this.docDragData = dragData instanceof DocumentDragData ? dragData : undefined; + this.annoDragData = dragData instanceof PdfAnnoDragData ? dragData : undefined; + this.linkDragData = dragData instanceof LinkDragData ? dragData : undefined; + this.columnDragData = dragData instanceof ColumnDragData ? dragData : undefined; } aborted: boolean; docDragData?: DocumentDragData; @@ -140,14 +140,12 @@ export namespace DragManager { linkSourceDocument: Doc; dontClearTextBox?: boolean; linkDocument?: Doc; - [id: string]: any; } export class ColumnDragData { constructor(colKey: SchemaHeaderField) { this.colKey = colKey; } colKey: SchemaHeaderField; - [id: string]: any; } // used by PDFs to conditionally (if the drop completes) create a text annotation when dragging from the PDF toolbar when a text region has been selected. // this is pretty clunky and should be rethought out using linkDrag or DocumentDrag @@ -216,7 +214,7 @@ export namespace DragManager { // drag links and drop link targets (aliasing them if needed) export async function StartLinkTargetsDrag(dragEle: HTMLElement, downX: number, downY: number, sourceDoc: Doc, specificLinks?: Doc[]) { - let draggedDocs = (specificLinks ? specificLinks : DocListCast(sourceDoc.links)).map(link => LinkManager.Instance.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[]; + const draggedDocs = (specificLinks ? specificLinks : DocListCast(sourceDoc.links)).map(link => LinkManager.Instance.getOppositeAnchor(link, sourceDoc)).filter(l => l) as Doc[]; if (draggedDocs.length) { const moddrag: Doc[] = []; @@ -225,7 +223,7 @@ export namespace DragManager { if (doc) moddrag.push(doc); } - let dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); + const dragData = new DragManager.DocumentDragData(moddrag.length ? moddrag : draggedDocs); dragData.moveDocument = (doc: Doc, targetCollection: Doc | undefined, addDocument: (doc: Doc) => boolean): boolean => { const document = SelectionManager.SelectedDocuments()[0]; document && document.props.removeDocument && document.props.removeDocument(doc); diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index f014c1329..58728ab7f 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -114,7 +114,7 @@ export class DocumentButtonBar extends React.Component<{ views: DocumentView[], const proto = Doc.GetProto(linkDoc); proto.sourceContext = this.props.views[0].props.ContainingCollectionDoc; - const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast((linkDoc.anchor2 as Doc).title) : "-untitled-"; + const anchor2Title = linkDoc.anchor2 instanceof Doc ? StrCast(linkDoc.anchor2.title) : "-untitled-"; const text = FormattedTextBox.ToolTipTextMenu.makeLink(linkDoc, anchor2Title, e.ctrlKey ? "onRight" : "inTab"); if (linkDoc.anchor2 instanceof Doc) { proto.title = text === "" ? proto.title : text + " to " + linkDoc.anchor2.title; // TODO open to more descriptive descriptions of following in text link diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index fd0287b6c..8adcf1220 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -5,7 +5,7 @@ import * as React from 'react'; import "./PreviewCursor.scss"; import { Docs } from '../documents/Documents'; // import { Transform } from 'prosemirror-transform'; -import { Doc } from '../../new_fields/Doc'; +import { Doc, HeightSym } from '../../new_fields/Doc'; import { Transform } from "../util/Transform"; import { TraceMobx } from '../../new_fields/util'; @@ -27,61 +27,53 @@ export class PreviewCursor extends React.Component<{}> { if (PreviewCursor.Visible) { if (e.clipboardData) { const newPoint = PreviewCursor._getTransform().transformPoint(PreviewCursor._clickPoint[0], PreviewCursor._clickPoint[1]); - runInAction(() => { PreviewCursor.Visible = false; }); - + runInAction(() => PreviewCursor.Visible = false); if (e.clipboardData.getData("text/plain") !== "") { // tests for youtube and makes video document if (e.clipboardData.getData("text/plain").indexOf("www.youtube.com/watch") !== -1) { const url = e.clipboardData.getData("text/plain").replace("youtube.com/watch?v=", "youtube.com/embed/"); - PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { + return PreviewCursor._addDocument(Docs.Create.VideoDocument(url, { title: url, width: 400, height: 315, nativeWidth: 600, nativeHeight: 472.5, x: newPoint[0], y: newPoint[1] })); - return; } // tests for URL and makes web document const re: any = /^https?:\/\//g; if (re.test(e.clipboardData.getData("text/plain"))) { const url = e.clipboardData.getData("text/plain"); - PreviewCursor._addDocument(Docs.Create.WebDocument(url, { - title: url, width: 300, height: 300, + return PreviewCursor._addDocument(Docs.Create.WebDocument(url, { + title: url, width: 500, height: 300, // nativeWidth: 300, nativeHeight: 472.5, x: newPoint[0], y: newPoint[1] })); - return; } // creates text document - const newBox = Docs.Create.TextDocument({ - width: 200, height: 100, + return PreviewCursor._addLiveTextDoc(Docs.Create.TextDocument({ + width: 500, + autoHeight: true, x: newPoint[0], y: newPoint[1], + limitHeight: 400, title: "-pasted text-" - }); - - newBox.proto!.autoHeight = true; - PreviewCursor._addLiveTextDoc(newBox); - return; + })); } //pasting in images if (e.clipboardData.getData("text/html") !== "" && e.clipboardData.getData("text/html").includes(" { return; } - var div = document.createElement("div"); + const div = document.createElement("div"); div.style.width = "90"; div.style.height = "20"; div.style.background = "gray"; diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index da56435f2..abd17ec4d 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -46,7 +46,7 @@ export class LinkMenuGroup extends React.Component { document.removeEventListener("pointermove", this.onLinkButtonMoved); document.removeEventListener("pointerup", this.onLinkButtonUp); - let targets = this.props.group.map(l => LinkManager.Instance.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[]; + const targets = this.props.group.map(l => LinkManager.Instance.getOppositeAnchor(l, this.props.sourceDoc)).filter(d => d) as Doc[]; DragManager.StartLinkTargetsDrag(this._drag.current!, e.x, e.y, this.props.sourceDoc, targets); } e.stopPropagation(); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index af09e57f4..a298fd6af 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -630,7 +630,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & { fireImmediately: true } ); - setTimeout(() => this.tryUpdateHeight(), 0); + setTimeout(() => this.tryUpdateHeight(NumCast(this.layoutDoc.limitHeight, 0))); } pushToGoogleDoc = async () => { @@ -1087,10 +1087,15 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & } @action - tryUpdateHeight() { - const scrollHeight = this._ref.current?.scrollHeight; + tryUpdateHeight(limitHeight?: number) { + let scrollHeight = this._ref.current?.scrollHeight; if (!this.layoutDoc.animateToPos && this.layoutDoc.autoHeight && scrollHeight && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation + if (limitHeight && scrollHeight > limitHeight) { + scrollHeight = limitHeight; + this.layoutDoc.limitHeight = undefined; + this.layoutDoc.autoHeight = false; + } const nh = this.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); const dh = NumCast(this.layoutDoc.height, 0); const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); -- cgit v1.2.3-70-g09d2 From 56e384f2d97d2c399adf21fcf58143773fe3fd53 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 14 Dec 2019 01:51:13 -0500 Subject: fixes to make nativewidth/height more robust for PDFs. fixes for search - filter out extension docs. --- src/client/documents/Documents.ts | 11 ++++--- src/client/util/DragManager.ts | 23 ++++++++------ .../util/Import & Export/DirectoryImportBox.tsx | 7 +---- src/client/util/SearchUtil.ts | 4 +-- src/client/views/DocComponent.tsx | 1 + src/client/views/collections/CollectionSubView.tsx | 4 +-- .../views/collections/ParentDocumentSelector.tsx | 2 +- src/client/views/nodes/PDFBox.tsx | 34 ++++++++++++-------- src/client/views/pdf/PDFMenu.tsx | 36 ++-------------------- src/client/views/pdf/PDFViewer.tsx | 4 +-- src/client/views/search/SearchBox.tsx | 5 ++- src/new_fields/Doc.ts | 11 +++++-- 12 files changed, 61 insertions(+), 81 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7df08c7e6..4ba45ac30 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -112,7 +112,7 @@ export interface DocumentOptions { dropConverter?: ScriptField; // script to run when documents are dropped on this Document. strokeWidth?: number; color?: string; - limitHeight?:number; // maximum height for newly created (eg, from pasting) text documents + limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents // [key: string]: Opt; } @@ -181,7 +181,7 @@ export namespace Docs { }], [DocumentType.PDF, { layout: { view: PDFBox, dataField: data }, - options: { nativeWidth: 1200, curPage: 1 } + options: { curPage: 1 } }], [DocumentType.ICON, { layout: { view: IconBox, dataField: data }, @@ -644,17 +644,20 @@ export namespace Docs { let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise)) | undefined = undefined; if (type.indexOf("image") !== -1) { ctor = Docs.Create.ImageDocument; + if (!options.width) options.width = 300; } if (type.indexOf("video") !== -1) { ctor = Docs.Create.VideoDocument; + if (!options.width) options.width = 600; + if (!options.height) options.height = options.width * 2 / 3; } if (type.indexOf("audio") !== -1) { ctor = Docs.Create.AudioDocument; } if (type.indexOf("pdf") !== -1) { ctor = Docs.Create.PdfDocument; - options.nativeWidth = 927; - options.nativeHeight = 1200; + if (!options.width) options.width = 400; + if (!options.height) options.height = options.width * 1200 / 927; } if (type.indexOf("excel") !== -1) { ctor = Docs.Create.DBDocument; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 326262895..2631a1e3c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -18,7 +18,7 @@ import { convertDropDataToButtons } from "./DropConverter"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( _reference: React.RefObject, - docFunc: () => Doc | Promise, + docFunc: () => Doc | Promise | undefined, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, treeViewId?: string, @@ -32,13 +32,15 @@ export function SetupDrag( document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); const doc = await docFunc(); - const dragData = new DragManager.DocumentDragData([doc]); - dragData.dropAction = dropAction; - dragData.moveDocument = moveFunc; - dragData.treeViewId = treeViewId; - dragData.dontHideOnDrop = dontHideOnDrop; - DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); - dragStarted && dragStarted(); + if (doc) { + const dragData = new DragManager.DocumentDragData([doc]); + dragData.dropAction = dropAction; + dragData.moveDocument = moveFunc; + dragData.treeViewId = treeViewId; + dragData.dontHideOnDrop = dontHideOnDrop; + DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); + dragStarted && dragStarted(); + } }; const onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); @@ -49,12 +51,13 @@ export function SetupDrag( e.stopPropagation(); if (e.shiftKey && CollectionDockingView.Instance) { e.persist(); - CollectionDockingView.Instance.StartOtherDrag({ + let dragDoc = await docFunc(); + dragDoc && CollectionDockingView.Instance.StartOtherDrag({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 - }, [await docFunc()]); + }, [dragDoc]); } else { document.addEventListener("pointermove", onRowMove); document.addEventListener("pointerup", onRowUp); diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index e6a215b2c..5b5bffd8c 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -122,12 +122,7 @@ export default class DirectoryImportBox extends React.Component await Promise.all(uploads.map(async ({ name, type, clientAccessPath, exifData }) => { const path = Utils.prepend(clientAccessPath); - const options = { - nativeWidth: 300, - width: 300, - title: name - }; - const document = await Docs.Get.DocumentFromType(type, path, options); + const document = await Docs.Get.DocumentFromType(type, path, { width: 300, title: name }); const { data, error } = exifData; if (document) { Doc.GetProto(document).exif = error || Docs.Get.DocumentHierarchyFromJson(data); diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 7a9176bec..1fda82880 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -64,7 +64,7 @@ export namespace SearchUtil { const textDocs = newIds.map((id: string) => textDocMap[id]).map(doc => doc as Doc); for (let i = 0; i < textDocs.length; i++) { const testDoc = textDocs[i]; - if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1) { + if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && testDoc.type !== DocumentType.EXTENSION && theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1) { theDocs.push(Doc.GetProto(testDoc)); theLines.push(newLines[i].map(line => line.replace(query, query.toUpperCase()))); } @@ -74,7 +74,7 @@ export namespace SearchUtil { const docs = ids.map((id: string) => docMap[id]).map(doc => doc as Doc); for (let i = 0; i < ids.length; i++) { const testDoc = docs[i]; - if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowAliases || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { + if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && testDoc.type !== DocumentType.EXTENSION && (options.allowAliases || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { theDocs.push(testDoc); theLines.push([]); } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index c7ddee7ea..7fbad4638 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -59,6 +59,7 @@ export function DocAnnotatableComponent

(schema @computed get layoutDoc() { return Doc.Layout(this.props.Document); } @computed get dataDoc() { return (this.props.DataDoc && this.props.Document.isTemplateField ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } + @computed get extensionDocSync() { return Doc.fieldExtensionDocSync(this.dataDoc, this.props.fieldKey); } @computed get annotationsKey() { return "annotations"; } @action.bound diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5c7794cc0..062521690 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -262,7 +262,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { .then(result => { const type = result["content-type"]; if (type) { - Docs.Get.DocumentFromType(type, str, { ...options, width: 300, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300 }) + Docs.Get.DocumentFromType(type, str, options) .then(doc => doc && this.props.addDocument(doc)); } }); @@ -281,7 +281,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { const dropFileName = file ? file.name : "-empty-"; promises.push(Networking.PostFormDataToServer("/upload", formData).then(results => { results.map(action(({ clientAccessPath }: any) => { - const full = { ...options, nativeWidth: type.indexOf("video") !== -1 ? 600 : 300, width: 300, title: dropFileName }; + const full = { ...options, width: 300, title: dropFileName }; const pathname = Utils.prepend(clientAccessPath); Docs.Get.DocumentFromType(type, pathname, full).then(doc => { doc && (Doc.GetProto(doc).fileUpload = basename(pathname).replace("upload_", "").replace(/\.[a-z0-9]*$/, "")); diff --git a/src/client/views/collections/ParentDocumentSelector.tsx b/src/client/views/collections/ParentDocumentSelector.tsx index 5208f65c4..31f19d42d 100644 --- a/src/client/views/collections/ParentDocumentSelector.tsx +++ b/src/client/views/collections/ParentDocumentSelector.tsx @@ -81,7 +81,7 @@ export class SelectorContextMenu extends React.Component { @observer export class ParentDocSelector extends React.Component { render() { - let flyout = ( + const flyout = (

diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 9f67f3eab..2f1e1832e 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -3,7 +3,7 @@ import { action, observable, runInAction, reaction, IReactionDisposer, trace, un import { observer } from "mobx-react"; import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; -import { Opt, WidthSym, Doc } from "../../../new_fields/Doc"; +import { Opt, WidthSym, Doc, HeightSym } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; @@ -49,6 +49,9 @@ export class PDFBox extends DocAnnotatableComponent constructor(props: any) { super(props); this._initialScale = this.props.ScreenToLocalTransform().Scale; + const nw = this.Document.nativeWidth = NumCast(this.extensionDocSync.nativeWidth, NumCast(this.Document.nativeWidth, 927)); + const nh = this.Document.nativeHeight = NumCast(this.extensionDocSync.nativeHeight, NumCast(this.Document.nativeHeight, 1200)); + !this.Document.fitWidth && !this.Document.ignoreAspect && (this.Document.height = this.Document[WidthSym]() * (nh / nw)); const backup = "oldPath"; const { Document } = this.props; @@ -78,10 +81,6 @@ export class PDFBox extends DocAnnotatableComponent this._selectReactionDisposer && this._selectReactionDisposer(); } componentDidMount() { - const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - if (pdfUrl instanceof PdfField) { - Pdfjs.getDocument(pdfUrl.url.href).promise.then(pdf => runInAction(() => this._pdf = pdf)); - } this._selectReactionDisposer = reaction(() => this.props.isSelected(), () => { document.removeEventListener("keydown", this.onKeyDown); @@ -90,9 +89,9 @@ export class PDFBox extends DocAnnotatableComponent } loaded = (nw: number, nh: number, np: number) => { - this.dataDoc.numPages = np; - this.Document.nativeWidth = nw * 96 / 72; - this.Document.nativeHeight = nh * 96 / 72; + this.extensionDocSync.numPages = np; + this.extensionDocSync.nativeWidth = this.Document.nativeWidth = nw * 96 / 72; + this.extensionDocSync.nativeHeight = this.Document.nativeHeight = nh * 96 / 72; !this.Document.fitWidth && !this.Document.ignoreAspect && (this.Document.height = this.Document[WidthSym]() * (nh / nw)); } @@ -220,9 +219,9 @@ export class PDFBox extends DocAnnotatableComponent @computed get renderTitleBox() { const classname = "pdfBox" + (this.active() ? "-interactive" : ""); return
{this.props.Document.title} @@ -248,10 +247,19 @@ export class PDFBox extends DocAnnotatableComponent
; } + _pdfjsRequested = false; render() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField, null); if (this.props.isSelected() || this.props.Document.scrollY !== undefined) this._everActive = true; - return !pdfUrl || !this._pdf || !this.extensionDoc || (!this._everActive && this.props.ScreenToLocalTransform().Scale > 2.5) ? - this.renderTitleBox : this.renderPdfView; + if (pdfUrl && this.extensionDoc && (this._everActive || (this.extensionDoc.nativeWidth && this.props.ScreenToLocalTransform().Scale < 2.5))) { + if (pdfUrl instanceof PdfField && this._pdf) { + return this.renderPdfView; + } + if (!this._pdfjsRequested) { + this._pdfjsRequested = true; + Pdfjs.getDocument(pdfUrl.url.href).promise.then(pdf => runInAction(() => this._pdf = pdf)); + } + } + return this.renderTitleBox; } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 38e10e99a..503696ae9 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -12,19 +12,17 @@ export default class PDFMenu extends AntimodeMenu { static Instance: PDFMenu; private _commentCont = React.createRef(); - private _snippetButton: React.RefObject = React.createRef(); @observable private _keyValue: string = ""; @observable private _valueValue: string = ""; @observable private _added: boolean = false; @observable public Highlighting: boolean = false; - @observable public Status: "pdf" | "annotation" | "snippet" | "" = ""; + @observable public Status: "pdf" | "annotation" | "" = ""; public StartDrag: (e: PointerEvent, ele: HTMLElement) => void = unimplementedFunction; public Highlight: (color: string) => Opt = (color: string) => undefined; public Delete: () => void = unimplementedFunction; - public Snippet: (marquee: { left: number, top: number, width: number, height: number }) => void = unimplementedFunction; public AddTag: (key: string, value: string) => boolean = returnFalse; public PinToPres: () => void = unimplementedFunction; public Marquee: { left: number; top: number; width: number; height: number; } | undefined; @@ -80,34 +78,6 @@ export default class PDFMenu extends AntimodeMenu { this.Delete(); } - snippetStart = (e: React.PointerEvent) => { - document.removeEventListener("pointermove", this.snippetDrag); - document.addEventListener("pointermove", this.snippetDrag); - document.removeEventListener("pointerup", this.snippetEnd); - document.addEventListener("pointerup", this.snippetEnd); - - e.stopPropagation(); - e.preventDefault(); - } - - snippetDrag = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (!this._dragging) { - this._dragging = true; - - this.Marquee && this.Snippet(this.Marquee); - } - } - - snippetEnd = (e: PointerEvent) => { - this._dragging = false; - document.removeEventListener("pointermove", this.snippetDrag); - document.removeEventListener("pointerup", this.snippetEnd); - e.stopPropagation(); - e.preventDefault(); - } - @action keyChanged = (e: React.ChangeEvent) => { this._keyValue = e.currentTarget.value; @@ -128,14 +98,12 @@ export default class PDFMenu extends AntimodeMenu { } render() { - const buttons = this.Status === "pdf" || this.Status === "snippet" ? + const buttons = this.Status === "pdf" ? [ , , - , ] : [ diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index e34d353f4..1a09991d2 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -417,7 +417,6 @@ export class PDFViewer extends DocAnnotatableComponent v.forEach(a => a.remove())); @@ -515,7 +514,6 @@ export class PDFViewer extends DocAnnotatableComponent { this.Document.height = this.Document[WidthSym]() * this._coverPath.height / this._coverPath.width; - this.Document.nativeHeight = nativeWidth * this._coverPath.height / this._coverPath.width; + this.Document.nativeHeight = (this.Document.nativeWidth || 0) * this._coverPath.height / this._coverPath.width; }).bind(this), 0); } const nativeWidth = (this.Document.nativeWidth || 0); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index b80c3bb54..2f28ebf76 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -234,8 +234,7 @@ export class SearchBox extends React.Component { y += 300; } } - return Docs.Create.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); - + return Docs.Create.TreeDocument(docs, { width: 200, height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` }); } @action.bound @@ -341,7 +340,7 @@ export class SearchBox extends React.Component { return (
{ e.stopPropagation(); e.preventDefault(); }}>
- + this._searchString ? this.startDragCollection() : undefined)} ref={this.collectionRef} title="Drag Results as Collection"> CreateDocumentExtensionForField(doc, fieldKey), 0); - return extension ? extension : undefined; + const extension = doc[fieldKey + "_ext"]; + if (extension === undefined) { + setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0); + } + return extension ? extension as Doc : undefined; + } + export function fieldExtensionDocSync(doc: Doc, fieldKey: string) { + return (doc[fieldKey + "_ext"] as Doc) || CreateDocumentExtensionForField(doc, fieldKey); } export function CreateDocumentExtensionForField(doc: Doc, fieldKey: string) { -- cgit v1.2.3-70-g09d2 From 55823d0cc300f5cdd90ee34013bfdee93b5709e6 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 15 Dec 2019 20:11:58 -0500 Subject: added a DocumentBox as a contentfitting container for another document. added a menu item for showing selected document. --- src/client/documents/DocumentTypes.ts | 3 +- src/client/documents/Documents.ts | 9 ++++ .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- .../views/nodes/ContentFittingDocumentView.tsx | 6 +-- src/client/views/nodes/DocumentBox.scss | 6 +++ src/client/views/nodes/DocumentBox.tsx | 55 ++++++++++++++++++++++ src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/ImageBox.tsx | 1 - src/new_fields/ScriptField.ts | 2 +- .../authentication/models/current_user_utils.ts | 1 + 10 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 src/client/views/nodes/DocumentBox.scss create mode 100644 src/client/views/nodes/DocumentBox.tsx (limited to 'src/client/documents') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index f6dd0c346..8f96b2fa6 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -25,5 +25,6 @@ export enum DocumentType { COLOR = "color", DOCULINK = "doculink", PDFANNO = "pdfanno", - INK = "ink" + INK = "ink", + DOCUMENT = "document" } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 4ba45ac30..50c51ace1 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -48,6 +48,7 @@ import { PresElementBox } from "../views/presentationview/PresElementBox"; import { QueryBox } from "../views/nodes/QueryBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { DocuLinkBox } from "../views/nodes/DocuLinkBox"; +import { DocumentBox } from "../views/nodes/DocumentBox"; import { InkingStroke } from "../views/InkingStroke"; import { InkField } from "../../new_fields/InkField"; const requestImageSize = require('../util/request-image-size'); @@ -171,6 +172,10 @@ export namespace Docs { layout: { view: KeyValueBox, dataField: data }, options: { height: 150 } }], + [DocumentType.DOCUMENT, { + layout: { view: DocumentBox, dataField: data }, + options: { height: 250 } + }], [DocumentType.VID, { layout: { view: VideoBox, dataField: data }, options: { currentTimecode: 0 }, @@ -482,6 +487,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options }); } + export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.DOCUMENT), document, { title: document ? document.title + "" : "container", ...options }); + } + export function FreeformDocument(documents: Array, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform }, id); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 9bb6fa97e..0b18e9f25 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -908,7 +908,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
- {!BoolCast(this.Document.LODdisable) && this.props.renderDepth > 0 && this.Document[WidthSym]() * this.Document[HeightSym]() / this.props.ScreenToLocalTransform().Scale < NumCast(this.Document.LODarea, 100000) ? this.placeholder : this.marqueeView} + {!BoolCast(this.Document.LODdisable) && !this.props.isAnnotationOverlay && this.props.renderDepth > 0 && this.Document[WidthSym]() * this.Document[HeightSym]() / this.props.ScreenToLocalTransform().Scale < NumCast(this.Document.LODarea, 100000) ? this.placeholder : this.marqueeView}
; } diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx index 5e3306a11..2565fd932 100644 --- a/src/client/views/nodes/ContentFittingDocumentView.tsx +++ b/src/client/views/nodes/ContentFittingDocumentView.tsx @@ -31,9 +31,9 @@ interface ContentFittingDocumentViewProps { CollectionDoc?: Doc; onClick?: ScriptField; getTransform: () => Transform; - addDocument: (document: Doc) => boolean; - moveDocument: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean; - removeDocument: (document: Doc) => boolean; + addDocument?: (document: Doc) => boolean; + moveDocument?: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean; + removeDocument?: (document: Doc) => boolean; active: (outsideReaction: boolean) => boolean; whenActiveChanged: (isActive: boolean) => void; addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean; diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss new file mode 100644 index 000000000..6a2f98166 --- /dev/null +++ b/src/client/views/nodes/DocumentBox.scss @@ -0,0 +1,6 @@ +.documentBox-container { + width: 100%; + height: 100%; + pointer-events: all; + background: gray; +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx new file mode 100644 index 000000000..2f2cba485 --- /dev/null +++ b/src/client/views/nodes/DocumentBox.tsx @@ -0,0 +1,55 @@ +import { observer } from "mobx-react"; +import { Doc } from "../../../new_fields/Doc"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { makeInterface } from "../../../new_fields/Schema"; +import { ComputedField } from "../../../new_fields/ScriptField"; +import { emptyFunction, emptyPath } from "../../../Utils"; +import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from "../ContextMenuItem"; +import { DocComponent } from "../DocComponent"; +import { ContentFittingDocumentView } from "./ContentFittingDocumentView"; +import "./DocumentBox.scss"; +import { FieldView, FieldViewProps } from "./FieldView"; +import React = require("react"); + +type DocBoxSchema = makeInterface<[typeof documentSchema]>; +const DocBoxDocument = makeInterface(documentSchema); + +@observer +export class DocumentBox extends DocComponent(DocBoxDocument) { + public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocumentBox, fieldKey); } + + + specificContextMenu = (e: React.MouseEvent): void => { + const funcs: ContextMenuProps[] = []; + funcs.push({ description: "Auto Show Selected", event: () => Doc.GetProto(this.props.Document).data = ComputedField.MakeFunction("selectedDocs(this,true,_last_)?.[0]"), icon: "expand-arrows-alt" }); + + ContextMenu.Instance.addItem({ description: "DocumentBox Funcs...", subitems: funcs, icon: "asterisk" }); + } + render() { + const containedDoc = this.props.Document[this.props.fieldKey] as Doc; + return
+ {!containedDoc ? (null) : } +
; + } +} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 1bbc82119..8f6bfc8e1 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -14,6 +14,7 @@ import { LinkFollowBox } from "../linking/LinkFollowBox"; import { YoutubeBox } from "./../../apis/youtube/YoutubeBox"; import { AudioBox } from "./AudioBox"; import { ButtonBox } from "./ButtonBox"; +import { DocumentBox } from "./DocumentBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; import { FontIconBox } from "./FontIconBox"; @@ -102,7 +103,7 @@ export class DocumentContentsView extends React.Component Date: Fri, 20 Dec 2019 13:50:36 -0500 Subject: fixed nested text box to stopPropagation on key press to prevent backscpace from deleting everything. made Esc desleect text and the document. fixed jumpToDOcument to focus annotationOn documents properly (particularly for sidebar text notes). fixed deselecting docsin textbox sidebar. --- src/client/documents/Documents.ts | 3 ++- src/client/util/DocumentManager.ts | 9 +++++--- src/client/util/ProsemirrorExampleTransfer.ts | 8 ++++++- src/client/util/RichTextRules.ts | 2 +- src/client/util/RichTextSchema.tsx | 11 +++++++--- src/client/views/nodes/FormattedTextBox.tsx | 31 ++++++++++++++++----------- 6 files changed, 42 insertions(+), 22 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 50c51ace1..304eccc02 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -97,6 +97,7 @@ export interface DocumentOptions { schemaColumns?: List; dockingConfig?: string; autoHeight?: boolean; + annotationOn?: Doc; removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; ischecked?: ScriptField; // returns whether a font icon box is checked @@ -316,7 +317,7 @@ export namespace Docs { */ export namespace Create { - const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "nativeWidth", "nativeHeight", "dropAction", "forceActive", "fitWidth"]; + const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "nativeWidth", "nativeHeight", "dropAction", "annotationOn", "forceActive", "fitWidth"]; /** * This function receives the relevant document prototype and uses diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 85303176f..60c251f0e 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -134,10 +134,13 @@ export class DocumentManager { finalDocView && Doc.linkFollowHighlight(finalDocView.props.Document); }; const docView = DocumentManager.Instance.getFirstDocumentView(targetDoc); - const annotatedDoc = await Cast(targetDoc.annotationOn, Doc); + let annotatedDoc = await Cast(docView?.props.Document.annotationOn, Doc); + if (annotatedDoc) { + let first = DocumentManager.Instance.getFirstDocumentView(annotatedDoc); + if (first) annotatedDoc = first.props.Document; + } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - annotatedDoc && docView.props.focus(annotatedDoc, false); - docView.props.focus(docView.props.Document, willZoom); + docView.props.focus(annotatedDoc || docView.props.Document, false); highlight(); } else { const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts index 3324d8abe..b879ca7aa 100644 --- a/src/client/util/ProsemirrorExampleTransfer.ts +++ b/src/client/util/ProsemirrorExampleTransfer.ts @@ -6,6 +6,8 @@ import { liftListItem, sinkListItem } from "./prosemirrorPatches.js"; import { splitListItem, wrapInList, } from "prosemirror-schema-list"; import { EditorState, Transaction, TextSelection } from "prosemirror-state"; import { TooltipTextMenu } from "./TooltipTextMenu"; +import { SelectionManager } from "./SelectionManager"; +import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false; @@ -46,7 +48,11 @@ export default function buildKeymap>(schema: S, mapKeys?: bind("Alt-ArrowUp", joinUp); bind("Alt-ArrowDown", joinDown); bind("Mod-BracketLeft", lift); - bind("Escape", selectParentNode); + bind("Escape", (state: EditorState, dispatch: (tx: Transaction) => void) => { + dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as any).blur?.(); + SelectionManager.DeselectAll(); + }); bind("Mod-b", toggleMark(schema.marks.strong)); bind("Mod-B", toggleMark(schema.marks.strong)); diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 62b20b3fa..5148af889 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -220,7 +220,7 @@ export const inpRules = { new InputRule( new RegExp(/%#$/), (state, match, start, end) => { - const target = Docs.Create.TextDocument({ width: 75, height: 35, backgroundColor: "yellow", autoHeight: true, fontSize: 9, title: "inline comment" }); + const target = Docs.Create.TextDocument({ width: 75, height: 35, backgroundColor: "yellow", annotationOn: FormattedTextBox.FocusedBox!.dataDoc, autoHeight: true, fontSize: 9, title: "inline comment" }); const node = (state.doc.resolve(start) as any).nodeAfter; const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 7a048ed0d..bede23cb2 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -765,14 +765,14 @@ export class DashDocView { renderDepth={1} PanelWidth={self._dashDoc[WidthSym]} PanelHeight={self._dashDoc[HeightSym]} - focus={emptyFunction} + focus={self._textBox.props.focus} backgroundColor={returnEmptyString} parentActive={returnFalse} whenActiveChanged={returnFalse} bringToFront={emptyFunction} zoomToScale={emptyFunction} getScale={returnOne} - dontRegisterView={true} + dontRegisterView={false} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} ContentScaling={this.contentScaling} @@ -780,7 +780,12 @@ export class DashDocView { } }); const self = this; - this._dashSpan.onkeydown = function (e: any) { }; + this._dashSpan.onkeydown = function (e: any) { + e.stopPropagation(); + if (e.key === "Tab" || e.key === "Enter") { + e.preventDefault(); + } + }; this._dashSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._dashSpan.onwheel = function (e: any) { e.preventDefault(); }; this._dashSpan.onkeyup = function (e: any) { e.stopPropagation(); }; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 662cc9aea..6d889b495 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -76,8 +76,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & public static blankState = () => EditorState.create(FormattedTextBox.Instance.config); public static Instance: FormattedTextBox; public static ToolTipTextMenu: TooltipTextMenu | undefined = undefined; + public ProseRef?: HTMLDivElement; private _ref: React.RefObject = React.createRef(); - private _proseRef?: HTMLDivElement; private _editorView: Opt; private _applyingChange: boolean = false; private _searchIndex = 0; @@ -244,7 +244,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark)); } protected createDropTarget = (ele: HTMLDivElement) => { - this._proseRef = ele; + this.ProseRef = ele; this.dropDisposer && this.dropDisposer(); ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); } @@ -571,7 +571,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._ruleFontSize = rules ? rules.size : 0; rules && setTimeout(() => { const view = this._editorView!; - if (this._proseRef) { + if (this.ProseRef) { const n = new NodeSelection(view.state.doc.resolve(0)); if (this._editorView!.state.doc.textContent === "") { view.dispatch(view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(0), view.state.doc.resolve(2))). @@ -794,10 +794,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & startup = NumCast(doc[fieldKey], 99).toString(); } } - if (this._proseRef) { + if (this.ProseRef) { const self = this; this._editorView && this._editorView.destroy(); - this._editorView = new EditorView(this._proseRef, { + this._editorView = new EditorView(this.ProseRef, { state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { const ref = editorView.domAtPos(editorView.state.selection.from); @@ -874,7 +874,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.preventDefault(); } if (e.button === 0 && this.active(true) && !e.altKey && !e.ctrlKey && !e.metaKey) { - e.stopPropagation(); + if (e.clientX < this.ProseRef!.getBoundingClientRect().right) { // don't stop propagation if clicking in the sidebar + e.stopPropagation(); + } } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { e.preventDefault(); @@ -901,7 +903,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.tryUpdateHeight(); // see if we need to preserve the insertion point - const prosediv = this._proseRef?.children?.[0] as any; + const prosediv = this.ProseRef?.children?.[0] as any; const keeplocation = prosediv?.keeplocation; prosediv && (prosediv.keeplocation = undefined); const pos = this._editorView?.state.selection.$from.pos || 1; @@ -925,8 +927,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pcords.pos + 2))); e.preventDefault(); } - if (!node && this._proseRef) { - const lastNode = this._proseRef.children[this._proseRef.children.length - 1].children[this._proseRef.children[this._proseRef.children.length - 1].children.length - 1]; // get the last prosemirror div + if (!node && this.ProseRef) { + const lastNode = this.ProseRef.children[this.ProseRef.children.length - 1].children[this.ProseRef.children[this.ProseRef.children.length - 1].children.length - 1]; // get the last prosemirror div if (e.clientY > lastNode.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, this._editorView!.state.doc.content.size))); } @@ -1057,17 +1059,20 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.preventDefault(); return; } - if (!this._editorView!.state.selection.empty && e.key === "%") { - this._editorView!.state.schema.EnteringStyle = true; + let state = this._editorView!.state; + if (!state.selection.empty && e.key === "%") { + state.schema.EnteringStyle = true; e.preventDefault(); e.stopPropagation(); return; } - if (this._editorView!.state.selection.empty || !this._editorView!.state.schema.EnteringStyle) { - this._editorView!.state.schema.EnteringStyle = false; + if (state.selection.empty || !state.schema.EnteringStyle) { + state.schema.EnteringStyle = false; } if (e.key === "Escape") { + this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as any).blur?.(); SelectionManager.DeselectAll(); } e.stopPropagation(); -- cgit v1.2.3-70-g09d2 From 15f2148f40c351589e18c1f9ac3b39a8de366a40 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 14 Jan 2020 17:15:36 -0500 Subject: fixes for stacking views to honor panelwidth/height -- allows stacking panels to be placed in Content fitting document views. --- src/client/documents/Documents.ts | 2 +- .../views/collections/CollectionStackingView.tsx | 31 +++++----- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 69 ++++++++++------------ src/new_fields/Doc.ts | 18 +++--- 5 files changed, 60 insertions(+), 62 deletions(-) (limited to 'src/client/documents') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e149963b9..be678d765 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -355,7 +355,7 @@ export namespace Docs { AudioBox.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: viewDoc }, { doc: d }, "audio link", "link to audio: " + d.title)); - return Doc.assign(viewDoc, delegateProps); + return Doc.assign(viewDoc, delegateProps, true); } /** diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 03c757a51..3ab0326e2 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -39,7 +39,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @observable _scroll = 0; // used to force the document decoration to update when scrolling @computed get sectionHeaders() { return Cast(this.props.Document.sectionHeaders, listSpec(SchemaHeaderField)); } @computed get sectionFilter() { return StrCast(this.props.Document.sectionFilter); } - @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized); } + @computed get filteredChildren() { return this.childDocs.filter(d => !d.isMinimized).map(d => (Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d).layout as Doc) || d); } @computed get xMargin() { return NumCast(this.props.Document.xMargin, 2 * this.gridGap); } @computed get yMargin() { return Math.max(this.props.Document.showTitle ? 30 : 0, NumCast(this.props.Document.yMargin, 2 * this.gridGap)); } @computed get gridGap() { return NumCast(this.props.Document.gridGap, 10); } @@ -52,22 +52,18 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } @computed get NodeWidth() { return this.props.PanelWidth() - this.gridGap; } - childDocHeight(child: Doc) { return this.getDocHeight(Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, child).layout); } - children(docs: Doc[]) { this._docXfs.length = 0; return docs.map((d, i) => { - const pair = Doc.GetLayoutDataDocPair(this.props.Document, this.props.DataDoc, this.props.fieldKey, d); - const layoutDoc = pair.layout ? Doc.Layout(pair.layout) : d; - const width = () => Math.min(layoutDoc.nativeWidth && !layoutDoc.ignoreAspect && !this.props.Document.fillColumn ? layoutDoc[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); - const height = () => this.getDocHeight(layoutDoc); + const width = () => Math.min(d.nativeWidth && !d.ignoreAspect && !this.props.Document.fillColumn ? d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns); + const height = () => this.getDocHeight(d); const dref = React.createRef(); - const dxf = () => this.getDocTransform(layoutDoc, dref.current!); + const dxf = () => this.getDocTransform(d, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return
- {this.getDisplayDoc(pair.layout || d, pair.data, dxf, width)} + {this.getDisplayDoc(d, (d.resolvedDataDoc as Doc) || d, dxf, width)}
; }); } @@ -114,7 +110,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const res = this.props.ContentScaling() * sectionsList.reduce((maxHght, s) => { const r1 = Math.max(maxHght, (this.Sections.size ? 50 : 0) + s.reduce((height, d, i) => { - const val = height + this.childDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap); + const val = height + this.getDocHeight(d) + (i === s.length - 1 ? this.yMargin : this.gridGap); return val; }, this.yMargin)); return r1; @@ -291,7 +287,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { sectionStacking = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { const key = this.sectionFilter; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; - const types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); + const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } @@ -316,15 +312,17 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const y = this._scroll; // required for document decorations to update when the text box container is scrolled const { scale, translateX, translateY } = Utils.GetScreenTransform(dref); const outerXf = Utils.GetScreenTransform(this._masonryGridRef!); + const scaling = 1 / Math.min(1, this.props.PanelHeight() / this.layoutDoc[HeightSym]()); const offset = this.props.ScreenToLocalTransform().transformDirection(outerXf.translateX - translateX, outerXf.translateY - translateY); - return this.props.ScreenToLocalTransform(). - translate(offset[0], offset[1] + (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0)); + const offsetx = (doc[WidthSym]() - doc[WidthSym]() / scaling) / 2; + const offsety = (this.props.ChromeHeight && this.props.ChromeHeight() < 0 ? this.props.ChromeHeight() : 0); + return this.props.ScreenToLocalTransform().translate(offset[0] - offsetx, offset[1] + offsety).scale(scaling); } sectionMasonry = (heading: SchemaHeaderField | undefined, docList: Doc[]) => { const key = this.sectionFilter; let type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined = undefined; - const types = docList.length ? docList.map(d => typeof d[key]) : this.childDocs.map(d => typeof d[key]); + const types = docList.length ? docList.map(d => typeof d[key]) : this.filteredChildren.map(d => typeof d[key]); if (types.map((i, idx) => types.indexOf(i) === idx).length === 1) { type = types[0]; } @@ -396,6 +394,11 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
) => this._scroll = e.currentTarget.scrollTop)} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 8f6bfc8e1..66886165e 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -82,7 +82,7 @@ export class DocumentContentsView extends React.Component { - requestImageSize(srcpath) + _resized = ""; + resize = (imgPath: string) => { + requestImageSize(imgPath) .then((size: any) => { const rotation = NumCast(this.dataDoc.rotation) % 180; const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; const aspect = realsize.height / realsize.width; if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { setTimeout(action(() => { - this._resized = true; - this.Document.height = this.Document[WidthSym]() * aspect; - this.Document.nativeHeight = realsize.height; - this.Document.nativeWidth = realsize.width; + if (this.pathInfos.srcpath === imgPath && (!this.layoutDoc.isTemplateDoc || this.dataDoc !== this.layoutDoc)) { + this._resized = imgPath; + this.Document.height = this.Document[WidthSym]() * aspect; + this.Document.nativeHeight = realsize.height; + this.Document.nativeWidth = realsize.width; + } }), 0); - } else this._resized = true; - }) - .catch((err: any) => console.log(err)); - } - fadesize = (srcpath: string) => { - requestImageSize(srcpath) - .then((size: any) => { - const rotation = NumCast(this.dataDoc.rotation) % 180; - const realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; - const aspect = realsize.height / realsize.width; - if (this.Document.width && (Math.abs(1 - NumCast(this.Document.height) / NumCast(this.Document.width) / (realsize.height / realsize.width)) > 0.1)) { - setTimeout(action(() => { - this.Document.height = this.Document[WidthSym]() * aspect; - this.Document.nativeHeight = realsize.height; - this.Document.nativeWidth = realsize.width; - }), 0); - } + } else this._resized = imgPath; }) .catch((err: any) => console.log(err)); } @@ -285,18 +271,16 @@ export class ImageBox extends DocAnnotatableComponent); } - @computed get content() { - TraceMobx(); - const extensionDoc = this.extensionDoc; - if (!extensionDoc) return (null); - // let transform = this.props.ScreenToLocalTransform().inverse(); + @computed get nativeSize() { const pw = typeof this.props.PanelWidth === "function" ? this.props.PanelWidth() : typeof this.props.PanelWidth === "number" ? (this.props.PanelWidth as any) as number : 50; - // var [sptX, sptY] = transform.transformPoint(0, 0); - // let [bptX, bptY] = transform.transformPoint(pw, this.props.PanelHeight()); - // let w = bptX - sptX; - const nativeWidth = (this.Document.nativeWidth || pw); const nativeHeight = (this.Document.nativeHeight || 1); + return { nativeWidth, nativeHeight }; + } + + @computed get pathInfos() { + const extensionDoc = this.extensionDoc!; + const { nativeWidth, nativeHeight } = this.nativeSize; let paths = [[Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png"), nativeWidth / nativeHeight]]; // this._curSuffix = ""; // if (w > 20) { @@ -308,15 +292,24 @@ export class ImageBox extends DocAnnotatableComponent
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index c809ad17a..d4634ba4b 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -290,14 +290,13 @@ export namespace Doc { * @param fields the fields to project onto the target. Its type signature defines a mapping from some string key * to a potentially undefined field, where each entry in this mapping is optional. */ - export function assign(doc: Doc, fields: Partial>>) { + export function assign(doc: Doc, fields: Partial>>, skipUndefineds: boolean = false) { for (const key in fields) { if (fields.hasOwnProperty(key)) { const value = fields[key]; - // Do we want to filter out undefineds? - // if (value !== undefined) { - doc[key] = value; - // } + if (!skipUndefineds || value !== undefined) { // Do we want to filter out undefineds? + doc[key] = value; + } } } return doc; @@ -406,8 +405,9 @@ export namespace Doc { } export function MakeAlias(doc: Doc) { const alias = !GetT(doc, "isPrototype", "boolean", true) ? Doc.MakeCopy(doc) : Doc.MakeDelegate(doc); - if (alias.layout instanceof Doc) { - alias.layout = Doc.MakeAlias(alias.layout); + let layout = Doc.Layout(alias); + if (layout instanceof Doc && layout !== alias) { + Doc.SetLayout(alias, Doc.MakeAlias(layout)); } const aliasNumber = Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1; alias.title = ComputedField.MakeFunction(`renameAlias(this, ${aliasNumber})`); @@ -455,6 +455,7 @@ export namespace Doc { if (resolvedDataDoc && Doc.WillExpandTemplateLayout(childDocLayout, resolvedDataDoc)) { const extensionDoc = fieldExtensionDoc(resolvedDataDoc, StrCast(childDocLayout.templateField, StrCast(childDocLayout.title))); layoutDoc = Doc.expandTemplateLayout(childDocLayout, extensionDoc !== resolvedDataDoc ? extensionDoc : undefined); + layoutDoc && (layoutDoc.resolvedDataDoc = resolvedDataDoc); } else layoutDoc = childDocLayout; return { layout: layoutDoc, data: resolvedDataDoc }; } @@ -468,7 +469,7 @@ export namespace Doc { // export function fieldExtensionDoc(doc: Doc, fieldKey: string) { const extension = doc[fieldKey + "_ext"]; - if (extension === undefined) { + if (doc instanceof Doc && extension === undefined) { setTimeout(() => CreateDocumentExtensionForField(doc, fieldKey), 0); } return extension ? extension as Doc : undefined; @@ -657,6 +658,7 @@ export namespace Doc { // the document containing the view layout information - will be the Document itself unless the Document has // a layout field. In that case, all layout information comes from there unless overriden by Document export function Layout(doc: Doc) { return Doc.LayoutField(doc) instanceof Doc ? doc[StrCast(doc.layoutKey, "layout")] as Doc : doc; } + export function SetLayout(doc: Doc, layout: Doc | string) { doc[StrCast(doc.layoutKey, "layout")] = layout; } export function LayoutField(doc: Doc) { return doc[StrCast(doc.layoutKey, "layout")]; } const manager = new DocData(); export function SearchQuery(): string { return manager._searchQuery; } -- cgit v1.2.3-70-g09d2