aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-04-03 16:45:22 -0400
committerBob Zeleznik <zzzman@gmail.com>2020-04-03 16:45:22 -0400
commit9d06cd45c732006ed5ee13734fa8145886e349c0 (patch)
tree232827026825a7a1a19cedae5856cae7e4ba0046
parentbde3849478db64548aa992108c655fdd5f1cf940 (diff)
fixed some issues with template buttons creating documents. simplified query boxe code. added a searchView.
-rw-r--r--src/client/documents/Documents.ts5
-rw-r--r--src/client/views/TemplateMenu.tsx12
-rw-r--r--src/client/views/nodes/QueryBox.scss6
-rw-r--r--src/client/views/nodes/QueryBox.tsx87
-rw-r--r--src/client/views/search/SearchBox.tsx226
-rw-r--r--src/server/authentication/models/current_user_utils.ts10
6 files changed, 124 insertions, 222 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index da8efe745..89e8d7ebc 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -164,8 +164,8 @@ export interface DocumentOptions {
selectedIndex?: number;
syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text
searchText?: string, //for searchbox
- sq?: string,
- fq?: string,
+ searchQuery?: string, // for queryBox
+ filterQuery?: string,
linearViewIsExpanded?: boolean; // is linear view expanded
}
@@ -548,7 +548,6 @@ export namespace Docs {
}
export function QueryDocument(options: DocumentOptions = {}) {
- console.log("yuh");
return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options);
}
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index 8eb5c5050..87ffb432d 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -124,7 +124,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
templateMenu.push(<OtherToggle key={"chrome"} name={"Chrome"} checked={layout._chromeStatus !== "disabled"} toggle={this.toggleChrome} />);
templateMenu.push(<OtherToggle key={"default"} name={"Default"} checked={templateName === "layout"} toggle={this.toggleDefault} />);
if (noteTypesDoc) {
- addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction("templateIsUsed(this, firstDoc)", { firstDoc: "string" }, { firstDoc: StrCast(firstDoc.title) }));
+ addedTypes.concat(noteTypes).map(template => template.treeViewChecked = ComputedField.MakeFunction(`templateIsUsed(this, "${StrCast(firstDoc.title)}")`, { firstDoc: "string" }));
this._addedKeys && Array.from(this._addedKeys).filter(key => !noteTypes.some(nt => nt.title === key)).forEach(template => templateMenu.push(
<OtherToggle key={template} name={template} checked={templateName === template} toggle={e => this.toggleLayout(e, template)} />));
templateMenu.push(
@@ -174,10 +174,12 @@ Scripting.addGlobal(function switchView(doc: Doc, template: Doc) {
return templateTitle && DocumentView.makeCustomViewClicked(doc, Docs.Create.FreeformDocument, templateTitle, template);
});
-Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitlte: string) {
+Scripting.addGlobal(function templateIsUsed(templateDoc: Doc, firstDocTitle: string) {
const firstDoc = SelectionManager.SelectedDocuments().length ? SelectionManager.SelectedDocuments()[0].props.Document : undefined;
- if (!firstDoc) return false;
- const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title);
- return StrCast(firstDoc.layoutKey) === "layout_" + template ? 'check' : 'unchecked';
+ if (firstDoc) {
+ const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title);
+ return StrCast(firstDoc.layoutKey) === "layout_" + template ? 'check' : 'unchecked';
+ }
+ return false;
// return SelectionManager.SelectedDocuments().some(view => StrCast(view.props.Document.layoutKey) === "layout_" + template) ? 'check' : 'unchecked'
}); \ No newline at end of file
diff --git a/src/client/views/nodes/QueryBox.scss b/src/client/views/nodes/QueryBox.scss
index e69de29bb..82f64054c 100644
--- a/src/client/views/nodes/QueryBox.scss
+++ b/src/client/views/nodes/QueryBox.scss
@@ -0,0 +1,6 @@
+.queryBox, .queryBox-dragging {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ pointer-events: all;
+} \ No newline at end of file
diff --git a/src/client/views/nodes/QueryBox.tsx b/src/client/views/nodes/QueryBox.tsx
index 95ea3e099..566c07dfe 100644
--- a/src/client/views/nodes/QueryBox.tsx
+++ b/src/client/views/nodes/QueryBox.tsx
@@ -1,42 +1,18 @@
import React = require("react");
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons';
-import { IReactionDisposer, computed } from "mobx";
+import { IReactionDisposer } from "mobx";
import { observer } from "mobx-react";
-import { FieldView, FieldViewProps } from './FieldView';
-import "./PresBox.scss";
-import { SearchBox } from "../search/SearchBox";
-import { SelectionManager } from "../../util/SelectionManager";
-import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
-import { emptyFunction, returnOne } from "../../../Utils";
-import { DocAnnotatableComponent } from '../DocComponent';
-import { makeInterface, createSchema } from "../../../new_fields/Schema";
import { documentSchema } from "../../../new_fields/documentSchemas";
-import { TraceMobx } from "../../../new_fields/util";
import { Id } from '../../../new_fields/FieldSymbols';
+import { makeInterface } from "../../../new_fields/Schema";
import { StrCast } from "../../../new_fields/Types";
+import { SelectionManager } from "../../util/SelectionManager";
+import { DocAnnotatableComponent } from '../DocComponent';
+import { SearchBox } from "../search/SearchBox";
+import { FieldView, FieldViewProps } from './FieldView';
+import "./QueryBox.scss";
-
-
-library.add(faArrowLeft);
-library.add(faArrowRight);
-library.add(faPlay);
-library.add(faStop);
-library.add(faPlus);
-library.add(faTimes);
-library.add(faMinus);
-library.add(faEdit);
-
-export const pageSchema = createSchema({
- curPage: "number",
- fitWidth: "boolean",
- googlePhotosUrl: "string",
- googlePhotosTags: "string"
-});
-
-
-type QueryDocument = makeInterface<[typeof pageSchema, typeof documentSchema]>;
-const QueryDocument = makeInterface(pageSchema, documentSchema);
+type QueryDocument = makeInterface<[typeof documentSchema]>;
+const QueryDocument = makeInterface(documentSchema);
@observer
export class QueryBox extends DocAnnotatableComponent<FieldViewProps, QueryDocument>(QueryDocument) {
@@ -46,52 +22,13 @@ export class QueryBox extends DocAnnotatableComponent<FieldViewProps, QueryDocum
}
componentWillUnmount() {
- this._docListChangedReaction && this._docListChangedReaction();
- }
-
- @computed get content() {
- let key = this.props.Document[Id];
- let sq = StrCast(this.props.Document.sq);
- let fq= StrCast(this.props.Document.fq);
- if (this.props.Document.sq){
- console.log("yes");
- console.log(sq);
- console.log(fq);
- return <SearchBox id={key} sq={sq} fq={fq}/>
- }
- else {
- console.log("no");
- return <SearchBox id={key} />
- }
+ this._docListChangedReaction?.();
}
- contentFunc = () => [this.content];
-
render() {
const dragging = !SelectionManager.GetIsDragging() ? "" : "-dragging";
- return <div className={`queryBox${dragging}`} style={{ width: "100%", height: "100%", position: "absolute", pointerEvents: "all" }} >
- {/* <CollectionFreeFormView {...this.props}
- PanelHeight={this.props.PanelHeight}
- PanelWidth={this.props.PanelWidth}
- annotationsKey={this.annotationKey}
- isAnnotationOverlay={true}
- focus={this.props.focus}
- isSelected={this.props.isSelected}
- select={emptyFunction}
- active={this.active}
- ContentScaling={returnOne}
- whenActiveChanged={this.whenActiveChanged}
- removeDocument={this.removeDocument}
- moveDocument={this.moveDocument}
- addDocument={this.addDocument}
- CollectionView={undefined}
- ScreenToLocalTransform={this.props.ScreenToLocalTransform}
- renderDepth={this.props.renderDepth + 1}
- ContainingCollectionDoc={this.props.ContainingCollectionDoc}
- chromeCollapsed={true}>
- {this.contentFunc}
- </CollectionFreeFormView> */}
- {this.contentFunc()}
+ return <div className={`queryBox${dragging}`} >
+ <SearchBox id={this.props.Document[Id]} searchQuery={StrCast(this.dataDoc.searchQuery)} filterQquery={StrCast(this.dataDoc.filterQuery)} />
</div >;
}
} \ No newline at end of file
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index 56b769396..e7941a9ba 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -15,20 +15,17 @@ import { SearchUtil } from '../../util/SearchUtil';
import "./SearchBox.scss";
import { SearchItem } from './SearchItem';
import { IconBar } from './IconBar';
-import { FieldFilters } from './FieldFilters';
import { FieldView } from '../nodes/FieldView';
import { DocumentType } from "../../documents/DocumentTypes";
import { DocumentView } from '../nodes/DocumentView';
import { SelectionManager } from '../../util/SelectionManager';
-
-
library.add(faTimes);
export interface SearchProps {
- id:string;
- sq?:string;
- fq?:string;
+ id: string;
+ searchQuery?: string;
+ filterQquery?: string;
}
export enum Keys {
@@ -44,11 +41,11 @@ export class SearchBox extends React.Component<SearchProps> {
@observable private _resultsOpen: boolean = false;
@observable private _searchbarOpen: boolean = false;
@observable private _results: [Doc, string[], string[]][] = [];
- private _resultsSet = new Map<Doc, number>();
@observable private _openNoResults: boolean = false;
@observable private _visibleElements: JSX.Element[] = [];
- private resultsRef = React.createRef<HTMLDivElement>();
+ private _resultsSet = new Map<Doc, number>();
+ private _resultsRef = React.createRef<HTMLDivElement>();
public inputRef = React.createRef<HTMLInputElement>();
private _isSearch: ("search" | "placeholder" | undefined)[] = [];
@@ -75,22 +72,16 @@ export class SearchBox extends React.Component<SearchProps> {
this.resultsScrolled = this.resultsScrolled.bind(this);
}
- private _reactionDisposer?: IReactionDisposer;
-
componentDidMount = () => {
if (this.inputRef.current) {
this.inputRef.current.focus();
- runInAction(() => {
- this._searchbarOpen = true;
- });
+ runInAction(() => this._searchbarOpen = true);
}
- if (this.props.sq && this.props.fq){
- console.log(this.props.sq);
- let sq= this.props.sq
-
- let fq =this.props.fq;
+ if (this.props.searchQuery && this.props.filterQquery) {
+ console.log(this.props.searchQuery);
+ const sq = this.props.searchQuery;
runInAction(() => {
- this._searchString=sq;
+ this._searchString = sq;
this.submitSearch();
});
}
@@ -99,12 +90,7 @@ export class SearchBox extends React.Component<SearchProps> {
@action
getViews = async (doc: Doc) => {
- const results = await SearchUtil.GetViewsOfDocument(doc);
- let toReturn: Doc[] = [];
- await runInAction(() => {
- toReturn = results;
- });
- return toReturn;
+ return await SearchUtil.GetViewsOfDocument(doc);
}
@action.bound
@@ -241,7 +227,7 @@ export class SearchBox extends React.Component<SearchProps> {
@action.bound
getIcons(): string[] { return this._icons; }
-//TODO: basically all of this
+ //TODO: basically all of this
//gets all of the collections of all the docviews that are selected
//if a collection is the only thing selected, search only in that collection (not its container)
getCurCollections(): Doc[] {
@@ -308,7 +294,6 @@ export class SearchBox extends React.Component<SearchProps> {
get fieldFiltersApplied() { return !(this._authorFieldStatus && this._titleFieldStatus); }
-
@action
submitSearch = async () => {
let query = this._searchString;
@@ -317,22 +302,19 @@ export class SearchBox extends React.Component<SearchProps> {
this._resultsSet.clear();
this._isSearch = [];
this._visibleElements = [];
- if (query === "") {
- return;
- }
- else {
+ if (query !== "") {
this._endIndex = 12;
this._maxSearchIndex = 0;
this._numTotalResults = -1;
await this.getResults(query);
- }
- runInAction(() => {
- this._resultsOpen = true;
- this._searchbarOpen = true;
- this._openNoResults = true;
- this.resultsScrolled();
- });
+ runInAction(() => {
+ this._resultsOpen = true;
+ this._searchbarOpen = true;
+ this._openNoResults = true;
+ this.resultsScrolled();
+ });
+ }
}
getAllResults = async (query: string) => {
@@ -348,7 +330,6 @@ export class SearchBox extends React.Component<SearchProps> {
getDataStatus() { return this._deletedDocsStatus; }
-
private NumResults = 25;
private lockPromise?: Promise<void>;
getResults = async (query: string) => {
@@ -438,8 +419,7 @@ export class SearchBox extends React.Component<SearchProps> {
console.log("create");
//return Docs.Create.TreeDocument(docs, { _width: 200, _height: 400, backgroundColor: "grey", title: `Search Docs: "${this._searchString}"` });
//return Docs.Create.SearchDocument(docs, { _width: 200, _height: 400, searchText: this._searchString, title: `Search Docs: "${this._searchString}"` });
- return Docs.Create.QueryDocument({_autoHeight: true, title: this._searchString, fq: this.filterQuery, sq: this._searchString,
- });
+ return Docs.Create.QueryDocument({ _autoHeight: true, title: this._searchString, filterQuery: this.filterQuery, searchQuery: this._searchString });
}
@action.bound
@@ -469,11 +449,11 @@ export class SearchBox extends React.Component<SearchProps> {
@action
resultsScrolled = (e?: React.UIEvent<HTMLDivElement>) => {
- if (!this.resultsRef.current) return;
- const scrollY = e ? e.currentTarget.scrollTop : this.resultsRef.current ? this.resultsRef.current.scrollTop : 0;
+ if (!this._resultsRef.current) return;
+ const scrollY = e ? e.currentTarget.scrollTop : this._resultsRef.current ? this._resultsRef.current.scrollTop : 0;
const itemHght = 53;
const startIndex = Math.floor(Math.max(0, scrollY / itemHght));
- const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this.resultsRef.current.getBoundingClientRect().height / itemHght)));
+ const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this._resultsRef.current.getBoundingClientRect().height / itemHght)));
this._endIndex = endIndex === -1 ? 12 : endIndex;
@@ -548,10 +528,10 @@ export class SearchBox extends React.Component<SearchProps> {
@action.bound
handleNodeChange = () => {
this._nodeStatus = !this._nodeStatus;
- if (this._nodeStatus){
+ if (this._nodeStatus) {
this.expandSection(`node${this.props.id}`)
}
- else{
+ else {
this.collapseSection(`node${this.props.id}`)
}
}
@@ -559,109 +539,107 @@ export class SearchBox extends React.Component<SearchProps> {
@action.bound
handleKeyChange = () => {
this._keyStatus = !this._keyStatus;
- if (this._keyStatus){
+ if (this._keyStatus) {
this.expandSection(`key${this.props.id}`);
}
- else{
+ else {
this.collapseSection(`key${this.props.id}`);
}
}
- @action.bound
- handleFilterChange=() =>{
- this._filterOpen=!this._filterOpen;
- if (this._filterOpen){
+ @action.bound
+ handleFilterChange = () => {
+ this._filterOpen = !this._filterOpen;
+ if (this._filterOpen) {
this.expandSection(`filterhead${this.props.id}`);
- document.getElementById(`filterhead${this.props.id}`)!.style.padding="5";
+ document.getElementById(`filterhead${this.props.id}`)!.style.padding = "5";
}
- else{
+ else {
this.collapseSection(`filterhead${this.props.id}`);
-
+
}
}
- // @observable
- // private menuHeight= 0;
@computed
- get menuHeight(){
+ get menuHeight() {
return document.getElementById("hi")?.clientHeight;
}
- collapseSection(thing:string) {
+ collapseSection(thing: string) {
let id = this.props.id;
- let element= document.getElementById(thing)!;
+ let element = document.getElementById(thing)!;
// get the height of the element's inner content, regardless of its actual size
var sectionHeight = element.scrollHeight;
-
+
// temporarily disable all css transitions
var elementTransition = element.style.transition;
element.style.transition = '';
-
+
// on the next frame (as soon as the previous style change has taken effect),
// explicitly set the element's height to its current pixel height, so we
// aren't transitioning out of 'auto'
- requestAnimationFrame(function() {
- element.style.height = sectionHeight + 'px';
- element.style.transition = elementTransition;
-
- // on the next frame (as soon as the previous style change has taken effect),
- // have the element transition to height: 0
- requestAnimationFrame(function() {
- element.style.height = 0 + 'px';
- thing == `filterhead${id}`? document.getElementById(`filterhead${id}`)!.style.padding="0" : null;
- });
+ requestAnimationFrame(function () {
+ element.style.height = sectionHeight + 'px';
+ element.style.transition = elementTransition;
+
+ // on the next frame (as soon as the previous style change has taken effect),
+ // have the element transition to height: 0
+ requestAnimationFrame(function () {
+ element.style.height = 0 + 'px';
+ thing == `filterhead${id}` ? document.getElementById(`filterhead${id}`)!.style.padding = "0" : null;
+ });
});
-
+
// mark the section as "currently collapsed"
element.setAttribute('data-collapsed', 'true');
- }
-
- expandSection(thing:string) {
+ }
+
+ expandSection(thing: string) {
console.log("expand");
- let element= document.getElementById(thing)!;
+ let element = document.getElementById(thing)!;
// get the height of the element's inner content, regardless of its actual size
var sectionHeight = element.scrollHeight;
-
+
// have the element transition to the height of its inner content
- let temp = element.style.height;
+ let temp = element.style.height;
element.style.height = sectionHeight + 'px';
-
+
// when the next css transition finishes (which should be the one we just triggered)
element.addEventListener('transitionend', function handler(e) {
- // remove this event listener so it only gets triggered once
- console.log("autoset");
- element.removeEventListener('transitionend', handler);
-
- // remove "height" from the element's inline styles, so it can return to its initial value
- element.style.height="auto";
- //element.style.height = undefined;
+ // remove this event listener so it only gets triggered once
+ console.log("autoset");
+ element.removeEventListener('transitionend', handler);
+
+ // remove "height" from the element's inline styles, so it can return to its initial value
+ element.style.height = "auto";
+ //element.style.height = undefined;
});
-
+
// mark the section as "currently not collapsed"
element.setAttribute('data-collapsed', 'false');
-
- }
- autoset(thing: string){
- let element= document.getElementById(thing)!;
+ }
+
+ autoset(thing: string) {
+ let element = document.getElementById(thing)!;
console.log("autoset");
- element.removeEventListener('transitionend', function(e){});
-
+ element.removeEventListener('transitionend', function (e) { });
+
// remove "height" from the element's inline styles, so it can return to its initial value
- element.style.height="auto";
+ element.style.height = "auto";
//element.style.height = undefined;
- }
+ }
+
+ @action.bound
+ updateTitleStatus() { this._titleFieldStatus = !this._titleFieldStatus; }
+
+ @action.bound
+ updateAuthorStatus() { this._authorFieldStatus = !this._authorFieldStatus; }
- @action.bound
- updateTitleStatus() { this._titleFieldStatus = !this._titleFieldStatus; }
-
- @action.bound
- updateAuthorStatus() { this._authorFieldStatus = !this._authorFieldStatus; }
-
- @action.bound
- updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; }
+ @action.bound
+ updateDataStatus() { this._deletedDocsStatus = !this._deletedDocsStatus; }
render() {
@@ -678,55 +656,27 @@ export class SearchBox extends React.Component<SearchProps> {
</div>
<div id={`filterhead${this.props.id}`} className="filter-form" >
- <div id={`filterhead2${this.props.id}`} className="filter-header" style={this._filterOpen ? { } : { }}>
+ <div id={`filterhead2${this.props.id}`} className="filter-header" style={this._filterOpen ? {} : {}}>
<button className="filter-item" style={this._basicWordStatus ? { background: "#aaaaa3", } : {}} onClick={this.handleWordQueryChange}>Keywords</button>
<button className="filter-item" style={this._keyStatus ? { background: "#aaaaa3" } : {}} onClick={this.handleKeyChange}>Keys</button>
<button className="filter-item" style={this._nodeStatus ? { background: "#aaaaa3" } : {}} onClick={this.handleNodeChange}>Nodes</button>
</div>
- <div id={`node${this.props.id}`} className="filter-body" style={this._nodeStatus ? { borderTop: "grey 1px solid" }: {borderTop: "0px"}}>
+ <div id={`node${this.props.id}`} className="filter-body" style={this._nodeStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}>
<IconBar />
</div>
- <div className="filter-key" id={`key${this.props.id}`} style={this._keyStatus ? { borderTop: "grey 1px solid" }: {borderTop: "0px"}}>
+ <div className="filter-key" id={`key${this.props.id}`} style={this._keyStatus ? { borderTop: "grey 1px solid" } : { borderTop: "0px" }}>
<div className="filter-keybar">
<button className="filter-item" style={this._titleFieldStatus ? { background: "#aaaaa3", } : {}} onClick={this.updateTitleStatus}>Title</button>
- <button className="filter-item" style={this._deletedDocsStatus ? { background: "#aaaaa3", } : {}} onClick={this.updateDataStatus}>Deleted Docs</button>
- <button className="filter-item" style={this._authorFieldStatus ? { background: "#aaaaa3", } : {}} onClick={this.updateAuthorStatus}>Author</button>
+ <button className="filter-item" style={this._deletedDocsStatus ? { background: "#aaaaa3", } : {}} onClick={this.updateDataStatus}>Deleted Docs</button>
+ <button className="filter-item" style={this._authorFieldStatus ? { background: "#aaaaa3", } : {}} onClick={this.updateAuthorStatus}>Author</button>
</div>
</div>
-
-
- {/* <div className="filter-options">
- <div className="filter-div">
- <div className="filter-header">
- <div className='filter-title words'>Required words</div>
- </div>
- <div className="filter-panel" >
- <button className="all-filter">Include All Keywords</button>
- </div>
- </div>
- <div className="filter-div">
- <div className="filter-header">
- <div className="filter-title icon">Filter by type of node</div>
- </div>
- <div className="filter-panel"></div>
- </div>
- <div className="filter-div">
- <div className="filter-header">
- <div className="filter-title field">Filter by Basic Keys</div>
- </div>
- <div className="filter-panel">
- <FieldFilters
- titleFieldStatus={this._titleFieldStatus} dataFieldStatus={this._deletedDocsStatus} authorFieldStatus={this._authorFieldStatus}
- updateAuthorStatus={this.updateAuthorStatus} updateDataStatus={this.updateDataStatus} updateTitleStatus={this.updateTitleStatus} /> </div>
- </div>
- </div>
- </div> */}
</div>
<div className="searchBox-results" onScroll={this.resultsScrolled} style={{
display: this._resultsOpen ? "flex" : "none",
height: this.resFull ? "auto" : this.resultHeight,
overflow: "visibile" // this.resFull ? "auto" : "visible"
- }} ref={this.resultsRef}>
+ }} ref={this._resultsRef}>
{this._visibleElements}
</div>
</div>
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 31667cbdc..d55d996d3 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -280,6 +280,13 @@ export class CurrentUserUtils {
/// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window
static setupExpandingButtons(doc: Doc) {
+ const queryTemplate = Docs.Create.MultirowDocument(
+ [
+ Docs.Create.QueryDocument({ title: "query", _height: 200 }),
+ Docs.Create.FreeformDocument([], { title: "data", _height: 100 })
+ ],
+ { _width: 400, _height: 300, title: "queryView", _chromeStatus: "disabled", _xMargin: 3, _yMargin: 3, _autoHeight: false });
+ queryTemplate.isTemplateDoc = makeTemplate(queryTemplate);
const slideTemplate = Docs.Create.MultirowDocument(
[
Docs.Create.MulticolumnDocument([], { title: "data", _height: 200 }),
@@ -303,7 +310,8 @@ export class CurrentUserUtils {
doc.redoBtn = ficon({ onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" });
doc.slidesBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: slideTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "presentation slide", icon: "sticky-note" });
doc.descriptionBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: descriptionTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "description view", icon: "sticky-note" });
- doc.templateButtons = blist({ title: "template buttons" }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc]);
+ doc.queryBtn = ficon({ onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: queryTemplate, removeDropProperties: new List<string>(["dropAction"]), title: "query view", icon: "sticky-note" });
+ doc.templateButtons = blist({ title: "template buttons" }, [doc.slidesBtn as Doc, doc.descriptionBtn as Doc, doc.queryBtn as Doc]);
doc.expandingButtons = blist({ title: "expanding buttons" }, [doc.undoBtn as Doc, doc.redoBtn as Doc, doc.templateButtons as Doc]);
doc.templateDocs = new PrefetchProxy(Docs.Create.TreeDocument([doc.noteTypes as Doc, doc.templateButtons as Doc], {
title: "template layouts", _xPadding: 0,