From e9f8804a68327c64e1ade13081cab0b3b6c0ce21 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 15 Aug 2020 16:02:22 -0400 Subject: fixes for search -- need to rethink how to get a sortable string field (removed _s suffix for now). --- solr-8.3.1/server/solr/dash/conf/schema.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'solr-8.3.1/server') diff --git a/solr-8.3.1/server/solr/dash/conf/schema.xml b/solr-8.3.1/server/solr/dash/conf/schema.xml index a0496444b..4f6ae57b2 100644 --- a/solr-8.3.1/server/solr/dash/conf/schema.xml +++ b/solr-8.3.1/server/solr/dash/conf/schema.xml @@ -1,6 +1,7 @@ id + @@ -49,18 +50,18 @@ - + - + - + -- cgit v1.2.3-70-g09d2 From ab89ef62d3f11c11f3f6e7162ca0e112bac1517e Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 17 Aug 2020 15:55:17 -0400 Subject: added sort to solr search options. removed delete field assignment when removing Documents. Allowed ToScriptScript and ToString to go through regardless of ACLs --- solr-8.3.1/server/solr/dash/conf/schema.xml | 2 +- src/client/util/SearchUtil.ts | 3 ++- src/client/views/DocComponent.tsx | 1 - src/client/views/collections/CollectionSchemaCells.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 - src/client/views/search/SearchBox.tsx | 17 +++++++++++++++-- src/fields/Doc.ts | 16 +++++----------- src/fields/util.ts | 4 ++-- 8 files changed, 26 insertions(+), 20 deletions(-) (limited to 'solr-8.3.1/server') diff --git a/solr-8.3.1/server/solr/dash/conf/schema.xml b/solr-8.3.1/server/solr/dash/conf/schema.xml index 4f6ae57b2..74c4b494c 100644 --- a/solr-8.3.1/server/solr/dash/conf/schema.xml +++ b/solr-8.3.1/server/solr/dash/conf/schema.xml @@ -51,7 +51,7 @@ - + diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 6dafbd58e..ce96ab67b 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -28,6 +28,7 @@ export namespace SearchUtil { start?: number; rows?: number; fq?: string; + sort?: string; allowAliases?: boolean; onlyAliases?: boolean; "facet"?: string; @@ -42,7 +43,7 @@ export namespace SearchUtil { if (options.onlyAliases) { replacedQuery = `{!join from=id to=proto_i}DEFAULT:${replacedQuery}`; } - const gotten = await rp.get(rpquery, { qs: { ...options, sort: "lastModified_d desc", q: replacedQuery } }); + const gotten = await rp.get(rpquery, { qs: { ...options, q: replacedQuery } }); const result: IdSearchResult = gotten.startsWith("<") ? { ids: [], docs: [], numFound: 0, lines: [] } : JSON.parse(gotten); if (!returnDocs) { return result; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 8c8bb6fde..23ce71c4f 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -135,7 +135,6 @@ export function ViewBoxAnnotatableComponent

{ Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey + "-annotations", doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; }); return true; } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index d46aa3574..fa4d8c51b 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -297,7 +297,7 @@ export class CollectionSchemaCell extends React.Component { let cfield = props.Document[props.fieldKey]; this.type = props.fieldKey; if (StrCast(this.props.Document._searchString).toLowerCase() !== "") { - let term = Field.toString(cfield as Field); + let term = (cfield instanceof Promise) ? "...promise pending..." : Field.toString(cfield as Field); term = term.toLowerCase(); const search = StrCast(this.props.Document._searchString).toLowerCase(); let start = term.indexOf(search); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 9d305145e..2064b0be4 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -208,7 +208,6 @@ export class CollectionView extends Touchable { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; }); return true; } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 07f1485c3..847bda137 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -4,7 +4,7 @@ import { action, computed, observable, runInAction, reaction, IReactionDisposer import { observer } from 'mobx-react'; import * as React from 'react'; import * as rp from 'request-promise'; -import { Doc, DocListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -24,6 +24,7 @@ import { ViewBoxBaseComponent } from "../DocComponent"; import { DocumentView } from '../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; +import { ColumnType } from "../collections/CollectionSchemaView"; export const searchSchema = createSchema({ id: "string", @@ -616,6 +617,18 @@ export class SearchBox extends ViewBoxBaseComponent { + switch (type) { + case ColumnType.Date: return "_d"; + case ColumnType.String: return "_t"; + case ColumnType.Boolean: return "_b"; + case ColumnType.Number: return "_n"; + } + } + const headers = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); + return headers.reduce((p: Opt, header: SchemaHeaderField) => p || (header.desc !== undefined && suffixMap(header.type) ? (header.heading + suffixMap(header.type) + (header.desc ? " desc" : " asc")) : undefined), undefined); + } private NumResults = 50; private lockPromise?: Promise; getResults = async (query: string) => { @@ -624,7 +637,7 @@ export class SearchBox extends ViewBoxBaseComponent { while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, sort: this.primarySort, fq: this.filterQuery, start: 0, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5f5fe98bc..0dcb8ab42 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -195,6 +195,8 @@ export class Doc extends RefField { @observable private ___fieldKeys: any = {}; + @observable + public [AclSym]: { [key: string]: symbol }; private [UpdatingFromServer]: boolean = false; @@ -204,17 +206,9 @@ export class Doc extends RefField { private [Self] = this; private [SelfProxy]: any; - public [FieldsSym] = (clear?: boolean) => { - if (clear) { - this.___fields = {}; - this.___fieldKeys = {}; - } - return this.___fields; - } - @observable - public [AclSym]: { [key: string]: symbol }; - public [WidthSym] = () => NumCast(this[SelfProxy]._width); - public [HeightSym] = () => NumCast(this[SelfProxy]._height); + public [FieldsSym](clear?: boolean) { return clear ? this.___fields = this.___fieldKeys = {} : this.___fields; } + public [WidthSym]() { return NumCast(this[SelfProxy]._width); } + public [HeightSym]() { return NumCast(this[SelfProxy]._height); } public [ToScriptString]() { return `DOC-"${this[Self][Id]}"-`; } public [ToString]() { return `Doc(${GetEffectiveAcl(this) === AclPrivate ? "-inaccessible-" : this.title})`; } public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; } diff --git a/src/fields/util.ts b/src/fields/util.ts index 3d832636f..e3d9ed2ef 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -5,7 +5,7 @@ import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action, trace } from "mobx"; -import { Parent, OnUpdate, Update, Id, SelfProxy, Self, HandleUpdate } from "./FieldSymbols"; +import { Parent, OnUpdate, Update, Id, SelfProxy, Self, HandleUpdate, ToString, ToScriptString } from "./FieldSymbols"; import { DocServer } from "../client/DocServer"; import { ComputedField } from "./ScriptField"; import { ScriptCast, StrCast } from "./Types"; @@ -286,7 +286,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an export function getter(target: any, in_prop: string | symbol | number, receiver: any): any { let prop = in_prop; - if (in_prop === FieldsSym || in_prop === Id || in_prop === HandleUpdate || in_prop === CachedUpdates) return target.__fields[prop] || target[prop]; + if (in_prop === ToString || in_prop === ToScriptString || in_prop === FieldsSym || in_prop === Id || in_prop === HandleUpdate || in_prop === CachedUpdates) return target.__fields[prop] || target[prop]; if (in_prop === AclSym) return _overrideAcl ? undefined : target[AclSym]; if (GetEffectiveAcl(target) === AclPrivate && !_overrideAcl) return prop === HeightSym || prop === WidthSym ? returnZero : undefined; if (prop === LayoutSym) { -- cgit v1.2.3-70-g09d2 From 4ab5484797ccc39a4e7924135f92259c2b15d88f Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 1 Sep 2020 23:15:55 -0400 Subject: trying new solr schema that splits words on whitespace. fixed context menu clicking in schema/search view. --- solr-8.3.1/server/solr/dash/conf/characters.txt | 3 +++ solr-8.3.1/server/solr/dash/conf/schema.xml | 24 +++++++++++++--------- src/client/util/SearchUtil.ts | 4 ++-- src/client/views/MainView.tsx | 4 +++- src/client/views/PropertiesView.tsx | 15 +++++++++++--- .../CollectionSchemaMovableTableHOC.tsx | 1 + src/client/views/search/SearchBox.tsx | 2 +- src/server/ApiManagers/SearchManager.ts | 2 +- src/server/Search.ts | 5 ++--- 9 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 solr-8.3.1/server/solr/dash/conf/characters.txt (limited to 'solr-8.3.1/server') diff --git a/solr-8.3.1/server/solr/dash/conf/characters.txt b/solr-8.3.1/server/solr/dash/conf/characters.txt new file mode 100644 index 000000000..3a4c81bc8 --- /dev/null +++ b/solr-8.3.1/server/solr/dash/conf/characters.txt @@ -0,0 +1,3 @@ +\# => ALPHA +@ => ALPHA +\u0023 => ALPHA \ No newline at end of file diff --git a/solr-8.3.1/server/solr/dash/conf/schema.xml b/solr-8.3.1/server/solr/dash/conf/schema.xml index 74c4b494c..11078caeb 100644 --- a/solr-8.3.1/server/solr/dash/conf/schema.xml +++ b/solr-8.3.1/server/solr/dash/conf/schema.xml @@ -5,19 +5,23 @@ - + - - - - - + + + + + + + - - - - + + + + + + diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index b34acce27..b09eff849 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -23,7 +23,7 @@ export namespace SearchUtil { } export interface SearchParams { - hl?: boolean; + hl?: string; "hl.fl"?: string; start?: number; rows?: number; @@ -39,7 +39,7 @@ export namespace SearchUtil { export async function Search(query: string, returnDocs: boolean, options: SearchParams = {}) { query = query || "*"; //If we just have a filter query, search for * as the query const rpquery = Utils.prepend("/dashsearch"); - let replacedQuery = query.replace(/type_t:([^ )])/g, (substring, arg) => `{!join from=id to=proto_i}type_t:${arg}`); + let replacedQuery = query.replace(/type_t:([^ )])/g, (substring, arg) => `{!join from=id to=proto_i}*:* AND ${arg}`); if (options.onlyAliases) { const header = query.match(/_[atnb]?:/) ? replacedQuery : "DEFAULT:" + replacedQuery; replacedQuery = `{!join from=id to=proto_i}${header}`; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 7dddd1669..6db518f1e 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -55,6 +55,7 @@ import { PDFMenu } from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { SearchBox } from './search/SearchBox'; +import { TraceMobx } from '../../fields/util'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -152,7 +153,7 @@ export class MainView extends React.Component { const targets = document.elementsFromPoint(e.x, e.y); if (targets.length) { const targClass = targets[0].className.toString(); - if (SearchBox.Instance._searchbarOpen) { + if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { const check = targets.some((thing) => (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || thing.className === "collectionSchema-header-menuOptions")); @@ -520,6 +521,7 @@ export class MainView extends React.Component { } @computed get search() { + TraceMobx(); return

{ const docs = SelectionManager.SelectedDocuments().length < 2 ? [this.dataDoc] : SelectionManager.SelectedDocuments().map(dv => dv.dataDoc); docs.forEach(doc => Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key))); const rows: JSX.Element[] = []; - const noviceReqFields = ["author", "creationDate"]; + const noviceReqFields = ["author", "creationDate", "tags"]; const noviceLayoutFields = ["_curPage"]; const noviceKeys = [...Array.from(Object.keys(ids)).filter(key => key[0] === "#" || key.indexOf("lastModified") !== -1 || (key[0] === key[0].toUpperCase() && !key.startsWith("ACL"))), ...noviceReqFields, ...noviceLayoutFields]; @@ -234,11 +234,20 @@ export class PropertiesView extends React.Component { docs.forEach(doc => { if (value.indexOf(":") !== -1) { const newVal = value[0].toUpperCase() + value.substring(1, value.length); - KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); + const splits = newVal.split(":"); + KeyValueBox.SetField(doc, splits[0], splits[1], true); + const tags = StrCast(doc.tags, ":"); + if (tags.includes(`${splits[0]}:`) && splits[1] === "undefined") { + KeyValueBox.SetField(doc, "tags", `"${tags.replace(splits[0] + ":", "")}"`, true); + } return true; } else if (value[0] === "#") { const newVal = value + `:'${value}'`; - KeyValueBox.SetField(doc, newVal.substring(0, newVal.indexOf(":")), newVal.substring(newVal.indexOf(":") + 1, newVal.length), true); + KeyValueBox.SetField(doc, value, `'${value}'`, true); + const tags = StrCast(doc.tags, ":"); + if (!tags.includes(`#${value}:`)) { + KeyValueBox.SetField(doc, "tags", `"${tags + value + ':'}"`, true); + } return true; } }); diff --git a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx index 383a9312f..881246bd4 100644 --- a/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx +++ b/src/client/views/collections/CollectionSchemaMovableTableHOC.tsx @@ -201,6 +201,7 @@ export class MovableRow extends React.Component { } onRowContextMenu = (e: React.MouseEvent): void => { + e.preventDefault(); const description = this.props.rowWrapped ? "Unwrap text on row" : "Text wrap row"; ContextMenu.Instance.addItem({ description: description, event: () => this.props.textWrapRow(this.props.rowInfo.original), icon: "file-pdf" }); } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index e6fd64a3c..3d564f073 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -286,7 +286,7 @@ export class SearchBox extends ViewBoxBaseComponent { while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, /*sort: this.primarySort,*/ fq: this.filterQuery, start: 0, rows: this._numResultsPerPage, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, /*sort: this.primarySort,*/ fq: this.filterQuery, start: 0, rows: this._numResultsPerPage, hl: "on", "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { diff --git a/src/server/ApiManagers/SearchManager.ts b/src/server/ApiManagers/SearchManager.ts index a5aaab63e..a52430ee8 100644 --- a/src/server/ApiManagers/SearchManager.ts +++ b/src/server/ApiManagers/SearchManager.ts @@ -62,7 +62,7 @@ export class SearchManager extends ApiManager { subscription: "/dashsearch", secureHandler: async ({ req, res }) => { const solrQuery: any = {}; - ["q", "fq", "start", "rows", "sort", "hl", "hl.fl"].forEach(key => solrQuery[key] = req.query[key]); + ["q", "fq", "start", "rows", "sort", "hl.maxAnalyzedChars", "hl", "hl.fl"].forEach(key => solrQuery[key] = req.query[key]); if (solrQuery.q === undefined) { res.send([]); return; diff --git a/src/server/Search.ts b/src/server/Search.ts index 3869867cd..68f61deb2 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -29,9 +29,8 @@ export namespace Search { export async function search(query: any) { try { - const searchResults = JSON.parse(await rp.get(pathTo("select"), { - qs: query - })); + const output = await rp.get(pathTo("select"), { qs: query }); + const searchResults = JSON.parse(output); const { docs, numFound } = searchResults.response; const ids = docs.map((field: any) => field.id); return { ids, numFound, highlighting: searchResults.highlighting }; -- cgit v1.2.3-70-g09d2