aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts10
-rw-r--r--src/client/util/RichTextSchema.tsx32
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx4
-rw-r--r--src/new_fields/Doc.ts19
-rw-r--r--src/new_fields/RichTextField.ts4
-rw-r--r--src/server/authentication/models/current_user_utils.ts18
8 files changed, 60 insertions, 31 deletions
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<string>;
- 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<DockedFrameProps> {
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 <DocumentView key={document[Id]}
LibraryPath={this._libraryPath}
Document={document}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 84e9b6abb..aec18ecbb 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -888,7 +888,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(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<Doc>(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