diff options
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 1 | ||||
-rw-r--r-- | src/client/views/EditableView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 9 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSchemaCells.tsx | 11 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/linking/LinkMenuItem.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentLinksButton.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextMenu.tsx | 3 | ||||
-rw-r--r-- | src/client/views/search/FieldFilters.scss | 12 | ||||
-rw-r--r-- | src/client/views/search/FieldFilters.tsx | 41 | ||||
-rw-r--r-- | src/client/views/search/FilterBox.scss | 178 | ||||
-rw-r--r-- | src/client/views/search/FilterBox.tsx | 431 | ||||
-rw-r--r-- | src/server/websocket.ts | 8 |
14 files changed, 25 insertions, 683 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index ea701ec33..53d187aa0 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -771,7 +771,6 @@ export class CurrentUserUtils { // setup the list of sidebar mode buttons which determine what is displayed in the sidebar static async setupSidebarButtons(doc: Doc) { - this.setupSidebarContainer(doc); await CurrentUserUtils.setupToolsBtnPanel(doc); CurrentUserUtils.setupWorkspaces(doc); CurrentUserUtils.setupCatalog(doc); diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index a5628d5ee..ec3e754fb 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -197,11 +197,11 @@ export class EditableView extends React.Component<EditableProps> { // contents = String(this.props.contents.valueOf()); - results.push(<span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize, color: this.props.contents ? "black" : "grey" }}>{contents ? contents.slice(0, this.props.positions![0]) : this.props.placeholder?.valueOf()}</span>); + results.push(<span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize, color: this.props.contents ? "black" : "grey" }}>{contents ? contents.slice(0, this.props.positions[0]) : this.props.placeholder?.valueOf()}</span>); positions.forEach((num, cur) => { results.push(<span style={{ backgroundColor: "#FFFF00", fontStyle: this.props.fontStyle, fontSize: this.props.fontSize, color: this.props.contents ? "black" : "grey" }}>{contents ? contents.slice(num, num + length) : this.props.placeholder?.valueOf()}</span>); let end = 0; - cur === positions.length - 1 ? end = contents!.length : end = positions[cur + 1]; + cur === positions.length - 1 ? end = contents.length : end = positions[cur + 1]; results.push(<span style={{ fontStyle: this.props.fontStyle, fontSize: this.props.fontSize, color: this.props.contents ? "black" : "grey" }}>{contents ? contents.slice(num + length, end) : this.props.placeholder?.valueOf()}</span>); } ); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 119fa3451..1b2dd1c44 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -82,8 +82,8 @@ export class MainView extends React.Component { @computed public get mainFreeform(): Opt<Doc> { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } @computed public get searchDoc() { return Cast(this.userDoc["search-panel"], Doc) as Doc; } - - @observable public sidebarContent: any = this.userDoc?.["sidebar"]; + sidebar: string = "sidebar"; + @observable public sidebarContent: any = this.userDoc?.[this.sidebar]; @observable public panelContent: string = "none"; @observable public showProperties: boolean = false; public isPointerDown = false; @@ -193,8 +193,9 @@ export class MainView extends React.Component { } if (targets && targets.length && SearchBox.Instance._searchbarOpen) { let check = false; + const icon = "icon"; targets.forEach((thing) => { - if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset["icon"] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") { + if (thing.className.toString() === "collectionSchemaView-table" || (thing as any)?.dataset[icon] === "filter" || thing.className.toString() === "beta" || thing.className.toString() === "collectionSchemaView-menuOptions-wrapper") { check = true; } }); @@ -731,7 +732,7 @@ export class MainView extends React.Component { @computed get search() { return <div className="mainView-searchPanel"> {/* <div style={{ float: "left", marginLeft: "10px" }}>{Doc.CurrentUserEmail}</div> */} - <div><DocumentView Document={this.searchDoc!} + <div><DocumentView Document={this.searchDoc} DataDoc={undefined} LibraryPath={emptyPath} addDocument={undefined} diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 7a80f4484..98b7b7739 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -32,6 +32,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import DatePicker from "react-datepicker"; import "react-datepicker/dist/react-datepicker.css"; import { DateField } from "../../../fields/DateField"; +import { RichTextField } from "../../../fields/RichTextField"; const path = require('path'); library.add(faExpand); @@ -292,8 +293,11 @@ export class CollectionSchemaCell extends React.Component<CellProps> { bing={() => { const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey])); if (cfield !== undefined) { - if (cfield.Text !== undefined) { - return (cfield.Text); + console.log(typeof (cfield)); + // if (typeof(cfield)===RichTextField) + const a = cfield as RichTextField; + if (a.Text !== undefined) { + return (a.Text); } else if (StrCast(cfield)) { return StrCast(cfield); @@ -884,7 +888,8 @@ export class CollectionSchemaButtons extends CollectionSchemaCell { // SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e)); // }; const doc = this.props.rowProps.original; - let buttons = <div style={{ + let buttons: JSX.Element | undefined = undefined; + buttons = <div style={{ paddingTop: 8, paddingLeft: 3, }}><button onClick={() => { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b896518ed..4025e25f9 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -151,10 +151,8 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: console.log(d); let newdocs = DocListCast(d.data); if (newdocs.length > 0) { - let vibecheck = false; - + let vibecheck: boolean | undefined = undefined; let newarray: Doc[] = []; - while (newdocs.length > 0) { newarray = []; newdocs.forEach((t) => { diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 6feb0a398..f4aed94e7 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -191,7 +191,6 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { case DocumentType.AUDIO: destinationIcon = "microphone"; break; case DocumentType.BUTTON: destinationIcon = "bolt"; break; case DocumentType.PRES: destinationIcon = "tv"; break; - case DocumentType.QUERY: destinationIcon = "search"; break; case DocumentType.SCRIPTING: destinationIcon = "terminal"; break; case DocumentType.IMPORT: destinationIcon = "cloud-upload-alt"; break; case DocumentType.DOCHOLDER: destinationIcon = "expand"; break; diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 4713ce447..025669b41 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -125,7 +125,7 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp } else if (this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink && DocumentLinksButton.StartLink !== this.props.View) { const linkDoc = DocUtils.MakeLink({ doc: DocumentLinksButton.StartLink.props.Document }, { doc: this.props.View.props.Document }, "long drag"); // this notifies any of the subviews that a document is made so that they can make finer-grained hyperlinks (). see note above in onLInkButtonMoved - DocumentLinksButton.StartLink!._link = this.props.View._link = linkDoc; + DocumentLinksButton.StartLink._link = this.props.View._link = linkDoc; setTimeout(action(() => DocumentLinksButton.StartLink!._link = this.props.View._link = undefined), 0); LinkManager.currentLink = linkDoc; if (linkDoc) { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index ab29f6889..a1f576029 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -236,7 +236,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) { this._applyingChange = true; - (curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()))) && (this.dataDoc["lastModified"] = new DateField(new Date(Date.now()))); + const lastmodified = "lastmodified"; + (curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()))) && (this.dataDoc[lastmodified] = new DateField(new Date(Date.now()))); if ((!curTemp && !curProto) || curText || curLayout?.Data.includes("dash")) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) if (json.replace(/"selection":.*/, "") !== curLayout?.Data.replace(/"selection":.*/, "")) { !curText && tx.storedMarks?.map(m => m.type.name === "pFontSize" && (Doc.UserDoc().fontSize = this.layoutDoc._fontSize = m.attrs.fontSize)); diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 6e268be48..5af07c15d 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -903,8 +903,9 @@ export default class RichTextMenu extends AntimodeMenu { ref_node = pos.nodeBefore; } if (pos.nodeAfter !== null && pos.nodeAfter !== undefined) { - if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos) + if (!pos.nodeBefore || this.view.state.selection.$from.pos !== this.view.state.selection.$to.pos) { ref_node = pos.nodeAfter; + } } if (!ref_node && pos.pos > 0) { let skip = false; diff --git a/src/client/views/search/FieldFilters.scss b/src/client/views/search/FieldFilters.scss deleted file mode 100644 index e1d0d8df5..000000000 --- a/src/client/views/search/FieldFilters.scss +++ /dev/null @@ -1,12 +0,0 @@ -.field-filters { - width: 100%; - display: grid; - // grid-template-columns: 18% 20% 60%; - grid-template-columns: 20% 25% 60%; -} - -.field-filters-required { - width: 100%; - display: grid; - grid-template-columns: 50% 50%; -}
\ No newline at end of file diff --git a/src/client/views/search/FieldFilters.tsx b/src/client/views/search/FieldFilters.tsx deleted file mode 100644 index 7a33282d2..000000000 --- a/src/client/views/search/FieldFilters.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from 'react'; -import { observable } from 'mobx'; -import { CheckBox } from './CheckBox'; -import { Keys } from './FilterBox'; -import "./FieldFilters.scss"; - -export interface FieldFilterProps { - titleFieldStatus: boolean; - dataFieldStatus: boolean; - authorFieldStatus: boolean; - updateTitleStatus(stat: boolean): void; - updateAuthorStatus(stat: boolean): void; - updateDataStatus(stat: boolean): void; -} - -export class FieldFilters extends React.Component<FieldFilterProps> { - - static Instance: FieldFilters; - - @observable public _resetBoolean = false; - @observable public _resetCounter: number = 0; - - constructor(props: FieldFilterProps) { - super(props); - FieldFilters.Instance = this; - } - - resetFieldFilters() { - this._resetBoolean = true; - } - - render() { - return ( - <div className="field-filters"> - <CheckBox default={true} numCount={3} parent={this} originalStatus={this.props.titleFieldStatus} updateStatus={this.props.updateTitleStatus} title={Keys.TITLE} /> - <CheckBox default={true} numCount={3} parent={this} originalStatus={this.props.authorFieldStatus} updateStatus={this.props.updateAuthorStatus} title={Keys.AUTHOR} /> - <CheckBox default={false} numCount={3} parent={this} originalStatus={this.props.dataFieldStatus} updateStatus={this.props.updateDataStatus} title={"Deleted Docs"} /> - </div> - ); - } -}
\ No newline at end of file diff --git a/src/client/views/search/FilterBox.scss b/src/client/views/search/FilterBox.scss deleted file mode 100644 index 094ea9cc5..000000000 --- a/src/client/views/search/FilterBox.scss +++ /dev/null @@ -1,178 +0,0 @@ -@import "../globalCssVariables"; -@import "./NaviconButton.scss"; - -.filter-form { - padding: 25px; - width: 440px; - position: relative; - right: 1px; - color: grey; - flex-direction: column; - display: inline-block; - transform-origin: top; - overflow: auto; - border-bottom: solid black 3px; - - .top-filter-header { - - #header { - text-transform: uppercase; - letter-spacing: 2px; - font-size: 13; - width: 80%; - } - - .close-icon { - width: 20%; - opacity: .6; - position: relative; - display: block; - - .line { - display: block; - background: $alt-accent; - width: 20; - height: 3; - position: absolute; - right: 0; - border-radius: ($height-line / 2); - - &.line-1 { - transform: rotate(45deg); - top: 45%; - } - - &.line-2 { - transform: rotate(-45deg); - top: 45%; - } - } - } - - .close-icon:hover { - opacity: 1; - } - - } - - .filter-options { - - .filter-div { - margin-top: 10px; - margin-bottom: 10px; - display: inline-block; - width: 100%; - border-color: rgba(178, 206, 248, .2); // $darker-alt-accent - border-top-style: solid; - - .filter-header { - display: flex; - align-items: center; - margin-bottom: 10px; - letter-spacing: 2px; - - .filter-title { - font-size: 13; - text-transform: uppercase; - margin-top: 10px; - margin-bottom: 10px; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - } - } - - .filter-header:hover .filter-title { - transform: scale(1.05); - } - - .filter-panel { - max-height: 0px; - width: 100%; - overflow: hidden; - opacity: 0; - transform-origin: top; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - text-align: center; - } - } - } - - .filter-buttons { - border-color: rgba(178, 206, 248, .2); // $darker-alt-accent - border-top-style: solid; - padding-top: 10px; - } -} - -.active-filters { - display: flex; - flex-direction: row-reverse; - justify-content: flex-end; - width: 100%; - margin-right: 30px; - position: relative; - - .active-icon { - max-width: 40px; - flex: initial; - - &.icon { - width: 40px; - text-align: center; - margin-bottom: 5px; - position: absolute; - } - - &.container { - display: flex; - flex-direction: column; - width: 40px; - } - - &.description { - text-align: center; - top: 40px; - position: absolute; - width: 40px; - font-size: 9px; - opacity: 0; - -webkit-transition: all 0.2s ease-in-out; - -moz-transition: all 0.2s ease-in-out; - -o-transition: all 0.2s ease-in-out; - transition: all 0.2s ease-in-out; - } - - &.icon:hover+.description { - opacity: 1; - } - } - - .col-icon { - height: 35px; - margin-left: 5px; - width: 35px; - background-color: black; - color: white; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - - .save-filter, - .reset-filter, - .all-filter { - background-color: gray; - } - - .save-filter:hover, - .reset-filter:hover, - .all-filter:hover { - background-color: $darker-alt-accent; - } - } -}
\ No newline at end of file diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx deleted file mode 100644 index eb61f9a14..000000000 --- a/src/client/views/search/FilterBox.tsx +++ /dev/null @@ -1,431 +0,0 @@ -import * as React from 'react'; -import { observer } from 'mobx-react'; -import { observable, action } from 'mobx'; -import "./SearchBox.scss"; -import { faTimes, faCheckCircle, faObjectGroup } from '@fortawesome/free-solid-svg-icons'; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { Doc } from '../../../fields/Doc'; -import { Id } from '../../../fields/FieldSymbols'; -import { DocumentType } from "../../documents/DocumentTypes"; -import { Cast, StrCast } from '../../../fields/Types'; -import * as _ from "lodash"; -import { IconBar } from './IconBar'; -import { FieldFilters } from './FieldFilters'; -import { SelectionManager } from '../../util/SelectionManager'; -import { DocumentView } from '../nodes/DocumentView'; -import { CollectionFilters } from './CollectionFilters'; -import * as $ from 'jquery'; -import "./FilterBox.scss"; -import { SearchBox } from './SearchBox'; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -library.add(faTimes); -library.add(faCheckCircle); -library.add(faObjectGroup); - -export enum Keys { - TITLE = "title", - AUTHOR = "author", - DATA = "data" -} - -@observer -export class FilterBox extends React.Component { - - static Instance: FilterBox; - public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.RTF, DocumentType.VID, DocumentType.WEB]; - - //if true, any keywords can be used. if false, all keywords are required. - //this also serves as an indicator if the word status filter is applied - @observable private _basicWordStatus: boolean = true; - @observable private _filterOpen: boolean = false; - //if icons = all icons, then no icon filter is applied - @observable private _icons: string[] = this._allIcons; - //if all of these are true, no key filter is applied - @observable private _anyKeywordStatus: boolean = true; - @observable private _allKeywordStatus: boolean = true; - @observable private _titleFieldStatus: boolean = true; - @observable private _authorFieldStatus: boolean = true; - @observable private _dataFieldStatus: boolean = true; - //this also serves as an indicator if the collection status filter is applied - @observable public _deletedDocsStatus: boolean = false; - @observable private _collectionStatus = false; - @observable private _collectionSelfStatus = true; - @observable private _collectionParentStatus = true; - @observable private _wordStatusOpen: boolean = false; - @observable private _typeOpen: boolean = false; - @observable private _colOpen: boolean = false; - @observable private _fieldOpen: boolean = false; - public _pointerTime: number = -1; - - constructor(props: Readonly<{}>) { - super(props); - FilterBox.Instance = this; - } - setupAccordion() { - $('document').ready(function () { - const acc = document.getElementsByClassName('filter-header'); - // tslint:disable-next-line: prefer-for-of - for (let i = 0; i < acc.length; i++) { - acc[i].addEventListener("click", function (this: HTMLElement) { - this.classList.toggle("active"); - - const panel = this.nextElementSibling as HTMLElement; - if (panel.style.maxHeight) { - panel.style.overflow = "hidden"; - panel.style.maxHeight = ""; - panel.style.opacity = "0"; - } else { - setTimeout(() => { - panel.style.overflow = "visible"; - }, 200); - setTimeout(() => { - panel.style.opacity = "1"; - }, 50); - panel.style.maxHeight = panel.scrollHeight + "px"; - - } - }); - - const el = acc[i] as HTMLElement; - el.click(); - } - }); - } - - @action.bound - minimizeAll() { - $('document').ready(function () { - const acc = document.getElementsByClassName('filter-header'); - - // tslint:disable-next-line: prefer-for-of - for (var i = 0; i < acc.length; i++) { - const classList = acc[i].classList; - if (classList.contains("active")) { - acc[i].classList.toggle("active"); - const panel = acc[i].nextElementSibling as HTMLElement; - panel.style.overflow = "hidden"; - panel.style.maxHeight = ""; - } - } - }); - } - - @action.bound - resetFilters = () => { - this._basicWordStatus = true; - IconBar.Instance.selectAll(); - FieldFilters.Instance.resetFieldFilters(); - } - - basicRequireWords(query: string): string { - const oldWords = query.split(" "); - const newWords: string[] = []; - oldWords.forEach(word => { - const newWrd = "+" + word; - newWords.push(newWrd); - }); - query = newWords.join(" "); - - return query; - } - - basicFieldFilters(query: string, type: string): string { - const oldWords = query.split(" "); - let mod = ""; - - if (type === Keys.AUTHOR) { - mod = " author_t:"; - } if (type === Keys.DATA) { - //TODO - } if (type === Keys.TITLE) { - mod = " title_t:"; - } - - const newWords: string[] = []; - oldWords.forEach(word => { - const newWrd = mod + word; - newWords.push(newWrd); - }); - - query = newWords.join(" "); - - return query; - } - - applyBasicFieldFilters(query: string) { - let finalQuery = ""; - - if (this._titleFieldStatus) { - finalQuery = finalQuery + this.basicFieldFilters(query, Keys.TITLE); - } - if (this._authorFieldStatus) { - finalQuery = finalQuery + this.basicFieldFilters(query, Keys.AUTHOR); - } - if (this._deletedDocsStatus) { - finalQuery = finalQuery + this.basicFieldFilters(query, Keys.DATA); - } - return finalQuery; - } - - get fieldFiltersApplied() { return !(this._authorFieldStatus && this._titleFieldStatus); } - - //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[] { - const selectedDocs: DocumentView[] = SelectionManager.SelectedDocuments(); - const collections: Doc[] = []; - - selectedDocs.forEach(async element => { - const layout: string = StrCast(element.props.Document.layout); - //checks if selected view (element) is a collection. if it is, adds to list to search through - if (layout.indexOf("Collection") > -1) { - //makes sure collections aren't added more than once - if (!collections.includes(element.props.Document)) { - collections.push(element.props.Document); - } - } - //makes sure collections aren't added more than once - if (element.props.ContainingCollectionDoc && !collections.includes(element.props.ContainingCollectionDoc)) { - collections.push(element.props.ContainingCollectionDoc); - } - }); - - return collections; - } - - getFinalQuery(query: string): string { - //alters the query so it looks in the correct fields - //if this is true, then not all of the field boxes are checked - //TODO: data - if (this.fieldFiltersApplied) { - query = this.applyBasicFieldFilters(query); - query = query.replace(/\s+/g, ' ').trim(); - } - - //alters the query based on if all words or any words are required - //if this._wordstatus is false, all words are required and a + is added before each - if (!this._basicWordStatus) { - query = this.basicRequireWords(query); - query = query.replace(/\s+/g, ' ').trim(); - } - - //if should be searched in a specific collection - if (this._collectionStatus) { - query = this.addCollectionFilter(query); - query = query.replace(/\s+/g, ' ').trim(); - } - return query; - } - - addCollectionFilter(query: string): string { - const collections: Doc[] = this.getCurCollections(); - const oldWords = query.split(" "); - - const collectionString: string[] = []; - collections.forEach(doc => { - const proto = doc.proto; - const protoId = (proto || doc)[Id]; - const colString: string = "{!join from=data_l to=id}id:" + protoId + " "; - collectionString.push(colString); - }); - - let finalColString = collectionString.join(" "); - finalColString = finalColString.trim(); - return "+(" + finalColString + ")" + query; - } - - get filterTypes() { - return this._icons.length === 9 ? undefined : this._icons; - } - - @action - filterDocsByType(docs: Doc[]) { - if (this._icons.length === 9) { - return docs; - } - const finalDocs: Doc[] = []; - docs.forEach(doc => { - const layoutresult = Cast(doc.type, "string"); - if (layoutresult && this._icons.includes(layoutresult)) { - finalDocs.push(doc); - } - }); - return finalDocs; - } - - getABCicon() { - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35"> - <path d="M25.4 47.9c-1.3 1.3-1.9 2.8-1.9 4.8 0 3.8 2.3 6.1 6.1 6.1 5.1 0 8-3.3 9-6.2 0.2-0.7 0.4-1.4 0.4-2.1v-6.1c-0.1 0-0.1 0-0.2 0C32.2 44.5 27.7 45.6 25.4 47.9z" /> - <path d="M64.5 28.6c-2.2 0-4.1 1.5-4.7 3.8l0 0.2c-0.1 0.3-0.1 0.7-0.1 1.1v3.3c0 0.4 0.1 0.8 0.2 1.1 0.6 2.2 2.4 3.6 4.6 3.6 3.2 0 5.2-2.6 5.2-6.7C69.5 31.8 68 28.6 64.5 28.6z" /> - <path d="M43.9 0C19.7 0 0 19.7 0 43.9s19.7 43.9 43.9 43.9 43.9-19.6 43.9-43.9S68.1 0 43.9 0zM40.1 65.5l-0.5-4c-3 3.1-7.4 4.9-12.1 4.9 -6.8 0-13.6-4.4-13.6-12.8 0-4 1.3-7.4 4-10 4.1-4.1 11.1-6.2 20.8-6.3 0-5.5-2.9-8.4-8.3-8.4 -3.6 0-7.4 1.1-10.2 2.9l-1.1 0.7 -2.4-6.9 0.7-0.4c3.7-2.4 8.9-3.8 14.1-3.8 10.9 0 16.7 6.2 16.7 17.9V54.6c0 4.1 0.2 7.2 0.7 9.7L49 65.5H40.1zM65.5 67.5c1.8 0 3-0.5 4-0.9l0.5-0.2 0.8 3.4 -0.3 0.2c-1 0.5-3 1.1-5.5 1.1 -5.8 0-9.7-4-9.7-9.9 0-6.1 4.3-10.3 10.4-10.3 2.1 0 4 0.5 4.9 1l0.3 0.2 -1 3.5 -0.5-0.3c-0.7-0.4-1.8-0.8-3.7-0.8 -3.7 0-6.1 2.6-6.1 6.6C59.5 64.8 61.9 67.5 65.5 67.5zM65 45.3c-2.5 0-4.5-0.9-5.9-2.7l-0.1 2.3h-3.8l0-0.5c0.1-1.2 0.2-3.1 0.2-4.8V16.7h4.3v10.8c1.4-1.6 3.5-2.5 6-2.5 2.2 0 4.1 0.8 5.5 2.3 1.8 1.8 2.8 4.5 2.8 7.7C73.8 42.1 69.3 45.3 65 45.3z" /> - </svg> - ); - } - - getTypeIcon() { - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35"> - <path d="M43.9 0C19.7 0 0 19.7 0 43.9s19.7 43.9 43.9 43.9 43.9-19.6 43.9-43.9S68.1 0 43.9 0zM43.9 12.2c4.1 0 7.5 3.4 7.5 7.5 0 4.1-3.4 7.5-7.5 7.5 -4.1 0-7.5-3.4-7.5-7.5C36.4 15.5 39.7 12.2 43.9 12.2zM11.9 50.4l7.5-13 7.5 13H11.9zM47.6 75.7h-7.5l-3.7-6.5 3.8-6.5h7.5l3.8 6.5L47.6 75.7zM70.7 70.7c-0.2 0.2-0.4 0.3-0.7 0.3s-0.5-0.1-0.7-0.3l-25.4-25.4 -25.4 25.4c-0.2 0.2-0.4 0.3-0.7 0.3s-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1 0-1.4l25.4-25.4 -25.4-25.4c-0.4-0.4-0.4-1 0-1.4s1-0.4 1.4 0l25.4 25.4 25.4-25.4c0.4-0.4 1-0.4 1.4 0s0.4 1 0 1.4l-25.4 25.4 25.4 25.4C71.1 69.7 71.1 70.3 70.7 70.7zM61.4 51.4v-15h15v15H61.4z" /> - </svg> - ); - } - - getKeyIcon() { - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 87.8 87.8" height="35"> - <path d="M38.5 32.4c0 3.4-2.7 6.1-6.1 6.1 -3.4 0-6.1-2.7-6.1-6.1 0-3.4 2.8-6.1 6.1-6.1C35.8 26.3 38.5 29 38.5 32.4zM87.8 43.9c0 24.2-19.6 43.9-43.9 43.9S0 68.1 0 43.9C0 19.7 19.7 0 43.9 0S87.8 19.7 87.8 43.9zM66.8 60.3L50.2 43.7c-0.5-0.5-0.6-1.2-0.4-1.8 2.4-5.6 1.1-12.1-3.2-16.5 -5.9-5.8-15.4-5.8-21.2 0l0 0c-4.3 4.3-5.6 10.8-3.2 16.5 3.2 7.6 12 11.2 19.7 8 0.6-0.3 1.4-0.1 1.8 0.4l3.1 3.1h3.9c1.2 0 2.2 1 2.2 2.2v3.6h3.6c1.2 0 2.2 1 2.2 2.2v4l1.6 1.6h6.5V60.3z" /> - </svg> - ); - } - - getColIcon() { - return ( - <div className="col-icon"> - <FontAwesomeIcon icon={faObjectGroup} size="lg" /> - </div> - ); - } - - @action.bound - openFilter = () => { - this._filterOpen = !this._filterOpen; - SearchBox.Instance.closeResults(); - this.setupAccordion(); - } - - //if true, any keywords can be used. if false, all keywords are required. - @action.bound - handleWordQueryChange = () => { - this._basicWordStatus = !this._basicWordStatus; - } - - @action.bound - updateIcon(newArray: string[]) { this._icons = newArray; } - - @action.bound - getIcons(): string[] { return this._icons; } - - stopProp = (e: React.PointerEvent) => { - e.stopPropagation(); - this._pointerTime = e.timeStamp; - } - - @action.bound - public closeFilter() { - this._filterOpen = false; - } - - @action.bound - updateAnyKeywordStatus(newStat: boolean) { this._anyKeywordStatus = newStat; } - - @action.bound - updateAllKeywordStatus(newStat: boolean) { this._allKeywordStatus = newStat; } - - @action.bound - updateTitleStatus(newStat: boolean) { this._titleFieldStatus = newStat; } - - @action.bound - updateAuthorStatus(newStat: boolean) { this._authorFieldStatus = newStat; } - - @action.bound - updateDataStatus(newStat: boolean) { this._deletedDocsStatus = newStat; } - - @action.bound - updateCollectionStatus(newStat: boolean) { this._collectionStatus = newStat; } - - @action.bound - updateSelfCollectionStatus(newStat: boolean) { this._collectionSelfStatus = newStat; } - - @action.bound - updateParentCollectionStatus(newStat: boolean) { this._collectionParentStatus = newStat; } - - getAnyKeywordStatus() { return this._anyKeywordStatus; } - getAllKeywordStatus() { return this._allKeywordStatus; } - getCollectionStatus() { return this._collectionStatus; } - getSelfCollectionStatus() { return this._collectionSelfStatus; } - getParentCollectionStatus() { return this._collectionParentStatus; } - getTitleStatus() { return this._titleFieldStatus; } - getAuthorStatus() { return this._authorFieldStatus; } - getDataStatus() { return this._deletedDocsStatus; } - - getActiveFilters() { - return ( - <div className="active-filters"> - {!this._basicWordStatus ? <div className="active-icon container"> - <div className="active-icon icon">{this.getABCicon()}</div> - <div className="active-icon description">Required Words Applied</div> - </div> : undefined} - {!(this._icons.length === 9) ? <div className="active-icon container"> - <div className="active-icon icon">{this.getTypeIcon()}</div> - <div className="active-icon description">Type Filters Applied</div> - </div> : undefined} - {!(this._authorFieldStatus && this._dataFieldStatus && this._titleFieldStatus) ? - <div className="active-icon container"> - <div className="active-icon icon">{this.getKeyIcon()}</div> - <div className="active-icon description">Field Filters Applied</div> - </div> : undefined} - {this._collectionStatus ? <div className="active-icon container"> - <div className="active-icon icon">{this.getColIcon()}</div> - <div className="active-icon description">Collection Filters Active</div> - </div> : undefined} - </div> - ); - } - - // Useful queries: - // Delegates of a document: {!join from=id to=proto_i}id:{protoId} - // Documents in a collection: {!join from=data_l to=id}id:{collectionProtoId} //id of collections prototype - render() { - return ( - <div> - <div style={{ display: "flex", flexDirection: "row-reverse" }}> - <SearchBox /> - {/* {this.getActiveFilters()} */} - </div> - {this._filterOpen ? ( - <div className="filter-form" onPointerDown={this.stopProp} id="filter-form" style={this._filterOpen ? { display: "flex", background: "black" } : { display: "none" }}> - <div className="top-filter-header" style={{ display: "flex", width: "100%" }}> - <div id="header">Filter Search Results</div> - <div style={{ marginLeft: "auto" }}></div> - <div className="close-icon" onClick={this.closeFilter}> - <span className="line line-1"></span> - <span className="line line-2"></span></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" onClick={this.handleWordQueryChange}>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"><IconBar /></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 className="filter-buttons" style={{ display: "flex", justifyContent: "space-around" }}> - <button className="save-filter" >Save Filters</button> - <button className="reset-filter" onClick={this.resetFilters}>Reset Filters</button> - </div> - </div> - ) : - undefined} - </div> - ); - } -}
\ No newline at end of file diff --git a/src/server/websocket.ts b/src/server/websocket.ts index cdce41a3a..2c8ec090a 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -286,16 +286,16 @@ export namespace WebSocket { dynfield = true; const val = docfield[key]; key = key.substring(7); - if (key==="_height"){ - Object.values(suffixMap).forEach(suf => {update[key] = { set: null };}); + if (key === "_height") { + Object.values(suffixMap).forEach(suf => { update[key] = { set: null }; }); } else { - Object.values(suffixMap).forEach(suf => {update[key + getSuffix(suf)] = { set: null };}); + Object.values(suffixMap).forEach(suf => { update[key + getSuffix(suf)] = { set: null }; }); } const term = ToSearchTerm(val); if (term !== undefined) { const { suffix, value } = term; - if (key==="_height"){ + if (key === "_height") { update[key] = { set: value }; } update[key + suffix] = { set: value }; |