From 17cab0166753aee765585e1eb700fd85583e7cbb Mon Sep 17 00:00:00 2001 From: monikahedman Date: Mon, 5 Aug 2019 19:11:54 -0400 Subject: clickable text box appears --- src/client/util/RichTextSchema.tsx | 70 +++++++++++++++++++++++++++++ src/client/util/TooltipTextMenu.tsx | 26 +++++++++++ src/client/views/nodes/FormattedTextBox.tsx | 8 ++-- 3 files changed, 101 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index ce9e29b26..491208c4c 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -110,6 +110,33 @@ export const nodes: { [index: string]: NodeSpec } = { // } // }] }, + + // TODO + checkbox: { + inline: true, + attrs: { + visibility: { default: false }, + // text: { default: undefined }, + // textslice: { default: undefined }, + // textlen: { default: 0 } + + }, + group: "inline", + toDOM(node) { + const attrs = { style: `width: 40px` }; + return ["span", { ...node.attrs, ...attrs }]; + }, + // parseDOM: [{ + // tag: "star", getAttrs(dom: any) { + // return { + // visibility: dom.getAttribute("visibility"), + // oldtext: dom.getAttribute("oldtext"), + // oldtextlen: dom.getAttribute("oldtextlen"), + // } + // } + // }] + }, + // :: NodeSpec An inline image (``) node. Supports `src`, // `alt`, and `href` attributes. The latter two default to the empty // string. @@ -522,6 +549,49 @@ export class ImageResizeView { } } +export class CheckboxView { + _view: any; + _collapsed: HTMLElement; + + constructor(node: any, view: any, getPos: any) { + this._collapsed = document.createElement("span"); + this._collapsed.textContent = node.attrs.visibility ? "⬛" : "⬜"; + this._collapsed.style.position = "relative"; + // this._collapsed.style.width = "80px"; + this._collapsed.style.height = "20px"; + let self = this; + this._view = view; + const js = node.toJSON; + node.toJSON = function () { + + return js.apply(this, arguments); + }; + this._collapsed.onpointerdown = function (e: any) { + console.log(node.attrs.visibility) + if (node.attrs.visibility) { + let y = getPos(); + const attrs = { ...node.attrs }; + attrs.visibility = !attrs.visibility; + view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs)); + self._collapsed.textContent = "⬜"; + } else { + let y = getPos(); + const attrs = { ...node.attrs }; + attrs.visibility = !attrs.visibility; + console.log(attrs.visibility) + view.dispatch(view.state.tr.setNodeMarkup(y, undefined, attrs)); + self._collapsed.textContent = "⬛"; + } + e.preventDefault(); + e.stopPropagation(); + console.log(node.attrs.visibility) + + }; + (this as any).dom = this._collapsed; + } + +} + export class SummarizedView { // TODO: highlight text that is summarized. to find end of region, walk along mark _collapsed: HTMLElement; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index d33a52d7f..8f66a0ad4 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -177,6 +177,7 @@ export class TooltipTextMenu { this.listTypeToIcon = new Map(); this.listTypeToIcon.set(schema.nodes.bullet_list, ":"); this.listTypeToIcon.set(schema.nodes.ordered_list, "1)"); + // this.listTypeToIcon.set(schema.nodes.checklist, "⬜"); this.listTypes = Array.from(this.listTypeToIcon.keys()); //custom tools @@ -186,6 +187,7 @@ export class TooltipTextMenu { this.tooltip.appendChild(this._brushdom); this.tooltip.appendChild(this.createLink().render(this.view).dom); this.tooltip.appendChild(this.createStar().render(this.view).dom); + this.tooltip.appendChild(this.createCheckbox().render(this.view).dom) this.updateListItemDropdown(":", this.listTypeBtnDom); @@ -439,6 +441,16 @@ export class TooltipTextMenu { return true; } + public static insertCheckbox(state: EditorState, dispatch: any) { + let newNode = schema.nodes.checkbox.create({ visibility: false }); + if (dispatch) { + //console.log(newNode.attrs.text.toString()); + dispatch(state.tr.replaceSelectionWith(newNode)); + wrapInList(nodeType)(state, dispatch); + } + return true; + } + //will display a remove-list-type button if selection is in list, otherwise will show list type dropdown updateListItemDropdown(label: string, listTypeBtn: any) { //remove old btn @@ -548,6 +560,20 @@ export class TooltipTextMenu { }); } + createCheckbox() { + return new MenuItem({ + title: "Checkbox", + label: "Checkbox", + icon: icons.code, + css: "color:white", + class: "checkbox", + execEvent: "", + run: (state, dispatch) => { + TooltipTextMenu.insertCheckbox(state, dispatch); + } + }) + } + deleteLinkItem() { const icon = { height: 16, width: 16, diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e076efe18..a2e610fc2 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -8,7 +8,7 @@ import { keymap } from "prosemirror-keymap"; import { Node as ProsNode } from "prosemirror-model"; import { EditorState, Plugin, Transaction, Selection } from "prosemirror-state"; import { NodeType, Slice, Node, Fragment } from 'prosemirror-model'; -import { EditorView } from "prosemirror-view"; +import { EditorView, NodeView } from "prosemirror-view"; import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { List } from '../../../new_fields/List'; @@ -21,7 +21,7 @@ import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from "../../util/DragManager"; import buildKeymap from "../../util/ProsemirrorExampleTransfer"; import { inpRules } from "../../util/RichTextRules"; -import { ImageResizeView, schema, SummarizedView } from "../../util/RichTextSchema"; +import { ImageResizeView, schema, SummarizedView, CheckboxView } from "../../util/RichTextSchema"; import { SelectionManager } from "../../util/SelectionManager"; import { TooltipLinkingMenu } from "../../util/TooltipLinkingMenu"; import { TooltipTextMenu } from "../../util/TooltipTextMenu"; @@ -38,6 +38,7 @@ import { For } from 'babel-types'; import { DateField } from '../../../new_fields/DateField'; import { Utils } from '../../../Utils'; import { MainOverlayTextBox } from '../MainOverlayTextBox'; +import { CheckBox } from '../search/CheckBox'; library.add(faEdit); library.add(faSmile, faTextHeight); @@ -469,7 +470,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe dispatchTransaction: this.dispatchTransaction, nodeViews: { image(node, view, getPos) { return new ImageResizeView(node, view, getPos); }, - star(node, view, getPos) { return new SummarizedView(node, view, getPos); } + star(node, view, getPos) { return new SummarizedView(node, view, getPos); }, + checkbox(node, view, getPos) { return new CheckboxView(node, view, getPos) as NodeView; } }, clipboardTextSerializer: this.clipboardTextSerializer, handlePaste: this.handlePaste, -- cgit v1.2.3-70-g09d2 From 030af1b9112cd12383abcd7f35142cc382ea4d6a Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 6 Aug 2019 17:55:43 -0400 Subject: end of day 8/6 --- src/client/util/RichTextSchema.tsx | 15 +++++++++++++++ src/client/util/TooltipTextMenu.tsx | 11 +++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 491208c4c..8e80de1a8 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -193,6 +193,12 @@ export const nodes: { [index: string]: NodeSpec } = { } }, + checkbox_list2: { + inline: false, + // content: 'list_item+', + group: 'block' + }, + // :: NodeSpec A hard line break, represented in the DOM as `
`. hard_break: { inline: true, @@ -215,6 +221,15 @@ export const nodes: { [index: string]: NodeSpec } = { // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }], // toDOM() { return ulDOM } }, + checkbox_list: { + ...bulletList, + content: 'list_item+', + group: 'block', + // style: 'list-style-type:none' + itemContent: "+", + // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=square' }], + // toDOM() { return ulDOM; } + }, //bullet_list: { // content: 'list_item+', // group: 'block', diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 8f66a0ad4..b1243cb1d 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -10,7 +10,7 @@ import { Node as ProsNode } from "prosemirror-model"; import "./TooltipTextMenu.scss"; const { toggleMark, setBlockType } = require("prosemirror-commands"); import { library } from '@fortawesome/fontawesome-svg-core'; -import { wrapInList, liftListItem, } from 'prosemirror-schema-list'; +import { wrapInList, liftListItem, bulletList, } from 'prosemirror-schema-list'; import { faListUl } from '@fortawesome/free-solid-svg-icons'; import { FieldViewProps } from "../views/nodes/FieldView"; const { openPrompt, TextField } = require("./ProsemirrorCopy/prompt.js"); @@ -177,7 +177,7 @@ export class TooltipTextMenu { this.listTypeToIcon = new Map(); this.listTypeToIcon.set(schema.nodes.bullet_list, ":"); this.listTypeToIcon.set(schema.nodes.ordered_list, "1)"); - // this.listTypeToIcon.set(schema.nodes.checklist, "⬜"); + // this.listTypeToIcon.set(schema.nodes.bullet_list, "⬜"); this.listTypes = Array.from(this.listTypeToIcon.keys()); //custom tools @@ -187,7 +187,7 @@ export class TooltipTextMenu { this.tooltip.appendChild(this._brushdom); this.tooltip.appendChild(this.createLink().render(this.view).dom); this.tooltip.appendChild(this.createStar().render(this.view).dom); - this.tooltip.appendChild(this.createCheckbox().render(this.view).dom) + this.tooltip.appendChild(this.createCheckbox().render(this.view).dom); this.updateListItemDropdown(":", this.listTypeBtnDom); @@ -441,12 +441,13 @@ export class TooltipTextMenu { return true; } + // this needs to change so it makes it into a bulleted list public static insertCheckbox(state: EditorState, dispatch: any) { let newNode = schema.nodes.checkbox.create({ visibility: false }); if (dispatch) { //console.log(newNode.attrs.text.toString()); dispatch(state.tr.replaceSelectionWith(newNode)); - wrapInList(nodeType)(state, dispatch); + wrapInList(newNode.type)(state, dispatch); } return true; } @@ -460,9 +461,11 @@ export class TooltipTextMenu { let toAdd: MenuItem[] = []; this.listTypeToIcon.forEach((icon, type) => { toAdd.push(this.dropdownNodeBtn(icon, "color: black; width: 40px;", type, this.view, this.listTypes, this.changeToNodeType)); + console.log(type.name) }); //option to remove the list formatting toAdd.push(this.dropdownNodeBtn("X", "color: black; width: 40px;", undefined, this.view, this.listTypes, this.changeToNodeType)); + toAdd.push(this.dropdownNodeBtn("⬜", "color:black; width:40px;", schema.nodes.checkbox_list, this.view, this.listTypes, this.changeToNodeType)) listTypeBtn = (new Dropdown(toAdd, { label: label, -- cgit v1.2.3-70-g09d2 From 8c4b8ae12fb418d38e5aab6c12514913f1565bb0 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Fri, 9 Aug 2019 17:02:02 -0400 Subject: send halp --- src/client/util/RichTextSchema.tsx | 52 +++++++++++----------- src/client/util/TooltipTextMenu.tsx | 9 ++-- .../views/collections/CollectionViewChromes.tsx | 2 + src/client/views/nodes/FormattedTextBox.tsx | 1 + 4 files changed, 33 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 8e80de1a8..733c50d20 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -6,6 +6,7 @@ import { orderedList, bulletList, listItem, } from 'prosemirror-schema-list'; import { EditorState, Transaction, NodeSelection, TextSelection, Selection, } from "prosemirror-state"; import { EditorView, } from "prosemirror-view"; import { View } from '@react-pdf/renderer'; +import { TooltipTextMenu } from './TooltipTextMenu'; const pDOM: DOMOutputSpecArray = ["p", 0], blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; @@ -111,30 +112,16 @@ export const nodes: { [index: string]: NodeSpec } = { // }] }, - // TODO checkbox: { inline: true, attrs: { - visibility: { default: false }, - // text: { default: undefined }, - // textslice: { default: undefined }, - // textlen: { default: 0 } - + visibility: { default: false } }, group: "inline", toDOM(node) { const attrs = { style: `width: 40px` }; return ["span", { ...node.attrs, ...attrs }]; }, - // parseDOM: [{ - // tag: "star", getAttrs(dom: any) { - // return { - // visibility: dom.getAttribute("visibility"), - // oldtext: dom.getAttribute("oldtext"), - // oldtextlen: dom.getAttribute("oldtextlen"), - // } - // } - // }] }, // :: NodeSpec An inline image (``) node. Supports `src`, @@ -193,12 +180,6 @@ export const nodes: { [index: string]: NodeSpec } = { } }, - checkbox_list2: { - inline: false, - // content: 'list_item+', - group: 'block' - }, - // :: NodeSpec A hard line break, represented in the DOM as `
`. hard_break: { inline: true, @@ -221,15 +202,20 @@ export const nodes: { [index: string]: NodeSpec } = { // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=disc' }], // toDOM() { return ulDOM } }, + checkbox_list: { - ...bulletList, - content: 'list_item+', + content: 'checklist_item+', + marks: '_', group: 'block', - // style: 'list-style-type:none' - itemContent: "+", - // parseDOM: [{ tag: "ul" }, { style: 'list-style-type=square' }], - // toDOM() { return ulDOM; } + // inline: true, + parseDOM: [ + { tag: "ul" } + ], + toDOM() { + return ["ul", { style: 'list-style: none' }, 0]; + }, }, + //bullet_list: { // content: 'list_item+', // group: 'block', @@ -241,6 +227,18 @@ export const nodes: { [index: string]: NodeSpec } = { list_item: { ...listItem, content: 'paragraph block*' + }, + + checklist_item: { + content: 'paragraph block*', + parseDOM: [{ tag: "li" }], + // toDOM() { + // return ["li", { style: 'content: checkbox' }, 0]; + // }, + toDOM() { + return ["li", 0]; + }, + defining: true } }; diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index b1243cb1d..8112ed868 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -441,13 +441,10 @@ export class TooltipTextMenu { return true; } - // this needs to change so it makes it into a bulleted list public static insertCheckbox(state: EditorState, dispatch: any) { let newNode = schema.nodes.checkbox.create({ visibility: false }); if (dispatch) { - //console.log(newNode.attrs.text.toString()); dispatch(state.tr.replaceSelectionWith(newNode)); - wrapInList(newNode.type)(state, dispatch); } return true; } @@ -461,7 +458,6 @@ export class TooltipTextMenu { let toAdd: MenuItem[] = []; this.listTypeToIcon.forEach((icon, type) => { toAdd.push(this.dropdownNodeBtn(icon, "color: black; width: 40px;", type, this.view, this.listTypes, this.changeToNodeType)); - console.log(type.name) }); //option to remove the list formatting toAdd.push(this.dropdownNodeBtn("X", "color: black; width: 40px;", undefined, this.view, this.listTypes, this.changeToNodeType)); @@ -529,6 +525,11 @@ export class TooltipTextMenu { liftListItem(schema.nodes.list_item)(view.state, view.dispatch); if (nodeType) { //add new wrapInList(nodeType)(view.state, view.dispatch); + // console.log(nodeType === schema.nodes.checkbox_list) + // if (nodeType === schema.nodes.checkbox_list) { + // TooltipTextMenu.insertCheckbox(view.state, view.dispatch) + // } + } } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 52c47e7e8..5b673c8ec 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -33,6 +33,8 @@ let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer export class CollectionViewBaseChrome extends React.Component { + //.*?doc\.(\w+).*?\("(\w+) + @observable private _viewSpecsOpen: boolean = false; @observable private _dateWithinValue: string = ""; @observable private _dateValue: Date | string = ""; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 303b1ac88..d1771eb0f 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -177,6 +177,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe this._editorView.updateState(state); if (state.selection.empty && FormattedTextBox._toolTipTextMenu) { const marks = tx.storedMarks; + console.log(marks) if (marks) { FormattedTextBox._toolTipTextMenu.mark_key_pressed(marks); } } this._applyingChange = true; -- cgit v1.2.3-70-g09d2 From 50c6d29c2ac197ed55aefa9bf46c6c85959d00f2 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Mon, 12 Aug 2019 17:34:46 -0400 Subject: bleh --- .../views/collections/CollectionViewChromes.scss | 2 +- .../views/collections/CollectionViewChromes.tsx | 42 +++++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss index 793cb7a8b..2006c08f3 100644 --- a/src/client/views/collections/CollectionViewChromes.scss +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -97,7 +97,7 @@ .collectionViewBaseChrome-viewSpecsMenu-lastRow { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr; grid-gap: 10px; margin: 10px; } diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 5b673c8ec..9e4a4ac5a 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -5,7 +5,7 @@ import { CollectionViewType } from "./CollectionBaseView"; import { undoBatch } from "../../util/UndoManager"; import { action, observable, runInAction, computed, IObservable, IObservableValue, reaction, autorun } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc, DocListCast, FieldResult } from "../../../new_fields/Doc"; import { DocLike } from "../MetadataEntryMenu"; import * as Autosuggest from 'react-autosuggest'; import { EditableView } from "../EditableView"; @@ -22,6 +22,7 @@ import { List } from "../../../new_fields/List"; import { Id } from "../../../new_fields/FieldSymbols"; import { threadId } from "worker_threads"; const datepicker = require('js-datepicker'); +import * as $ from 'jquery'; interface CollectionViewChromeProps { CollectionView: CollectionView; @@ -33,7 +34,7 @@ let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer export class CollectionViewBaseChrome extends React.Component { - //.*?doc\.(\w+).*?\("(\w+) + //(!)?\(\(\(doc.(\w+) && \(doc.\w+ as \w+\).includes\(\"(\w+)\"\) @observable private _viewSpecsOpen: boolean = false; @observable private _dateWithinValue: string = ""; @@ -41,6 +42,8 @@ export class CollectionViewBaseChrome extends React.Component { this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); @@ -122,10 +136,10 @@ export class CollectionViewBaseChrome extends React.Component { + this.openViewSpecs(e); - let keyRestrictionScript = `${this._keyRestrictions.map(i => i[1]) - .reduce((acc: string, value: string, i: number) => value ? `${acc} && ${value}` : acc)}`; + let keyRestrictionScript = this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && "); let yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0; let monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0; let weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0; @@ -145,9 +159,10 @@ export class CollectionViewBaseChrome extends React.Component); } + clearFilter = () => { + let compiled = CompileScript("return true", { params: { doc: Doc.name }, typecheck: false }); + if (compiled.compiled) { + this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled); + } + } + render() { return (
@@ -248,9 +270,10 @@ export class CollectionViewBaseChrome extends React.Component { }} - onPointerDown={this.openViewSpecs} /> + onPointerDown={this.openViewSpecs} + id="viewSpecsInput" /> {this.getPivotInput()}
+
-- cgit v1.2.3-70-g09d2 From 180a1268d6e732bca9557da7f935ec540de4b878 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 13 Aug 2019 16:31:34 -0400 Subject: key restrictions working properly --- src/client/views/MainView.tsx | 2 +- .../views/collections/CollectionViewChromes.tsx | 73 +++++++++++++++++----- src/client/views/collections/KeyRestrictionRow.tsx | 6 +- 3 files changed, 62 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 031478477..daa047797 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -478,7 +478,7 @@ export class MainView extends React.Component { }; return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} > - +
    diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 9e4a4ac5a..9ac724ba8 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -23,6 +23,7 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { threadId } from "worker_threads"; const datepicker = require('js-datepicker'); import * as $ from 'jquery'; +import { firebasedynamiclinks } from "googleapis/build/src/apis/firebasedynamiclinks"; interface CollectionViewChromeProps { CollectionView: CollectionView; @@ -30,6 +31,12 @@ interface CollectionViewChromeProps { collapse?: (value: boolean) => any; } +interface Filter { + key: string; + value: string; + contains: boolean; +} + let stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation(); @observer @@ -42,12 +49,47 @@ export class CollectionViewBaseChrome extends React.Component { + let re: any = /(!)?\(\(\(doc\.(\w+)\s+&&\s+\(doc\.\w+\s+as\s+\w+\)\.includes\(\"(\w+)\"\)/g; + let arr: any[] = re.exec(script); + let toReturn: Filter[] = []; + if (arr !== null) { + let filter: Filter = { + key: arr[2], + value: arr[3], + contains: (arr[1] === "!") ? false : true, + }; + toReturn.push(filter); + script = script.replace(arr[0], ""); + if (re.exec(script) !== null) { + toReturn.push(...this.getFilters(script)); + } + else { return toReturn; } + } + return toReturn; + } + + addKeyRestrictions = (fields: Filter[]) => { + + if (fields.length !== 0) { + for (let i = 0; i < fields.length; i++) { + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[i][1] = value)} />, ""]); + + } + if (this._keyRestrictions.length === 1) { + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); + } + } + else { + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); + } + } + componentDidMount = () => { setTimeout(() => this._picker = datepicker("#" + this._datePickerElGuid, { disabler: (date: Date) => date > new Date(), @@ -55,21 +97,14 @@ export class CollectionViewBaseChrome extends React.Component { - this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[0][1] = value)} />, ""]); - this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[1][1] = value)} />, ""]); - + this.addKeyRestrictions(fields); // chrome status is one of disabled, collapsed, or visible. this determines initial state from document let chromeStatus = this.props.CollectionView.props.Document.chromeStatus; if (chromeStatus) { @@ -129,17 +164,19 @@ export class CollectionViewBaseChrome extends React.Component { let index = this._keyRestrictions.length; - this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]); + this._keyRestrictions.push([ runInAction(() => this._keyRestrictions[index][1] = value)} />, ""]); this.openViewSpecs(e); } - @action + @action.bound applyFilter = (e: React.MouseEvent) => { this.openViewSpecs(e); - let keyRestrictionScript = this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && "); + console.log(this._keyRestrictions) + + let keyRestrictionScript = "(" + this._keyRestrictions.map(i => i[1]).filter(i => i.length > 0).join(" && ") + ")"; let yearOffset = this._dateWithinValue[1] === 'y' ? 1 : 0; let monthOffset = this._dateWithinValue[1] === 'm' ? parseInt(this._dateWithinValue[0]) : 0; let weekOffset = this._dateWithinValue[1] === 'w' ? parseInt(this._dateWithinValue[0]) : 0; @@ -234,11 +271,15 @@ export class CollectionViewBaseChrome extends React.Component); } + @action.bound clearFilter = () => { let compiled = CompileScript("return true", { params: { doc: Doc.name }, typecheck: false }); if (compiled.compiled) { this.props.CollectionView.props.Document.viewSpecScript = new ScriptField(compiled); } + + this._keyRestrictions = []; + this.addKeyRestrictions([]); } render() { diff --git a/src/client/views/collections/KeyRestrictionRow.tsx b/src/client/views/collections/KeyRestrictionRow.tsx index 1b59547d8..e35b7d7d3 100644 --- a/src/client/views/collections/KeyRestrictionRow.tsx +++ b/src/client/views/collections/KeyRestrictionRow.tsx @@ -7,12 +7,14 @@ import { Doc } from "../../../new_fields/Doc"; interface IKeyRestrictionProps { contains: boolean; script: (value: string) => void; + field: string; + value: string; } @observer export default class KeyRestrictionRow extends React.Component { - @observable private _key = ""; - @observable private _value = ""; + @observable private _key = this.props.field; + @observable private _value = this.props.value; @observable private _contains = this.props.contains; render() { -- cgit v1.2.3-70-g09d2 From 18bc52d98999c6e0d7814429d8bb7358473e9aff Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 13 Aug 2019 16:48:58 -0400 Subject: adding web thing --- package.json | 2 +- src/client/views/MainView.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/package.json b/package.json index d699d1e6f..a4343982e 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "js-datepicker": "^4.6.6", "jsonwebtoken": "^8.5.0", "jsx-to-string": "^1.4.0", - "lodash": "^4.17.11", + "lodash": "^4.17.15", "mobile-detect": "^1.4.3", "mobx": "^5.9.0", "mobx-react": "^5.3.5", diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index b34a901e1..ae5f0b12f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -448,6 +448,7 @@ export class MainView extends React.Component { //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); + let addWebNode = action(() => Docs.Create.WebDocument("https://javascript.info/regexp-groups", { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })); @@ -457,6 +458,7 @@ export class MainView extends React.Component { let btns: [React.RefObject, IconName, string, () => Doc][] = [ [React.createRef(), "object-group", "Add Collection", addColNode], + [React.createRef(), "globe-asia", "Add Website", addWebNode], [React.createRef(), "bolt", "Add Button", addButtonDocument], // [React.createRef(), "clone", "Add Docking Frame", addDockingNode], [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], -- cgit v1.2.3-70-g09d2 From 31e9872ec5ec5b84c645adcf7acf06e20e2dc060 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Tue, 13 Aug 2019 17:47:01 -0400 Subject: yikes --- src/client/views/MainView.tsx | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ae5f0b12f..51eb79edc 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,6 +40,7 @@ import { CollectionTreeView } from './collections/CollectionTreeView'; import { ClientUtils } from '../util/ClientUtils'; import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; import { DictationManager } from '../util/DictationManager'; +import * as $ from 'jquery'; @observer export class MainView extends React.Component { @@ -436,6 +437,40 @@ export class MainView extends React.Component { } } + // @computed + // get webURL() { + // let URL: string = ""; + + // return URL; + // } + @observable private webpageURL: string = ""; + + @action + onURLChange = (e: React.ChangeEvent) => { + this.webpageURL = e.target.value; + } + + @observable webDoc: Doc | undefined = undefined; + + @action + onURLSubmit = () => { + this.webDoc = Docs.Create.WebDocument(this.webpageURL, { width: this.pwidth * .7, height: this.pheight, title: this.webpageURL }); + } + + @action + makeWebDocument() { + let mod = document.getElementById("webpage-input"); + if (mod) mod.style.display = "flex"; + while (true) { + if (this.webDoc !== undefined) { + if (mod) mod.style.display = "none"; + console.log(this.webpageURL) + console.log(this.webDoc) + return this.webDoc; + } + } + } + @observable private _colorPickerDisplay = false; /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ @@ -448,7 +483,7 @@ export class MainView extends React.Component { //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); - let addWebNode = action(() => Docs.Create.WebDocument("https://javascript.info/regexp-groups", { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); + let addWebNode = action(() => this.makeWebDocument()); let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })); @@ -482,6 +517,11 @@ export class MainView extends React.Component { DocServer.setFieldWriteMode("viewType", mode2); }; return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} > +
    + + +
    + -- cgit v1.2.3-70-g09d2 From 81100809b0f824cfc1481b19dbe38c31814539e1 Mon Sep 17 00:00:00 2001 From: monikahedman Date: Wed, 14 Aug 2019 17:20:57 -0400 Subject: drag new webpage and easy URL change working --- src/client/views/Main.scss | 11 +++ src/client/views/MainView.tsx | 42 +----------- src/client/views/nodes/WebBox.scss | 133 ++++++++++++++++++++++++++++++++++--- src/client/views/nodes/WebBox.tsx | 87 +++++++++++++++++++++++- 4 files changed, 222 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index f76abaff3..d84decdfe 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -295,4 +295,15 @@ ul#add-options-list { z-index: 999; transition: 0.5s all ease; pointer-events: none; +} + +.webpage-input { + display: none; + height: 60px; + width: 600px; + position: absolute; + + .url-input { + width: 80%; + } } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 51eb79edc..5b19e95ed 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -41,6 +41,7 @@ import { ClientUtils } from '../util/ClientUtils'; import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; import { DictationManager } from '../util/DictationManager'; import * as $ from 'jquery'; +import { KeyValueBox } from './nodes/KeyValueBox'; @observer export class MainView extends React.Component { @@ -437,41 +438,6 @@ export class MainView extends React.Component { } } - // @computed - // get webURL() { - // let URL: string = ""; - - // return URL; - // } - @observable private webpageURL: string = ""; - - @action - onURLChange = (e: React.ChangeEvent) => { - this.webpageURL = e.target.value; - } - - @observable webDoc: Doc | undefined = undefined; - - @action - onURLSubmit = () => { - this.webDoc = Docs.Create.WebDocument(this.webpageURL, { width: this.pwidth * .7, height: this.pheight, title: this.webpageURL }); - } - - @action - makeWebDocument() { - let mod = document.getElementById("webpage-input"); - if (mod) mod.style.display = "flex"; - while (true) { - if (this.webDoc !== undefined) { - if (mod) mod.style.display = "none"; - console.log(this.webpageURL) - console.log(this.webDoc) - return this.webDoc; - } - } - } - - @observable private _colorPickerDisplay = false; /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ nodesMenu() { @@ -483,7 +449,7 @@ export class MainView extends React.Component { //let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" })); - let addWebNode = action(() => this.makeWebDocument()); + let addWebNode = action(() => Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })); let addDragboxNode = action(() => Docs.Create.DragboxDocument({ width: 40, height: 40, title: "drag collection" })); let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })); let addButtonDocument = action(() => Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })); @@ -517,10 +483,6 @@ export class MainView extends React.Component { DocServer.setFieldWriteMode("viewType", mode2); }; return < div id="add-nodes-menu" style={{ left: this.flyoutWidth + 20, bottom: 20 }} > -
    - - -
    diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index eb09b0693..c37f08eca 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -1,16 +1,18 @@ - -.webBox-cont, .webBox-cont-interactive{ +.webBox-cont, +.webBox-cont-interactive { padding: 0vw; position: absolute; top: 0; - left:0; + left: 0; width: 100%; height: 100%; overflow: auto; - pointer-events: none ; + pointer-events: none; } + .webBox-cont-interactive { pointer-events: all; + span { user-select: text !important; } @@ -18,8 +20,8 @@ #webBox-htmlSpan { position: absolute; - top:0; - left:0; + top: 0; + left: 0; } .webBox-overlay { @@ -29,8 +31,123 @@ } .webBox-button { - padding : 0vw; + padding: 0vw; border: none; - width : 100%; + width: 100%; + height: 100%; +} + +.webView-urlEditor { + position: relative; + opacity: 0.9; + z-index: 9001; + transition: top .5s; + background: lightgrey; + padding: 10px; + + + .urlEditor { + display: grid; + grid-template-columns: 1fr auto; + padding-bottom: 10px; + overflow: hidden; + + .collectionViewBaseChrome { + display: flex; + + .collectionViewBaseChrome-viewPicker { + font-size: 75%; + text-transform: uppercase; + letter-spacing: 2px; + background: rgb(238, 238, 238); + color: grey; + outline-color: black; + border: none; + padding: 12px 10px 11px 10px; + margin-left: 50px; + } + + .collectionViewBaseChrome-viewPicker:active { + outline-color: black; + } + + .collectionViewBaseChrome-collapse { + transition: all .5s, opacity 0.3s; + position: absolute; + width: 40px; + transform-origin: top left; + // margin-top: 10px; + } + + .collectionViewBaseChrome-viewSpecs { + margin-left: 10px; + display: grid; + + + + .collectionViewBaseChrome-viewSpecsMenu { + overflow: hidden; + transition: height .5s, display .5s; + position: absolute; + top: 60px; + z-index: 100; + display: flex; + flex-direction: column; + background: rgb(238, 238, 238); + box-shadow: grey 2px 2px 4px; + + .qs-datepicker { + left: unset; + right: 0; + } + + .collectionViewBaseChrome-viewSpecsMenu-row { + display: grid; + grid-template-columns: 150px 200px 150px; + margin-top: 10px; + margin-right: 10px; + + .collectionViewBaseChrome-viewSpecsMenu-rowLeft, + .collectionViewBaseChrome-viewSpecsMenu-rowMiddle, + .collectionViewBaseChrome-viewSpecsMenu-rowRight { + font-size: 75%; + letter-spacing: 2px; + color: grey; + margin-left: 10px; + padding: 5px; + border: none; + outline-color: black; + } + } + + .collectionViewBaseChrome-viewSpecsMenu-lastRow { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-gap: 10px; + margin: 10px; + } + } + } + } + + button:hover { + transform: scale(1); + } + + .collectionStackingViewChrome-sectionFilter:hover { + cursor: text; + } + } +} + +.webpage-urlInput { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + letter-spacing: 2px; + outline-color: black; + background: rgb(238, 238, 238); + width: 100%; + margin-right: 10px; height: 100%; } \ No newline at end of file diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index c8749b7cd..ff5297783 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -7,13 +7,23 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./WebBox.scss"; import React = require("react"); import { InkTool } from "../../../new_fields/InkField"; -import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { observable, action, computed } from "mobx"; +import { listSpec } from "../../../new_fields/Schema"; +import { Field, FieldResult } from "../../../new_fields/Doc"; +import { RefField } from "../../../new_fields/RefField"; +import { ObjectField } from "../../../new_fields/ObjectField"; +import { updateSourceFile } from "typescript"; +import { KeyValueBox } from "./KeyValueBox"; @observer export class WebBox extends React.Component { public static LayoutString() { return FieldView.LayoutString(WebBox); } + @observable private collapsed: boolean = true; + @observable private url: string = ""; componentWillMount() { @@ -30,6 +40,76 @@ export class WebBox extends React.Component { } } + @action + onURLChange = (e: React.ChangeEvent) => { + this.url = e.target.value; + } + + @action + submitURL = () => { + const script = KeyValueBox.CompileKVPScript(`new WebField("${this.url}")`); + if (!script) return; + KeyValueBox.ApplyKVPScript(this.props.Document, "data", script); + let mod = document.getElementById("webpage-input"); + if (mod) mod.style.display = "none"; + } + + @computed + get getURL() { + let urlField: FieldResult = Cast(this.props.Document.data, WebField) + if (urlField) return urlField.url.toString(); + return ""; + } + + onValueKeyDown = async (e: React.KeyboardEvent) => { + if (e.key === "Enter") { + e.stopPropagation(); + this.submitURL(); + } + } + + urlEditor() { + return ( +
    +
    +
    + +
    + + +
    +
    +
    +
    + ); + } + + @action + toggleCollapse = () => { + // this.props.CollectionView.props.Document.chromeStatus = this.props.CollectionView.props.Document.chromeStatus === "enabled" ? "this.collapsed" : "enabled"; + // if (this.props.collapse) { + // this.props.collapse(this.props.CollectionView.props.Document.chromeStatus !== "enabled"); + // } + this.collapsed = !this.collapsed; + } + _ignore = 0; onPreWheel = (e: React.WheelEvent) => { this._ignore = e.timeStamp; @@ -53,12 +133,13 @@ export class WebBox extends React.Component { if (field instanceof HtmlField) { view = ; } else if (field instanceof WebField) { - view =