diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/ButtonBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 20 | ||||
| -rw-r--r-- | src/client/views/nodes/FaceRectangles.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/FieldView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 9 | ||||
| -rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 57 | ||||
| -rw-r--r-- | src/client/views/nodes/KeyValueBox.tsx | 19 | ||||
| -rw-r--r-- | src/client/views/nodes/KeyValuePair.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 14 |
9 files changed, 95 insertions, 38 deletions
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index d2c23fdab..e2c559c9a 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -70,7 +70,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt render() { return ( <div className="buttonBox-outerDiv" onContextMenu={this.onContextMenu}> - <button className="buttonBox-mainButton" onClick={this.onClick}>{this.Document.text || "Button"}</button> + <button className="buttonBox-mainButton" onClick={this.onClick}>{this.Document.text || this.Document.title || "Button"}</button> </div> ); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f101222ae..4b5cf3a43 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -99,6 +99,7 @@ export interface DocumentViewProps { zoomToScale: (scale: number) => void; getScale: () => number; animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void; + ChromeHeight?: () => number; } const schema = createSchema({ @@ -439,7 +440,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu e.stopPropagation(); let annotationDoc = de.data.annotationDocument; annotationDoc.linkedToDoc = true; + de.data.targetContext = this.props.ContainingCollectionView!.props.Document; let targetDoc = this.props.Document; + targetDoc.targetContext = de.data.targetContext; let annotations = await DocListCastAsync(annotationDoc.annotations); if (annotations) { annotations.forEach(anno => { @@ -448,7 +451,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc); if (pdfDoc) { - DocUtils.MakeLink(annotationDoc, targetDoc, undefined, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); + DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); } } if (de.data instanceof DragManager.LinkDragData) { @@ -644,6 +647,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu @computed get nativeHeight() { return this.Document.nativeHeight || 0; } @computed get contents() { return (<DocumentContentsView {...this.props} + ChromeHeight={this.chromeHeight} isSelected={this.isSelected} select={this.select} selectOnLoad={this.props.selectOnLoad} layoutKey={"layout"} @@ -651,6 +655,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu DataDoc={this.dataDoc} />); } + chromeHeight = () => { + let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; + let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle); + return showTitle ? 25 : 0; + } + get layoutDoc() { // if this document's layout field contains a document (ie, a rendering template), then we will use that // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. @@ -666,8 +676,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined; - let showTitle = showOverlays && showOverlays.title !== "undefined" ? showOverlays.title : StrCast(this.layoutDoc.showTitle); - let showCaption = showOverlays && showOverlays.caption !== "undefined" ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); + let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle); + let showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : StrCast(this.layoutDoc.showCaption); let templates = Cast(this.layoutDoc.templates, listSpec("string")); if (!showOverlays && templates instanceof List) { templates.map(str => { @@ -716,11 +726,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu transformOrigin: "top left", transform: `scale(${1 / this.props.ContentScaling()})` }}> <EditableView - contents={this.layoutDoc[showTitle]} + contents={(this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle]} display={"block"} height={72} fontSize={12} - GetValue={() => StrCast(this.layoutDoc[showTitle!])} + GetValue={() => StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle!])} SetValue={(value: string) => (Doc.GetProto(this.layoutDoc)[showTitle!] = value) ? true : true} /> </div> diff --git a/src/client/views/nodes/FaceRectangles.tsx b/src/client/views/nodes/FaceRectangles.tsx index 3570531b2..acf1aced3 100644 --- a/src/client/views/nodes/FaceRectangles.tsx +++ b/src/client/views/nodes/FaceRectangles.tsx @@ -20,7 +20,7 @@ export interface RectangleTemplate { export default class FaceRectangles extends React.Component<FaceRectanglesProps> { render() { - let faces = DocListCast(Doc.GetProto(this.props.document).faces); + let faces = DocListCast(this.props.document.faces); let templates: RectangleTemplate[] = faces.map(faceDoc => { let rectangle = Cast(faceDoc.faceRectangle, Doc) as Doc; let style = { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index ffaee8042..da54ecc3a 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -48,6 +48,8 @@ export interface FieldViewProps { PanelHeight: () => number; setVideoBox?: (player: VideoBox) => void; setPdfBox?: (player: PDFBox) => void; + ContentScaling: () => number; + ChromeHeight?: () => number; } @observer diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 2db0776ba..87b1d43c1 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -37,6 +37,7 @@ import React = require("react"); import { For } from 'babel-types'; import { DateField } from '../../../new_fields/DateField'; import { Utils } from '../../../Utils'; +import { MainOverlayTextBox } from '../MainOverlayTextBox'; library.add(faEdit); library.add(faSmile, faTextHeight); @@ -413,7 +414,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe fieldExtDoc.annotations = new List<Doc>(targetAnnotations); } - let link = DocUtils.MakeLink(this.props.Document, region); + let link = DocUtils.MakeLink(this.props.Document, region, doc); if (link) { cbe.clipboardData!.setData("dash/linkDoc", link[Id]); linkId = link[Id]; @@ -527,6 +528,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } if (targetContext) { DocumentManager.Instance.jumpToDocument(targetContext, ctrlKey, false, document => this.props.addDocTab(document, undefined, location ? location : "inTab")); + } else if (jumpToDoc) { + DocumentManager.Instance.jumpToDocument(jumpToDoc, ctrlKey, false, document => this.props.addDocTab(document, undefined, location ? location : "inTab")); + } } }); @@ -642,7 +646,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let nh = NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.props.Document.height, 0); let sh = scrBounds.height; - this.props.Document.height = nh ? dh / nh * sh : sh; + const ChromeHeight = MainOverlayTextBox.Instance.ChromeHeight; + this.props.Document.height = (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0); this.dataDoc.nativeHeight = nh ? sh : undefined; } } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 29a76b0c8..dbe545048 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -25,9 +25,12 @@ import { Docs, DocumentType } from '../../documents/Documents'; import { DocServer } from '../../DocServer'; import { Font } from '@react-pdf/renderer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { CognitiveServices } from '../../cognitive_services/CognitiveServices'; +import { CognitiveServices, Service, Tag, Confidence } from '../../cognitive_services/CognitiveServices'; import FaceRectangles from './FaceRectangles'; import { faEye } from '@fortawesome/free-regular-svg-icons'; +import { ComputedField } from '../../../new_fields/ScriptField'; +import { CompileScript } from '../../util/Scripting'; +import { thisExpression } from 'babel-types'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); const { Howl } = require('howler'); @@ -96,7 +99,11 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD this.props.Document.width = drop.width; this.props.Document.height = drop.height; Doc.GetProto(this.props.Document).type = DocumentType.TEMPLATE; - this.props.Document.layout = temp; + if (this.props.DataDoc && this.props.DataDoc.layout === this.props.Document) { + this.props.DataDoc.layout = temp; + } else { + this.props.Document.layout = temp; + } e.stopPropagation(); } else if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) { Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url); @@ -226,20 +233,56 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD funcs.push({ description: "Rotate", event: this.rotate, icon: "expand-arrows-alt" }); let modes: ContextMenuProps[] = []; - let dataDoc = Doc.GetProto(this.props.Document); - modes.push({ description: "Generate Tags", event: () => CognitiveServices.Image.generateMetadata(dataDoc), icon: "tag" }); - modes.push({ description: "Find Faces", event: () => CognitiveServices.Image.extractFaces(dataDoc), icon: "camera" }); + modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" }); + modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" }); ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: funcs, icon: "asterisk" }); ContextMenu.Instance.addItem({ description: "Analyze...", subitems: modes, icon: "eye" }); } } + extractFaces = () => { + let converter = (results: any) => { + let faceDocs = new List<Doc>(); + results.map((face: CognitiveServices.Image.Face) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!)); + return faceDocs; + }; + CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["faces"], this.url, Service.Face, converter); + } + + generateMetadata = (threshold: Confidence = Confidence.Excellent) => { + let converter = (results: any) => { + let tagDoc = new Doc; + let tagsList = new List(); + results.tags.map((tag: Tag) => { + tagsList.push(tag.name); + let sanitized = tag.name.replace(" ", "_"); + let script = `return (${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`; + let computed = CompileScript(script, { params: { this: "Doc" } }); + computed.compiled && (tagDoc[sanitized] = new ComputedField(computed)); + }); + this.extensionDoc.generatedTags = tagsList; + tagDoc.title = "Generated Tags Doc"; + tagDoc.confidence = threshold; + return tagDoc; + }; + CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter); + } + @action onDotDown(index: number) { this.Document.curPage = index; } + @computed get fieldExtensionDoc() { + return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); + } + + @computed private get url() { + let data = Cast(Doc.GetProto(this.props.Document).data, ImageField); + return data ? data.url.href : undefined; + } + dots(paths: string[]) { let nativeWidth = FieldValue(this.Document.nativeWidth, 1); let dist = Math.min(nativeWidth / paths.length, 40); @@ -287,7 +330,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD let aspect = size.height / size.width; let rotation = NumCast(this.dataDoc.rotation) % 180; if (rotation === 90 || rotation === 270) aspect = 1 / aspect; - if (Math.abs(layoutdoc[HeightSym]() / layoutdoc[WidthSym]() - aspect) > 0.01) { + if (Math.abs(NumCast(layoutdoc.height) - size.height) > 1 || Math.abs(NumCast(layoutdoc.width) - size.width) > 1) { setTimeout(action(() => { layoutdoc.height = layoutdoc[WidthSym]() * aspect; layoutdoc.nativeHeight = size.height; @@ -394,7 +437,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD style={{ color: [DocListCast(this.extensionDoc.audioAnnotations).length ? "blue" : "gray", "green", "red"][this._audioState] }} icon={faFileAudio} size="sm" /> </div> {/* {this.lightbox(paths)} */} - <FaceRectangles document={this.props.Document} color={"#0000FF"} backgroundColor={"#0000FF"} /> + <FaceRectangles document={this.extensionDoc} color={"#0000FF"} backgroundColor={"#0000FF"} /> </div>); } }
\ No newline at end of file diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 77824b4ff..f10079169 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -20,6 +20,8 @@ import { RichTextField } from "../../../new_fields/RichTextField"; import { ImageField } from "../../../new_fields/URLField"; import { SelectionManager } from "../../util/SelectionManager"; import { listSpec } from "../../../new_fields/Schema"; +import { CollectionViewType } from "../collections/CollectionBaseView"; +import { undoBatch } from "../../util/UndoManager"; export type KVPScript = { script: CompiledScript; @@ -89,6 +91,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> { return false; } + @undoBatch public static SetField(doc: Doc, key: string, value: string) { const script = this.CompileKVPScript(value); if (!script) return false; @@ -195,6 +198,9 @@ export class KeyValueBox extends React.Component<FieldViewProps> { } let fieldTemplate = await this.inferType(sourceDoc[metaKey], metaKey); + if (!fieldTemplate) { + return; + } let previousViewType = fieldTemplate.viewType; Doc.MakeTemplate(fieldTemplate, metaKey, Doc.GetProto(parentStackingDoc)); previousViewType && (fieldTemplate.viewType = previousViewType); @@ -211,14 +217,17 @@ export class KeyValueBox extends React.Component<FieldViewProps> { return Docs.Create.StackingDocument([], options); } let first = await Cast(data[0], Doc); - if (!first) { + if (!first || !first.data) { return Docs.Create.StackingDocument([], options); } - switch (first.type) { - case "image": - return Docs.Create.StackingDocument([], options); - case "text": + switch (first.data.constructor) { + case RichTextField: return Docs.Create.TreeDocument([], options); + case ImageField: + return Docs.Create.MasonryDocument([], options); + default: + console.log(`Template for ${first.data.constructor} not supported!`); + return undefined; } } else if (data instanceof ImageField) { return Docs.Create.ImageDocument("https://image.flaticon.com/icons/png/512/23/23765.png", options); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 064f3edcc..3775f0f47 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,7 +1,7 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { emptyFunction, returnFalse, returnZero, returnTrue } from '../../../Utils'; +import { emptyFunction, returnFalse, returnZero, returnTrue, returnOne } from '../../../Utils'; import { CompileScript, CompiledScript, ScriptOptions } from "../../util/Scripting"; import { Transform } from '../../util/Transform'; import { EditableView } from "../EditableView"; @@ -16,6 +16,7 @@ import { DragManager, SetupDrag } from '../../util/DragManager'; import { ContextMenu } from '../ContextMenu'; import { Docs } from '../../documents/Documents'; import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { undoBatch } from '../../util/UndoManager'; // Represents one row in a key value plane @@ -70,6 +71,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> { PanelWidth: returnZero, PanelHeight: returnZero, addDocTab: returnZero, + ContentScaling: returnOne }; let contents = <FieldView {...props} />; // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; @@ -91,12 +93,12 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> { <tr className={this.props.rowStyle} onPointerEnter={action(() => this.isPointerOver = true)} onPointerLeave={action(() => this.isPointerOver = false)}> <td className="keyValuePair-td-key" style={{ width: `${this.props.keyWidth}%` }}> <div className="keyValuePair-td-key-container"> - <button style={hover} className="keyValuePair-td-key-delete" onClick={() => { + <button style={hover} className="keyValuePair-td-key-delete" onClick={undoBatch(() => { if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) { props.Document[props.fieldKey] = undefined; } else props.Document.proto![props.fieldKey] = undefined; - }}> + })}> X </button> <input diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 4973340df..fa072aecf 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -69,24 +69,10 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen componentDidMount() { if (this.props.setPdfBox) this.props.setPdfBox(this); - - document.removeEventListener("copy", this.copy); - document.addEventListener("copy", this.copy); } componentWillUnmount() { this._reactionDisposer && this._reactionDisposer(); - document.removeEventListener("copy", this.copy); - } - - private copy = (e: ClipboardEvent) => { - if (this.props.active()) { - if (e.clipboardData) { - e.clipboardData.setData("text/plain", text); - e.clipboardData.setData("dash/pdfOrigin", this.props.Document[Id]); - e.preventDefault(); - } - } } public GetPage() { |
