diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/ColorBox.tsx | 9 | ||||
| -rw-r--r-- | src/client/views/nodes/DataVizBox/utils/D3Utils.ts | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 6 | ||||
| -rw-r--r-- | src/client/views/nodes/EquationBox.scss | 9 | ||||
| -rw-r--r-- | src/client/views/nodes/FontIconBox/FontIconBox.tsx | 51 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkDocPreview.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/MapBox/MapBox.tsx | 1 | ||||
| -rw-r--r-- | src/client/views/nodes/ScreenshotBox.scss | 36 | ||||
| -rw-r--r-- | src/client/views/nodes/ScreenshotBox.tsx | 12 | ||||
| -rw-r--r-- | src/client/views/nodes/ScriptingBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 14 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 22 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/RichTextRules.ts | 26 |
13 files changed, 98 insertions, 93 deletions
diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx index aae759702..1b6fe5748 100644 --- a/src/client/views/nodes/ColorBox.tsx +++ b/src/client/views/nodes/ColorBox.tsx @@ -14,6 +14,8 @@ import { ActiveInkColor, ActiveInkWidth, SetActiveInkColor, SetActiveInkWidth } import './ColorBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; import { RichTextMenu } from './formattedText/RichTextMenu'; +import { ScriptingGlobals } from '../../util/ScriptingGlobals'; +import { DashColor } from '../../../Utils'; @observer export class ColorBox extends ViewBoxBaseComponent<FieldViewProps>() { @@ -81,3 +83,10 @@ export class ColorBox extends ViewBoxBaseComponent<FieldViewProps>() { ); } } + + +ScriptingGlobals.add( + function interpColors(c1:string, c2:string, weight=0.5) { + return DashColor(c1).mix(DashColor(c2),weight) + } +)
\ No newline at end of file diff --git a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts index e1ff6f8eb..10bfb0c64 100644 --- a/src/client/views/nodes/DataVizBox/utils/D3Utils.ts +++ b/src/client/views/nodes/DataVizBox/utils/D3Utils.ts @@ -34,7 +34,6 @@ export const createLineGenerator = (xScale: d3.ScaleLinear<number, number, never }; export const xAxisCreator = (g: d3.Selection<SVGGElement, unknown, null, undefined>, height: number, xScale: d3.ScaleLinear<number, number, never>) => { - console.log('x axis creator being called'); g.attr('class', 'x-axis').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickSize(15)); }; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 70d2f95ea..bb9f45bdd 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,5 +1,5 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; -import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import { Bounce, Fade, Flip, LightSpeed, Roll, Rotate, Zoom } from 'react-reveal'; @@ -47,11 +47,11 @@ import { DocumentLinksButton } from './DocumentLinksButton'; import './DocumentView.scss'; import { FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; -import { KeyValueBox } from './KeyValueBox'; import { LinkAnchorBox } from './LinkAnchorBox'; import { PresEffect, PresEffectDirection } from './trails'; import { PinProps, PresBox } from './trails/PresBox'; import React = require('react'); +import { SettingsManager } from '../../util/SettingsManager'; const { Howl } = require('howler'); interface Window { @@ -1110,7 +1110,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps const targetDoc = showTitle?.startsWith('_') ? this.layoutDoc : this.rootDoc; const background = StrCast( SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor, - Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().headingColor) : 'rgba(0,0,0,0.4)' + Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().headingColor) : SettingsManager.Instance.userVariantColor ); const sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', ''); const titleView = !showTitle ? null : ( diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss index 9714e1bd0..f5871db22 100644 --- a/src/client/views/nodes/EquationBox.scss +++ b/src/client/views/nodes/EquationBox.scss @@ -1,8 +1,9 @@ -@import "../global/globalCssVariables.scss"; +@import '../global/globalCssVariables.scss'; .equationBox-cont { - transform-origin: top left; + transform-origin: center; + background-color: #e7e7e7; > span { - width: 100%; + width: 100%; } -}
\ No newline at end of file +} diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx index ad3532502..1b2209224 100644 --- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx @@ -267,20 +267,25 @@ export class FontIconBox extends DocComponent<ButtonProps>() { return ScriptCast(this.rootDoc.script); } + colorBatch:UndoManager.Batch|undefined; /** * Color button */ @computed get colorButton() { const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); const curColor = this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent'; const tooltip: string = StrCast(this.rootDoc.toolTip); return ( <ColorPicker setSelectedColor={value => { - const s = this.colorScript; - s && undoable(() => s.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)(); + if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`); + this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false }); + }} + setFinalColor={value => { + this.colorScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, value: value, _readOnly_: false }); + this.colorBatch?.end(); + this.colorBatch= undefined; }} selectedColor={curColor} type={Type.PRIM} @@ -378,38 +383,26 @@ export class FontIconBox extends DocComponent<ButtonProps>() { } render() { - // determine dash button metadata const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); - const tooltip: string = StrCast(this.rootDoc.toolTip); - const onClickScript = ScriptCast(this.rootDoc.onClick); - // TODO:glr Add label of button type - let button: JSX.Element = this.defaultButton; + const tooltip = StrCast(this.rootDoc.toolTip); + const scriptFunc = () => ScriptCast(this.rootDoc.onClick)?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false }); + const btnProps = { tooltip, icon: this.Icon(color)!, label: this.label }; // prettier-ignore switch (this.type) { - case ButtonType.EditableText: - button = this.editableText; break; - case ButtonType.DropdownList: - button = this.dropdownListButton; break; - case ButtonType.ColorButton: - button = this.colorButton; break; case ButtonType.NumberDropdownButton: case ButtonType.NumberInlineButton: - case ButtonType.NumberSliderButton: - button = this.numberDropdown; break; - case ButtonType.DropdownButton: - button = this.dropdownButton; break; - case ButtonType.MultiToggleButton: - button = this.multiToggleButton; break; - case ButtonType.ToggleButton: button = this.toggleButton; break; + case ButtonType.NumberSliderButton: return this.numberDropdown; + case ButtonType.EditableText: return this.editableText; + case ButtonType.DropdownList: return this.dropdownListButton; + case ButtonType.ColorButton: return this.colorButton; + case ButtonType.DropdownButton: return this.dropdownButton; + case ButtonType.MultiToggleButton: return this.multiToggleButton; + case ButtonType.ToggleButton: return this.toggleButton; case ButtonType.ClickButton: - case ButtonType.ToolButton: - button = <IconButton tooltip={tooltip} color={color} icon={this.Icon(color)!} label={this.label}/>; break; - case ButtonType.TextButton: - button = <Button tooltip={tooltip} icon={this.Icon(color)!} text={StrCast(this.rootDoc.buttonText)} label={this.label}/>; break; - case ButtonType.MenuButton: - button = <IconButton tooltip={tooltip} onPointerDown={() => onClickScript?.script.run({ this: this.layoutDoc, self: this.rootDoc, _readOnly_: false })} tooltipPlacement='right' size={Size.LARGE} color={color} icon={this.Icon(color)!} label={this.label}/>; break; + case ButtonType.ToolButton: return <IconButton {...btnProps} size={Size.LARGE} color={color} />; + case ButtonType.TextButton: return <Button {...btnProps} text={StrCast(this.rootDoc.buttonText)}/>; + case ButtonType.MenuButton: return <IconButton {...btnProps} color={color} size={Size.LARGE} tooltipPlacement='right' onPointerDown={scriptFunc} />; } - - return button; + return this.defaultButton; } } diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 86191de63..d69009415 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -4,7 +4,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import wiki from 'wikijs'; import { Doc, DocCastAsync, Opt } from '../../../fields/Doc'; -import { Height, Width } from '../../../fields/DocSymbols'; +import { DirectLinks, Height, Width } from '../../../fields/DocSymbols'; import { Cast, DocCast, NumCast, PromiseValue, StrCast } from '../../../fields/Types'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnNone, setupMoveUpEvents } from '../../../Utils'; import { DocServer } from '../../DocServer'; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index de0b57fd7..4919ee94c 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -61,7 +61,6 @@ const script = document.createElement('script'); script.defer = true; script.async = true; script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places,drawing`; -console.log(script.src); document.head.appendChild(script); /** diff --git a/src/client/views/nodes/ScreenshotBox.scss b/src/client/views/nodes/ScreenshotBox.scss index 6fb5ea7b3..1e9b64a0b 100644 --- a/src/client/views/nodes/ScreenshotBox.scss +++ b/src/client/views/nodes/ScreenshotBox.scss @@ -1,6 +1,5 @@ .screenshotBox { transform-origin: top left; - background: white; color: black; // .screenshotBox-viewer { // opacity: 0.99; // hack! overcomes some kind of Chrome weirdness where buttons (e.g., snapshot) disappear at some point as the video is resized larger @@ -12,46 +11,39 @@ #CANCAN { canvas { - width:100% !important; + width: 100% !important; height: 100% !important; } } -.screenshotBox-content, .screenshotBox-content-interactive, .screenshotBox-cont-fullScreen { +.screenshotBox-content, +.screenshotBox-content-interactive, +.screenshotBox-cont-fullScreen { width: 100%; z-index: -1; // 0; // logically this should be 0 (or unset) which would give us transparent brush strokes over videos. However, this makes Chrome crawl to a halt position: absolute; } -.screenshotBox-content, .screenshotBox-content-interactive, .screenshotBox-content-fullScreen { - height: Auto; +.screenshotBox-content, +.screenshotBox-content-interactive, +.screenshotBox-content-fullScreen { + height: Auto; } .screenshotBox-uiButtons { - background:dimgray; - border: orange solid 1px; position: absolute; right: 25; top: 0; - width:25; + width: 22; height: 25; - .screenshotBox-snapshot{ - color : white; - top :0px; - right : 5px; - position: absolute; - background-color:rgba(50, 50, 50, 0.2); - transform-origin: left top; - pointer-events:all; - } - .screenshotBox-recorder{ - color : white; - top :0px; + .screenshotBox-recorder { + color: white; + top: 4px; left: 5px; position: absolute; - background-color:rgba(50, 50, 50, 0.2); + background-color: rgba(50, 50, 50, 0.2); transform-origin: left top; - pointer-events:all; + pointer-events: all; } } diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 312b3c619..271ff3cf8 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -25,6 +25,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; import './ScreenshotBox.scss'; import { VideoBox } from './VideoBox'; +import { SettingsManager } from '../../util/SettingsManager'; declare class MediaRecorder { constructor(e: any, options?: any); // whatever MediaRecorder has @@ -224,7 +225,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl const aud_chunks: any = []; this._audioRec.ondataavailable = (e: any) => aud_chunks.push(e.data); this._audioRec.onstop = async (e: any) => { - const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({file}))); + const [{ result }] = await Networking.UploadFilesToServer(aud_chunks.map((file: any) => ({ file }))); if (!(result instanceof Error)) { this.dataDoc[this.props.fieldKey + '-audio'] = new AudioField(result.accessPaths.agnostic.client); } @@ -235,9 +236,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl this._videoRec.onstart = () => (this.dataDoc[this.props.fieldKey + '-recordingStart'] = new DateField(new Date())); this._videoRec.ondataavailable = (e: any) => vid_chunks.push(e.data); this._videoRec.onstop = async (e: any) => { - console.log('screenshotbox: upload'); const file = new File(vid_chunks, `${this.rootDoc[Id]}.mkv`, { type: vid_chunks[0].type, lastModified: Date.now() }); - const [{ result }] = await Networking.UploadFilesToServer({file}); + const [{ result }] = await Networking.UploadFilesToServer({ file }); this.dataDoc[this.fieldKey + '_duration'] = (new Date().getTime() - this.recordingStart!) / 1000; if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox @@ -313,7 +313,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl </> </CollectionFreeFormView> </div> - <div style={{ background: 'white', position: 'relative', height: this.formattedPanelHeight() }}> + <div style={{ background: SettingsManager.Instance.userColor, position: 'relative', height: this.formattedPanelHeight() }}> {!(this.dataDoc[this.fieldKey + '-dictation'] instanceof Doc) ? null : ( <FormattedTextBox {...this.props} @@ -335,8 +335,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl </div> </div> {!this.props.isSelected() ? null : ( - <div className="screenshotBox-uiButtons"> - <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording}> + <div className="screenshotBox-uiButtons" style={{ background: SettingsManager.Instance.userColor }}> + <div className="screenshotBox-recorder" style={{ color: SettingsManager.Instance.userBackgroundColor, background: SettingsManager.Instance.userVariantColor }} key="snap" onPointerDown={this.toggleRecording}> <FontAwesomeIcon icon="file" size="lg" /> </div> </div> diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx index 3ad3c911d..7c8a1849e 100644 --- a/src/client/views/nodes/ScriptingBox.tsx +++ b/src/client/views/nodes/ScriptingBox.tsx @@ -610,7 +610,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable ' ': { dataProvider: (token: any) => this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { @@ -621,7 +620,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable '.': { dataProvider: (token: any) => this.handleToken(token), component: (blob: any) => { - console.log('Blob', blob); return this.renderFuncListElement(blob.entity); }, output: (item: any, trigger: any) => { diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 34a1229ba..f5df42161 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -125,11 +125,15 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps this._searchRef.current?.setRangeText(searchString); }); } - if (clear) { - this._iframe?.contentWindow?.getSelection()?.empty(); - } - if (searchString) { - (this._iframe?.contentWindow as any)?.find(searchString, false, bwd, true); + try { + if (clear) { + this._iframe?.contentWindow?.getSelection()?.empty(); + } + if (searchString) { + (this._iframe?.contentWindow as any)?.find(searchString, false, bwd, true); + } + } catch (e) { + console.log("WebBox search error", e) } return true; }; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 24d2f0e13..1dcc445e8 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -96,6 +96,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps private _scrollRef: React.RefObject<HTMLDivElement> = React.createRef(); private _editorView: Opt<EditorView>; public _applyingChange: string = ''; + private _finishingLink = false; private _searchIndex = 0; private _lastTimedMark: Mark | undefined = undefined; private _cachedLinks: Doc[] = []; @@ -245,7 +246,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (!pinProps && this._editorView?.state.selection.empty) return this.rootDoc; const anchor = Docs.Create.ConfigDocument({ title: StrCast(this.rootDoc.title), annotationOn: this.rootDoc }); this.addDocument(anchor); + this._finishingLink = true; this.makeLinkAnchor(anchor, OpenWhere.addRight, undefined, 'Anchored Selection', false, addAsAnnotation); + this._finishingLink = false; PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), scrollable: true } }, this.rootDoc); return anchor; }; @@ -326,7 +329,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now()))); if ((!prevData && !protoData) || newText || (!newText && !templateData)) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if (this.props.isContentActive() && removeSelection(newJson) !== removeSelection(prevData?.Data)) { + if ((this._finishingLink || this.props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) { const numstring = NumCast(dataDoc[this.fieldKey], null); dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText); dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited @@ -457,8 +460,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (node.firstChild === null && !node.marks.find((m: Mark) => m.type.name === schema.marks.noAutoLinkAnchor.name) && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) { alink = alink ?? - (LinkManager.Links(this.Document).find(link => Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target)) || - DocUtils.MakeLink(this.props.Document, target, { link_relationship: LinkManager.AutoKeywords })!); + (LinkManager.Links(this.rootDoc).find( + link => + Doc.AreProtosEqual(Cast(link.link_anchor_1, Doc, null), this.rootDoc) && // + Doc.AreProtosEqual(Cast(link.link_anchor_2, Doc, null), target) + ) || + DocUtils.MakeLink(this.rootDoc, target, { link_relationship: LinkManager.AutoKeywords })!); newAutoLinks.add(alink); const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }]; allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? [])); @@ -840,7 +847,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const appearance = cm.findByDescription('Appearance...'); const appearanceItems = appearance && 'subitems' in appearance ? appearance.subitems : []; - appearanceItems.push({ description: 'Change Perspective...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); + appearanceItems.push({ description: 'Change Style...', noexpand: true, subitems: changeItems, icon: 'external-link-alt' }); // this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" }); !Doc.noviceMode && @@ -924,7 +931,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps let image_url = await gptImageCall((this.dataDoc.text as RichTextField)?.Text); if (image_url) { const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [image_url] }); - const source = Utils.prepend(result.accessPaths.agnostic.client); + const source = result.accessPaths.agnostic.client; const newDoc = Docs.Create.ImageDocument(source, { x: NumCast(this.rootDoc.x) + NumCast(this.layoutDoc._width) + 10, y: NumCast(this.rootDoc.y), @@ -1996,12 +2003,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps } cycleAlternateText = () => { if (this.layoutDoc._layout_enableAltContentUI) { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; this.rootDoc[`_${this.props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined; } }; @computed get overlayAlternateIcon() { - const usePath = this.rootDoc[`${this.props.fieldKey}_usePath`]; + const usePath = this.rootDoc[`_${this.props.fieldKey}_usePath`]; return ( <Tooltip title={ @@ -2080,7 +2087,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps ? {} : { transform: `scale(${scale})`, - transformOrigin: 'top left', width: `${100 / scale}%`, height: `${100 / scale}%`, }), diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index ac1e7ce5d..8bafc2cef 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -243,13 +243,13 @@ export class RichTextRules { // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document // [[<fieldKey> : <Doc>]] - // [[:Doc]] => hyperlink + // [[:docTitle]] => hyperlink // [[fieldKey]] => show field // [[fieldKey=value]] => show field and also set its value - // [[fieldKey:Doc]] => show field of doc + // [[fieldKey:docTitle]] => show field of doc new InputRule(new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-zA-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; - const docId = match[3]?.replace(':', ''); + const docTitle = match[3]?.replace(':', ''); const value = match[2]?.substring(1); const linkToDoc = (target: Doc) => { const rstate = this.TextBox.EditorView?.state; @@ -266,12 +266,12 @@ export class RichTextRules { } }; if (!fieldKey) { - if (docId) { - const target = DocServer.QUERY_SERVER_CACHE(docId); - if (target) setTimeout(() => linkToDoc(target)); - else DocServer.GetRefField(docId).then(docx => linkToDoc((docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docId + '(auto)', _width: 500, _height: 500 }, docId))); - - return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + if (docTitle) { + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + setTimeout(() => linkToDoc(target)); + return state.tr.deleteRange(end - 1, end).deleteRange(start, start + 3); + } } return state.tr; } @@ -279,8 +279,12 @@ export class RichTextRules { const num = value.match(/^[0-9.]$/); this.Document[DocData][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value; } - const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId, hideKey: false }); - return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + const target = DocServer.FindDocByTitle(docTitle); + if (target) { + const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId: target[Id], hideKey: false }); + return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true); + } + return state.tr; }), // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document |
