From b420caf2c7ecd386cae2cc550904522474b541aa Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 26 Mar 2024 22:34:10 -0400 Subject: added empty image tool and click on empty image to select from filesystem. fixed following links in lightbox and showing links to stackedTimelines. fixed embedding docs into text. fixed not resizing text boxes that also show up in pivot view. prevent context menu from going off top of screen. fixed freeform clustering colors and click to type. fixed links to stackedTimeline marks, and titles for marks. made title editing from doc deco and header use same syntax as keyValue. fixed marquee selection on webBoxes. turn off transitions in freeformdocview after timeout. enabled iconifying templates to propagate to "offspring". fixes images in templates. don't show headr on schema views. --- src/client/views/DocumentDecorations.tsx | 71 ++++++++++++-------------------- 1 file changed, 27 insertions(+), 44 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2fb9f0fc1..4d9b93896 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -34,6 +34,7 @@ import { Colors } from './global/globalEnums'; import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { KeyValueBox } from './nodes/KeyValueBox'; interface DocumentDecorationsProps { PanelWidth: number; @@ -57,7 +58,7 @@ export class DocumentDecorations extends ObservableReactComponent { - if (this._accumulatedTitle.startsWith('#') || this._accumulatedTitle.startsWith('=')) { + if (this._accumulatedTitle.startsWith('$')) { this._titleControlString = this._accumulatedTitle; - } else if (this._titleControlString.startsWith('#')) { + } else if (this._titleControlString.startsWith('$')) { if (this._accumulatedTitle.startsWith('-->#')) { SelectionManager.Docs.forEach(doc => (doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`))); } @@ -131,26 +132,7 @@ export class DocumentDecorations extends ObservableReactComponent')) { - const title = titleField.toString().replace(/\.?/, ''); - const curKey = Doc.LayoutFieldKey(d.Document); - if (curKey !== title) { - if (title) { - if (d.dataDoc[title] === undefined || d.dataDoc[title] instanceof RichTextField || typeof d.dataDoc[title] === 'string') { - d.Document.layout_fieldKey = `layout_${title}`; - d.Document[`layout_${title}`] = FormattedTextBox.LayoutString(title); - d.Document[`${title}_nativeWidth`] = d.Document[`${title}_nativeHeight`] = 0; - } - } else { - d.Document.layout_fieldKey = undefined; - } - } - } else { - Doc.SetInPlace(d.Document, titleFieldKey, titleField, true); - } + KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); }), 'edit title' ); @@ -181,7 +163,8 @@ export class DocumentDecorations extends ObservableReactComponent this.onBackgroundMove(true, e), emptyFunction, action(e => { - !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('#') ? this.selectionTitle : this._titleControlString); + const selected = SelectionManager.Views.length === 1 ? SelectionManager.Docs[0] : undefined; + !this._editingTitle && (this._accumulatedTitle = this._titleControlString.startsWith('$') ? (selected && Field.toKeyValueString(selected, this._titleControlString.substring(1))) || '-unset-' : this._titleControlString); this._editingTitle = true; this._keyinput.current && setTimeout(this._keyinput.current.focus); }) @@ -622,11 +605,8 @@ export class DocumentDecorations extends ObservableReactComponent { - this._editingTitle = false; - !hideTitle && this.titleBlur(); - })} - onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} - onKeyDown={hideTitle ? emptyFunction : this.titleEntered} - onPointerDown={e => e.stopPropagation()} - /> + <> + {r - x < 150 ? null : {this._titleControlString + ':'}} + { + this._editingTitle = false; + !hideTitle && this.titleBlur(); + })} + onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} + onKeyDown={hideTitle ? emptyFunction : this.titleEntered} + onPointerDown={e => e.stopPropagation()} + /> + ) : (
{hideTitle ? null : ( -- cgit v1.2.3-70-g09d2 From ccbe6cafa422616ec4ffe5c2d1caed7597719007 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 30 Mar 2024 10:14:19 -0400 Subject: cleanup of import orderings. --- src/client/util/CaptureManager.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 3 +- src/client/views/GlobalKeyHandler.ts | 8 +- src/client/views/LightboxView.tsx | 2 +- src/client/views/PropertiesView.tsx | 3 +- src/client/views/collections/CollectionMenu.tsx | 12 +- .../views/collections/CollectionNoteTakingView.tsx | 7 +- src/client/views/collections/TabDocView.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +- .../collectionSchema/CollectionSchemaView.tsx | 14 +- .../views/newlightbox/Header/LightboxHeader.tsx | 108 ++++---- .../RecommendationList/RecommendationList.tsx | 295 +++++++++++---------- src/client/views/nodes/DocumentView.tsx | 3 +- src/client/views/nodes/EquationBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 4 +- src/client/views/nodes/trails/PresBox.tsx | 4 +- src/client/views/topbar/TopBar.tsx | 6 +- 18 files changed, 253 insertions(+), 228 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx index 2e13aff2f..8451357ef 100644 --- a/src/client/util/CaptureManager.tsx +++ b/src/client/util/CaptureManager.tsx @@ -2,9 +2,9 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { addStyleSheet } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { DocCast, StrCast } from '../../fields/Types'; -import { addStyleSheet } from '../../Utils'; import { LightboxView } from '../views/LightboxView'; import { MainViewModal } from '../views/MainViewModal'; import './CaptureManager.scss'; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 4d9b93896..6698cd5bc 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -10,7 +10,6 @@ import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, HierarchyMapping, ReverseHierarchyMap } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, DocData } from '../../fields/DocSymbols'; import { InkField } from '../../fields/InkField'; -import { RichTextField } from '../../fields/RichTextField'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { GetEffectiveAcl } from '../../fields/util'; @@ -33,8 +32,8 @@ import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { Colors } from './global/globalEnums'; import { DocumentView, OpenWhereMod } from './nodes/DocumentView'; import { ImageBox } from './nodes/ImageBox'; -import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { KeyValueBox } from './nodes/KeyValueBox'; +import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; interface DocumentDecorationsProps { PanelWidth: number; diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 667d8dbb0..2f64ea28c 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -13,18 +13,18 @@ import { SettingsManager } from '../util/SettingsManager'; import { SharingManager } from '../util/SharingManager'; import { SnappingManager } from '../util/SnappingManager'; import { UndoManager } from '../util/UndoManager'; -import { CollectionDockingView } from './collections/CollectionDockingView'; -import { CollectionFreeFormView } from './collections/collectionFreeForm'; -import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; import { MainView } from './MainView'; +import { CollectionDockingView } from './collections/CollectionDockingView'; +import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline'; +import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { DocumentLinksButton } from './nodes/DocumentLinksButton'; import { OpenWhereMod } from './nodes/DocumentView'; -import { AnchorMenu } from './pdf/AnchorMenu'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; +import { AnchorMenu } from './pdf/AnchorMenu'; const modifiers = ['control', 'meta', 'shift', 'alt']; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo; diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx index 3d77ee901..ef4b5b4ca 100644 --- a/src/client/views/LightboxView.tsx +++ b/src/client/views/LightboxView.tsx @@ -19,9 +19,9 @@ import { Transform } from '../util/Transform'; import { GestureOverlay } from './GestureOverlay'; import './LightboxView.scss'; import { ObservableReactComponent } from './ObservableReactComponent'; +import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { CollectionStackedTimeline } from './collections/CollectionStackedTimeline'; -import { DefaultStyleProvider, wavyBorderPath } from './StyleProvider'; import { TabDocView } from './collections/TabDocView'; import { DocumentView, OpenWhere, OpenWhereMod } from './nodes/DocumentView'; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index dc814bb16..ae29382c1 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -10,7 +10,7 @@ import * as React from 'react'; import { ColorResult, SketchPicker } from 'react-color'; import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs" import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils'; -import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; +import { Doc, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc'; import { AclAdmin, DocAcl, DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { InkField } from '../../fields/InkField'; @@ -41,7 +41,6 @@ import { DocumentView, OpenWhere } from './nodes/DocumentView'; import { StyleProviderFuncType } from './nodes/FieldView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; -import { LinkBox } from './nodes/LinkBox'; const _global = (window /* browser */ || global) /* node */ as any; interface PropertiesViewProps { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 8729ef549..4f25f69ef 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -1,15 +1,16 @@ -import * as React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Tooltip } from '@mui/material'; import { Toggle, ToggleType, Type } from 'browndash-components'; -import { action, computed, Lambda, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { Lambda, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { DocData } from '../../../fields/DocSymbols'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { RichTextField } from '../../../fields/RichTextField'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../../Utils'; import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; @@ -19,11 +20,10 @@ import { undoBatch } from '../../util/UndoManager'; import { AntimodeMenu } from '../AntimodeMenu'; import { EditableView } from '../EditableView'; import { MainView } from '../MainView'; -import { DocumentView, DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; import { DefaultStyleProvider } from '../StyleProvider'; -import { CollectionLinearView } from './collectionLinear'; +import { DocumentView, DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; import './CollectionMenu.scss'; -import { DocData } from '../../../fields/DocSymbols'; +import { CollectionLinearView } from './collectionLinear'; interface CollectionMenuProps { panelHeight: () => number; diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 6318620e0..5b91216cb 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,4 +1,4 @@ -import { action, computed, IReactionDisposer, makeObservable, observable, observe, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, Field, Opt } from '../../../fields/Doc'; @@ -9,7 +9,7 @@ import { listSpec } from '../../../fields/Schema'; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; -import { DivHeight, emptyFunction, returnFalse, returnZero, smoothScroll, Utils } from '../../../Utils'; +import { DivHeight, emptyFunction, returnZero, smoothScroll, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DragManager, dropActionType } from '../../util/DragManager'; import { SnappingManager } from '../../util/SnappingManager'; @@ -19,14 +19,13 @@ import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { LightboxView } from '../LightboxView'; import { DocumentView } from '../nodes/DocumentView'; -import { FocusViewOptions, FieldViewProps } from '../nodes/FieldView'; +import { FieldViewProps, FocusViewOptions } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { StyleProp } from '../StyleProvider'; import './CollectionNoteTakingView.scss'; import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn'; import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider'; import { CollectionSubView } from './CollectionSubView'; -import { JsxElement } from 'typescript'; const _global = (window /* browser */ || global) /* node */ as any; /** diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index 699ec3b95..3ff58c326 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -30,7 +30,7 @@ import { ObservableReactComponent } from '../ObservableReactComponent'; import { DefaultStyleProvider, StyleProp } from '../StyleProvider'; import { Colors } from '../global/globalEnums'; import { DocumentView, OpenWhere, OpenWhereMod, returnEmptyDocViewList } from '../nodes/DocumentView'; -import { FocusViewOptions, FieldViewProps } from '../nodes/FieldView'; +import { FieldViewProps, FocusViewOptions } from '../nodes/FieldView'; import { KeyValueBox } from '../nodes/KeyValueBox'; import { DashFieldView } from '../nodes/formattedText/DashFieldView'; import { PinProps, PresBox, PresMovement } from '../nodes/trails'; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 1b562939b..d435173f3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,6 +1,6 @@ import { Bezier } from 'bezier-js'; import { Colors } from 'browndash-components'; -import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; @@ -17,7 +17,7 @@ import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../ import { ImageField } from '../../../../fields/URLField'; import { TraceMobx } from '../../../../fields/util'; import { GestureUtils } from '../../../../pen-gestures/GestureUtils'; -import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, numberValue, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; +import { aggregateBounds, DashColor, emptyFunction, intersectRect, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, Utils } from '../../../../Utils'; import { CognitiveServices } from '../../../cognitive_services/CognitiveServices'; import { Docs, DocUtils } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 5f4948808..df023b00f 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,33 +1,33 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Popup, PopupTrigger, Type } from 'browndash-components'; -import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; +import { ObservableMap, action, computed, makeObservable, observable, observe } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; -import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; +import { DocUtils, Docs, DocumentOptions, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; import { SettingsManager } from '../../../util/SettingsManager'; -import { undoable, undoBatch } from '../../../util/UndoManager'; +import { undoBatch, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { EditableView } from '../../EditableView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; -import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; -import { DocData } from '../../../../fields/DocSymbols'; const { default: { SCHEMA_NEW_NODE_HEIGHT } } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export enum ColumnType { diff --git a/src/client/views/newlightbox/Header/LightboxHeader.tsx b/src/client/views/newlightbox/Header/LightboxHeader.tsx index a272ce294..76efe0185 100644 --- a/src/client/views/newlightbox/Header/LightboxHeader.tsx +++ b/src/client/views/newlightbox/Header/LightboxHeader.tsx @@ -1,62 +1,70 @@ -import './LightboxHeader.scss'; -import * as React from 'react'; -import { INewLightboxHeader } from "./utils"; -import { NewLightboxView } from '../NewLightboxView'; -import { StrCast } from '../../../../fields/Types'; -import { EditableText } from '../components/EditableText'; -import { getType } from '../utils'; import { Button, IconButton, Size, Type } from 'browndash-components'; -import { MdExplore, MdTravelExplore } from 'react-icons/md' -import { BsBookmark, BsBookmarkFill } from 'react-icons/bs' +import * as React from 'react'; +import { BsBookmark, BsBookmarkFill } from 'react-icons/bs'; +import { MdTravelExplore } from 'react-icons/md'; import { Doc } from '../../../../fields/Doc'; +import { StrCast } from '../../../../fields/Types'; import { LightboxView } from '../../LightboxView'; import { Colors } from '../../global/globalEnums'; - +import { NewLightboxView } from '../NewLightboxView'; +import { EditableText } from '../components/EditableText'; +import { getType } from '../utils'; +import './LightboxHeader.scss'; +import { INewLightboxHeader } from './utils'; export const NewLightboxHeader = (props: INewLightboxHeader) => { - const {height = 100, width} = props; - const [doc, setDoc] = React.useState(LightboxView.LightboxDoc) - const [editing, setEditing] = React.useState(false) - const [title, setTitle] = React.useState( - (null) - ) + const { height = 100, width } = props; + const [doc, setDoc] = React.useState(LightboxView.LightboxDoc); + const [editing, setEditing] = React.useState(false); + const [title, setTitle] = React.useState(null); React.useEffect(() => { - let lbDoc = LightboxView.LightboxDoc - setDoc(lbDoc) + let lbDoc = LightboxView.LightboxDoc; + setDoc(lbDoc); if (lbDoc) { setTitle( - { - if(lbDoc) lbDoc.title = newText; - }} - setEditing={setEditing} - />) + { + if (lbDoc) lbDoc.title = newText; + }} + setEditing={setEditing} + /> + ); } - }, [LightboxView.LightboxDoc]) + }, [LightboxView.LightboxDoc]); - const [saved, setSaved] = React.useState(false) + const [saved, setSaved] = React.useState(false); - if (!doc) return null - else return
e.stopPropagation()} style={{ minHeight: height, height: height, width: width }}> -
-
Title
- {title} -
-
-
Type
-
{getType(StrCast(doc.type))}
-
-
- setSaved(!saved)} color={Colors.DARK_GRAY} icon={saved ? : }/> - setSaved(!saved)} color={Colors.DARK_GRAY} icon={saved ? : }/> -
-
-
-
-} \ No newline at end of file + if (!doc) return null; + else + return ( +
e.stopPropagation()} style={{ minHeight: height, height: height, width: width }}> +
+
Title
+ {title} +
+
+
Type
+
{getType(StrCast(doc.type))}
+
+
+ setSaved(!saved)} color={Colors.DARK_GRAY} icon={saved ? : } /> + setSaved(!saved)} color={Colors.DARK_GRAY} icon={saved ? : } /> +
+
+
+
+ ); +}; diff --git a/src/client/views/newlightbox/RecommendationList/RecommendationList.tsx b/src/client/views/newlightbox/RecommendationList/RecommendationList.tsx index 9f3c32e4e..1d502b73f 100644 --- a/src/client/views/newlightbox/RecommendationList/RecommendationList.tsx +++ b/src/client/views/newlightbox/RecommendationList/RecommendationList.tsx @@ -1,74 +1,67 @@ -import { GrClose } from 'react-icons/gr'; -import { IRecommendation, Recommendation } from "../components"; -import './RecommendationList.scss'; +import { IconButton, Size, Type } from 'browndash-components'; import * as React from 'react'; -import { IRecommendationList } from "./utils"; -import { NewLightboxView } from '../NewLightboxView'; -import { DocCast, StrCast } from '../../../../fields/Types'; import { FaCaretDown, FaCaretUp } from 'react-icons/fa'; -import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc'; -import { IDocRequest, fetchKeywords, fetchRecommendations } from '../utils'; -import { IBounds } from '../ExploreView/utils'; +import { GrClose } from 'react-icons/gr'; +import { DocListCast, StrListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; -import { Id } from '../../../../fields/FieldSymbols'; +import { StrCast } from '../../../../fields/Types'; import { LightboxView } from '../../LightboxView'; -import { IconButton, Size, Type } from 'browndash-components'; import { Colors } from '../../global/globalEnums'; +import { IBounds } from '../ExploreView/utils'; +import { NewLightboxView } from '../NewLightboxView'; +import { IRecommendation, Recommendation } from '../components'; +import { IDocRequest, fetchKeywords, fetchRecommendations } from '../utils'; +import './RecommendationList.scss'; +import { IRecommendationList } from './utils'; export const RecommendationList = (props: IRecommendationList) => { - const {loading, keywords} = props - const [loadingKeywords, setLoadingKeywords] = React.useState(true) - const [showMore, setShowMore] = React.useState(false) - const [keywordsLoc, setKeywordsLoc] = React.useState([]) - const [update, setUpdate] = React.useState(true) - const initialRecs: IRecommendation[] = [ - {loading: true}, - {loading: true}, - {loading: true}, - {loading: true}, - {loading: true} - ]; - const [recs, setRecs] = React.useState(initialRecs) + const { loading, keywords } = props; + const [loadingKeywords, setLoadingKeywords] = React.useState(true); + const [showMore, setShowMore] = React.useState(false); + const [keywordsLoc, setKeywordsLoc] = React.useState([]); + const [update, setUpdate] = React.useState(true); + const initialRecs: IRecommendation[] = [{ loading: true }, { loading: true }, { loading: true }, { loading: true }, { loading: true }]; + const [recs, setRecs] = React.useState(initialRecs); React.useEffect(() => { const getKeywords = async () => { - let text = StrCast(LightboxView.LightboxDoc?.text) - console.log('[1] fetching keywords') - const response = await fetchKeywords(text, 5, true) - console.log('[2] response:', response) + let text = StrCast(LightboxView.LightboxDoc?.text); + console.log('[1] fetching keywords'); + const response = await fetchKeywords(text, 5, true); + console.log('[2] response:', response); const kw = response.keywords; console.log(kw); NewLightboxView.SetKeywords(kw); if (LightboxView.LightboxDoc) { - console.log('setting keywords on doc') + console.log('setting keywords on doc'); LightboxView.LightboxDoc.keywords = new List(kw); setKeywordsLoc(NewLightboxView.Keywords); } - setLoadingKeywords(false) - } - let keywordsList = StrListCast(LightboxView.LightboxDoc!.keywords) + setLoadingKeywords(false); + }; + let keywordsList = StrListCast(LightboxView.LightboxDoc!.keywords); if (!keywordsList || keywordsList.length < 2) { - setLoadingKeywords(true) - getKeywords() - setUpdate(!update) + setLoadingKeywords(true); + getKeywords(); + setUpdate(!update); } else { - setKeywordsLoc(keywordsList) - setLoadingKeywords(false) - setUpdate(!update) + setKeywordsLoc(keywordsList); + setLoadingKeywords(false); + setUpdate(!update); } - }, [NewLightboxView.LightboxDoc]) + }, [NewLightboxView.LightboxDoc]); - // terms: vannevar bush, information spaces, + // terms: vannevar bush, information spaces, React.useEffect(() => { const getRecommendations = async () => { - console.log('fetching recommendations') - let query = 'undefined' - if (keywordsLoc) query = keywordsLoc.join(',') - let src = StrCast(NewLightboxView.LightboxDoc?.text) - let dashDocs:IDocRequest[] = []; + console.log('fetching recommendations'); + let query = 'undefined'; + if (keywordsLoc) query = keywordsLoc.join(','); + let src = StrCast(NewLightboxView.LightboxDoc?.text); + let dashDocs: IDocRequest[] = []; // get linked docs - let linkedDocs = DocListCast(NewLightboxView.LightboxDoc?.links) - console.log("linked docs", linkedDocs) + let linkedDocs = DocListCast(NewLightboxView.LightboxDoc?.links); + console.log('linked docs', linkedDocs); // get context docs (docs that are also in the collection) // let contextDocs: Doc[] = DocListCast(DocCast(LightboxView.LightboxDoc?.context).data) // let docId = LightboxView.LightboxDoc && LightboxView.LightboxDoc[Id] @@ -83,114 +76,142 @@ export const RecommendationList = (props: IRecommendationList) => { // }) // } // }) - console.log("dash docs", dashDocs) + console.log('dash docs', dashDocs); if (query !== undefined) { - const response = await fetchRecommendations(src, query, [], true) - const num_recs = response.num_recommendations - const recs = response.recommendations - const keywords = response.keywords + const response = await fetchRecommendations(src, query, [], true); + const num_recs = response.num_recommendations; + const recs = response.recommendations; + const keywords = response.keywords; const response_bounds: IBounds = { - max_x: response.max_x, - max_y: response.max_y, - min_x: response.min_x, - min_y: response.min_y - } + max_x: response.max_x, + max_y: response.max_y, + min_x: response.min_x, + min_y: response.min_y, + }; // if (NewLightboxView.NewLightboxDoc) { // NewLightboxView.NewLightboxDoc.keywords = new List(keywords); // setKeywordsLoc(NewLightboxView.Keywords); // } // console.log(response_bounds) - NewLightboxView.SetBounds(response_bounds) + NewLightboxView.SetBounds(response_bounds); const recommendations: IRecommendation[] = []; for (const key in recs) { - console.log(key) + console.log(key); const title = recs[key].title; - const url = recs[key].url - const type = recs[key].type - const text = recs[key].text - const transcript = recs[key].transcript - const previewUrl = recs[key].previewUrl - const embedding = recs[key].embedding - const distance = recs[key].distance - const source = recs[key].source - const related_concepts = recs[key].related_concepts - const docId = recs[key].doc_id - related_concepts.length >= 1 && recommendations.push({ - title: title, - data: url, - type: type, - text: text, - transcript: transcript, - previewUrl: previewUrl, - embedding: embedding, - distance: Math.round(distance * 100) / 100, - source: source, - related_concepts: related_concepts, - docId: docId - }) + const url = recs[key].url; + const type = recs[key].type; + const text = recs[key].text; + const transcript = recs[key].transcript; + const previewUrl = recs[key].previewUrl; + const embedding = recs[key].embedding; + const distance = recs[key].distance; + const source = recs[key].source; + const related_concepts = recs[key].related_concepts; + const docId = recs[key].doc_id; + related_concepts.length >= 1 && + recommendations.push({ + title: title, + data: url, + type: type, + text: text, + transcript: transcript, + previewUrl: previewUrl, + embedding: embedding, + distance: Math.round(distance * 100) / 100, + source: source, + related_concepts: related_concepts, + docId: docId, + }); } recommendations.sort((a, b) => { if (a.distance && b.distance) { - return a.distance - b.distance - } else return 0 - }) - console.log("[rec]: ", recommendations) - NewLightboxView.SetRecs(recommendations) - setRecs(recommendations) + return a.distance - b.distance; + } else return 0; + }); + console.log('[rec]: ', recommendations); + NewLightboxView.SetRecs(recommendations); + setRecs(recommendations); } - } + }; getRecommendations(); - }, [update]) - - + }, [update]); - return
{e.stopPropagation()}}> -
-
- Recommendations -
- {NewLightboxView.LightboxDoc &&
- The recommendations are produced based on the text in the document {StrCast(NewLightboxView.LightboxDoc.title)}. The following keywords are used to fetch the recommendations. -
} -
Keywords
- {loadingKeywords ?
-
-
-
-
+ return ( +
{ + e.stopPropagation(); + }}> +
+
Recommendations
+ {NewLightboxView.LightboxDoc && ( +
+ The recommendations are produced based on the text in the document{' '} + + {StrCast(NewLightboxView.LightboxDoc.title)} + + . The following keywords are used to fetch the recommendations.
- : -
- {keywordsLoc && keywordsLoc.map((word, ind) => { - return
- {word} - } onClick={() => { - let kw = keywordsLoc - kw.splice(ind) - NewLightboxView.SetKeywords(kw) - }}/> + )} +
Keywords
+ {loadingKeywords ? ( +
+
+
+
+
- })} -
- } - {!showMore ? -
{setShowMore(true)}}> - More + ) : ( +
+ {keywordsLoc && + keywordsLoc.map((word, ind) => { + return ( +
+ {word} + } + onClick={() => { + let kw = keywordsLoc; + kw.splice(ind); + NewLightboxView.SetKeywords(kw); + }} + /> +
+ ); + })} +
+ )} + {!showMore ? ( +
{ + setShowMore(true); + }}> + More +
+ ) : ( +
+
{ + setShowMore(false); + }}> + Less +
+
Type
+
Sources
+
+ )}
- : -
-
{setShowMore(false)}}> - Less -
-
Type
-
Sources
+
+ {recs && + recs.map((rec: IRecommendation) => { + return ; + })}
- } -
-
- {recs && recs.map((rec: IRecommendation) => { - return - })}
-
-} \ No newline at end of file + ); +}; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 58820a498..a04030a5f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,6 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { Howl } from 'howler'; -import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction, trace } from 'mobx'; +import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Bounce, Fade, Flip, JackInTheBox, Roll, Rotate, Zoom } from 'react-awesome-reveal'; @@ -50,7 +50,6 @@ import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails'; -import { InkingStroke } from '../InkingStroke'; interface Window { MediaRecorder: MediaRecorder; } diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx index c43f89be1..a557cff4f 100644 --- a/src/client/views/nodes/EquationBox.tsx +++ b/src/client/views/nodes/EquationBox.tsx @@ -1,6 +1,7 @@ import { action, makeObservable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { DivHeight, DivWidth } from '../../../Utils'; import { Id } from '../../../fields/FieldSymbols'; import { NumCast, StrCast } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; @@ -11,7 +12,6 @@ import { LightboxView } from '../LightboxView'; import './EquationBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; import EquationEditor from './formattedText/EquationEditor'; -import { DivHeight, DivWidth } from '../../../Utils'; @observer export class EquationBox extends ViewBoxBaseComponent() { diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index 7ad250714..36bd037ca 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -15,9 +15,9 @@ import { EditableView } from '../EditableView'; import { LightboxView } from '../LightboxView'; import { StyleProp } from '../StyleProvider'; import { ComparisonBox } from './ComparisonBox'; +import { DocumentView } from './DocumentView'; import { FieldView, FieldViewProps } from './FieldView'; import './LinkBox.scss'; -import { DocumentView } from './DocumentView'; @observer export class LinkBox extends ViewBoxBaseComponent() { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index f4d5eef05..434415b96 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { htmlToText } from 'html-to-text'; -import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as WebRequest from 'web-request'; @@ -34,7 +34,7 @@ import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; import { SidebarAnnos } from '../SidebarAnnos'; import { StyleProp } from '../StyleProvider'; import { DocumentView, OpenWhere } from './DocumentView'; -import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView'; +import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import { LinkInfo } from './LinkDocPreview'; import { PinProps, PresBox } from './trails'; import './WebBox.scss'; diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ae6da8fb0..cd9fec839 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -18,6 +18,7 @@ import { DocServer } from '../../../DocServer'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; import { DocumentManager } from '../../../util/DocumentManager'; +import { dropActionType } from '../../../util/DragManager'; import { ScriptingGlobals } from '../../../util/ScriptingGlobals'; import { SelectionManager } from '../../../util/SelectionManager'; import { SerializationHelper } from '../../../util/SerializationHelper'; @@ -32,11 +33,10 @@ import { ViewBoxBaseComponent } from '../../DocComponent'; import { Colors } from '../../global/globalEnums'; import { LightboxView } from '../../LightboxView'; import { DocumentView, OpenWhere, OpenWhereMod } from '../DocumentView'; -import { FocusViewOptions, FieldView, FieldViewProps } from '../FieldView'; +import { FieldView, FieldViewProps, FocusViewOptions } from '../FieldView'; import { ScriptingBox } from '../ScriptingBox'; import './PresBox.scss'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; -import { dropActionType } from '../../../util/DragManager'; export interface pinDataTypes { scrollable?: boolean; dataviz?: number[]; diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx index addad2bbc..eab33114e 100644 --- a/src/client/views/topbar/TopBar.tsx +++ b/src/client/views/topbar/TopBar.tsx @@ -3,6 +3,7 @@ import { Button, IconButton, isDark, Size, Type } from 'browndash-components'; import { action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Flip } from 'react-awesome-reveal'; import { FaBug } from 'react-icons/fa'; import { Doc, DocListCast } from '../../../fields/Doc'; import { AclAdmin, DashVersion } from '../../../fields/DocSymbols'; @@ -11,6 +12,7 @@ import { GetEffectiveAcl } from '../../../fields/util'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue } from '../../../Utils'; import { CurrentUserUtils } from '../../util/CurrentUserUtils'; import { DocumentManager } from '../../util/DocumentManager'; +import { dropActionType } from '../../util/DragManager'; import { PingManager } from '../../util/PingManager'; import { ReportManager } from '../../util/reportManager/ReportManager'; import { ServerStats } from '../../util/ServerStats'; @@ -23,11 +25,9 @@ import { CollectionLinearView } from '../collections/collectionLinear'; import { DashboardView } from '../DashboardView'; import { Colors } from '../global/globalEnums'; import { DocumentViewInternal, returnEmptyDocViewList } from '../nodes/DocumentView'; +import { ObservableReactComponent } from '../ObservableReactComponent'; import { DefaultStyleProvider } from '../StyleProvider'; import './TopBar.scss'; -import { dropActionType } from '../../util/DragManager'; -import { Flip } from 'react-awesome-reveal'; -import { ObservableReactComponent } from '../ObservableReactComponent'; /** * ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user -- cgit v1.2.3-70-g09d2 From 47ae05389d7ce564efde19b7a639b38842759cc1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 31 Mar 2024 00:09:33 -0400 Subject: fixed dropdown in title bar location. moved rotate button up to not interfere with button bar. don't blur title when editing it. fix drawgging rotate center on templates. support setting alternate colors for text docs -- pretty hacky. fixed tabbing through dashFieldViews. --- src/client/views/DocumentDecorations.scss | 2 +- src/client/views/DocumentDecorations.tsx | 21 +++++++++++++++------ src/client/views/StyleProvider.tsx | 5 ++++- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/global/globalScripts.ts | 4 +++- src/client/views/nodes/DocumentView.scss | 6 ++++++ src/client/views/nodes/DocumentView.tsx | 6 +++++- .../views/nodes/formattedText/DashFieldView.tsx | 17 ++++++++++------- .../views/nodes/formattedText/FormattedTextBox.tsx | 7 +++++-- 9 files changed, 50 insertions(+), 20 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index ac0ef054c..239c0a977 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -14,7 +14,7 @@ $resizeHandler: 8px; height: 30; width: 30; right: -40; - bottom: -40; + bottom: -20; //top: calc(50% - 15px); position: absolute; pointer-events: all; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6698cd5bc..951e0912c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -73,11 +73,18 @@ export class DocumentDecorations extends ObservableReactComponent { + let inputting = false; + if (this._titleControlString.startsWith('$')) { + const titleFieldKey = this._titleControlString.substring(1); + if (SelectionManager.Views[0]?.Document[titleFieldKey] !== this._accumulatedTitle) { + inputting = true; + } + } const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2}; const {x,y} = Utils.rotPt(e.clientX - center.x, e.clientY - center.y, NumCast(SelectionManager.Views.lastElement()?.screenToViewTransform().Rotate)); - (this._showNothing = !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && // + (this._showNothing = !inputting && !DocumentButtonBar.Instance?._tooltipOpen && !(this.Bounds.x !== Number.MAX_VALUE && // (this.Bounds.x > center.x+x || this.Bounds.r < center.x+x || this.Bounds.y > center.y+y || this.Bounds.b < center.y+y ))); })); // prettier-ignore @@ -336,8 +343,8 @@ export class DocumentDecorations extends ObservableReactComponent // return false to keep getting events this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]) as any as boolean, action(e => (this._isRotating = false)), // upEvent - action(e => (seldocview.Document.rotation_centerX = seldocview.Document.rotation_centerY = 0)) + action(e => (seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0)), + true ); // prettier-ignore + e.stopPropagation(); }; @action @@ -617,7 +626,7 @@ export class DocumentDecorations extends ObservableReactComponent { this._editingTitle = false; - !hideTitle && this.titleBlur(); + this.titleBlur(); })} onChange={action(e => !hideTitle && (this._accumulatedTitle = e.target.value))} onKeyDown={hideTitle ? emptyFunction : this.titleEntered} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 749198fe6..dcec2fe3d 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -200,7 +200,10 @@ export function DefaultStyleProvider(doc: Opt, props: Opt = StrCast(doc?.[fieldKey + 'backgroundColor'], StrCast(doc?.backgroundColor, isCaption ? 'rgba(0,0,0,0.4)' : '')); + const dataKey = doc ? Doc.LayoutFieldKey(doc) : ""; + const usePath = StrCast(doc?.[dataKey + "_usePath"]); + const alternate = usePath.includes(":hover") ? ( doc?.isHovering ? '_' + usePath.replace(":hover","") : "") : usePath ? "_" +usePath:usePath; + let docColor: Opt = StrCast(doc?.[fieldKey+alternate], StrCast(doc?.['backgroundColor' +alternate], isCaption ? 'rgba(0,0,0,0.4)' : '')); if (doc?.[StrCast(doc?.layout_fieldKey)] instanceof Doc) docColor = StrCast(doc._backgroundColor,docColor) // prettier-ignore switch (layoutDoc?.type) { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index d435173f3..791124f50 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1288,7 +1288,7 @@ export class CollectionFreeFormView extends CollectionSubView div { + transform-origin: top left !important; + } +} + .contentFittingDocumentView { position: relative; display: flex; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a04030a5f..fc2da18d9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -843,7 +843,11 @@ export class DocumentViewInternal extends DocComponent - {!dropdownWidth ? null :
{this.fieldsDropdown(showTitle)}
} + {!dropdownWidth ? null : ( +
+ {this.fieldsDropdown(showTitle)} +
+ )}
this._nodeSelected; @@ -38,6 +39,7 @@ export class DashFieldView { const self = this; this.node = node; this.tbox = tbox; + this.getpos = getPos; this.dom = document.createElement('div'); this.dom.style.width = node.attrs.width; this.dom.style.height = node.attrs.height; @@ -54,13 +56,13 @@ export class DashFieldView { const editor = tbox.EditorView; if (editor) { const state = editor.state; - for (var i = state.selection.to; i < state.doc.content.size; i++) { + for (var i = self.getpos() + 1; i < state.doc.content.size; i++) { if (state.doc.nodeAt(i)?.type.name === state.schema.nodes.dashField.name) { editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(i)))); return; } } - tBox.setFocus(state.selection.to); + // tBox.setFocus(state.selection.to); } } }; @@ -137,7 +139,7 @@ export class DashFieldViewInternal extends ObservableReactComponent (this._dashDoc = this._props.dataDoc ? doc[DocData] : doc); + const setDoc = action((doc: Doc) => (this._dashDoc = this._props.dataDoc ? doc[DocData] : doc)); if (this._props.docId) { DocServer.GetRefField(this._props.docId).then(dashDoc => dashDoc instanceof Doc && setDoc(dashDoc)); @@ -255,7 +257,7 @@ export class DashFieldViewInternal extends ObservableReactComponent | undefined) => { - event && this._dashDoc && (this._dashDoc[this._fieldKey] = event.target.value); + event && this._dashDoc && (this._dashDoc[this._fieldKey] = event.target.value === '-unset-' ? undefined : event.target.value); }; @computed get values() { @@ -281,13 +283,14 @@ export class DashFieldViewInternal extends ObservableReactComponent )} {this._props.fieldKey.startsWith('#') || this._hideValue ? null : this.fieldValueContent} - {/* {!this.values.length ? null : ( - + {this.values.map(val => ( ))} - )} */} + )}
); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 66df1eaf2..3700b08d6 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -2064,8 +2064,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this._isHovering = true))} - onPointerLeave={action(() => (this._isHovering = false))} + onPointerEnter={action(() => { + this._isHovering = true; + this.layoutDoc[`_${this._props.fieldKey}_usePath`] && (this.Document.isHovering = true); + })} + onPointerLeave={action(() => (this.Document.isHovering = this._isHovering = false))} ref={r => { this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); this._oldWheel = r; -- cgit v1.2.3-70-g09d2 From 108e27f0d08a8d6d3b3fcd456d6cca999c077e8b Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 31 Mar 2024 23:09:53 -0400 Subject: fixed scrolling to targets in text views. fixed referencing fields on another doc from text box. fixed '@name' technique for publishing documents to also remove documents and work anywhere a title is set. --- src/client/documents/Documents.ts | 5 ++++ src/client/util/Scripting.ts | 2 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 6 ---- .../views/collections/CollectionDockingView.tsx | 25 ++++++++++++++-- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- .../views/nodes/formattedText/DashFieldView.tsx | 8 ++--- .../views/nodes/formattedText/FormattedTextBox.tsx | 34 ++++++++++------------ .../views/nodes/formattedText/RichTextRules.ts | 13 +++------ src/client/views/nodes/formattedText/nodes_rts.ts | 1 - src/fields/Doc.ts | 13 +++++++-- src/fields/util.ts | 16 +++++++++- 12 files changed, 78 insertions(+), 49 deletions(-) (limited to 'src/client/views/DocumentDecorations.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6a0d45543..eb15c332f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1516,6 +1516,9 @@ export namespace DocUtils { return linkDoc; }); + const a = source.layout_unrendered ? 'link_anchor_1.annotationOn' : 'link_anchor_1'; + const b = target.layout_unrendered ? 'link_anchor_2.annotationOn' : 'link_anchor_2'; + return makeLink( Docs.Create.LinkDocument( source, @@ -1529,6 +1532,8 @@ export namespace DocUtils { link_displayLine: linkSettings.link_displayLine, link_relationship: linkSettings.link_relationship, link_description: linkSettings.link_description, + x: ComputedField.MakeFunction(`(this.${a}.x+this.${b}.x)/2`) as any, + y: ComputedField.MakeFunction(`(this.${a}.y+this.${b}.y)/2`) as any, link_autoMoveAnchors: true, _lockedPosition: true, _layout_showCaption: '', // removed since they conflict with showing a link with a LinkBox (ie, line, not comparison box) diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 31222aa50..422e708bc 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -250,7 +250,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const outputText = host.readFile('file.js'); const diagnostics = ts.getPreEmitDiagnostics(program).concat(testResult.diagnostics); - + if (script.startsWith('@')) options.typecheck = true; // need the compilation to fail so that the script will return itself as a string (instead of nothing) const result = Run(outputText, paramNames, diagnostics, script, options); if (options.globals) { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index d65e0b406..15ce4c15f 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -416,7 +416,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => ( )} {DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== doc ?
{this.endLinkButton}
: null} - {Doc.noviceMode ? null :
{this.templateButton}
} +
{this.templateButton}
{!SelectionManager.Views?.some(v => v.allLinks.length) ? null :
{this.followLinkButton}
}
{this.pinButton}
{this.recordButton}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 951e0912c..9e469ed1f 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -131,12 +131,6 @@ export class DocumentDecorations extends ObservableReactComponent { if (titleFieldKey === 'title') { d.dataDoc.title_custom = !this._accumulatedTitle.startsWith('-'); - if (StrCast(d.Document.title).startsWith('@') && !this._accumulatedTitle.startsWith('@')) { - Doc.RemFromMyPublished(d.Document); - } - if (!StrCast(d.Document.title).startsWith('@') && this._accumulatedTitle.startsWith('@')) { - Doc.AddToMyPublished(d.Document); - } } KeyValueBox.SetField(d.Document, titleFieldKey, this._accumulatedTitle); }), diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 25bfdb588..b2897a9b7 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -3,14 +3,14 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import * as GoldenLayout from '../../../client/goldenLayout'; -import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; -import { ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { FieldValue, ImageCast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util'; +import { GetEffectiveAcl, inheritParentAcls, SetPropSetterCb } from '../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, emptyFunction, incrementTitleCopy } from '../../../Utils'; import { DocServer } from '../../DocServer'; import { Docs } from '../../documents/Documents'; @@ -32,6 +32,7 @@ import './CollectionDockingView.scss'; import { CollectionFreeFormView } from './collectionFreeForm'; import { CollectionSubView } from './CollectionSubView'; import { TabDocView } from './TabDocView'; +import { ComputedField } from '../../../fields/ScriptField'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -313,8 +314,26 @@ export class CollectionDockingView extends CollectionSubView() { } }; + /** + * This publishes Docs having titles starting with '@' to Doc.myPublishedDocs + * Once published, any text that uses the 'title' in its body will automatically + * be linked to this published document. + * @param target + * @param title + */ + titleChanged = (target: any, value: any) => { + const title = Field.toString(value); + if (title.startsWith('@') && !title.substring(1).match(/[\(\)\[\]@]/) && title.length > 1) { + const embedding = DocListCast(target.proto_embeddings).lastElement(); + embedding && Doc.AddToMyPublished(embedding); + } else if (!title.startsWith('@')) { + DocListCast(target.proto_embeddings).forEach(doc => Doc.RemFromMyPublished(doc)); + } + }; + componentDidMount: () => void = async () => { this._unmounting = false; + SetPropSetterCb('title', this.titleChanged); // this overrides any previously assigned callback for the property if (this._containerRef.current) { this._lightboxReactionDisposer = reaction( () => LightboxView.LightboxDoc, diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6b3a56b0b..6eca91e9d 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -499,7 +499,7 @@ export class MarqueeView extends ObservableReactComponent ); @@ -119,7 +118,6 @@ interface IDashFieldViewInternal { height: number; editable: boolean; nodeSelected: () => boolean; - dataDoc: boolean; node: any; getPos: any; unclickable: () => boolean; @@ -139,7 +137,7 @@ export class DashFieldViewInternal extends ObservableReactComponent (this._dashDoc = this._props.dataDoc ? doc[DocData] : doc)); + const setDoc = action((doc: Doc) => (this._dashDoc = doc)); if (this._props.docId) { DocServer.GetRefField(this._props.docId).then(dashDoc => dashDoc instanceof Doc && setDoc(dashDoc)); @@ -168,7 +166,7 @@ export class DashFieldViewInternal extends ObservableReactComponent !this._props.tbox.ProseRef?.contains(document.activeElement) && this._props.tbox._props.onBlur?.()); } }); - selectedCell = (): [Doc, number] => [this._dashDoc!, 0]; + selectedCell = (): [Doc, number] | undefined => (this._dashDoc ? [this._dashDoc, 0] : undefined); columnWidth = () => Math.min(this._props.tbox._props.PanelWidth(), Math.max(50, this._props.tbox._props.PanelWidth() - 100)); // try to leave room for the fieldKey // set the display of the field's value (checkbox for booleans, span of text for strings) @@ -284,7 +282,7 @@ export class DashFieldViewInternal extends ObservableReactComponent +