From cfef242e9b76ba9caca2fc1871af74af6775538f Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Sep 2023 20:43:20 -0400 Subject: dropping link button on same collection makes a pushpin. fixed broken undo typing to crate doc in sidebar. fixed min/max scaling for cropped images and made annotationOverlays start to use it. Fixed nested text boxes to stopPropagation on pointer down to enable editing of translations in sidebar. moved sidebar filters onto doc's filters. Added metadata filters back to sidebar. Added an -any- option to filtersPanel. fixed schema view preview window, added buttons and sliders. --- src/client/views/FilterPanel.tsx | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 0d4f4df5a..a601706ce 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -235,7 +235,7 @@ export class FilterPanel extends React.Component { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); - const set = new Set([String.fromCharCode(127) + '--undefined--']); + const set = new Set([String.fromCharCode(127) + '--undefined--', Doc.FilterAny]); if (facetHeader === 'tags') allCollectionDocs.forEach(child => StrListCast(child[facetHeader]) @@ -257,24 +257,16 @@ export class FilterPanel extends React.Component { }; render() { - // console.log('this is frist one today ' + this._allFacets); - this._allFacets.forEach(element => console.log(element)); - // const options = Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => pair[1].filterable ).map(facet => value: facet, label: facet) //this._allFacets.filter(facet => this.activeFacetHeaders.indexOf(facet) === -1).map(facet => ({ value: facet, label: facet })); - // console.log('HEELLLLLL ' + DocumentOptions); - - let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest']; + let filteredOptions: string[] = ['author', 'tags', 'text', 'acl-Guest', ...this._allFacets.filter(facet => facet[0] === facet.charAt(0).toUpperCase())]; Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => { if (pair[1].filterable) { filteredOptions.push(pair[0]); - console.log('THIS IS FILTERABLE ALKDJFIIEII' + filteredOptions); } }); let options = filteredOptions.map(facet => ({ value: facet, label: facet })); - // Object.entries(this._documentOptions).forEach((pair: [string, FInfo]) => console.log('this is first piar ' + pair[0] + ' this is second piar ' + pair[1].filterable)); - return (
@@ -398,13 +390,13 @@ export class FilterPanel extends React.Component {
filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue) - ?.split(Doc.FilterSep)[2] === 'check' - } + ?.split(Doc.FilterSep)[2] ?? '' + )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? (fval === Doc.FilterAny ? 'exists' : 'check') : 'remove'), 'set filter')} /> {facetValue}
-- cgit v1.2.3-70-g09d2 From 5b6c52fe703757a5d6ad1fccab935fae297189bb Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 13 Sep 2023 12:58:48 -0400 Subject: fixed text filters to be removable, have the right colors, and update when selected doc changes. updated filter dropdown to only show parents with filters. fixed colors of link doc preview. --- src/client/views/FilterPanel.tsx | 22 +++++++++++++++------- src/client/views/StyleProvider.tsx | 4 +++- src/client/views/nodes/LinkDocPreview.tsx | 4 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index a601706ce..4af29c70e 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -16,6 +16,7 @@ import './FilterPanel.scss'; import { FieldView } from './nodes/FieldView'; import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; import { SettingsManager } from '../util/SettingsManager'; +import { Id } from '../../fields/FieldSymbols'; interface filterProps { rootDoc: Doc; @@ -341,9 +342,13 @@ export class FilterPanel extends React.Component {
{ - for (var key of this.facetValues(renderInfo.facetHeader)) { - if (this.mapActiveFiltersToFacets.get(key)) { - Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove'); + if (renderInfo.facetHeader === 'text') { + Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, 'match', 'remove'); + } else { + for (var key of this.facetValues(renderInfo.facetHeader)) { + if (this.mapActiveFiltersToFacets.get(key)) { + Doc.setDocFilter(this.targetDoc, renderInfo.facetHeader, key, 'remove'); + } } } this._selectedFacetHeaders.delete(renderInfo.facetHeader); @@ -370,15 +375,18 @@ export class FilterPanel extends React.Component { } private displayFacetValueFilterUIs(type: string | undefined, facetHeader: string, renderInfoDomain?: number[] | undefined, renderInfoRange?: number[]): React.ReactNode { - switch (type /* renderInfo.type */) { - case 'text': // if (this.chosenFacets.get(facetHeader) === 'text') + switch (type) { + case 'text': return ( filter.split(Doc.FilterSep)[0] === facetHeader) - ?.split(Doc.FilterSep)[1] ?? '-empty-' + ?.split(Doc.FilterSep)[1] } + style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }} onBlur={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')} onKeyDown={e => e.key === 'Enter' && undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')(e)} /> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 775ccd067..96b2ddf70 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -318,7 +318,9 @@ export function DefaultStyleProvider(doc: Opt, props: Opt ({ + items={[ ...(dashView ? [dashView]: []), ...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])] + .filter(dv => StrListCast(dv.rootDoc.childFilters).length || StrListCast(dv.rootDoc.childRangeFilters).length) + .map(dv => ({ text: StrCast(dv.rootDoc.title), val: dv as any, style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor}, diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 0ee83bc08..198cbe851 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -204,7 +204,7 @@ export class LinkDocPreview extends React.Component { }; @computed get previewHeader() { return !this._linkDoc || !this._markerTargetDoc || !this._targetDoc || !this._linkSrc ? null : ( -
+
Edit Link
} placement="top">
@@ -302,7 +302,7 @@ export class LinkDocPreview extends React.Component { className="linkDocPreview" ref={this._linkDocRef} onPointerDown={this.followLinkPointerDown} - style={{ left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> + style={{ borderColor: SettingsManager.userColor, left: this.props.location[0], top: this.props.location[1], width: this.width() + borders, height: this.height() + borders + (this.props.showHeader ? 37 : 0) }}> {this.docPreview}
); -- cgit v1.2.3-70-g09d2 From 2b96f355ea7f4aa0e1fcf0dbee8ce6bf6e8f09d4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Sep 2023 14:27:05 -0400 Subject: revised how to do filtering by links. --- src/client/documents/Documents.ts | 28 +++++++--------------------- src/client/views/FilterPanel.tsx | 15 +++++++-------- src/client/views/InkTangentHandles.tsx | 1 - src/client/views/nodes/MapBox/MapBox.tsx | 6 +++--- src/fields/Doc.ts | 25 ++++++++++++++++++++----- 5 files changed, 37 insertions(+), 38 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 055950e6f..254be67b9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -15,7 +15,7 @@ import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } fro import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField, YoutubeField } from '../../fields/URLField'; import { inheritParentAcls, SharingPermissions } from '../../fields/util'; import { Upload } from '../../server/SharedMediaTypes'; -import { aggregateBounds, OmitKeys, Utils } from '../../Utils'; +import { OmitKeys, Utils } from '../../Utils'; import { YoutubeBox } from '../apis/youtube/YoutubeBox'; import { DocServer } from '../DocServer'; import { Networking } from '../Network'; @@ -1296,20 +1296,6 @@ export namespace DocUtils { for (const facetKey of Object.keys(filterFacets).filter(fkey => fkey !== 'cookies' && fkey !== Utils.noDragsDocFilter.split(Doc.FilterSep)[0])) { const facet = filterFacets[facetKey]; - let links = true; - const linkedTo = filterFacets['-linkedTo'] && Array.from(Object.keys(filterFacets['-linkedTo']))?.[0]; - const linkedToField = filterFacets['-linkedTo']?.[linkedTo]; - const allLinks = linkedTo && linkedToField ? LinkManager.Instance.getAllRelatedLinks(d) : []; - // prettier-ignore - if (linkedTo) { - if (allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_1)?.[linkedToField]))) || // - allLinks.some(d => linkedTo === Field.toScriptString(DocCast(DocCast(d.link_anchor_2)?.[linkedToField])))) - { - links = true; - } - else links = false - } - // facets that match some value in the field of the document (e.g. some text field) const matches = Object.keys(facet).filter(value => value !== 'cookies' && facet[value] === 'match'); @@ -1319,16 +1305,16 @@ export namespace DocUtils { // metadata facets that exist const exists = Object.keys(facet).filter(value => facet[value] === 'exists'); - // metadata facets that exist + // facets that unset metadata (a hack for making cookies work) const unsets = Object.keys(facet).filter(value => facet[value] === 'unset'); - // facets that have an x next to them + // facets that specify that a field must not match a specific value const xs = Object.keys(facet).filter(value => facet[value] === 'x'); - if (!linkedTo && !unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; + if (!unsets.length && !exists.length && !xs.length && !checks.length && !matches.length) return true; const failsNotEqualFacets = !xs.length ? false : xs.some(value => Doc.matchFieldValue(d, facetKey, value)); const satisfiesCheckFacets = !checks.length ? true : checks.some(value => Doc.matchFieldValue(d, facetKey, value)); - const satisfiesExistsFacets = !exists.length ? true : exists.some(value => d[facetKey] !== undefined); + const satisfiesExistsFacets = !exists.length ? true : exists.some(value => (facetKey !== '-linkedTo' ? d[facetKey] !== undefined : LinkManager.Instance.getAllRelatedLinks(d).length)); const satisfiesUnsetsFacets = !unsets.length ? true : unsets.some(value => d[facetKey] === undefined); const satisfiesMatchFacets = !matches.length ? true @@ -1344,11 +1330,11 @@ export namespace DocUtils { }); // if we're ORing them together, the default return is false, and we return true for a doc if it satisfies any one set of criteria if (parentCollection?.childFilters_boolean === 'OR') { - if (links && satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; + if (satisfiesUnsetsFacets && satisfiesExistsFacets && satisfiesCheckFacets && !failsNotEqualFacets && satisfiesMatchFacets) return true; } // if we're ANDing them together, the default return is true, and we return false for a doc if it doesn't satisfy any set of criteria else { - if (!links || !satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; + if (!satisfiesUnsetsFacets || !satisfiesExistsFacets || !satisfiesCheckFacets || failsNotEqualFacets || (matches.length && !satisfiesMatchFacets)) return false; } } return parentCollection?.childFilters_boolean === 'OR' ? false : true; diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 4af29c70e..312dc3a70 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -56,7 +56,7 @@ export class FilterPanel extends React.Component { @computed get _allFacets() { // trace(); - const noviceReqFields = ['author', 'tags', 'text', 'type']; + const noviceReqFields = ['author', 'tags', 'text', 'type', '-linkedTo']; const noviceLayoutFields: string[] = []; //["_layout_curPage"]; const noviceFields = [...noviceReqFields, ...noviceLayoutFields]; @@ -118,7 +118,7 @@ export class FilterPanel extends React.Component { // } gatherFieldValues(childDocs: Doc[], facetKey: string) { - const valueSet = new Set(); + const valueSet = new Set(StrListCast(this.props.rootDoc.childFilters).map(filter => filter.split(Doc.FilterSep)[1])); let rtFields = 0; let subDocs = childDocs; if (subDocs.length > 0) { @@ -127,7 +127,6 @@ export class FilterPanel extends React.Component { newarray = []; subDocs.forEach(t => { const facetVal = t[facetKey]; - // console.log("facetVal " + facetVal) if (facetVal instanceof RichTextField || typeof facetVal === 'string') rtFields++; facetVal !== undefined && valueSet.add(Field.toString(facetVal as Field)); (facetVal === true || facetVal == false) && valueSet.add(Field.toString(!facetVal)); @@ -182,14 +181,14 @@ export class FilterPanel extends React.Component { }); if (facetHeader === 'text') { - return { facetHeader: facetHeader, renderType: 'text' }; + return { facetHeader, renderType: 'text' }; } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) { const extendedMinVal = minVal - Math.min(1, Math.floor(Math.abs(maxVal - minVal) * 0.1)); const extendedMaxVal = Math.max(minVal + 1, maxVal + Math.min(1, Math.ceil(Math.abs(maxVal - minVal) * 0.05))); const ranged = Doc.readDocRangeFilter(this.targetDoc, facetHeader); // not the filter range, but the zooomed in range on the filter - return { facetHeader: facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] }; + return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] }; } else { - return { facetHeader: facetHeader, renderType: 'checkbox' }; + return { facetHeader, renderType: 'checkbox' }; } }) ); @@ -236,7 +235,7 @@ export class FilterPanel extends React.Component { facetValues = (facetHeader: string) => { const allCollectionDocs = new Set(); SearchUtil.foreachRecursiveDoc(this.targetDocChildren, (depth: number, doc: Doc) => allCollectionDocs.add(doc)); - const set = new Set([String.fromCharCode(127) + '--undefined--', Doc.FilterAny]); + const set = new Set([...StrListCast(this.props.rootDoc.childFilters).map(filter => filter.split(Doc.FilterSep)[1]), Doc.FilterNone, Doc.FilterAny]); if (facetHeader === 'tags') allCollectionDocs.forEach(child => StrListCast(child[facetHeader]) @@ -404,7 +403,7 @@ export class FilterPanel extends React.Component { ?.split(Doc.FilterSep)[2] ?? '' )} type={type} - onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? (fval === Doc.FilterAny ? 'exists' : 'check') : 'remove'), 'set filter')} + onChange={undoable(e => Doc.setDocFilter(this.targetDoc, facetHeader, fval, e.target.checked ? 'check' : 'remove'), 'set filter')} /> {facetValue}
diff --git a/src/client/views/InkTangentHandles.tsx b/src/client/views/InkTangentHandles.tsx index 71e0ff63c..65f6a6dfa 100644 --- a/src/client/views/InkTangentHandles.tsx +++ b/src/client/views/InkTangentHandles.tsx @@ -12,7 +12,6 @@ import { UndoManager } from '../util/UndoManager'; import { Colors } from './global/globalEnums'; import { InkingStroke } from './InkingStroke'; import { InkStrokeProperties } from './InkStrokeProperties'; -import { DocumentView } from './nodes/DocumentView'; export interface InkHandlesProps { inkDoc: Doc; inkView: InkingStroke; diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx index 3e22c0d0e..d7469e530 100644 --- a/src/client/views/nodes/MapBox/MapBox.tsx +++ b/src/client/views/nodes/MapBox/MapBox.tsx @@ -350,7 +350,7 @@ export class MapBox extends ViewBoxAnnotatableComponent color !== '' && DashColor(color).alpha() !== 1; return isTransparent(StrCast(doc[key])); } + if (key === '-linkedTo') { + // links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("...")) + const allLinks = LinkManager.Instance.getAllRelatedLinks(doc); + const matchLink = (value: string, anchor: Doc) => { + const linkedToExp = value?.split('='); + if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value; + return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; + }; + // prettier-ignore + return (value === Doc.FilterNone && !allLinks.length) || + (value === Doc.FilterAny && !!allLinks.length) || + (allLinks.some(link => matchLink(value,DocCast(link.link_anchor_1)) || + matchLink(value,DocCast(link.link_anchor_2)) )); + } if (typeof value === 'string') { value = value.replace(`,${Utils.noRecursionHack}`, ''); } const fieldVal = doc[key]; if (Cast(fieldVal, listSpec('string'), []).length) { - const vals = Cast(fieldVal, listSpec('string'), []); + const vals = StrListCast(fieldVal); const docs = vals.some(v => (v as any) instanceof Doc); if (docs) return value === Field.toString(fieldVal as Field); return vals.some(v => v.includes(value)); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } const fieldStr = Field.toString(fieldVal as Field); - return fieldStr.includes(value) || (value === String.fromCharCode(127) + '--undefined--' && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring + return fieldStr.includes(value) || (value === Doc.FilterAny && fieldVal !== undefined) || (value === Doc.FilterNone && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } export function deiconifyView(doc: Doc) { @@ -1520,18 +1534,19 @@ export namespace Doc { export const FilterSep = '::'; export const FilterAny = '--any--'; + export const FilterNone = '--undefined--'; // filters document in a container collection: // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined - export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'removeAll' | 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { + export function setDocFilter(container: Opt, key: string, value: any, modifiers: 'remove' | 'match' | 'check' | 'x' | 'exists' | 'unset', toggle?: boolean, fieldPrefix?: string, append: boolean = true) { if (!container) return; const filterField = '_' + (fieldPrefix ? fieldPrefix + '_' : '') + 'childFilters'; const childFilters = StrListCast(container[filterField]); runInAction(() => { for (let i = 0; i < childFilters.length; i++) { const fields = childFilters[i].split(FilterSep); // split key:value:modifier - if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || modifiers === 'removeAll' || (fields[2] === 'match' && modifiers === 'remove'))) { + if (fields[0] === key && (fields[1] === value.toString() || modifiers === 'match' || (fields[2] === 'match' && modifiers === 'remove'))) { if (fields[2] === modifiers && modifiers && fields[1] === value.toString()) { if (toggle) modifiers = 'remove'; else return; @@ -1543,7 +1558,7 @@ export namespace Doc { } if (!childFilters.length && modifiers === 'match' && value === undefined) { container[filterField] = undefined; - } else if (modifiers !== 'remove' && modifiers !== 'removeAll') { + } else if (modifiers !== 'remove') { !append && (childFilters.length = 0); childFilters.push(key + FilterSep + value + FilterSep + modifiers); container[filterField] = new List(childFilters); -- cgit v1.2.3-70-g09d2 From 84aa8806a62e2e957e8281d7d492139e3d8225f2 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 18 Sep 2023 14:41:53 -0400 Subject: removed filter checkboxes for list values since they don't work. fixed any/undefined filtering for tags or other list fields. --- src/client/views/FilterPanel.tsx | 8 ++++++-- src/fields/Doc.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src/client/views/FilterPanel.tsx') diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 312dc3a70..69ceb0f65 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -17,6 +17,7 @@ import { FieldView } from './nodes/FieldView'; import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components'; import { SettingsManager } from '../util/SettingsManager'; import { Id } from '../../fields/FieldSymbols'; +import { List } from '../../fields/List'; interface filterProps { rootDoc: Doc; @@ -245,8 +246,11 @@ export class FilterPanel extends React.Component { else allCollectionDocs.forEach(child => { const fieldVal = child[facetHeader] as Field; - set.add(Field.toString(fieldVal)); - (fieldVal === true || fieldVal === false) && set.add((!fieldVal).toString()); + if (!(fieldVal instanceof List)) { + // currently we have no good way of filtering based on a field that is a list + set.add(Field.toString(fieldVal)); + (fieldVal === true || fieldVal === false) && set.add((!fieldVal).toString()); + } }); const facetValues = Array.from(set).filter(v => v); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 78a03d782..56b97e42f 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1481,14 +1481,18 @@ export namespace Doc { value = value.replace(`,${Utils.noRecursionHack}`, ''); } const fieldVal = doc[key]; + // prettier-ignore + if ((value === Doc.FilterAny && fieldVal !== undefined) || + (value === Doc.FilterNone && fieldVal === undefined)) { + return true; + } if (Cast(fieldVal, listSpec('string'), []).length) { const vals = StrListCast(fieldVal); const docs = vals.some(v => (v as any) instanceof Doc); if (docs) return value === Field.toString(fieldVal as Field); return vals.some(v => v.includes(value)); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } - const fieldStr = Field.toString(fieldVal as Field); - return fieldStr.includes(value) || (value === Doc.FilterAny && fieldVal !== undefined) || (value === Doc.FilterNone && fieldVal === undefined); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring + return Field.toString(fieldVal as Field).includes(value); // bcz: arghh: Todo: comparison should be parameterized as exact, or substring } export function deiconifyView(doc: Doc) { -- cgit v1.2.3-70-g09d2