From 1c75007a5b12224009d0ccfd531e7406b0792760 Mon Sep 17 00:00:00 2001 From: Abdullah Ahmed Date: Mon, 7 Oct 2019 11:02:20 -0400 Subject: idk --- src/new_fields/FieldSymbols.ts | 3 ++- src/new_fields/RichTextField.ts | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src/new_fields') diff --git a/src/new_fields/FieldSymbols.ts b/src/new_fields/FieldSymbols.ts index b5b3aa588..8e5161dac 100644 --- a/src/new_fields/FieldSymbols.ts +++ b/src/new_fields/FieldSymbols.ts @@ -7,4 +7,5 @@ export const Id = Symbol("Id"); export const OnUpdate = Symbol("OnUpdate"); export const Parent = Symbol("Parent"); export const Copy = Symbol("Copy"); -export const ToScriptString = Symbol("ToScriptString"); \ No newline at end of file +export const ToScriptString = Symbol("ToScriptString"); +export const ToPlainText = Symbol("ToPlainText"); \ No newline at end of file diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index d2f76c969..390045ee1 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -1,7 +1,7 @@ import { ObjectField } from "./ObjectField"; import { serializable } from "serializr"; import { Deserializable } from "../client/util/SerializationHelper"; -import { Copy, ToScriptString } from "./FieldSymbols"; +import { Copy, ToScriptString, ToPlainText } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; @scriptingGlobal @@ -23,4 +23,8 @@ export class RichTextField extends ObjectField { return `new RichTextField("${this.Data}")`; } + [ToPlainText]() { + return this.Data; + } + } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From c6e2eee8e5b035ed4cab1e7bb1315a36d43255c5 Mon Sep 17 00:00:00 2001 From: ab Date: Tue, 8 Oct 2019 16:02:25 -0400 Subject: switching out --- src/client/views/MainView.tsx | 1 - src/client/views/Recommendations.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 3 --- src/client/views/nodes/DocumentContentsView.tsx | 6 ------ src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/ImageBox.tsx | 1 - src/new_fields/RichTextField.ts | 17 ++++++++++++++++- 7 files changed, 19 insertions(+), 15 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 17de708a2..e6f500e75 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -41,7 +41,6 @@ import { FilterBox } from './search/FilterBox'; import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; //import { DocumentManager } from '../util/DocumentManager'; import { RecommendationsBox } from './Recommendations'; -import PresModeMenu from './presentationview/PresentationModeMenu'; import { PresBox } from './nodes/PresBox'; import { OverlayView } from './OverlayView'; diff --git a/src/client/views/Recommendations.tsx b/src/client/views/Recommendations.tsx index b7b1d84d0..c44dfc032 100644 --- a/src/client/views/Recommendations.tsx +++ b/src/client/views/Recommendations.tsx @@ -174,7 +174,7 @@ export class RecommendationsBox extends React.Component { {this.DocumentIcon(doc)} {NumCast(doc.score).toFixed(4)} -
DocumentManager.Instance.jumpToDocument(doc, true, undefined, undefined, undefined, this.props.Document.sourceDocContext as Doc)}> +
DocumentManager.Instance.jumpToDocument(doc, false)}>
DocUtils.MakeLink(this.props.Document.sourceDoc as Doc, doc, undefined, "User Selected Link", "Generated from Recommender", undefined)}> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 3ee069e4c..d2b8afa02 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -12,7 +12,6 @@ import { BoolCast, Cast, DateCast, NumCast, StrCast } from "../../../../new_fiel import { CurrentUserUtils } from "../../../../server/authentication/models/current_user_utils"; import { aggregateBounds, emptyFunction, intersectRect, returnEmptyString, returnOne, Utils } from "../../../../Utils"; import { CognitiveServices } from "../../../cognitive_services/CognitiveServices"; -import { DocServer } from "../../../DocServer"; import { Docs } from "../../../documents/Documents"; import { DocumentType } from "../../../documents/DocumentTypes"; import { DocumentManager } from "../../../util/DocumentManager"; @@ -28,7 +27,6 @@ import { InkingCanvas } from "../../InkingCanvas"; import { CollectionFreeFormDocumentView, positionSchema } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; import { documentSchema, DocumentViewProps } from "../../nodes/DocumentView"; -import { FormattedTextBox } from "../../nodes/FormattedTextBox"; import { pageSchema } from "../../nodes/ImageBox"; import PDFMenu from "../../pdf/PDFMenu"; import { CollectionSubView } from "../CollectionSubView"; @@ -41,7 +39,6 @@ import React = require("react"); import v5 = require("uuid/v5"); import { ClientRecommender } from "../../../ClientRecommender"; import { SearchUtil } from "../../../util/SearchUtil"; -import { SearchBox } from "../../SearchBox"; import { RouteStore } from "../../../../server/RouteStore"; import { string, number, elementType } from "prop-types"; import { DocServer } from "../../../DocServer"; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index e5eb8dbce..919c13055 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -2,8 +2,6 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; import { Doc } from "../../../new_fields/Doc"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { Cast } from "../../../new_fields/Types"; -import { OmitKeys, Without } from "../../../Utils"; import { HistogramBox } from "../../northstar/dash-nodes/HistogramBox"; import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox"; import { CollectionDockingView } from "../collections/CollectionDockingView"; @@ -30,14 +28,10 @@ import { PresElementBox } from "../presentationview/PresElementBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; import React = require("react"); -import { FieldViewProps } from "./FieldView"; import { Without, OmitKeys } from "../../../Utils"; import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; -import { Doc } from "../../../new_fields/Doc"; -import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox"; import { RecommendationsBox } from "../../views/Recommendations"; -import { ScriptField } from "../../../new_fields/ScriptField"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? type BindingProps = Without; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0064b98c3..070b1f426 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -621,7 +621,7 @@ export class DocumentView extends DocComponent(Docu recommendations.documentIconHeight = 150; recommendations.sourceDoc = this.props.Document; recommendations.sourceDocContext = this.props.ContainingCollectionView!.props.Document; - CollectionDockingView.Instance.AddRightSplit(recommendations, undefined); + CollectionDockingView.AddRightSplit(recommendations, undefined); // RecommendationsBox.Instance.displayRecommendations(e.pageX + 100, e.pageY); } @@ -641,7 +641,7 @@ export class DocumentView extends DocComponent(Docu body.href = urls[i]; bodies.push(body); } - CollectionDockingView.Instance.AddRightSplit(Docs.Create.SchemaDocument(headers, bodies, { title: `Showing External Recommendations for "${StrCast(doc.title)}"` }), undefined); + CollectionDockingView.AddRightSplit(Docs.Create.SchemaDocument(headers, bodies, { title: `Showing External Recommendations for "${StrCast(doc.title)}"` }), undefined); } onPointerEnter = (e: React.PointerEvent): void => { Doc.BrushDoc(this.props.Document); }; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index f36b9895f..7ffe64b9b 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -29,7 +29,6 @@ import "./ImageBox.scss"; import React = require("react"); import { SearchUtil } from '../../util/SearchUtil'; import { ClientRecommender } from '../../ClientRecommender'; -import { DocumentType } from '../../documents/Documents'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); const { Howl } = require('howler'); diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index 390045ee1..f41ea0350 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -4,6 +4,9 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { Copy, ToScriptString, ToPlainText } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; +const delimiter = "\n"; +const joiner = ""; + @scriptingGlobal @Deserializable("RichTextField") export class RichTextField extends ObjectField { @@ -24,7 +27,19 @@ export class RichTextField extends ObjectField { } [ToPlainText]() { - return this.Data; + // Because we're working with plain text, just concatenate all paragraphs + let content = JSON.parse(this.Data).doc.content; + let paragraphs = content.filter((item: any) => item.type === "paragraph"); + + // Functions to flatten ProseMirror paragraph objects (and their components) to plain text + // While this function already exists in state.doc.textBeteen(), it doesn't account for newlines + let blockText = (block: any) => block.text; + let concatenateParagraph = (p: any) => (p.content ? p.content.map(blockText).join(joiner) : "") + delimiter; + + // Concatentate paragraphs and string the result together + let textParagraphs: string[] = paragraphs.map(concatenateParagraph); + let plainText = textParagraphs.join(joiner); + return plainText.substring(0, plainText.length - 1); } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 05399b3916df7311d07e7c375f90261e9c8ead80 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 25 Feb 2020 00:57:37 -0500 Subject: added optional display templates for metadata field values --- src/client/documents/Documents.ts | 10 ++++--- src/client/util/RichTextSchema.tsx | 32 ++++++++++++++-------- .../views/collections/CollectionDockingView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 4 +-- src/new_fields/Doc.ts | 19 +++++++++---- src/new_fields/RichTextField.ts | 4 +++ .../authentication/models/current_user_utils.ts | 18 ++++++++---- 8 files changed, 60 insertions(+), 31 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ff64489bb..ff152ec6c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -97,7 +97,10 @@ export interface DocumentOptions { isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; templates?: List; - backgroundColor?: string | ScriptField; + backgroundColor?: string | ScriptField; // background color for data doc + _backgroundColor?: string | ScriptField; // background color for each template layout doc ( overrides backgroundColor ) + color?: string; // foreground color data doc + _color?: string; // foreground color for each template layout doc (overrides color) ignoreClick?: boolean; lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed @@ -133,7 +136,6 @@ export interface DocumentOptions { sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script strokeWidth?: number; - color?: string; treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view treeViewHideTitle?: boolean; // whether to hide the title of a tree view treeViewHideHeaderFields?: boolean; // whether to hide the drop down options for tree view items. @@ -405,8 +407,8 @@ export namespace Docs { Scripting.addGlobal(Buxton); const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", - "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", - "isButton", "isBackground", "removeDropProperties", "treeViewOpen"]; + "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "_backgroundColor", + "_color", "isButton", "isBackground", "removeDropProperties", "treeViewOpen"]; /** * This function receives the relevant document prototype and uses diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index cfbae5dca..ae3f4e731 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -8,7 +8,7 @@ import { EditorState, NodeSelection, Plugin, TextSelection } from "prosemirror-s import { StepMap } from "prosemirror-transform"; import { EditorView } from "prosemirror-view"; import * as ReactDOM from 'react-dom'; -import { Doc, Field, HeightSym, WidthSym } from "../../new_fields/Doc"; +import { Doc, Field, HeightSym, WidthSym, DocListCast } from "../../new_fields/Doc"; import { Id } from "../../new_fields/FieldSymbols"; import { ObjectField } from "../../new_fields/ObjectField"; import { ComputedField } from "../../new_fields/ScriptField"; @@ -850,17 +850,19 @@ export class DashDocView { export class DashFieldView { - _fieldWrapper: HTMLDivElement; - _labelSpan: HTMLSpanElement; - _fieldSpan: HTMLDivElement; + _fieldWrapper: HTMLDivElement; // container for label and value + _labelSpan: HTMLSpanElement; // field label + _fieldSpan: HTMLDivElement; // field value _reactionDisposer: IReactionDisposer | undefined; _textBoxDoc: Doc; @observable _dashDoc: Doc | undefined; _fieldKey: string; + _options: Doc[] = []; constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { this._fieldKey = node.attrs.fieldKey; this._textBoxDoc = tbox.props.Document; + this._options = DocListCast(tbox.props.Document[node.attrs.fieldKey + "_options"]); this._fieldWrapper = document.createElement("div"); this._fieldWrapper.style.width = node.attrs.width; this._fieldWrapper.style.height = node.attrs.height; @@ -877,11 +879,15 @@ export class DashFieldView { this._fieldSpan.addEventListener("input", this.onchanged); this._fieldSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._fieldSpan.onkeyup = function (e: any) { e.stopPropagation(); }; - this._fieldSpan.onmousedown = function (e: any) { - console.log(e); - e.stopPropagation(); - }; + this._fieldSpan.onmousedown = function (e: any) { e.stopPropagation(); }; + const self = this; + const setDashDoc = (doc: Doc) => { + self._dashDoc = doc; + if (this._dashDoc && self._options?.length && !this._dashDoc[node.attrs.fieldKey]) { + this._dashDoc[node.attrs.fieldKey] = StrCast(self._options[0].title); + } + } this._fieldSpan.onkeydown = function (e: any) { e.stopPropagation(); if ((e.key === "a" && e.ctrlKey) || (e.key === "a" && e.metaKey)) { @@ -902,10 +908,9 @@ export class DashFieldView { this._labelSpan.style.fontSize = "larger"; this._labelSpan.innerHTML = `${node.attrs.fieldKey}: `; if (node.attrs.docid) { - const self = this; - DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && runInAction(() => self._dashDoc = dashDoc)); + DocServer.GetRefField(node.attrs.docid).then(async dashDoc => dashDoc instanceof Doc && runInAction(() => setDashDoc(dashDoc))); } else { - this._dashDoc = tbox.props.DataDoc || tbox.dataDoc; + setDashDoc(tbox.props.DataDoc || tbox.dataDoc); } this._reactionDisposer?.(); this._reactionDisposer = reaction(() => this._dashDoc?.[node.attrs.fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)", { fireImmediately: true }); @@ -916,7 +921,10 @@ export class DashFieldView { } onchanged = () => { this._reactionDisposer?.(); - this._dashDoc![this._fieldKey] = this._fieldSpan.innerText; + + let newText = this._fieldSpan.innerText; + this._options?.forEach(opt => StrCast(opt.title).startsWith(newText) && (newText = StrCast(opt.title))); + this._dashDoc![this._fieldKey] = newText; this._reactionDisposer = reaction(() => this._dashDoc?.[this._fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)"); } diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 83dbb4263..1e38a8927 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -715,7 +715,7 @@ export class DockedFrameRenderer extends React.Component { TraceMobx(); if (!this._document) return (null); const document = this._document; - const resolvedDataDoc = !Doc.AreProtosEqual(this._document[DataSym], this._document) && this._document[DataSym];// document.layout instanceof Doc ? document : this._dataDoc; + const resolvedDataDoc = !Doc.AreProtosEqual(this._document[DataSym], this._document) ? this._document[DataSym] : undefined;// document.layout instanceof Doc ? document : this._dataDoc; return (Docu render() { if (!(this.props.Document instanceof Doc)) return (null); - const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor?.(this.Document); + const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document); const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); const borderRounding = this.layoutDoc.borderRounding; const localScale = fullDegree; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index eac495082..5a664f31c 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -192,10 +192,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); if (!curTemp || curText) { // if no template, or there's text, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()), curText); - this.dataDoc[this.props.fieldKey + "-noTemplate"] = curTemp?.Text !== curText; + this.dataDoc[this.props.fieldKey + "-noTemplate"] = curTemp?.Text !== curText; // mark the data field as being split from the template if it has been edited } else { // if we've deleted all the text in a note driven by a template, then restore the template data this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(curTemp.Data))); - this.dataDoc[this.props.fieldKey + "-noTemplate"] = undefined; + this.dataDoc[this.props.fieldKey + "-noTemplate"] = undefined; // mark the data field as not being split from any template it might have } this._applyingChange = false; } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 6142ebb36..10f4309be 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,7 +17,6 @@ import { listSpec } from "./Schema"; import { ComputedField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; -import { DocumentManager } from "../client/util/DocumentManager"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -612,15 +611,16 @@ export namespace Doc { templateField.isTemplateForField = metadataFieldKey; templateField.title = metadataFieldKey; + const templateFieldValue = templateField[metadataFieldKey]; // move any data that the template field had been rendering over to the template doc so that things will still be rendered // when the template field is adjusted to point to the new metadatafield key. // note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well. // note 2: this will not overwrite any field that already exists on the template doc at the field key - if (!templateDoc?.[metadataFieldKey] && templateField.data instanceof ObjectField) { - Cast(templateField.data, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); - (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateField.data)); + if (!templateDoc?.[metadataFieldKey] && templateFieldValue instanceof ObjectField) { + Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); + (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue)); } - if (templateField.data instanceof RichTextField && (templateField.data.Text || templateField.data.Data.toString().includes("dashField"))) { + if (templateFieldValue instanceof RichTextField && (templateFieldValue.Text || templateFieldValue.Data.toString().includes("dashField"))) { templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); } @@ -838,6 +838,15 @@ export namespace Doc { DocServer.GetRefField(id).then(layout => layout instanceof Doc && (doc[field] = layout)); return id; } + + export function enumeratedTextTemplate(doc: Doc, layoutString: string, dataKey: string, optionKey: string, modes: Doc[]) { + doc[dataKey] = RichTextField.DashField(optionKey); + doc.layout = layoutString; + const optionsField = `${optionKey}_options`; + doc[optionsField] = new List(modes); + doc.backgroundColor = ComputedField.MakeFunction(`this['${optionsField}'].find(doc => doc.title === this.expandedTemplate.${optionKey})?._backgroundColor || "white"`); + doc.color = ComputedField.MakeFunction(`this['${optionsField}'].find(doc => doc.title === this.expandedTemplate.${optionKey}).color || "black"`); + } } Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index a0f21f45e..712f3e76b 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -30,4 +30,8 @@ export class RichTextField extends ObjectField { return this.Text; } + public static DashField(fieldKey:string) { + return new RichTextField(`{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"${fieldKey}","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}`, ""); + } + } \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 8fe2257fc..aaf3a3eb6 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -37,13 +37,19 @@ export class CurrentUserUtils { static setupDefaultDocTemplates(doc: Doc, buttons?: string[]) { const noteTemplates = [ - Docs.Create.TextDocument("", { title: "Note", backgroundColor: "yellow", isTemplateDoc: true }), - Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink", isTemplateDoc: true }), - Docs.Create.TextDocument("", { title: "Topic", backgroundColor: "lightBlue", isTemplateDoc: true }), - Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen", isTemplateDoc: true }), - Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange", isTemplateDoc: true }) + Docs.Create.TextDocument("", { title: "Note", backgroundColor: "yellow" }), + Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink" }), + Docs.Create.TextDocument("", { title: "Topic", backgroundColor: "lightBlue" }), + Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen" }), + Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange" }) ]; - doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates, { title: "Note Types", _height: 75 })); + const modes = [ + Docs.Create.TextDocument("", { title: "todo", _backgroundColor: "blue", color: "white" }), + Docs.Create.TextDocument("", { title: "in progress", _backgroundColor: "yellow", color: "black" }), + Docs.Create.TextDocument("", { title: "completed", _backgroundColor: "green", color: "white" }) + ] + Doc.enumeratedTextTemplate(Doc.GetProto(noteTemplates[4]), FormattedTextBox.LayoutString("Todo"), "Todo", "taskStatus", modes); + doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt) ? nt : nt), { title: "Note Types", _height: 75 })); } // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools -- cgit v1.2.3-70-g09d2 From 9399d2a44261ffce3f33cf1ea2dac032a8d3fdc8 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 25 Feb 2020 02:53:23 -0500 Subject: improved text templates to work better with captions --- src/client/documents/Documents.ts | 3 +-- src/client/util/RichTextSchema.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 23 ++++++++++++++++++++-- src/client/views/nodes/FormattedTextBox.tsx | 12 +++++------ src/new_fields/Doc.ts | 15 +++++++++----- .../authentication/models/current_user_utils.ts | 4 ++-- 6 files changed, 41 insertions(+), 18 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ff152ec6c..6d5fd5677 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -77,7 +77,6 @@ export interface DocumentOptions { _gridGap?: number; // gap between items in masonry view _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts - _textTemplate?: RichTextField; // template used by a formattedTextBox to create a text box to render _itemIndex?: number; // which item index the carousel viewer is showing _showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts x?: number; @@ -911,7 +910,7 @@ export namespace DocUtils { description: "Add Note ...", subitems: DocListCast((Doc.UserDoc().noteTypes as Doc).data).map((note, i) => ({ description: ":" + StrCast(note.title), - event: (args: { x: number, y: number }) => docTextAdder(Docs.Create.TextDocument("", { _width: 200, x, y, _autoHeight: true, layout: note, title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1) })), + event: (args: { x: number, y: number }) => docTextAdder(Docs.Create.TextDocument("", { _width: 200, x, y, _autoHeight: note._autoHeight !== false, layout: note, title: StrCast(note.title) + "#" + (note.aliasCount = NumCast(note.aliasCount) + 1) })), icon: "eye" })) as ContextMenuProps[], icon: "eye" diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index ae3f4e731..626d9d75d 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -807,7 +807,7 @@ export class DashDocView { if (finalLayout !== dashDoc && finalKey) { const finalLayoutField = finalLayout[finalKey]; if (finalLayoutField instanceof ObjectField) { - finalLayout._textTemplate = ComputedField.MakeFunction(`copyField(this.${finalKey})`, { this: Doc.name }); + finalLayout[finalKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${finalKey})`, { this: Doc.name }); } } this._reactionDisposer?.(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index aec18ecbb..3660c327a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -813,6 +813,25 @@ export class DocumentView extends DocComponent(Docu return anchor.type === DocumentType.AUDIO && NumCast(ept) ? false : true; } + // bcz: ARGH! these two are the same as in DocumentContentsView (without the _). They should be reconciled to be the same functions... + get _dataDoc() { + if (this.props.DataDoc === undefined && typeof Doc.LayoutField(this.props.Document) !== "string") { + // if there is no dataDoc (ie, we're not rendering a template layout), but this document has a layout document (not a layout string), + // then we render the layout document as a template and use this document as the data context for the template layout. + const proto = Doc.GetProto(this.props.Document); + return proto instanceof Promise ? undefined : proto; + } + return this.props.DataDoc instanceof Promise ? undefined : this.props.DataDoc; + } + get _layoutDoc() { + if (this.props.LayoutDoc || (this.props.DataDoc === undefined && typeof Doc.LayoutField(this.props.Document) !== "string")) { + // if there is no dataDoc (ie, we're not rendering a template layout), but this document has a layout document (not a layout string), + // then we render the layout document as a template and use this document as the data context for the template layout. + return Doc.expandTemplateLayout(this.props.LayoutDoc?.() || Doc.Layout(this.props.Document), this.props.Document); + } + return Doc.Layout(this.props.Document); + } + @computed get innards() { TraceMobx(); const showTitle = StrCast(this.layoutDoc._showTitle); @@ -825,8 +844,8 @@ export class DocumentView extends DocComponent(Docu
); const captionView = (!showCaption ? (null) :
- diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 5a664f31c..a320cff75 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -186,13 +186,13 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & const tsel = this._editorView.state.selection.$from; tsel.marks().filter(m => m.type === this._editorView!.state.schema.marks.user_mark).map(m => AudioBox.SetScrubTime(Math.max(0, m.attrs.modified * 5000 - 1000))); const curText = state.doc.textBetween(0, state.doc.content.size, "\n\n"); - const curTemp = Cast(this.props.Document._textTemplate, RichTextField); + const curTemp = Cast(this.props.Document[this.props.fieldKey + "-textTemplate"], RichTextField); if (!this._applyingChange) { this._applyingChange = true; this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); if (!curTemp || curText) { // if no template, or there's text, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON()), curText); - this.dataDoc[this.props.fieldKey + "-noTemplate"] = curTemp?.Text !== curText; // mark the data field as being split from the template if it has been edited + this.dataDoc[this.props.fieldKey + "-noTemplate"] = (curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited } else { // if we've deleted all the text in a note driven by a template, then restore the template data this._editorView.updateState(EditorState.fromJSON(this.config, JSON.parse(curTemp.Data))); this.dataDoc[this.props.fieldKey + "-noTemplate"] = undefined; // mark the data field as not being split from any template it might have @@ -504,10 +504,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._reactionDisposer = reaction( () => { - if (this.dataDoc[this.props.fieldKey + "-noTemplate"] || !this.props.Document._textTemplate) { + if (this.dataDoc[this.props.fieldKey + "-noTemplate"] || !this.props.Document[this.props.fieldKey + "-textTemplate"]) { return Cast(this.dataDoc[this.props.fieldKey], RichTextField, null)?.Data; } - return Cast(this.props.Document._textTemplate, RichTextField, null)?.Data; + return Cast(this.props.Document[this.props.fieldKey + "-textTemplate"], RichTextField, null)?.Data; }, incomingValue => { if (incomingValue !== undefined && this._editorView && !this._applyingChange) { @@ -752,8 +752,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & private setupEditor(config: any, fieldKey: string) { const curText = Cast(this.dataDoc[this.props.fieldKey], RichTextField, null); - const useTemplate = !curText?.Text && this.props.Document._textTemplate; - const rtfField = Cast((useTemplate && this.props.Document._textTemplate) || this.dataDoc[fieldKey], RichTextField); + const useTemplate = !curText?.Text && this.props.Document[this.props.fieldKey + "-textTemplate"]; + const rtfField = Cast((useTemplate && this.props.Document[this.props.fieldKey + "-textTemplate"]) || this.dataDoc[fieldKey], RichTextField); if (this.ProseRef) { const self = this; this._editorView?.destroy(); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 10f4309be..8e28a1e00 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -47,7 +47,7 @@ export namespace Field { } else if (field instanceof RefField) { return field[ToString](); } - return "(null)"; + return ""; } export function IsField(field: any): field is Field; export function IsField(field: any, includeUndefined: true): field is Field | undefined; @@ -611,7 +611,8 @@ export namespace Doc { templateField.isTemplateForField = metadataFieldKey; templateField.title = metadataFieldKey; - const templateFieldValue = templateField[metadataFieldKey]; + const templateFieldValue = templateField[metadataFieldKey] || templateField.data; + const templateCaptionValue = templateField.caption; // move any data that the template field had been rendering over to the template doc so that things will still be rendered // when the template field is adjusted to point to the new metadatafield key. // note 1: if the template field contained a list of documents, each of those documents will be converted to templates as well. @@ -620,8 +621,11 @@ export namespace Doc { Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue)); } + if (templateCaptionValue instanceof RichTextField && (templateCaptionValue.Text || templateCaptionValue.Data.toString().includes("dashField"))) { + templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`, { this: Doc.name }); + } if (templateFieldValue instanceof RichTextField && (templateFieldValue.Text || templateFieldValue.Data.toString().includes("dashField"))) { - templateField._textTemplate = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); + templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); } // get the layout string that the template uses to specify its layout @@ -839,8 +843,9 @@ export namespace Doc { return id; } - export function enumeratedTextTemplate(doc: Doc, layoutString: string, dataKey: string, optionKey: string, modes: Doc[]) { - doc[dataKey] = RichTextField.DashField(optionKey); + export function enumeratedTextTemplate(doc: Doc, layoutString: string, captionKey: string, optionKey: string, modes: Doc[]) { + doc.caption = RichTextField.DashField(optionKey); + doc._showCaption = captionKey; doc.layout = layoutString; const optionsField = `${optionKey}_options`; doc[optionsField] = new List(modes); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index aaf3a3eb6..36259f513 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -41,14 +41,14 @@ export class CurrentUserUtils { Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink" }), Docs.Create.TextDocument("", { title: "Topic", backgroundColor: "lightBlue" }), Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen" }), - Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange" }) + Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption" }) ]; const modes = [ Docs.Create.TextDocument("", { title: "todo", _backgroundColor: "blue", color: "white" }), Docs.Create.TextDocument("", { title: "in progress", _backgroundColor: "yellow", color: "black" }), Docs.Create.TextDocument("", { title: "completed", _backgroundColor: "green", color: "white" }) ] - Doc.enumeratedTextTemplate(Doc.GetProto(noteTemplates[4]), FormattedTextBox.LayoutString("Todo"), "Todo", "taskStatus", modes); + Doc.enumeratedTextTemplate(Doc.GetProto(noteTemplates[4]), FormattedTextBox.LayoutString("Todo"), "caption", "taskStatus", modes); doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt) ? nt : nt), { title: "Note Types", _height: 75 })); } -- cgit v1.2.3-70-g09d2 From c5c8c99151de576548dab215b82d44132b06f9a4 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 25 Feb 2020 12:45:33 -0500 Subject: added inheritable computations to template fields --- src/client/util/RichTextSchema.tsx | 27 ++++++++++++++++----------- src/new_fields/ScriptField.ts | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 626d9d75d..cc6b035d7 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -21,6 +21,7 @@ import { DocumentManager } from "./DocumentManager"; import ParagraphNodeSpec from "./ParagraphNodeSpec"; import { Transform } from "./Transform"; import React = require("react"); +import { CollectionSchemaBooleanCell } from "../views/collections/CollectionSchemaCells"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; @@ -869,6 +870,16 @@ export class DashFieldView { this._fieldWrapper.style.position = "relative"; this._fieldWrapper.style.display = "inline-block"; + const onchanged = (e: any) => { + this._reactionDisposer?.(); + let newText = this._fieldSpan.innerText.startsWith(":=") ? ":=-computed-" : this._fieldSpan.innerText; + this._options?.forEach(opt => StrCast(opt.title).startsWith(newText) && (newText = StrCast(opt.title))); + this._dashDoc![this._fieldKey] = newText; + if (newText.startsWith(":=") && this._dashDoc && e.data === null && !e.inputType.includes("delete")) { + Doc.Layout(tbox.props.Document)[this._fieldKey] = ComputedField.MakeFunction(this._fieldSpan.innerText.substring(2)); + } + } + this._fieldSpan = document.createElement("div"); this._fieldSpan.id = Utils.GenerateGuid(); this._fieldSpan.contentEditable = "true"; @@ -876,7 +887,7 @@ export class DashFieldView { this._fieldSpan.style.display = "inline-block"; this._fieldSpan.style.minWidth = "50px"; this._fieldSpan.style.backgroundColor = "rgba(155, 155, 155, 0.24)"; - this._fieldSpan.addEventListener("input", this.onchanged); + this._fieldSpan.addEventListener("input", onchanged); this._fieldSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._fieldSpan.onkeyup = function (e: any) { e.stopPropagation(); }; this._fieldSpan.onmousedown = function (e: any) { e.stopPropagation(); }; @@ -913,21 +924,15 @@ export class DashFieldView { setDashDoc(tbox.props.DataDoc || tbox.dataDoc); } this._reactionDisposer?.(); - this._reactionDisposer = reaction(() => this._dashDoc?.[node.attrs.fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)", { fireImmediately: true }); + this._reactionDisposer = reaction(() => { + const dashVal = this._dashDoc?.[node.attrs.fieldKey]; + return StrCast(dashVal).startsWith(":=") || !dashVal ? Doc.Layout(tbox.props.Document)[this._fieldKey] : dashVal; + }, fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)", { fireImmediately: true }); this._fieldWrapper.appendChild(this._labelSpan); this._fieldWrapper.appendChild(this._fieldSpan); (this as any).dom = this._fieldWrapper; } - onchanged = () => { - this._reactionDisposer?.(); - - let newText = this._fieldSpan.innerText; - this._options?.forEach(opt => StrCast(opt.title).startsWith(newText) && (newText = StrCast(opt.title))); - this._dashDoc![this._fieldKey] = newText; - this._reactionDisposer = reaction(() => this._dashDoc?.[this._fieldKey], fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)"); - - } destroy() { this._reactionDisposer?.(); } diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 4c78ea3aa..131e1f339 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -130,7 +130,7 @@ export class ScriptField extends ObjectField { export class ComputedField extends ScriptField { _lastComputedResult: any; //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc - value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ this: doc, _last_: this._lastComputedResult }, console.log).result); + value = computedFn((doc: Doc) => this._lastComputedResult = this.script.run({ source: doc.expandedTemplate || doc, this: doc, _last_: this._lastComputedResult }, console.log).result); public static MakeScript(script: string, params: object = {}) { const compiled = ScriptField.CompileScript(script, params, false); return compiled.compiled ? new ComputedField(compiled) : undefined; -- cgit v1.2.3-70-g09d2 From dfeaa7b032376bc4001fcfdc197016ff1f09ebdf Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 25 Feb 2020 13:37:00 -0500 Subject: added 'source' parameter for computedField functions -- its the source document as opposed to 'this' which is the layout template) --- src/new_fields/ScriptField.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/new_fields') diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index 131e1f339..9288fea9e 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -106,7 +106,7 @@ export class ScriptField extends ObjectField { } public static CompileScript(script: string, params: object = {}, addReturn = false, capturedVariables?: { [name: string]: Field }) { const compiled = CompileScript(script, { - params: { this: Doc.name, _last_: "any", ...params }, + params: { this: Doc.name, source: Doc.name, _last_: "any", ...params }, typecheck: false, editable: true, addReturn: addReturn, -- cgit v1.2.3-70-g09d2 From 3c48667061fb417e3a7657a1951659d25b453a9f Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 27 Feb 2020 15:10:14 -0500 Subject: streamlined setting enumerations for fields in text boxes. --- src/client/documents/Documents.ts | 8 ++-- src/client/util/RichTextSchema.tsx | 47 +++++++++++++++------- .../views/collections/CollectionTimeView.scss | 4 +- src/new_fields/Doc.ts | 32 +++++++++++---- .../authentication/models/current_user_utils.ts | 15 +++---- 5 files changed, 73 insertions(+), 33 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6d5fd5677..a0b8a6382 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -622,12 +622,12 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, _viewType: CollectionViewType.Schema }); } - export function TreeDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Tree }); + export function TreeDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Tree }, id); } - export function StackingDocument(documents: Array, options: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Stacking }); + export function StackingDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Stacking }, id); } export function MulticolumnDocument(documents: Array, options: DocumentOptions) { diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index cc6b035d7..a56aac9b1 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -22,6 +22,10 @@ import ParagraphNodeSpec from "./ParagraphNodeSpec"; import { Transform } from "./Transform"; import React = require("react"); import { CollectionSchemaBooleanCell } from "../views/collections/CollectionSchemaCells"; +import { ContextMenu } from "../views/ContextMenu"; +import { ContextMenuProps } from "../views/ContextMenuItem"; +import { Docs } from "../documents/Documents"; +import { CollectionView } from "../views/collections/CollectionView"; const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; @@ -863,23 +867,13 @@ export class DashFieldView { constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) { this._fieldKey = node.attrs.fieldKey; this._textBoxDoc = tbox.props.Document; - this._options = DocListCast(tbox.props.Document[node.attrs.fieldKey + "_options"]); this._fieldWrapper = document.createElement("div"); this._fieldWrapper.style.width = node.attrs.width; this._fieldWrapper.style.height = node.attrs.height; this._fieldWrapper.style.position = "relative"; this._fieldWrapper.style.display = "inline-block"; - const onchanged = (e: any) => { - this._reactionDisposer?.(); - let newText = this._fieldSpan.innerText.startsWith(":=") ? ":=-computed-" : this._fieldSpan.innerText; - this._options?.forEach(opt => StrCast(opt.title).startsWith(newText) && (newText = StrCast(opt.title))); - this._dashDoc![this._fieldKey] = newText; - if (newText.startsWith(":=") && this._dashDoc && e.data === null && !e.inputType.includes("delete")) { - Doc.Layout(tbox.props.Document)[this._fieldKey] = ComputedField.MakeFunction(this._fieldSpan.innerText.substring(2)); - } - } - + const self = this; this._fieldSpan = document.createElement("div"); this._fieldSpan.id = Utils.GenerateGuid(); this._fieldSpan.contentEditable = "true"; @@ -887,12 +881,18 @@ export class DashFieldView { this._fieldSpan.style.display = "inline-block"; this._fieldSpan.style.minWidth = "50px"; this._fieldSpan.style.backgroundColor = "rgba(155, 155, 155, 0.24)"; - this._fieldSpan.addEventListener("input", onchanged); this._fieldSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._fieldSpan.onkeyup = function (e: any) { e.stopPropagation(); }; this._fieldSpan.onmousedown = function (e: any) { e.stopPropagation(); }; + this._fieldSpan.oncontextmenu = function (e: any) { + ContextMenu.Instance.addItem({ + description: "Show Enumeration Templates", event: () => { + e.stopPropagation(); + DocServer.GetRefField(node.attrs.fieldKey).then(collview => collview instanceof Doc && tbox.props.addDocTab(collview, "onRight")); + }, icon: "expand-arrows-alt" + }); + }; - const self = this; const setDashDoc = (doc: Doc) => { self._dashDoc = doc; if (this._dashDoc && self._options?.length && !this._dashDoc[node.attrs.fieldKey]) { @@ -910,6 +910,25 @@ export class DashFieldView { } e.preventDefault(); } + if (e.key === "Enter" && e.ctrlKey) { + Doc.addEnumerationToTextField(self._textBoxDoc, node.attrs.fieldKey, [Docs.Create.TextDocument(self._fieldSpan.innerText, { title: self._fieldSpan.innerText })]); + e.preventDefault(); + } else if (e.key === "Enter") { + e.preventDefault(); + let newText = self._fieldSpan.innerText.startsWith(":=") ? ":=-computed-" : self._fieldSpan.innerText; + // look for a document whose id === the fieldKey being displayed. If there's a match, then that document + // holds the different enumerated values for the field in the titles of its collected documents. + // if there's a partial match from the start of the input text, complete the text --- TODO: make this an auto suggest box and select from a drop down. + + // alternatively, if the text starts with a ':=' then treat it as an expression by making a computed field from its value storing it in the key + DocServer.GetRefField(node.attrs.fieldKey).then(options => { + (options instanceof Doc) && DocListCast(options.data).forEach(opt => StrCast(opt.title).startsWith(newText) && (newText = StrCast(opt.title))); + self._fieldSpan.innerHTML = self._dashDoc![self._fieldKey] = newText; + if (newText.startsWith(":=") && self._dashDoc && e.data === null && !e.inputType.includes("delete")) { + Doc.Layout(tbox.props.Document)[self._fieldKey] = ComputedField.MakeFunction(self._fieldSpan.innerText.substring(2)); + } + }); + } }; this._labelSpan = document.createElement("span"); @@ -924,7 +943,7 @@ export class DashFieldView { setDashDoc(tbox.props.DataDoc || tbox.dataDoc); } this._reactionDisposer?.(); - this._reactionDisposer = reaction(() => { + this._reactionDisposer = reaction(() => { // this reaction will update the displayed text whenever the document's fieldKey's value changes const dashVal = this._dashDoc?.[node.attrs.fieldKey]; return StrCast(dashVal).startsWith(":=") || !dashVal ? Doc.Layout(tbox.props.Document)[this._fieldKey] : dashVal; }, fval => this._fieldSpan.innerHTML = Field.toString(fval as Field) || "(null)", { fireImmediately: true }); diff --git a/src/client/views/collections/CollectionTimeView.scss b/src/client/views/collections/CollectionTimeView.scss index 6ea5e6908..865fc3cd2 100644 --- a/src/client/views/collections/CollectionTimeView.scss +++ b/src/client/views/collections/CollectionTimeView.scss @@ -10,7 +10,6 @@ .collectionTimeView-backBtn { background: green; display: inline; - margin-right: 20px; } .collectionFreeform-customText { @@ -68,6 +67,9 @@ padding: 5px; border: 1px solid black; display:none; + span { + margin-left : 10px; + } } .collectionTimeView-treeView { diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 8e28a1e00..8ea347ec3 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -17,6 +17,7 @@ import { listSpec } from "./Schema"; import { ComputedField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; +import { Docs } from "../client/documents/Documents"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -571,7 +572,7 @@ export namespace Doc { export function ApplyTemplate(templateDoc: Doc) { if (templateDoc) { const applied = ApplyTemplateTo(templateDoc, Doc.MakeDelegate(new Doc()), "layout", templateDoc.title + "(..." + _applyCount++ + ")"); - applied && (Doc.GetProto(applied).layout = applied.layout); + applied && (Doc.GetProto(applied).type = templateDoc.type); return applied; } return undefined; @@ -843,14 +844,31 @@ export namespace Doc { return id; } - export function enumeratedTextTemplate(doc: Doc, layoutString: string, captionKey: string, optionKey: string, modes: Doc[]) { - doc.caption = RichTextField.DashField(optionKey); + // setup a document to use enumerated values for a specified field name: + // doc: text document + // layoutString: species which text field receives the document's main text (e.g., FormattedTextBox.LayoutString("Todo") ) + // enumeratedFieldKey : specifies which enumerated field of the document is displayed in the caption (e.g., taskStatus) + // captionKey: specifies which field holds the caption template (e.g., caption) -- ideally this wouldn't be needed but would be derived from the layoutString's target field key + // + export function enumeratedTextTemplate(doc: Doc, layoutString: string, enumeratedFieldKey: string, enumeratedDocs: Doc[], captionKey: string = "caption") { + doc.caption = RichTextField.DashField(enumeratedFieldKey); doc._showCaption = captionKey; doc.layout = layoutString; - const optionsField = `${optionKey}_options`; - doc[optionsField] = new List(modes); - doc.backgroundColor = ComputedField.MakeFunction(`this['${optionsField}'].find(doc => doc.title === this.expandedTemplate.${optionKey})?._backgroundColor || "white"`); - doc.color = ComputedField.MakeFunction(`this['${optionsField}'].find(doc => doc.title === this.expandedTemplate.${optionKey}).color || "black"`); + + Doc.addEnumerationToTextField(doc, enumeratedFieldKey, enumeratedDocs); + } + + export function addEnumerationToTextField(doc: Doc, enumeratedFieldKey: string, enumeratedDocs: Doc[]) { + DocServer.GetRefField(enumeratedFieldKey).then(optionsCollection => { + if (!(optionsCollection instanceof Doc)) { + optionsCollection = Docs.Create.StackingDocument([], { title: `${enumeratedFieldKey} field set` }, enumeratedFieldKey); + Doc.AddDocToList((Doc.UserDoc().fieldTypes as Doc), "data", optionsCollection as Doc); + } + const options = optionsCollection as Doc; + doc.backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options }); + doc.color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options }); + enumeratedDocs.map(enumeratedDoc => !DocListCast(options.data).find(d => d.title === enumeratedDoc.title) && Doc.AddDocToList(options, "data", enumeratedDoc)); + }); } } diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 36259f513..ea19d9da8 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -36,6 +36,11 @@ export class CurrentUserUtils { @observable public static GuestMobile: Doc | undefined; static setupDefaultDocTemplates(doc: Doc, buttons?: string[]) { + const taskStatusValues = [ + Docs.Create.TextDocument("todo", { title: "todo", _backgroundColor: "blue", color: "white" }), + Docs.Create.TextDocument("in progress", { title: "in progress", _backgroundColor: "yellow", color: "black" }), + Docs.Create.TextDocument("completed", { title: "completed", _backgroundColor: "green", color: "white" }) + ]; const noteTemplates = [ Docs.Create.TextDocument("", { title: "Note", backgroundColor: "yellow" }), Docs.Create.TextDocument("", { title: "Idea", backgroundColor: "pink" }), @@ -43,12 +48,8 @@ export class CurrentUserUtils { Docs.Create.TextDocument("", { title: "Person", backgroundColor: "lightGreen" }), Docs.Create.TextDocument("", { title: "Todo", backgroundColor: "orange", _autoHeight: false, _height: 100, _showCaption: "caption" }) ]; - const modes = [ - Docs.Create.TextDocument("", { title: "todo", _backgroundColor: "blue", color: "white" }), - Docs.Create.TextDocument("", { title: "in progress", _backgroundColor: "yellow", color: "black" }), - Docs.Create.TextDocument("", { title: "completed", _backgroundColor: "green", color: "white" }) - ] - Doc.enumeratedTextTemplate(Doc.GetProto(noteTemplates[4]), FormattedTextBox.LayoutString("Todo"), "caption", "taskStatus", modes); + doc.fieldTypes = Docs.Create.TreeDocument([], { title: "field enumerations" }); + Doc.enumeratedTextTemplate(Doc.GetProto(noteTemplates[4]), FormattedTextBox.LayoutString("Todo"), "taskStatus", taskStatusValues); doc.noteTypes = new PrefetchProxy(Docs.Create.TreeDocument(noteTemplates.map(nt => makeTemplate(nt) ? nt : nt), { title: "Note Types", _height: 75 })); } @@ -196,7 +197,7 @@ export class CurrentUserUtils { return Docs.Create.ButtonDocument({ _width: 50, _height: 25, title: "Library", fontSize: 10, letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", - sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc.recentlyClosed as Doc], { + sourcePanel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, Docs.Prototypes.MainLinkDocument(), doc, doc.recentlyClosed as Doc], { title: "Library", _xMargin: 5, _yMargin: 5, _gridGap: 5, forceActive: true, dropAction: "alias", lockedPosition: true, boxShadow: "0 0", }), targetContainer: sidebarContainer, -- cgit v1.2.3-70-g09d2 From 8190b6557065828e3a5e7a6505c0963a433e27d1 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 27 Feb 2020 17:05:39 -0500 Subject: adding colors to schema view will update the enumerated colors used by text boxes in freeformview. --- .../views/collections/CollectionStackingView.tsx | 5 ++++- .../CollectionStackingViewFieldColumn.tsx | 4 ++-- src/client/views/nodes/PresBox.tsx | 2 -- src/client/views/pdf/Annotation.tsx | 2 +- src/new_fields/Doc.ts | 20 ++++++++++++++++---- 5 files changed, 23 insertions(+), 10 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index a1cc21319..4495e8248 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -24,6 +24,7 @@ import "./CollectionStackingView.scss"; import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewFieldColumn"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionViewType } from "./CollectionView"; +import { Docs } from "../../documents/Documents"; @observer export class CollectionStackingView extends CollectionSubView(doc => doc) { @@ -348,7 +349,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { @action addGroup = (value: string) => { if (value && this.sectionHeaders) { - this.sectionHeaders.push(new SchemaHeaderField(value)); + const schemaHdrField = new SchemaHeaderField(value); + this.sectionHeaders.push(schemaHdrField); + Doc.addEnumerationToTextField(undefined, this.sectionFilter, [Docs.Create.TextDocument(value, { title: value, _backgroundColor: schemaHdrField.color })]); return true; } return false; diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 8c23ecd49..058733cc9 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -68,10 +68,10 @@ export class CollectionStackingViewFieldColumn extends React.Component d[key] = castedValue); + de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, false)); } else { - de.complete.docDragData.droppedDocuments.forEach(d => d[key] = undefined); + de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, undefined, false)); } this.props.parent.onInternalDrop(e, de); e.stopPropagation(); diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 791ed5ef1..4180ee255 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -10,7 +10,6 @@ import { listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { returnFalse } from "../../../Utils"; -import { Docs } from "../../documents/Documents"; import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import { CollectionDockingView } from "../collections/CollectionDockingView"; @@ -20,7 +19,6 @@ import { ContextMenuProps } from "../ContextMenuItem"; import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; -import { PrefetchProxy } from "../../../new_fields/Proxy"; library.add(faArrowLeft); library.add(faArrowRight); diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index 58823c93d..d23c81065 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -1,7 +1,7 @@ import React = require("react"); import { action, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, WidthSym, Opt, DocListCastAsync } from "../../../new_fields/Doc"; +import { Doc, DocListCast, HeightSym, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 8ea347ec3..d364bfe28 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -858,16 +858,28 @@ export namespace Doc { Doc.addEnumerationToTextField(doc, enumeratedFieldKey, enumeratedDocs); } - export function addEnumerationToTextField(doc: Doc, enumeratedFieldKey: string, enumeratedDocs: Doc[]) { + export async function getEnumerationTextField(enumeratedFieldKey: string) { + return (await DocServer.GetRefField(enumeratedFieldKey)) as Doc; + } + + export function addEnumerationToTextField(doc: Opt, enumeratedFieldKey: string, enumeratedDocs: Doc[]) { DocServer.GetRefField(enumeratedFieldKey).then(optionsCollection => { if (!(optionsCollection instanceof Doc)) { optionsCollection = Docs.Create.StackingDocument([], { title: `${enumeratedFieldKey} field set` }, enumeratedFieldKey); Doc.AddDocToList((Doc.UserDoc().fieldTypes as Doc), "data", optionsCollection as Doc); } const options = optionsCollection as Doc; - doc.backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options }); - doc.color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options }); - enumeratedDocs.map(enumeratedDoc => !DocListCast(options.data).find(d => d.title === enumeratedDoc.title) && Doc.AddDocToList(options, "data", enumeratedDoc)); + doc && (doc.backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options })); + doc && (doc.color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options })); + enumeratedDocs.map(enumeratedDoc => { + const found = DocListCast(options.data).find(d => d.title === enumeratedDoc.title); + if (found) { + found._backgroundColor = enumeratedDoc._backgroundColor || found._backgroundColor; + found._color = enumeratedDoc._color || found._color; + } else { + Doc.AddDocToList(options, "data", enumeratedDoc); + } + }); }); } } -- cgit v1.2.3-70-g09d2 From 44a521a2b333913ee83bd325b84d1dbd03339398 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 27 Feb 2020 22:05:12 -0500 Subject: schema view & Stacking view code cleanup and minor ui fixes --- .../views/collections/CollectionSchemaView.tsx | 43 ++--------- .../views/collections/CollectionStackingView.scss | 18 ++++- .../views/collections/CollectionStackingView.tsx | 30 +++----- .../CollectionStackingViewFieldColumn.tsx | 89 ++++++---------------- src/new_fields/Doc.ts | 4 +- 5 files changed, 58 insertions(+), 126 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9486d195a..6eeceb552 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -28,6 +28,7 @@ import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { CollectionView } from "./CollectionView"; import { ContentFittingDocumentView } from "../nodes/ContentFittingDocumentView"; +import { setupMoveUpEvents, emptyFunction } from "../../../Utils"; library.add(faCog, faPlus, faSortUp, faSortDown); library.add(faTable); @@ -43,8 +44,8 @@ export enum ColumnType { // this map should be used for keys that should have a const type of value const columnTypes: Map = new Map([ ["title", ColumnType.String], - ["x", ColumnType.Number], ["y", ColumnType.Number], ["width", ColumnType.Number], ["height", ColumnType.Number], - ["nativeWidth", ColumnType.Number], ["nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean], + ["x", ColumnType.Number], ["y", ColumnType.Number], ["_width", ColumnType.Number], ["_height", ColumnType.Number], + ["_nativeWidth", ColumnType.Number], ["_nativeHeight", ColumnType.Number], ["isPrototype", ColumnType.Boolean], ["page", ColumnType.Number], ["curPage", ColumnType.Number], ["currentTimecode", ColumnType.Number], ["zIndex", ColumnType.Number] ]); @@ -54,9 +55,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { private _startPreviewWidth = 0; private DIVIDER_WIDTH = 4; - @observable previewScript: string = ""; @observable previewDoc: Doc | undefined = undefined; - @observable private _node: HTMLDivElement | null = null; @observable private _focusedTable: Doc = this.props.Document; @computed get previewWidth() { return () => NumCast(this.props.Document.schemaPreviewWidth); } @@ -75,9 +74,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action setPreviewDoc = (doc: Doc) => this.previewDoc = doc; - @undoBatch - @action setPreviewScript = (script: string) => this.previewScript = script - //toggles preview side-panel of schema @action toggleExpander = () => { @@ -86,27 +82,17 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { onDividerDown = (e: React.PointerEvent) => { this._startPreviewWidth = this.previewWidth(); - e.stopPropagation(); - e.preventDefault(); - document.addEventListener("pointermove", this.onDividerMove); - document.addEventListener('pointerup', this.onDividerUp); + setupMoveUpEvents(this, e, this.onDividerMove, emptyFunction, action(() => this.toggleExpander())); } @action - onDividerMove = (e: PointerEvent): void => { + onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => { const nativeWidth = this._mainCont!.getBoundingClientRect(); const minWidth = 40; const maxWidth = 1000; const movedWidth = this.props.ScreenToLocalTransform().transformDirection(nativeWidth.right - e.clientX, 0)[0]; const width = movedWidth < minWidth ? minWidth : movedWidth > maxWidth ? maxWidth : movedWidth; this.props.Document.schemaPreviewWidth = width; - } - @action - onDividerUp = (e: PointerEvent): void => { - document.removeEventListener("pointermove", this.onDividerMove); - document.removeEventListener('pointerup', this.onDividerUp); - if (this._startPreviewWidth === this.previewWidth()) { - this.toggleExpander(); - } + return false; } onPointerDown = (e: React.PointerEvent): void => { @@ -119,9 +105,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } @computed - get previewDocument(): Doc | undefined { - return this.previewDoc ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(this.previewDoc[this.previewScript], Doc)) : this.previewDoc) : undefined; - } + get previewDocument(): Doc | undefined { return this.previewDoc; } getPreviewTransform = (): Transform => { return this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this.tableWidth, - this.borderWidth); @@ -477,8 +461,7 @@ export class SchemaTable extends React.Component { @undoBatch createRow = () => { - const newDoc = Docs.Create.TextDocument("", { title: "", _width: 100, _height: 30 }); - this.props.addDocument(newDoc); + this.props.addDocument(Docs.Create.TextDocument("", { title: "", _width: 100, _height: 30 })); } @undoBatch @@ -559,16 +542,6 @@ export class SchemaTable extends React.Component { columns[index] = columnField; this.columns = columns; } - - // const typesDoc = FieldValue(Cast(this.props.Document.schemaColumnTypes, Doc)); - // if (!typesDoc) { - // let newTypesDoc = new Doc(); - // newTypesDoc[key] = type; - // this.props.Document.schemaColumnTypes = newTypesDoc; - // return; - // } else { - // typesDoc[key] = type; - // } } @undoBatch diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 293dc5414..8e3919532 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -160,9 +160,7 @@ } .collectionStackingView-sectionHeader { text-align: center; - margin-left: 2px; - margin-right: 2px; - margin-top: 10px; + margin: auto; background: $main-accent; // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong @@ -214,6 +212,7 @@ left: 0; top: 0; height: 100%; + display: none; [class*="css"] { max-width: 102px; @@ -251,6 +250,7 @@ right: 0; top: 0; height: 100%; + display: none; [class*="css"] { max-width: 102px; @@ -285,6 +285,18 @@ right: 25px; top: 0; height: 100%; + display: none; + } + } + .collectionStackingView-sectionHeader:hover { + .collectionStackingView-sectionColor { + display:unset; + } + .collectionStackingView-sectionOptions { + display:unset; + } + .collectionStackingView-sectionDelete { + display:unset; } } diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 4495e8248..d1f45af90 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -11,7 +11,7 @@ import { listSpec } from "../../../new_fields/Schema"; import { SchemaHeaderField } from "../../../new_fields/SchemaHeaderField"; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../new_fields/Types"; import { TraceMobx } from "../../../new_fields/util"; -import { Utils } from "../../../Utils"; +import { Utils, setupMoveUpEvents, emptyFunction } from "../../../Utils"; import { DragManager } from "../../util/DragManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; @@ -61,7 +61,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const dxf = () => this.getDocTransform(d, dref.current!); this._docXfs.push({ dxf: dxf, width: width, height: height }); const rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); - const style = this.isStackingView ? { width: width(), marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; + const style = this.isStackingView ? { width: width(), marginTop: this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return
{this.getDisplayDoc(d, this.props.DataDoc, dxf, width)}
; @@ -79,8 +79,9 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { setTimeout(() => this.props.Document.sectionHeaders = new List(), 0); return new Map(); } - const sectionHeaders = this.sectionHeaders; + const sectionHeaders: SchemaHeaderField[] = Array.from(this.sectionHeaders); const fields = new Map(sectionHeaders.map(sh => [sh, []] as [SchemaHeaderField, []])); + let changed = false; this.filteredChildren.map(d => { const sectionValue = (d[this.sectionFilter] ? d[this.sectionFilter] : `NO ${this.sectionFilter.toUpperCase()} VALUE`) as object; // the next five lines ensures that floating point rounding errors don't create more than one section -syip @@ -96,8 +97,10 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { const newSchemaHeader = new SchemaHeaderField(castedSectionValue ? castedSectionValue.toString() : `NO ${this.sectionFilter.toUpperCase()} VALUE`); fields.set(newSchemaHeader, [d]); sectionHeaders.push(newSchemaHeader); + changed = true; } }); + changed && setTimeout(action(() => { if (this.sectionHeaders) { this.sectionHeaders.length = 0; this.sectionHeaders.push(...sectionHeaders); } }), 0); return fields; } @@ -204,26 +207,13 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } columnDividerDown = (e: React.PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); runInAction(() => this._cursor = "grabbing"); - document.addEventListener("pointermove", this.onDividerMove); - document.addEventListener('pointerup', this.onDividerUp); - this._columnStart = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; + setupMoveUpEvents(this, e, this.onDividerMove, action(() => this._cursor = "grab"), emptyFunction); } @action - onDividerMove = (e: PointerEvent): void => { - const dragPos = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0]; - const delta = dragPos - this._columnStart; - this._columnStart = dragPos; - this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta); - } - - @action - onDividerUp = (e: PointerEvent): void => { - runInAction(() => this._cursor = "grab"); - document.removeEventListener("pointermove", this.onDividerMove); - document.removeEventListener('pointerup', this.onDividerUp); + onDividerMove = (e: PointerEvent, down: number[], delta: number[]) => { + this.layoutDoc.columnWidth = Math.max(10, this.columnWidth + delta[0]); + return false; } @computed get columnDragger() { diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx index 058733cc9..17011698f 100644 --- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx +++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx @@ -20,7 +20,10 @@ import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { EditableView } from "../EditableView"; import { CollectionStackingView } from "./CollectionStackingView"; +import { setupMoveUpEvents, emptyFunction } from "../../../Utils"; import "./CollectionStackingView.scss"; +import { listSpec } from "../../../new_fields/Schema"; +import { Schema } from "prosemirror-model"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -42,20 +45,15 @@ interface CSVFieldColumnProps { @observer export class CollectionStackingViewFieldColumn extends React.Component { @observable private _background = "inherit"; - @observable private _createAliasSelected: boolean = false; - private _dropRef: HTMLDivElement | null = null; private dropDisposer?: DragManager.DragDropDisposer; private _headerRef: React.RefObject = React.createRef(); - private _startDragPosition: { x: number, y: number } = { x: 0, y: 0 }; - private _sensitivity: number = 16; @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; createColumnDropRef = (ele: HTMLDivElement | null) => { - this._dropRef = ele; - this.dropDisposer && this.dropDisposer(); + this.dropDisposer?.(); if (ele) { this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this)); } @@ -63,16 +61,10 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = false; if (de.complete.docDragData) { const key = StrCast(this.props.parent.props.Document.sectionFilter); const castedValue = this.getValue(this._heading); - if (castedValue) { - de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, false)); - } - else { - de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, undefined, false)); - } + de.complete.docDragData.droppedDocuments.forEach(d => Doc.SetInPlace(d, key, castedValue, false)); this.props.parent.onInternalDrop(e, de); e.stopPropagation(); } @@ -93,7 +85,6 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document.sectionFilter); const castedValue = this.getValue(value); if (castedValue) { @@ -114,7 +105,6 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = false; if (this.props.headingObject) { this.props.headingObject.setColor(color); this._color = color; @@ -124,22 +114,18 @@ export class CollectionStackingViewFieldColumn extends React.Component { if (SelectionManager.GetIsDragging()) { - this._createAliasSelected = false; this._background = "#b4b4b4"; } } @action pointerLeave = () => { - this._createAliasSelected = false; this._background = "inherit"; - document.removeEventListener("pointermove", this.startDrag); } @action addDocument = (value: string, shiftDown?: boolean) => { if (!value) return false; - this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document.sectionFilter); const newDoc = Docs.Create.TextDocument(value, { _height: 18, _width: 200, title: value, _autoHeight: true }); newDoc[key] = this.getValue(this.props.heading); @@ -151,7 +137,6 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = false; const key = StrCast(this.props.parent.props.Document.sectionFilter); this.props.docList.forEach(d => d[key] = undefined); if (this.props.parent.sectionHeaders && this.props.headingObject) { @@ -162,7 +147,6 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = false; if (this.props.headingObject) { this._headingsHack++; this.props.headingObject.setCollapsed(!this.props.headingObject.collapsed); @@ -170,46 +154,23 @@ export class CollectionStackingViewFieldColumn extends React.Component { - const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX - this._startDragPosition.x, e.clientY - this._startDragPosition.y); - if (Math.abs(dx) + Math.abs(dy) > this._sensitivity) { - const alias = Doc.MakeAlias(this.props.parent.props.Document); - const key = StrCast(this.props.parent.props.Document.sectionFilter); - let value = this.getValue(this._heading); - value = typeof value === "string" ? `"${value}"` : value; - alias.viewSpecScript = ScriptField.MakeFunction(`doc.${key} === ${value}`, { doc: Doc.name }); - if (alias.viewSpecScript) { - DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); - } - - e.stopPropagation(); - document.removeEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); - } - } - - pointerUp = (e: PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - - document.removeEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); - } - headerDown = (e: React.PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - - const [dx, dy] = this.props.screenToLocalTransform().transformDirection(e.clientX, e.clientY); - this._startDragPosition = { x: dx, y: dy }; + setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); + } - if (this._createAliasSelected) { - document.removeEventListener("pointermove", this.startDrag); - document.addEventListener("pointermove", this.startDrag); - document.removeEventListener("pointerup", this.pointerUp); - document.addEventListener("pointerup", this.pointerUp); + startDrag = (e: PointerEvent, down: number[], delta: number[]) => { + const alias = Doc.MakeAlias(this.props.parent.props.Document); + alias._width = this.props.parent.props.PanelWidth() / (Cast(this.props.parent.props.Document.schemaColumns, listSpec(SchemaHeaderField))?.length || 1); + alias.sectionFilter = undefined; + const key = StrCast(this.props.parent.props.Document.sectionFilter); + let value = this.getValue(this._heading); + value = typeof value === "string" ? `"${value}"` : value; + alias.viewSpecScript = ScriptField.MakeFunction(`doc.${key} === ${value}`, { doc: Doc.name }); + if (alias.viewSpecScript) { + DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY); + return true; } - runInAction(() => this._createAliasSelected = false); + return false; } renderColorPicker = () => { @@ -242,17 +203,11 @@ export class CollectionStackingViewFieldColumn extends React.Component { - this._createAliasSelected = true; - } - renderMenu = () => { - const selected = this._createAliasSelected; return (
-
Create Alias
+
{ })}>Add options here
); @@ -328,6 +283,7 @@ export class CollectionStackingViewFieldColumn extends React.Component headings.indexOf(i) === idx); const evContents = heading ? heading : this.props.type && this.props.type === "number" ? "0" : `NO ${key.toUpperCase()} VALUE`; const headerEditableViewProps = { @@ -352,6 +308,7 @@ export class CollectionStackingViewFieldColumn extends React.Component
doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options })); - doc && (doc.color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options })); + doc && (Doc.GetProto(doc).backgroundColor = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey})?._backgroundColor || "white"`, undefined, { options })); + doc && (Doc.GetProto(doc).color = ComputedField.MakeFunction(`options.data.find(doc => doc.title === (this.expandedTemplate||this).${enumeratedFieldKey}).color || "black"`, undefined, { options })); enumeratedDocs.map(enumeratedDoc => { const found = DocListCast(options.data).find(d => d.title === enumeratedDoc.title); if (found) { -- cgit v1.2.3-70-g09d2 From 5c139f0001cd10e5699a716c1e64d2c2c0b2d800 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 28 Feb 2020 12:17:03 -0500 Subject: allowing different text templates to be the default. fixing transparency. removing audio by default from notes. --- src/client/documents/Documents.ts | 5 +++- src/client/util/Import & Export/ImageUtils.ts | 2 +- src/client/util/RichTextSchema.tsx | 8 ++--- src/client/views/InkingControl.tsx | 3 +- src/client/views/TemplateMenu.tsx | 5 ++++ .../collectionFreeForm/CollectionFreeFormView.tsx | 4 +-- .../collections/collectionFreeForm/MarqueeView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 6 ++-- src/client/views/nodes/FormattedTextBox.scss | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 34 +++++++++++++--------- src/client/views/nodes/ImageBox.tsx | 19 ++++++------ src/new_fields/documentSchemas.ts | 13 +++++---- 12 files changed, 63 insertions(+), 41 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a0b8a6382..aab44f668 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -77,6 +77,8 @@ export interface DocumentOptions { _gridGap?: number; // gap between items in masonry view _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts + _xPadding?: number; + _yPadding?: number; _itemIndex?: number; // which item index the carousel viewer is showing _showSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts x?: number; @@ -174,7 +176,7 @@ export namespace Docs { const TemplateMap: TemplateMap = new Map([ [DocumentType.TEXT, { layout: { view: FormattedTextBox, dataField: data }, - options: { _height: 150 } + options: { _height: 150, _xMargin: 10, _yMargin: 10 } }], [DocumentType.HIST, { layout: { view: HistogramBox, dataField: data }, @@ -407,6 +409,7 @@ export namespace Docs { const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "dropAction", "childDropAction", "_annotationOn", "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_showSidebar", "_showTitle", "_showCaption", "_showTitleHover", "_backgroundColor", + "_xMargin", "_yMargin", "_xPadding", "_yPadding", "_color", "isButton", "isBackground", "removeDropProperties", "treeViewOpen"]; /** diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index ff909cc6b..ab8c73d15 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -24,7 +24,7 @@ export namespace ImageUtils { const proto = Doc.GetProto(document); proto["data-nativeWidth"] = nativeWidth; proto["data-nativeHeight"] = nativeHeight; - proto.contentSize = contentSize; + proto.contentSize = contentSize ? contentSize : undefined; return data !== undefined; }; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index a56aac9b1..4a80a1af8 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -910,11 +910,11 @@ export class DashFieldView { } e.preventDefault(); } - if (e.key === "Enter" && e.ctrlKey) { - Doc.addEnumerationToTextField(self._textBoxDoc, node.attrs.fieldKey, [Docs.Create.TextDocument(self._fieldSpan.innerText, { title: self._fieldSpan.innerText })]); - e.preventDefault(); - } else if (e.key === "Enter") { + if (e.key === "Enter") { e.preventDefault(); + if (e.ctrlKey) { + Doc.addEnumerationToTextField(self._textBoxDoc, node.attrs.fieldKey, [Docs.Create.TextDocument(self._fieldSpan.innerText, { title: self._fieldSpan.innerText })]); + } let newText = self._fieldSpan.innerText.startsWith(":=") ? ":=-computed-" : self._fieldSpan.innerText; // look for a document whose id === the fieldKey being displayed. If there's a match, then that document // holds the different enumerated values for the field in the titles of its collected documents. diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 374c2df27..5cd3c265d 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -29,8 +29,7 @@ export class InkingControl { if (number < 0) { number = 0xFFFFFFFF + number + 1; } - - return number.toString(16).toUpperCase(); + return (number < 16 ? "0" : "") + number.toString(16).toUpperCase(); } @undoBatch diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 595c3817e..5029b4074 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -61,6 +61,10 @@ export class TemplateMenu extends React.Component { DocumentView.FloatDoc(topDocView, ex, ey); } + toggleAudio = (e: React.ChangeEvent): void => { + this.props.docViews.map(dv => dv.props.Document._showAudio = e.target.checked); + } + @undoBatch @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { @@ -102,6 +106,7 @@ export class TemplateMenu extends React.Component { const templateMenu: Array = []; this.props.templates.forEach((checked, template) => templateMenu.push()); + templateMenu.push(); templateMenu.push(); templateMenu.push(); this._addedKeys && Array.from(this._addedKeys).map(layout => diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 4458c7dcf..ca8d5e18b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -51,8 +51,8 @@ export const panZoomSchema = createSchema({ arrangeInit: ScriptField, useClusters: "boolean", fitToBox: "boolean", - xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set - yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set + _xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set + _yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set panTransformType: "string", scrollHeight: "number", fitX: "number", diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index b1cca027d..b8e9acf85 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -18,6 +18,7 @@ import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import "./MarqueeView.scss"; import React = require("react"); import { CollectionView } from "../CollectionView"; +import { FormattedTextBox } from "../../nodes/FormattedTextBox"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -104,7 +105,7 @@ export class MarqueeView extends React.Component 48 && e.keyCode <= 57) { const notes = DocListCast((CurrentUserUtils.UserDocument.noteTypes as Doc).data); const text = Docs.Create.TextDocument("", { _width: 200, _height: 100, x: x, y: y, _autoHeight: true, title: "-typed text-" }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 06ca9b5f4..7683ad269 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -909,17 +909,19 @@ export class DocumentView extends DocComponent(Docu render() { if (!(this.props.Document instanceof Doc)) return (null); const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document); + const finalColor = this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor; const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document); const borderRounding = this.layoutDoc.borderRounding; const localScale = fullDegree; + console.log("Background = " + this.props.Document.title + " " + finalColor); const highlightColors = Cast(Doc.UserDoc().activeWorkspace, Doc, null)?.darkScheme ? ["transparent", "#65350c", "#65350c", "yellow", "magenta", "cyan", "orange"] : ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid"]; let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc._viewType !== CollectionViewType.Linear; highlighting = highlighting && this.props.focus !== emptyFunction; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way - return
Doc.BrushDoc(this.props.Document)} onPointerLeave={e => Doc.UnBrushDoc(this.props.Document)} style={{ @@ -931,7 +933,7 @@ export class DocumentView extends DocComponent(Docu outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, boxShadow: this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" : undefined, - background: this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor, + background: finalColor, width: "100%", height: "100%", opacity: this.Document.opacity diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index c203ca0c3..db2bb751f 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -95,8 +95,8 @@ .formattedTextBox-inner-rounded, .formattedTextBox-inner { - padding: 10px 10px; height: 100%; + white-space: pre-wrap; } // .menuicon { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index a320cff75..3567dbbd5 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -375,12 +375,15 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & toggleSidebar = () => this._sidebarMovement < 5 && (this.props.Document.sidebarWidthPercent = StrCast(this.props.Document.sidebarWidthPercent, "0%") === "0%" ? "25%" : "0%"); + public static DefaultLayout: Doc | string | undefined; specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; + this.props.Document.isTemplateDoc && funcs.push({ description: "Make Default Layout", event: async () => FormattedTextBox.DefaultLayout = this.props.Document.proto as Doc, icon: "eye" }); + funcs.push({ description: "Reset Default Layout", event: () => FormattedTextBox.DefaultLayout = undefined, icon: "eye" }); !this.props.Document.expandedTemplate && funcs.push({ description: "Make Template", event: () => { this.props.Document.isTemplateDoc = true; Doc.AddDocToList(Cast(Doc.UserDoc().noteTypes, Doc, null), "data", this.props.Document); }, icon: "eye" }); - funcs.push({ description: "Toggle Sidebar", event: () => { e.stopPropagation(); this.props.Document._showSidebar = !this.props.Document._showSidebar; }, icon: "expand-arrows-alt" }); - funcs.push({ description: "Record Bullet", event: () => { e.stopPropagation(); this.recordBullet(); }, icon: "expand-arrows-alt" }); - funcs.push({ description: "Toggle Menubar", event: () => { e.stopPropagation(); this.toggleMenubar(); }, icon: "expand-arrows-alt" }); + funcs.push({ description: "Toggle Sidebar", event: () => this.props.Document._showSidebar = !this.props.Document._showSidebar, icon: "expand-arrows-alt" }); + funcs.push({ description: "Record Bullet", event: () => this.recordBullet(), icon: "expand-arrows-alt" }); + funcs.push({ description: "Toggle Menubar", event: () => this.toggleMenubar(), icon: "expand-arrows-alt" }); ["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option => funcs.push({ description: (FormattedTextBox._highlights.indexOf(option) === -1 ? "Highlight " : "Unhighlight ") + option, event: () => { @@ -1125,7 +1128,11 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & onPointerLeave={action(() => this._entered = false)} >
-
+
{!this.props.Document._showSidebar ? (null) : this.sidebarWidthPercent === "0%" ?
this.toggleSidebar()} /> : @@ -1152,15 +1159,16 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
this.toggleSidebar()} />
} -
{ - this._recording ? this.stopDictation(true) : this.recordDictation(); - setTimeout(() => this._editorView!.focus(), 500); - e.stopPropagation(); - }} > - -
+ {!this.props.Document._showAudio ? (null) : +
{ + this._recording ? this.stopDictation(true) : this.recordDictation(); + setTimeout(() => this._editorView!.focus(), 500); + e.stopPropagation(); + }} > + +
}
); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 99000a0a9..c46191270 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -407,15 +407,16 @@ export class ImageBox extends DocAnnotatableComponent
}
-
- -
+ {!this.props.Document._showAudio ? (null) : +
+ +
} {this.considerDownloadIcon} {this.considerGooglePhotosLink()} diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index f3726cb5a..7006163e0 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -15,9 +15,14 @@ export const documentSchema = createSchema({ _nativeHeight: "number", // " _width: "number", // width of document in its container's coordinate system _height: "number", // " - _showCaption: "string", // whether editable caption text is overlayed at the bottom of the document - _showTitle: "string", // the fieldkey whose contents should be displayed at the top of the document - _showTitleHover: "string", // the showTitle should be shown only on hover + _xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set + _yPadding: "number", // pixels of padding on top/bottom of collectionfreeformview contents when fitToBox is set + _xMargin: "number", // margin added on left/right of most documents to add separation from their container + _yMargin: "number", // margin added on top/bottom of most documents to add separation from their container + _showCaption: "string", // whether editable caption text is overlayed at the bottom of the document + _showTitle: "string", // the fieldkey whose contents should be displayed at the top of the document + _showTitleHover: "string", // the showTitle should be shown only on hover + _showAudio: "boolean", // whether to show the audio record icon on documents _freeformLayoutEngine: "string",// the string ID for the layout engine to use to layout freeform view documents _LODdisable: "boolean", // whether to disbale LOD switching for CollectionFreeFormViews _pivotField: "string", // specifies which field should be used as the timeline/pivot axis @@ -53,8 +58,6 @@ export const documentSchema = createSchema({ strokeWidth: "number", fontSize: "string", fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view - xPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set - yPadding: "number", // pixels of padding on left/right of collectionfreeformview contents when fitToBox is set letterSpacing: "string", textTransform: "string" }); -- cgit v1.2.3-70-g09d2