8000 UI for Classification and Nearest Neighbor Analyzers (#15387) · strogo/arangodb@fbdd9bd · GitHub
[go: up one dir, main page]

Skip to content

Commit fbdd9bd

Browse files
adityamukhoKVS85
andauthored
UI for Classification and Nearest Neighbor Analyzers (arangodb#15387)
* React-specific rules. * Analyzers view. * Modal component for React. * Analyzer delete functional, +notifications. * Stable render of modal children, +AddAnalyzer form stub. * Fixed broken modal re-open. * Delimiter form ready. * All forms ready. * Removed 'Tree' mode. * Analyzer create functional. * Fixed stopwords/stopwordsPath mixup. * 'Create Analyzer' form schema validation. * Added missing fields to Text and N-Gram analyzer forms. * Added support for copying existing analyzer to form state. * Implemented view analyzer details. * UX improvements. As suggested in arangodb#14599. * Fixed analyzer selection. * Added UI for AQL and GeoJSON analyzers. * Added UI for GeoPoint analyzer. * Improved validation, +dispatcher to manage state, +form cache. * Changed button styles to match theme. +fixed minor bug in form field setter +error div spacing fix. * Removed 'pointer' cursor on text field labels. * Added help links to locale and delimiter inputs. * Added help text to delimiter field. * Fix bug that caused crash in case of pre-selected analyzer being deleted. * Fixed parsing and UI for latitude/longitude elements. * Reusable form and grid components based on Pure.css. * View mode now provides both JSON and (disabled) form views. * Using relative field paths to support embeddable forms. * Normalized accent input, +made all inputs location agnostic. +Renamed OptionsInput.tsx to GeoOptionsInput.tsx. * Pipeline Analyzer form functional. * Switched to simple text display for code view. * Use text cursor for code view mode. * Added UIs for Stopwords, Collation and Segmentation Analyzers. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed DB base URL evaluation. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Switched to Pure.css-based grid components. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Allow rw access when server is running in non-authenticated mode. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed radio button rendering. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Minor UI improvements. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed modal height issues, +fixed JSON form double scrollbar. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Maximized modal height for view mode. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Minor UI improvements. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed null values for blank numeric inputs. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * UI improvements. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Slightly improved responsive grid. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Reusing FormState as action button prop. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Stricter type restrictions. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Temp commit before switching to other work (build broken). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Restored changes before merge. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Added ajv merge patch * Stable ids for elements. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Temp commit before branch change. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Temp commit before branch change. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Changed filter input id. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed build. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Temp commit before branch switch. * Schema complete. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Views UI partially complete. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * ArangoTable component now accepts extra parameters. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Label now optional for text and dropdown components. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Removed Int type. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed FormProps. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Added LinkPropertiesForm (stub) and ViewPropertiesForm (partial). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Ignored MSVC project files. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed analyzer compile errors. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed build (analyzers tested, views untested). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Layout improvements. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Added ConsolidationPolicyForm.tsx. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Better table formatting. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Nested table for stored value fields array. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Extracted IconButton component due to frequent use, extracted nested inputs - LinkPropertiesInput.tsx and StoredValueFieldsInput.tsx. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Used IconButton component, replacing repeated custom markup. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Redefined IconButton classes for consistency with existing defined styles. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Recursive form render working. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * View creation successful (w/ recursive link properties). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * View display in both form/code mode now functional. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Restricted consolidation policy input to 'tier'. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Views edit works (mostly). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Converted all form inputs to controlled components. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Rebuild UI * Primary Sort accepts 'asc': boolean as an alternative to direction field. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Removed unused form component. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * De-duplicated JSON forms. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Added post processor to invoke custom logic during action dispatch. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Removed auto-fix during validation. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Correctly differentiate between and 0-valued and empty numeric fields (workaround for JS quirk). Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Extracted method for boolean field setter. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Fixed multiple field validation issues. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * 'Store Values' field rendered as checklist. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Temp commit before migrating working directory. * Optimized filter function. * Removed unused export. * Autocomplete - initial implementation. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Autocomplete multi-select React component partially ready. * Autocomplete - multi-select React component ready. * Switched to 'flex' layout. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Show 'In Background' field only at collection level. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Minor fixes. * Removed link caching from form (was confusing to use). * Non-modal view details - info page ready. * Settings page partially built. * Non-modal view details - settings and consolidation pages ready. * Non-modal view details - links pages ready. * Non-modal view details - json page ready. * Removed unused files. * Use current view name during JSON copy. * Added analyzers: classification, nearest_neighbors. * Disable analyzer form in 'view' mode. * Disable 'add analyzer' button for users without 'rw' permission. * Added `minScore` field to 'Tier' consolidation policy type. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Moved `consolidationIntervalMsec` to settings page, renamed consolidation menu item. Signed-off-by: Aditya Mukhopadhyay <aditya@arangodb.com> * Formatting changes. Co-authored-by: Vadim Kondratyev <vadim@arangodb.com>
1 parent ddbfba9 commit fbdd9bd

File tree

7 files changed

+195
-20
lines changed

7 files changed

+195
-20
lines changed

js/apps/system/_admin/aardvark/APP/react/src/views/analyzers/Actions.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ const ViewButton = ({ analyzer, modalCid }: ButtonProps) => {
138138
<legend style={{ fontSize: '12pt' }}>Configuration</legend>
139139
{getForm({
140140
formState,
141-
dispatch: noop
141+
dispatch: noop,
142+
disabled: true
142143
})}
143144
</fieldset>
144145
</Cell>

js/apps/system/_admin/aardvark/APP/react/src/views/analyzers/AnalyzersReactView.jsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ArangoTable, ArangoTD, ArangoTH } from '../../components/arango/table';
77
import Modal, { ModalBody, ModalFooter, ModalHeader } from '../../components/modal/Modal';
88
import { Cell, Grid } from '../../components/pure-css/grid';
99
import { getApiRouteForCurrentDB } from '../../utils/arangoClient';
10-
import { facetedFilter, getChangeHandler, usePermissions } from '../../utils/helpers';
10+
import { facetedFilter, getChangeHandler, isAdminUser, usePermissions } from '../../utils/helpers';
1111
import Actions from './Actions';
1212
import AddAnalyzer from './AddAnalyzer';
1313
import { typeNameMap } from './constants';
@@ -150,9 +150,13 @@ const AnalyzersReactView = () => {
150150
<div className={'contentDiv'} id={'analyzersContent'} style={{ paddingTop: 0 }}>
151151
<Grid>
152152
<Cell size={'1'}>
153-
<div className={'sectionHeader'}>
154-
<div className={'title'}><AddAnalyzer analyzers={analyzers}/></div>
155-
</div>
153+
{
154+
isAdminUser(permissions)
155+
? <div className={'sectionHeader'}>
156+
<div className={'title'}><AddAnalyzer analyzers={analyzers}/></div>
157+
</div>
158+
: null
159+
}
156160
<ArangoTable className={'arango-table'}>
157161
<thead>
158162
<tr>

js/apps/system/_admin/aardvark/APP/react/src/views/analyzers/constants.ts

Lines changed: 105 additions & 15 deletions
< 7802 td data-grid-cell-id="diff-b2bfa1d94103aa367f3b32952b303d677fac74721e734ff14925c31933ae594a-383-408-0" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative diff-line-number-neutral left-side">383
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable camelcase */
12
import { JSONSchemaType } from 'ajv';
23
import _, { merge, partial } from 'lodash';
34

@@ -12,6 +13,8 @@ export const typeNameMap = {
1213
stopwords: 'Stopwords',
1314
collation: 'Collation',
1415
segmentation: 'Segmentation',
16+
nearest_neighbors: 'Nearest Neighbors',
17+
classification: 'Classification',
1518
pipeline: 'Pipeline',
1619
geojson: 'GeoJSON',
1720
geopoint: 'GeoPoint'
@@ -105,23 +108,41 @@ export type AqlState = {
105108
};
106109

107110
export type StopwordsState = StopwordsProperty & {
108-
type: 'stopwords',
111+
type: 'stopwords';
109112
properties: {
110113
hex?: boolean;
111-
}
114+
};
112115
};
113116

114117
export type CollationState = LocaleProperty & {
115118
type: 'collation';
116119
};
117120

118121
export type SegmentationState = CaseProperty & {
119-
type: 'segmentation',
122+
type: 'segmentation';
120123
properties: {
121124
break?: 'all' | 'alpha' | 'graphic';
122125
};
123126
};
124127

128+
export type ModelProperty = {
129+
properties: {
130+
model_location: string;
131+
top_k?: number; // [0, 2147483647]
132+
};
133+
};
134+
135+
export type NearestNeighborsState = ModelProperty & {
136+
type: 'nearest_neighbors';
137+
};
138+
139+
export type ClassificationState = ModelProperty & {
140+
type: 'classification';
141+
properties: {
142+
threshold?: number; // [0.0, 1.0]
143+
};
144+
};
145+
125146
export type PipelineState = DelimiterState
126147
| StemState
127148
| NormState
@@ -130,7 +151,9 @@ export type PipelineState = DelimiterState
130151
| AqlState
131152
| StopwordsState
132153
| CollationState
133-
| SegmentationState;
154+
| SegmentationState
155+
| NearestNeighborsState
156+
| ClassificationState;
134157

135158
export type PipelineStates = {
136159
type: 'pipeline';
@@ -174,6 +197,8 @@ export type AnalyzerTypeState = IdentityState
174197
| StopwordsState
175198
| CollationState
176199
| SegmentationState
200+
| NearestNeighborsState
201+
| ClassificationState
177202
| PipelineStates
178203
| GeoJsonState
179204
| GeoPointState;
@@ -247,7 +272,7 @@ const mergeBase = partial(merge, _, baseSchema);
247272

248273
const identitySchema = mergeBase({
249274
properties: {
250-
type: {
275+
'type': {
251276
const: 'identity'
252277
}
253278
},
@@ -256,7 +281,7 @@ const identitySchema = mergeBase({
256281

257282
const delimiterSchema = mergeBase({
258283
properties: {
259-
type: {
284+
'type': {
260285
const: 'delimiter'
261286
},
262287
'properties': {
@@ -281,7 +306,7 @@ const delimiterSchema = mergeBase({
281306

282307
const stemSchema = mergeBase({
283308
properties: {
284-
type: {
309+
'type': {
285310
const: 'stem'
286311
},
287312
'properties': {
@@ -302,7 +327,7 @@ const stemSchema = mergeBase({
302327

303328
const normSchema = mergeBase({
304329
properties: {
305-
type: {
330+
'type': {
306331
const: 'norm'
307332
},
308333
'properties': {
@@ -325,7 +350,7 @@ const normSchema = mergeBase({
325350

326351
const ngramSchema = mergeBase({
327352
properties: {
328-
type: {
353+
'type': {
329354
const: 'ngram'
330355
},
331356
'properties': {
@@ -378,7 +403,7 @@ const ngramSchema = mergeBase({
378403

379404
const textSchema = mergeBase({
380405
properties: {
381-
type: {
406+
'type': {
382407
const: 'text'
408
},
384409
'properties': {
@@ -437,7 +462,7 @@ const textSchema = mergeBase({
437462

438463
const aqlSchema = mergeBase({
439464
properties: {
440-
type: {
465+
'type': {
441466
const: 'aql'
442467
},
443468
'properties': {
@@ -486,7 +511,7 @@ const aqlSchema = mergeBase({
486511

487512
const stopwordsSchema = mergeBase({
488513
properties: {
489-
type: {
514+
'type': {
490515
const: 'stopwords'
491516
},
492517
'properties': {
@@ -518,7 +543,7 @@ const stopwordsSchema = mergeBase({
518543

519544
const collationSchema = mergeBase({
520545
properties: {
521-
type: {
546+
'type': {
522547
const: 'collation'
523548
},
524549
'properties': {
@@ -539,7 +564,7 @@ const collationSchema = mergeBase({
539564

540565
const segmentationSchema = mergeBase({
541566
properties: {
542-
type: {
567+
'type': {
543568
const: 'segmentation'
544569
},
545570
'properties': {
@@ -560,6 +585,67 @@ const segmentationSchema = mergeBase({
560585
required: ['type', 'properties']
561586
});
562587

588+
const nearestNeighborsSchema = mergeBase({
589+
properties: {
590+
'type': {
591+
const: 'nearest_neighbors'
592+
},
593+
'properties': {
594+
type: 'object',
595+
nullable: false,
596+
properties: {
597+
model_location: {
598+
type: 'string',
599+
nullable: false
600+
},
601+
top_k: {
602+
type: 'integer',
603+
minimum: 0,
604+
maximum: 2147483647,
605+
nullable: false
606+
}
607+
}
608+
},
609+
additionalProperties: false,
610+
default: {}
611+
},
612+
required: ['type', 'properties']
613+
});
614+
615+
const classificationSchema = mergeBase({
616+
properties: {
617+
'type': {
618+
const: 'classification'
619+
},
620+
'properties': {
621+
type: 'object',
622+
nullable: false,
623+
properties: {
624+
model_location: {
625+
type: 'string',
626+
nullable: false
627+
},
628+
top_k: {
629+
type: 'integer',
630+
minimum: 0,
631+
maximum: 2147483647,
632+
nullable: false
633+
},
634+
threshold: {
635+
type: 'number',
636+
nullable: false,
637+
minimum: 0,
638+
maximum: 1,
639+
default: 0
640+
}
641+
}
642+
},
643+
additionalProperties: false,
644+
default: {}
645+
},
646+
required: ['type', 'properties']
647+
});
648+
563649
const pipelineSchema = mergeBase({
564650
properties: {
565651
type: {
@@ -586,7 +672,9 @@ const pipelineSchema = mergeBase({
586672
aqlSchema,
587673
stopwordsSchema,
588674
collationSchema,
589-
segmentationSchema
675+
segmentationSchema,
676+
nearestNeighborsSchema,
677+
classificationSchema
590678
],
591679
errorMessage: {
592680
discriminator: '/type should be one of "delimiter", "stem", "norm", "ngram", "text", "aql",' +
@@ -677,6 +765,8 @@ export const formSchema: JSONSchemaType<FormState> = {
677765
stopwordsSchema,
678766
collationSchema,
679767
segmentationSchema,
768+
nearestNeighborsSchema,
769+
classificationSchema,
680770
pipelineSchema,
681771
geojsonSchema,
682772
geopointSchema
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React, { Dispatch } from "react";
2+
import { ClassificationState, ModelProperty } from "../constants";
3+
import { DispatchArgs, FormProps } from '../../../utils/constants' 10000 ;
4+
import ModelInput from "./inputs/ModelInput";
5+
import { Cell, Grid } from "../../../components/pure-css/grid";
6+
import { getNumericFieldSetter } from "../../../utils/helpers";
7+
import Textbox from "../../../components/pure-css/form/Textbox";
8+
9+
const ClassificationForm = ({ formState, dispatch, disabled }: FormProps<ClassificationState>) =>
10+
<Grid>
11+
<Cell size={'1'}>
12+
<ModelInput formState={formState} dispatch={dispatch as Dispatch<DispatchArgs<ModelProperty>>}
13+
disabled={disabled}/>
14+
</Cell>
15+
<Cell size={'1-3'}>
16+
<Textbox label={'Threshold'} type={'number'} value={formState.properties.threshold} disabled={disabled}
17+
onChange={getNumericFieldSetter('properties.threshold', dispatch)}/>
18+
</Cell>
19+
</Grid>;
20+
21+
export default ClassificationForm;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React, { Dispatch } from "react";
2+
import { ModelProperty, NearestNeighborsState } from "../constants";
3+
import { DispatchArgs, FormProps } from '../../../utils/constants';
4+
import ModelInput from "./inputs/ModelInput";
5+
6+
const NearestNeighborsForm = ({ formState, dispatch, disabled }: FormProps<NearestNeighborsState>) =>
7+
<ModelInput formState={formState} dispatch={dispatch as Dispatch<DispatchArgs<ModelProperty>>}
8+
disabled={disabled}/>;
9+
10+
export default NearestNeighborsForm;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React, { ChangeEvent } from "react";
2+
import { FormProps } from '../../../../utils/constants';
3+
import Textbox from "../../../../components/pure-css/form/Textbox";
4+
import { Cell, Grid } from "../../../../components/pure-css/grid";
5+
import { getNumericFieldSetter, getNumericFieldValue } from "../../../../utils/helpers"; DFC9
6+
import { ModelProperty } from "../../constants";
7+
8+
const ModelInput = ({ formState, dispatch, disabled }: FormProps<ModelProperty>) => {
9+
const updateModelLocation = (event: ChangeEvent<HTMLInputElement>) => {
10+
dispatch({
11+
type: 'setField',
12+
field: {
13+
path: 'properties.model_location',
14+
value: event.target.value
15+
}
16+
});
17+
};
18+
19+
return <Grid>
20+
<Cell size={'2-3'}>
21+
<Textbox label={'Model Location'} type={'text'} value={formState.properties.model_location || ''}
22+
disabled={disabled} onChange={updateModelLocation} required={true}/>
23+
</Cell>
24+
25+
<Cell size={'1-3'}>
26+
<Textbox label={'Top K'} type={'number'} min={0} max={2147483647} disabled={disabled}
27+
value={getNumericFieldValue(formState.properties.top_k)}
28+
onChange={getNumericFieldSetter('properties.top_k', dispatch)}/>
29+
</Cell>
30+
</Grid>;
31+
};
32+
33+
export default ModelInput;

0 commit comments

Comments
 (0)
0