aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/DashFieldView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/DashFieldView.tsx')
-rw-r--r--src/client/util/DashFieldView.tsx260
1 files changed, 260 insertions, 0 deletions
diff --git a/src/client/util/DashFieldView.tsx b/src/client/util/DashFieldView.tsx
new file mode 100644
index 000000000..d31ec9cb1
--- /dev/null
+++ b/src/client/util/DashFieldView.tsx
@@ -0,0 +1,260 @@
+import { IReactionDisposer, observable, reaction, runInAction } from "mobx";
+import { Doc, DocListCast, Field } from "../../new_fields/Doc";
+import { List } from "../../new_fields/List";
+import { listSpec } from "../../new_fields/Schema";
+import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField";
+import { ComputedField } from "../../new_fields/ScriptField";
+import { Cast, StrCast } from "../../new_fields/Types";
+import { Utils } from "../../Utils";
+import { DocServer } from "../DocServer";
+import { CollectionViewType } from "../views/collections/CollectionView";
+import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
+import React = require("react");
+
+
+interface IDashFieldView {
+ node: any,
+ view: any,
+ getPos: any,
+ tbox: FormattedTextBox
+}
+export class DashFieldView extends React.Component<IDashFieldView> {
+
+ _reactionDisposer: IReactionDisposer | undefined;
+ _textBoxDoc?: Doc; //Added "?""
+ @observable _dashDoc: Doc | undefined;
+ _fieldKey?: string; //Added "?" and added "as string"
+ _options: Doc[] = [];
+
+ constructor(props: IDashFieldView) {
+ super(props)
+ this._fieldKey = this.props.node.attrs.fieldKey;
+ this._textBoxDoc = this.props.tbox.props.Document;
+
+ if (this.props.node.attrs.docid) {
+ DocServer.GetRefField(this.props.node.attrs.docid).
+ then(async dashDoc => dashDoc instanceof Doc && runInAction(() => this.setDashDoc(dashDoc)));
+ } else {
+ this.setDashDoc(this.props.tbox.props.DataDoc || this.props.tbox.dataDoc);
+ }
+
+ this._reactionDisposer?.();
+ var elementFieldCheck = document.getElementById("fieldCheckId") as HTMLInputElement;
+ this._reactionDisposer = reaction(() => { // this reaction will update the displayed text whenever the document's fieldKey's value changes
+ const dashVal = this._dashDoc?.[this._fieldKey as string];
+ return StrCast(dashVal).startsWith(":=") || dashVal === "" ? Doc.Layout(this.props.tbox.props.Document)[this._fieldKey as string] : dashVal;
+ }, fval => {
+ const boolVal = Cast(fval, "boolean", null);
+ if (boolVal === true || boolVal === false) {
+ elementFieldCheck.checked = boolVal;
+ } else {
+ elementFieldCheck.innerHTML = Field.toString(fval as Field) || "";
+ }
+ elementFieldCheck.style.display = (boolVal === true || boolVal === false) ? "inline-block" : "none";
+ elementFieldCheck.style.display = !(boolVal === true || boolVal === false) ? "inline-block" : "none";
+ }, { fireImmediately: true });
+
+ }
+
+ setDashDoc = (doc: Doc) => {
+ this._dashDoc = doc;
+ if (this._options?.length && !this._dashDoc[this._fieldKey as string]) {
+ this._dashDoc[this._fieldKey as string] = StrCast(this._options[0].title);
+ }
+ // NOTE: if the field key starts with "@", then the actual field key is stored in the field 'fieldKey' (removing the @).
+ this._fieldKey = this._fieldKey?.startsWith("@") ? StrCast(this.props.tbox.props.Document[StrCast(this._fieldKey as string).substring(1)]) : this._fieldKey as string;
+ var elementlabelSpan = document.getElementById("labelSpanId") as HTMLElement;
+ elementlabelSpan.innerHTML = `${this._fieldKey}: `;
+ const fieldVal = Cast(this._dashDoc?.[this._fieldKey], "boolean", null);
+ var elementfieldCheck = document.getElementById("fieldCheckId") as HTMLElement;
+ elementfieldCheck.style.display = (fieldVal === true || fieldVal === false) ? "inline-block" : "none";
+ elementfieldCheck.style.display = !(fieldVal === true || fieldVal === false) ? "inline-block" : "none";
+ };
+
+ updateText = (forceMatch: boolean) => {
+ var elementEnumarables = document.getElementById("enumarablesId") as HTMLElement;
+ elementEnumarables.style.display = "none";
+ var elementfieldSpan = document.getElementById("fieldSpanId") as HTMLElement;
+ const newText = elementfieldSpan.innerText.startsWith(":=") || elementfieldSpan.innerText.startsWith("=:=") ? ":=-computed-" : elementfieldSpan.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.
+ DocServer.GetRefField(this._fieldKey as string).then(options => {
+ let modText = "";
+ (options instanceof Doc) && DocListCast(options.data).forEach(opt => (forceMatch ? StrCast(opt.title).startsWith(newText) : StrCast(opt.title) === newText) && (modText = StrCast(opt.title)));
+ var elementfieldSpan = document.getElementById("fieldSpanId") as HTMLElement;
+ if (modText) {
+ elementfieldSpan.innerHTML = this._dashDoc![this._fieldKey as string] = modText;
+ Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey as string, []);
+ } // 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
+ else if (elementfieldSpan.innerText.startsWith(":=")) {
+ this._dashDoc![this._fieldKey as string] = ComputedField.MakeFunction(elementfieldSpan.innerText.substring(2));
+ } else if (elementfieldSpan.innerText.startsWith("=:=")) {
+ Doc.Layout(this.props.tbox.props.Document)[this._fieldKey as string] = ComputedField.MakeFunction(elementfieldSpan.innerText.substring(3));
+ } else {
+ this._dashDoc![this._fieldKey as string] = newText;
+ }
+ });
+ };
+
+ onPointerDownEnumerables = async (e: any) => {
+ e.stopPropagation();
+ var elementfieldSpan = document.getElementById("fieldSpanId") as HTMLElement;
+ const collview = await Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey as string, [{ title: elementfieldSpan.innerText }]);
+ collview instanceof Doc && this.props.tbox.props.addDocTab(collview, "onRight");
+ };
+
+ onChangefieldCheck = (e: any) => {
+ this._dashDoc![this._fieldKey as string] = e.target.checked;
+ };
+
+ onKeyPressfieldSpan = function (e: any) { e.stopPropagation(); };
+
+ onKeyUpfieldSpan = function (e: any) { e.stopPropagation(); };
+
+ onMouseDownfieldSpan = function (e: any) {
+ e.stopPropagation();
+ var element = document.getElementById("enumerables") as HTMLElement;
+ element.style.display = "inline-block";
+ };
+
+ onBlurfieldSpan = (e: any) => { this.updateText(false); }; //Pas importé
+
+ onKeyDownfieldSpan = (e: any) => {
+ e.stopPropagation();
+ if ((e.key === "a" && e.ctrlKey) || (e.key === "a" && e.metaKey)) {
+ if (window.getSelection) {
+ const range = document.createRange();
+ var elementfieldSpan = document.getElementById("fieldSpanId") as HTMLElement;
+
+ range.selectNodeContents(elementfieldSpan);
+ window.getSelection()!.removeAllRanges();
+ window.getSelection()!.addRange(range);
+ }
+ e.preventDefault();
+ }
+ if (e.key === "Enter") {
+ e.preventDefault();
+ var elementfieldSpan = document.getElementById("fieldSpanId") as HTMLElement;
+
+ e.ctrlKey && Doc.addFieldEnumerations(this._textBoxDoc, this._fieldKey as string, [{ title: elementfieldSpan.innerText }]);
+ this.updateText(true); //added this
+ }
+ };
+
+ onPointerDownLabelSpan = (e: any) => {
+
+ e.stopPropagation();
+ let container = this.props.tbox.props.ContainingCollectionView;
+ while (container?.props.Document.isTemplateForField || container?.props.Document.isTemplateDoc) {
+ container = container.props.ContainingCollectionView;
+ }
+ if (container) {
+ const alias = Doc.MakeAlias(container.props.Document);
+ alias.viewType = CollectionViewType.Time;
+ let list = Cast(alias.schemaColumns, listSpec(SchemaHeaderField));
+ if (!list) {
+ alias.schemaColumns = list = new List<SchemaHeaderField>();
+ }
+ list.map(c => c.heading).indexOf(this._fieldKey as string) === -1 && list.push(new SchemaHeaderField(this._fieldKey, "#f1efeb"));
+ list.map(c => c.heading).indexOf("text") === -1 && list.push(new SchemaHeaderField("text", "#f1efeb"));
+ alias._pivotField = this._fieldKey as string;
+ this.props.tbox.props.addDocTab(alias, "onRight");
+ }
+ };
+
+ destroy() {
+ this._reactionDisposer?.();
+ }
+ selectNode() { }
+
+ render() {
+
+ const fieldStyle = {
+ width: this.props.node.props.width,
+ height: this.props.node.props.height,
+ position: 'relative' as 'relative',
+ display: 'inline-flex'
+ };
+
+ let enumerablesStyle = {
+ width: "10px",
+ height: "10px",
+ position: 'relative' as 'relative',
+ display: 'none',
+ background: "dimGray"
+ };
+
+ const fieldCheckStyle = {
+ minWidth: "12px",
+ position: 'relative' as 'relative',
+ display: 'none',
+ backgroundColor: "rgba(155, 155, 155, 0.24)"
+ };
+
+ const fieldSpanStyle = {
+ minWidth: "12px",
+ position: 'relative' as 'relative',
+ display: 'none',
+ backgroundColor: "rgba(155, 155, 155, 0.24)"
+ };
+
+ const labelSpanStyle = {
+ position: 'relative' as 'relative',
+ display: 'inline-block',
+ backgroundColor: "rgba(155, 155, 155, 0.44)",
+ fontSize: "small",
+ title: "click to see related tags"
+ };
+
+ const fieldCheckId = Utils.GenerateGuid();
+ const fieldSpanId = Utils.GenerateGuid();
+
+ return (
+ <div
+ className="fieldWrapper"
+ style={fieldStyle}>
+
+ <span
+ className="labelSpan"
+ id='labelSpanId'
+ style={labelSpanStyle}
+ onPointerDown={this.onPointerDownLabelSpan}
+ //innerHTML= {this._fieldKey}
+ >
+ </span>
+
+ <input
+ className="fieldCheck"
+ id={fieldCheckId}
+ type="checkbox"
+ style={fieldCheckStyle}
+ onChange={this.onChangefieldCheck}>
+ </input>
+
+ <div
+ className="fieldSpan"
+ id={fieldSpanId}
+ contentEditable="true"
+ style={fieldSpanStyle}
+ onBlur={this.onBlurfieldSpan}
+ onKeyDown={this.onKeyDownfieldSpan}
+ onKeyPress={this.onKeyPressfieldSpan}
+ onKeyUp={this.onKeyUpfieldSpan}
+ onMouseDown={this.onMouseDownfieldSpan}
+ >
+ </div>
+
+ <div
+ className="enumerables"
+ id="enumerablesId"
+ style={enumerablesStyle}
+ onPointerDown={this.onPointerDownEnumerables}>
+
+ </div>
+
+ </div >
+ )
+ }
+} \ No newline at end of file