added more search/display fields and made more robust

This commit is contained in:
Malar Kannan
2017-06-20 18:50:54 +05:30
parent 6159f53137
commit 2c62605deb
5 changed files with 210 additions and 93 deletions

View File

@@ -1,34 +1,38 @@
import * as React from 'react';
import * as _ from 'lodash';
import {
// Button,
// Classes,
// InputGroup,
// Intent,
// Menu,
// MenuItem,
// Popover,
// Position,
// Spinner,
// Switch,
// Tag,
// Tooltip,
FocusStyleManager,
} from '@blueprintjs/core';
import * as XML from 'xml2js';
import * as XPath from 'xml2js-xpath';
const { Flex, Box } = require('reflexbox');
FocusStyleManager.onlyShowFocusOnTabs();
type ReactEvent = React.ChangeEvent<HTMLInputElement>;
enum EditorMode {
Empty = 1, Edit, Add
}
interface LexEditorProps {
fileName: RequestInfo;
}
const searchLensMap = {
'label': 'label[0]',
'unl': 'unl[0]',
'synset': 'lexprops[0].wnsynset[0]',
'guid': 'guid[0]',
'pos': 'pos[0]',
'image': 'image[0]',
'relations': 'relations[0]',
'frame': 'syntacticprops[0].property[0]._',
'morphclass': 'lexprops[0].morphology[0].morph[0]._',
'stats': 'stats[0].property[0]._',
'lang': '$.id',
};
class LexEditor extends React.Component<LexEditorProps, any> {
constructor(props: LexEditorProps) {
super(props);
this.handleOnSearch = this.handleOnSearch.bind(this);
this.state = { lexData: {}, matchedEntries: [] };
}
@@ -39,91 +43,204 @@ class LexEditor extends React.Component<LexEditorProps, any> {
XML.parseString(xmlString, (err, lexData) => {
this.setState({ ...this.state, lexData });
});
})
.catch((e) => {
console.log('errored :', e);
});
// .catch((error) => {
// console.error(error);
// });
}
public render() {
return (
<div>
<LexSearch handleOnSearch={this.handleOnSearch} />
<LexMatches matchedEntries={this.state.matchedEntries} />
</div>
);
}
private handleOnSearch(event: ReactEvent): void {
let searchText = event.target.value;
// this.setState({ ...this.state, searchText });
let pathQ = './/lang';
let words = XPath.find(this.state.lexData.document, pathQ);
let matchedEntries = words.filter((obj) => {
if (obj.label[0] === searchText) {
return true;
}
return false;
});
this.setState({ ...this.state, matchedEntries });
}
}
interface LexSearchProps {
handleOnSearch: (e: ReactEvent) => void;
}
class LexSearch extends React.Component<LexSearchProps, null> {
public render() {
return (
<div className="pt-input-group" style={{ width: '300px' }}>
<span className="pt-icon pt-icon-search" />
<input
className="pt-input"
type="search"
placeholder="Search input"
dir="auto"
onChange={e => this.props.handleOnSearch(e)}
<LexSearch handleOnSearch={(e: any) => this.handleOnSearch(e)} />
<LexMatches
matchedEntries={this.state.matchedEntries}
mode={this.state.mode}
searchText={this.state.searchText}
searchType={this.state.searchType}
/>
</div>
);
}
}
class LexMatches extends React.Component<any, any> {
public render() {
return (
<div>
{this.props.matchedEntries.map((mObj: any) => {
console.log('Matched ObjectEntry' + mObj);
return (<LexEntry key={mObj.unl} lexItem={mObj} />);
})}
</div>
);
private handleOnSearch(searchEvent: any): void {
let searchText = searchEvent.searchValue;
let searchType = searchLensMap[searchEvent.searchType];
let matchedEntries = _.chain(this.state.lexData)
.get<any>('document.lexicon[0].item')
.flatMap((o: any) => _.chain(o)
.get<any>('entry')
.map((p: any) => _.chain(p)
.get<any>('lang[0]')
.set('guid[0]', o.$.guid)
.value())
.value()
)
.filter((q: any) => _.get<any>(q, searchType, '') === searchText)
.value();
let emptyOrAdd = searchText === '' ? EditorMode.Empty : EditorMode.Add;
let mode = matchedEntries.length > 0 ? EditorMode.Edit : emptyOrAdd;
this.setState({ ...this.state, matchedEntries, mode, searchText, searchType });
}
}
class LexEntry extends React.Component<any, any> {
class LexSearch extends React.Component<any, any> {
searchType: String = 'label';
searchValue: String = '';
public render() {
return (
<div className="pt-form-group">
<label className="pt-label" htmlFor="example-form-group-input-a">
UNL
<Flex p={1} align="center" className="pt-control-group">
<div
className="pt-select"
onChange={e => this.handleTypeChange(e)}
>
<select>
{_.keys(searchLensMap).map(k => {
return <option value={k}> {_.capitalize(k)}</option>;
})}
</select>
</div>
<div className="pt-input-group" style={{ width: '120px' }}>
<span className="pt-icon pt-icon-search" />
<input
type="text"
className="pt-input"
placeholder="Search input"
dir="auto"
onChange={e => this.handleLookup(e)}
/>
</div>
</Flex>
);
}
private handleLookup(e: any) {
this.searchValue = e.target.value;
this.props.handleOnSearch({ searchType: this.searchType, searchValue: this.searchValue });
}
private handleTypeChange(e: any) {
this.searchType = e.target.value;
this.props.handleOnSearch({ searchType: this.searchType, searchValue: this.searchValue });
}
}
function selectMode(props: any) {
let editEntries = props.matchedEntries.map((mObj: any) => {
let uniqueKey = mObj.guid[0] + '#' + mObj.$.id;
return (<LexEdit key={uniqueKey} lexItem={mObj} />);
});
switch (props.mode) {
case EditorMode.Edit:
return editEntries;
case EditorMode.Add:
let addProps = {};
_.set(addProps, props.searchType, props.searchText);
return <LexEdit lexItem={addProps} />;
default:
return (
<div className="pt-non-ideal-state">
<div className="pt-non-ideal-state-visual pt-non-ideal-state-icon">
<span className="pt-icon pt-icon-folder-open" />
</div>
<h4 className="pt-non-ideal-state-title">Empty</h4>
<div className="pt-non-ideal-state-description">
Type something in the searchbar.
</div>
</div>
);
}
}
function LexMatches(props: any) {
return (
<Flex m={10} align="center" wrap={true}>
{selectMode(props)}
</Flex>
);
}
class LexEdit extends React.Component<any, any> {
public render() {
let li = this.props.lexItem;
let lexFields = _.keys(searchLensMap).map(e => {
return this.getLabelField(e, searchLensMap[e], li);
});
return (
<Box wx={240} mx={10} my={20} className="pt-card pt-elevation-2 pt-interactive">
<label className="pt-label">
GUID {_.get<any>(li, 'guid', '')}
</label>
<div className="pt-form-content">
<label className="pt-label">
Language: {_.get<any>(li, '$.id', '')}
</label>
<Box column={true} m={1}>
{lexFields}
</Box>
</Box>
);
}
private getLabelField(text: string, labelLens: string, li: any) {
return (
<LexField
key={text}
labelText={_.capitalize(text)}
fieldType={text}
fieldText={_.get<any>(li, labelLens, '')}
fieldHandler={(e: any) => this.handleOnChange(e)}
/>
);
}
private handleOnChange(event: any) {
this.setState(event);
}
}
class LexField extends React.Component<any, any> {
constructor(props: any) {
super(props);
this.state = { fieldText: this.props.fieldText };
}
public render() {
return (
<div className="pt-form-group pt-inline">
<Box w={2 / 5}>
<label style={{ textAlign: 'right' }} className="pt-label" htmlFor="example-form-group-input-a">
{this.props.labelText}
</label>
</Box>
<Box w={3 / 5}>
<input
id="example-form-group-input-a"
className="pt-input"
style={{ width: '300px' }}
placeholder="UNL Value"
value={this.props.lexItem.unl}
style={{ width: '110px' }}
placeholder={this.props.fieldType}
value={this.state.fieldText}
type="text"
dir="auto"
onChange={(e: any) => this.onFieldChange(e)}
/>
</div>
</Box>
</div>
);
}
public componentWillReceiveProps(nextProps: any) {
if (this.props.fieldText !== nextProps.fieldText) {
let fieldText = nextProps.fieldText;
this.setState({ ...this.state, fieldText });
}
}
private onFieldChange(e: any) {
let fieldText = e.target.value;
let eventData = {};
eventData[this.props.fieldType] = fieldText;
this.setState({ ...this.state, fieldText });
this.props.fieldHandler(eventData);
}
}
export default LexEditor;