aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/FilterPanel.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/FilterPanel.tsx')
-rw-r--r--src/client/views/FilterPanel.tsx173
1 files changed, 88 insertions, 85 deletions
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index 0521c4a4b..c97edd7f0 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -1,19 +1,22 @@
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, makeObservable, observable, ObservableMap } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider';
import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai';
import { CiCircleRemove } from 'react-icons/ci';
-import { Doc, DocListCast, Field, LinkedTo, StrListCast } from '../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, LinkedTo, StrListCast } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { List } from '../../fields/List';
import { RichTextField } from '../../fields/RichTextField';
-import { DocumentManager } from '../util/DocumentManager';
import { SearchUtil } from '../util/SearchUtil';
-import { SettingsManager } from '../util/SettingsManager';
+import { SnappingManager } from '../util/SnappingManager';
import { undoable } from '../util/UndoManager';
import { FieldsDropdown } from './FieldsDropdown';
import './FilterPanel.scss';
+import { DocumentView } from './nodes/DocumentView';
import { Handle, Tick, TooltipRail, Track } from './nodes/SliderBox-components';
import { ObservableReactComponent } from './ObservableReactComponent';
@@ -37,7 +40,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
return this._props.Document;
}
@computed get targetDocChildKey() {
- const targetView = DocumentManager.Instance.getFirstDocumentView(this.Document);
+ const targetView = DocumentView.getFirstDocumentView(this.Document);
return targetView?.ComponentView?.annotationKey ?? targetView?.ComponentView?.fieldKey ?? 'data';
}
@computed get targetDocChildren() {
@@ -58,7 +61,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
@computed get mapActiveFiltersToFacets() {
const filters = new Map<string, string>();
- //this.targetDoc.docFilters
+ // this.targetDoc.docFilters
this.activeFilters.map(filter => filters.set(filter.split(Doc.FilterSep)[1], filter.split(Doc.FilterSep)[0]));
return filters;
}
@@ -73,7 +76,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// ["#tags", "width", "height"]
//
@computed get activeFacetHeaders() {
- const activeHeaders = new Array();
+ const activeHeaders = [] as string[];
this.activeFilters.map(filter => activeHeaders.push(filter.split(Doc.FilterSep)[0]));
return activeHeaders;
@@ -83,19 +86,20 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
const valueSet = new Set<string>(childFilters.map(filter => filter.split(Doc.FilterSep)[1]));
let rtFields = 0;
let subDocs = childDocs;
- let gatheredDocs = [] as Doc[];
+ const gatheredDocs = [] as Doc[];
if (subDocs.length > 0) {
let newarray: Doc[] = [];
while (subDocs.length > 0) {
newarray = [];
+ // eslint-disable-next-line no-loop-func
subDocs.forEach(t => {
gatheredDocs.push(t);
const facetVal = t[facetKey];
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));
+ facetVal !== undefined && valueSet.add(Field.toString(facetVal as FieldType));
+ (facetVal === true || facetVal === false) && valueSet.add(Field.toString(!facetVal));
const fieldKey = Doc.LayoutFieldKey(t);
- const annos = !Field.toString(Doc.LayoutField(t) as Field).includes('CollectionView');
+ const annos = !Field.toString(Doc.LayoutField(t) as FieldType).includes('CollectionView');
DocListCast(t[annos ? fieldKey + '_annotations' : fieldKey]).forEach(newdoc => newarray.push(newdoc));
annos && DocListCast(t[fieldKey + '_sidebar']).forEach(newdoc => newarray.push(newdoc));
});
@@ -115,7 +119,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// @observable _chosenFacets = new ObservableMap<string, 'text' | 'checkbox' | 'slider' | 'range'>();
@observable _chosenFacetsCollapse = new ObservableMap<string, boolean>();
- @observable _collapseReturnKeys = new Array();
+ @observable _collapseReturnKeys = [] as string[];
// this computed function gets the active filters and maps them to their headers
//
@@ -130,11 +134,11 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
const facetValues = FilterPanel.gatherFieldValues(this.targetDocChildren, facetHeader, StrListCast(this.Document.childFilters));
let nonNumbers = 0;
- let minVal = Number.MAX_VALUE,
- maxVal = -Number.MAX_VALUE;
- facetValues.strings.map(val => {
+ let minVal = Number.MAX_VALUE;
+ let maxVal = -Number.MAX_VALUE;
+ facetValues.strings.forEach(val => {
const num = val ? Number(val) : Number.NaN;
- if (Number.isNaN(num)) {
+ if (isNaN(num)) {
val && nonNumbers++;
} else {
minVal = Math.min(num, minVal);
@@ -144,14 +148,14 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
if (facetHeader === 'text') {
return { facetHeader, renderType: 'text' };
- } else if (facetHeader !== 'tags' && nonNumbers / facetValues.strings.length < 0.1) {
+ }
+ 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.Document, facetHeader); // not the filter range, but the zooomed in range on the filter
- return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged ? ranged : [extendedMinVal, extendedMaxVal] };
- } else {
- return { facetHeader, renderType: 'checkbox' };
+ const ranged: number[] | undefined = Doc.readDocRangeFilter(this.Document, facetHeader); // not the filter range, but the zooomed in range on the filter
+ return { facetHeader, renderType: 'range', domain: [extendedMinVal, extendedMaxVal], range: ranged || [extendedMinVal, extendedMaxVal] };
}
+ return { facetHeader, renderType: 'checkbox' };
})
);
}
@@ -171,17 +175,17 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
sortingCurrentFacetValues = (facetHeader: string) => {
this._collapseReturnKeys.splice(0);
- Array.from(this.activeRenderedFacetInfos.keys()).map(renderInfo => {
+ Array.from(this.activeRenderedFacetInfos.keys()).forEach(renderInfo => {
if (renderInfo.renderType === 'range' && renderInfo.facetHeader === facetHeader && renderInfo.range) {
- this._collapseReturnKeys.push(renderInfo.range.map(number => number.toFixed(2)));
+ this._collapseReturnKeys.push(...renderInfo.range.map(number => number.toFixed(2)));
}
});
- for (var key of this.facetValues(facetHeader)) {
+ this.facetValues(facetHeader).forEach(key => {
if (this.mapActiveFiltersToFacets.get(key)) {
this._collapseReturnKeys.push(key);
}
- }
+ });
return <div className=" filterbox-collpasedAndActive">{this._collapseReturnKeys.join(', ')}</div>;
};
@@ -198,7 +202,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
);
else
allCollectionDocs.forEach(child => {
- const fieldVal = child[facetHeader] as Field;
+ const fieldVal = child[facetHeader] as FieldType;
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));
@@ -209,7 +213,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
let nonNumbers = 0;
- facetValues.map(val => Number.isNaN(Number(val)) && nonNumbers++);
+ facetValues.map(val => isNaN(Number(val)) && nonNumbers++);
return nonNumbers / facetValues.length > 0.1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2));
};
@@ -218,7 +222,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
<div className="filterBox-treeView">
<div className="filterBox-select">
<div style={{ width: '100%' }}>
- <FieldsDropdown Document={this.Document} selectFunc={this.facetClick} showPlaceholder={true} placeholder="add a filter" addedFields={['acl-Guest', LinkedTo]} />
+ <FieldsDropdown Document={this.Document} selectFunc={this.facetClick} showPlaceholder placeholder="add a filter" addedFields={['acl_Guest', LinkedTo]} />
</div>
{/* THE FOLLOWING CODE SHOULD BE DEVELOPER FOR BOOLEAN EXPRESSION (AND / OR) */}
{/* <div className="filterBox-select-bool">
@@ -234,34 +238,31 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
<div className="filterBox-tree" key="tree">
{Array.from(this.activeRenderedFacetInfos.keys()).map(
- (
- renderInfo // iterato over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
- ) => (
+ // iterate over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
+ renderInfo => (
<div>
<div className="filterBox-facetHeader">
<div className="filterBox-facetHeader-Header"> </div>
{renderInfo.facetHeader.charAt(0).toUpperCase() + renderInfo.facetHeader.slice(1)}
-
<div
className="filterBox-facetHeader-collapse"
- onClick={action(e => {
+ onClick={action(() => {
const collapseBoolValue = this._chosenFacetsCollapse.get(renderInfo.facetHeader);
this._chosenFacetsCollapse.set(renderInfo.facetHeader, !collapseBoolValue);
})}>
{this._chosenFacetsCollapse.get(renderInfo.facetHeader) ? <AiOutlinePlusSquare /> : <AiOutlineMinusSquare />}
</div>
-
<div
className="filterBox-facetHeader-remove"
- onClick={action(e => {
+ onClick={action(() => {
if (renderInfo.facetHeader === 'text') {
Doc.setDocFilter(this.Document, renderInfo.facetHeader, 'match', 'remove');
} else {
- for (var key of this.facetValues(renderInfo.facetHeader)) {
+ this.facetValues(renderInfo.facetHeader).forEach((key: string) => {
if (this.mapActiveFiltersToFacets.get(key)) {
Doc.setDocFilter(this.Document, renderInfo.facetHeader, key, 'remove');
}
- }
+ });
}
this._selectedFacetHeaders.delete(renderInfo.facetHeader);
this._chosenFacetsCollapse.delete(renderInfo.facetHeader);
@@ -292,15 +293,15 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
return (
<input
key={this.Document[Id]}
- placeholder={'enter text to match'}
+ placeholder="enter text to match"
defaultValue={
StrListCast(this.Document._childFilters)
.find(filter => filter.split(Doc.FilterSep)[0] === facetHeader)
?.split(Doc.FilterSep)[1]
}
- style={{ color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+ style={{ color: SnappingManager.userColor, background: SnappingManager.userBackgroundColor }}
onBlur={undoable(e => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')}
- onKeyDown={e => e.key === 'Enter' && undoable(e => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')(e)}
+ onKeyDown={e => e.key === 'Enter' && undoable(() => Doc.setDocFilter(this.Document, facetHeader, e.currentTarget.value, !e.currentTarget.value ? 'remove' : 'match'), 'set text filter')()}
/>
);
case 'checkbox':
@@ -312,7 +313,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
style={{ width: 20, marginLeft: 20 }}
checked={['check', 'exists'].includes(
StrListCast(this.Document._childFilters)
- .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] == facetValue)
+ .find(filter => filter.split(Doc.FilterSep)[0] === facetHeader && filter.split(Doc.FilterSep)[1] === facetValue)
?.split(Doc.FilterSep)[2] ?? ''
)}
type={type}
@@ -324,55 +325,56 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
});
case 'range':
- const domain = renderInfoDomain;
- const range = renderInfoRange;
- if (domain) {
- return (
- <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45, float: 'right' }}>
- <Slider
- mode={2}
- step={Math.min(1, 0.1 * (domain[1] - domain[0]))}
- domain={[domain[0], domain[1]]} // -1000, 1000
- rootStyle={{ position: 'relative', width: '100%' }}
- onChange={values => Doc.setDocRangeFilter(this.Document, facetHeader, values)}
- values={renderInfoRange!}>
- <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
- <Handles>
- {({ handles, activeHandleID, getHandleProps }) => (
- <div className="slider-handles">
- {handles.map((handle, i) => {
- // const value = i === 0 ? defaultValues[0] : defaultValues[1];
- return (
+ {
+ const domain = renderInfoDomain;
+ if (domain) {
+ return (
+ <div className="sliderBox-outerDiv" style={{ width: '95%', height: 45, float: 'right' }}>
+ <Slider
+ mode={2}
+ step={Math.min(1, 0.1 * (domain[1] - domain[0]))}
+ domain={[domain[0], domain[1]]} // -1000, 1000
+ rootStyle={{ position: 'relative', width: '100%' }}
+ onChange={values => Doc.setDocRangeFilter(this.Document, facetHeader, values)}
+ values={renderInfoRange!}>
+ <Rail>{railProps => <TooltipRail {...railProps} />}</Rail>
+ <Handles>
+ {({ handles, activeHandleID, getHandleProps }) => (
+ <div className="slider-handles">
+ {handles.map(handle => (
+ // const value = i === 0 ? defaultValues[0] : defaultValues[1];
<div>
<Handle key={handle.id} handle={handle} domain={domain} isActive={handle.id === activeHandleID} getHandleProps={getHandleProps} />
</div>
- );
- })}
- </div>
- )}
- </Handles>
- <Tracks left={false} right={false}>
- {({ tracks, getTrackProps }) => (
- <div className="slider-tracks">
- {tracks.map(({ id, source, target }) => (
- <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
- ))}
- </div>
- )}
- </Tracks>
- <Ticks count={5}>
- {({ ticks }) => (
- <div className="slider-ticks">
- {ticks.map(tick => (
- <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
- ))}
- </div>
- )}
- </Ticks>
- </Slider>
- </div>
- );
+ ))}
+ </div>
+ )}
+ </Handles>
+ <Tracks left={false} right={false}>
+ {({ tracks, getTrackProps }) => (
+ <div className="slider-tracks">
+ {tracks.map(({ id, source, target }) => (
+ <Track key={id} source={source} target={target} disabled={false} getTrackProps={getTrackProps} />
+ ))}
+ </div>
+ )}
+ </Tracks>
+ <Ticks count={5}>
+ {({ ticks }) => (
+ <div className="slider-ticks">
+ {ticks.map(tick => (
+ <Tick key={tick.id} tick={tick} count={ticks.length} format={(val: number) => val.toString()} />
+ ))}
+ </div>
+ )}
+ </Ticks>
+ </Slider>
+ </div>
+ );
+ }
}
+ break;
+ default:
// case 'range'
// return <Slider ...
@@ -386,5 +388,6 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
// <dimain changing handles >
// <?div
}
+ return undefined;
}
}