From 70c7532c8a6472f61eedd4661a172d70bc50184e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 30 Jun 2019 01:48:47 -0400 Subject: added drag off of context search results. add fit to contents for preview of collections in search. --- src/client/util/DragManager.ts | 28 +++++--- .../views/collections/CollectionSchemaView.tsx | 4 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 7 +- src/client/views/globalCssVariables.scss | 2 + src/client/views/globalCssVariables.scss.d.ts | 1 + src/client/views/nodes/DocumentView.tsx | 1 + src/client/views/nodes/FieldView.tsx | 1 + src/client/views/search/FilterBox.tsx | 4 +- src/client/views/search/SearchBox.tsx | 1 - src/client/views/search/SearchItem.scss | 8 ++- src/client/views/search/SearchItem.tsx | 83 ++++++++++++++-------- 11 files changed, 90 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index a6bba3656..7dc48fb78 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,18 +1,24 @@ -import { action, runInAction, observable } from "mobx"; -import { Doc, DocListCastAsync } from "../../new_fields/Doc"; -import { Cast, StrCast } from "../../new_fields/Types"; +import { action, runInAction } from "mobx"; +import { Doc } from "../../new_fields/Doc"; +import { Cast } from "../../new_fields/Types"; +import { URLField } from "../../new_fields/URLField"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; import * as globalCssVariables from "../views/globalCssVariables.scss"; +import { DocumentManager } from "./DocumentManager"; import { LinkManager } from "./LinkManager"; -import { URLField } from "../../new_fields/URLField"; import { SelectionManager } from "./SelectionManager"; -import { Docs, DocUtils } from "../documents/Documents"; -import { DocumentManager } from "./DocumentManager"; -import { Id } from "../../new_fields/FieldSymbols"; export type dropActionType = "alias" | "copy" | undefined; -export function SetupDrag(_reference: React.RefObject, docFunc: () => Doc | Promise, moveFunc?: DragManager.MoveFunction, dropAction?: dropActionType, options?: any, dontHideOnDrop?: boolean) { +export function SetupDrag( + _reference: React.RefObject, + docFunc: () => Doc | Promise, + moveFunc?: DragManager.MoveFunction, + dropAction?: dropActionType, + options?: any, + dontHideOnDrop?: boolean, + dragStarted?: () => void +) { let onRowMove = async (e: PointerEvent) => { e.stopPropagation(); e.preventDefault(); @@ -20,12 +26,13 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () document.removeEventListener("pointermove", onRowMove); document.removeEventListener('pointerup', onRowUp); let doc = await docFunc(); - var dragData = new DragManager.DocumentDragData([doc], [doc]); + var dragData = new DragManager.DocumentDragData([doc], [undefined]); dragData.dropAction = dropAction; dragData.moveDocument = moveFunc; dragData.options = options; dragData.dontHideOnDrop = dontHideOnDrop; DragManager.StartDocumentDrag([_reference.current!], dragData, e.x, e.y); + dragStarted && dragStarted(); }; let onRowUp = (): void => { document.removeEventListener("pointermove", onRowMove); @@ -34,6 +41,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () let onItemDown = async (e: React.PointerEvent) => { if (e.button === 0) { e.stopPropagation(); + e.preventDefault(); if (e.shiftKey && CollectionDockingView.Instance) { CollectionDockingView.Instance.StartOtherDrag(e, [await docFunc()]); } else { @@ -111,6 +119,8 @@ export namespace DragManager { hideSource: boolean | (() => boolean); + dragHasStarted?: () => void; + withoutShiftDrag?: boolean; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 6529074f8..b0d46953c 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -119,8 +119,8 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { let fieldContentView = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => { - (this.props.CollectionView.props.isSelected() ? - SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e) : undefined); + (!this.props.CollectionView.props.isSelected() ? undefined : + SetupDrag(reference, () => props.Document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); }; let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4c8fe3c26..b1aba10bf 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -50,9 +50,9 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { @computed get nativeHeight() { return this.Document.nativeHeight || 0; } public get isAnnotationOverlay() { return this.props.fieldKey === "annotations" || this.props.fieldExt === "annotations"; } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } - private panX = () => this.Document.panX || 0; - private panY = () => this.Document.panY || 0; - private zoomScaling = () => this.Document.scale || 1; + private panX = () => this.props.fitToBox ? this.props.fitToBox[0] : this.Document.panX || 0; + private panY = () => this.props.fitToBox ? this.props.fitToBox[1] : this.Document.panY || 0; + private zoomScaling = () => this.props.fitToBox ? this.props.fitToBox[2] : this.Document.scale || 1; private centeringShiftX = () => !this.nativeWidth ? this._pwidth / 2 : 0; // shift so pan position is at center of window for non-overlay collections private centeringShiftY = () => !this.nativeHeight ? this._pheight / 2 : 0;// shift so pan position is at center of window for non-overlay collections private getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth + 1, -this.borderWidth + 1).translate(-this.centeringShiftX(), -this.centeringShiftY()).transform(this.getLocalTransform()); @@ -444,6 +444,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { render() { const containerName = `collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`; const easing = () => this.props.Document.panTransformType === "Ease"; + if (this.props.fieldExt) Doc.UpdateDocumentExtensionForField(this.extensionDoc, this.props.fieldKey); return (
; Document: Doc; DataDoc?: Doc; + fitToBox?: number[]; addDocument?: (doc: Doc, allowDuplicates?: boolean) => boolean; removeDocument?: (doc: Doc) => boolean; moveDocument?: (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 89a8cad56..3f5a2e744 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -31,6 +31,7 @@ export interface FieldViewProps { fieldKey: string; fieldExt: string; leaveNativeSize?: boolean; + fitToBox?: number[]; ContainingCollectionView: Opt; Document: Doc; DataDoc?: Doc; diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index cc1feeaf7..c39ec1145 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react'; import { observable, action } from 'mobx'; import "./SearchBox.scss"; import { faTimes } from '@fortawesome/free-solid-svg-icons'; -import { library} from '@fortawesome/fontawesome-svg-core'; +import { library } from '@fortawesome/fontawesome-svg-core'; import { Doc } from '../../../new_fields/Doc'; import { Id } from '../../../new_fields/FieldSymbols'; import { DocTypes } from '../../documents/Documents'; @@ -57,7 +57,7 @@ export class FilterBox extends React.Component { componentDidMount = () => { document.addEventListener("pointerdown", (e) => { - if (e.timeStamp !== this._pointerTime) { + if (!e.defaultPrevented && e.timeStamp !== this._pointerTime) { SearchBox.Instance.closeSearch(); } }); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index f53a4e34f..a2556133b 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -15,7 +15,6 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; -import { Pager } from './Pager'; @observer export class SearchBox extends React.Component { diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index b3472ddec..fa4c9cb38 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -122,7 +122,6 @@ .search-label { font-size: 10; - padding: 5px; position: relative; right: 0px; text-transform: capitalize; @@ -174,10 +173,15 @@ -webkit-transform: scale(0); -ms-transform: scale(0); transform: scale(0); - // height: 100% } } .search-overview:hover { z-index: 1; +} +.collection { + display:flex; +} +.collection-item { + width:35px; } \ No newline at end of file diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index d992d0fd1..b72f8c814 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -1,29 +1,26 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faMusic, faLink, faChartBar, faGlobeAsia } from '@fortawesome/free-solid-svg-icons'; +import { faCaretUp, faChartBar, faFilePdf, faFilm, faGlobeAsia, faImage, faLink, faMusic, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; -import { observable, runInAction, computed, action } from "mobx"; -import { listSpec } from "../../../new_fields/Schema"; -import { Doc, WidthSym } from "../../../new_fields/Doc"; +import { emptyFunction, returnFalse, returnOne } from "../../../Utils"; +import { DocTypes } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { SetupDrag } from "../../util/DragManager"; +import { LinkManager } from "../../util/LinkManager"; import { SearchUtil } from "../../util/SearchUtil"; -import { Id } from "../../../new_fields/FieldSymbols"; -import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { observer } from "mobx-react"; -import "./SearchItem.scss"; +import { Transform } from "../../util/Transform"; +import { SEARCH_THUMBNAIL_SIZE } from "../../views/globalCssVariables.scss"; import { CollectionViewType } from "../collections/CollectionBaseView"; -import { DocTypes } from "../../documents/Documents"; -import { FilterBox } from "./FilterBox"; +import { CollectionDockingView } from "../collections/CollectionDockingView"; import { DocumentView } from "../nodes/DocumentView"; -import "./SelectorContextMenu.scss"; import { SearchBox } from "./SearchBox"; -import { LinkManager } from "../../util/LinkManager"; -import { DocumentContentsView } from "../nodes/DocumentContentsView"; -import { ImageBox } from "../nodes/ImageBox"; -import { emptyFunction, returnFalse, returnOne } from "../../../Utils"; -import { Transform } from "../../util/Transform"; +import "./SearchItem.scss"; +import "./SelectorContextMenu.scss"; export interface SearchItemProps { doc: Doc; @@ -74,13 +71,21 @@ export class SelectorContextMenu extends React.Component { CollectionDockingView.Instance.AddRightSplit(col, undefined); }; } - render() { return ( - < div className="parents"> +

Contexts:

- {this._docs.map(doc => )} - {this._otherDocs.map(doc => )} + {[...this._docs, ...this._otherDocs].map(doc => { + let item = React.createRef(); + return
+
doc.col, undefined, undefined, undefined, undefined, () => SearchBox.Instance.closeSearch())}> + +
+ {doc.col.title} +
+ } + )}
); } @@ -101,14 +106,30 @@ export class SearchItem extends React.Component { public get DocumentIcon() { let layoutresult = StrCast(this.props.doc.type); if (!this._useIcons) { - let returnXDimension = () => this._useIcons ? 50 : 250; + let renderDoc = this.props.doc; + let box: number[] = []; + if (layoutresult.indexOf(DocTypes.COL) !== -1) { + renderDoc = Doc.MakeDelegate(renderDoc); + let bounds = DocListCast(renderDoc.data).reduce((bounds, doc) => { + var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)] + let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()]; + return { + x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y), + r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b) + }; + }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); + box = [(bounds.x + bounds.r) / 2, (bounds.y + bounds.b) / 2, Number(SEARCH_THUMBNAIL_SIZE) / (bounds.r - bounds.x), this._displayDim]; + } + let returnXDimension = () => this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE); let returnYDimension = () => this._displayDim; - let scale = () => returnXDimension() / NumCast(this.props.doc.nativeWidth, returnXDimension()); + let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension()); return
this._displayDim = this._useIcons ? 50 : 250)} - onPointerLeave={action(() => this._displayDim = this._useIcons ? 50 : 250)} > + onPointerDown={action(() => { this._useIcons = !this._useIcons; this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE) })} + onPointerEnter={action(() => this._displayDim = this._useIcons ? 50 : Number(SEARCH_THUMBNAIL_SIZE))} + onPointerLeave={action(() => this._displayDim = 50)} > { layoutresult.indexOf(DocTypes.HIST) !== -1 ? faChartBar : layoutresult.indexOf(DocTypes.WEB) !== -1 ? faGlobeAsia : faCaretUp; - return ; + return
{ this._useIcons = false; this._displayDim = Number(SEARCH_THUMBNAIL_SIZE) })} > + +
; } collectionRef = React.createRef(); @@ -166,7 +189,7 @@ export class SearchItem extends React.Component { } @action - pointerDown = (e: React.PointerEvent) => { this._useIcons = !this._useIcons; SearchBox.Instance.openSearch(e); }; + pointerDown = (e: React.PointerEvent) => SearchBox.Instance.openSearch(e); highlightDoc = (e: React.PointerEvent) => { if (this.props.doc.type === DocTypes.LINK) { @@ -205,10 +228,8 @@ export class SearchItem extends React.Component { render() { return (
-
{ - this.pointerDown; - SetupDrag(this.collectionRef, this.startDocDrag); - }} > +
{this.props.doc.title}
-- cgit v1.2.3-70-g09d2