From c0eedb45557488ea400a2274c3ffa2404e78511b Mon Sep 17 00:00:00 2001 From: Malar Kannan Date: Mon, 31 Jul 2017 17:19:56 +0530 Subject: [PATCH] implemented morph exceptions --- package.json | 40 +++--- src/LexAccessors.tsx | 41 ++++-- src/LexEdit.tsx | 2 +- src/LexEditor.tsx | 2 +- src/LexInputContainer.tsx | 265 ++++++++++++++++++++++++++++++++++++++ src/LexSetup.tsx | 4 +- src/LexSingleInput.tsx | 148 --------------------- walle_server.py | 4 +- 8 files changed, 324 insertions(+), 182 deletions(-) create mode 100644 src/LexInputContainer.tsx delete mode 100644 src/LexSingleInput.tsx diff --git a/package.json b/package.json index c3850f2..645f354 100644 --- a/package.json +++ b/package.json @@ -3,32 +3,32 @@ "version": "0.1.0", "private": true, "dependencies": { - "eslint": "^4.2.0", + "eslint": "^4.3.0", "eslint-config-react-app": "^1.0.5", - "react": "^15.5.4", - "react-addons-css-transition-group": "^15.5.2", - "react-dom": "^15.5.4", + "react": "^15.6.1", + "react-addons-css-transition-group": "^15.6.0", + "react-dom": "^15.6.1", "react-redux": "^5.0.5", - "react-sortable-hoc": "^0.6.5", + "react-sortable-hoc": "^0.6.6", "react-transition-group": "^1.1.3", "reflexbox": "^3.0.0-0", - "semantic-ui-css": "^2.2.10", - "semantic-ui-react": "^0.68.5", + "semantic-ui-css": "^2.2.11", + "semantic-ui-react": "^0.71.3", "xml2js": "^0.4.17", "xml2js-xpath": "^0.8.0" }, "devDependencies": { "@types/es6-shim": "^0.31.34", "@types/jest": "^19.2.4", - "@types/lodash": "^4.14.66", - "@types/node": "^7.0.29", + "@types/lodash": "^4.14.71", + "@types/node": "^7.0.39", "@types/pure-render-decorator": "^0.2.27", - "@types/react": "^15.0.27", - "@types/react-addons-css-transition-group": "^15.0.2", - "@types/react-dom": "^15.5.0", - "@types/react-redux": "^4.4.46", + "@types/react": "^15.6.0", + "@types/react-addons-css-transition-group": "^15.0.3", + "@types/react-dom": "^15.5.1", + "@types/react-redux": "^4.4.47", "@types/react-sortable-hoc": "^0.6.0", - "@types/react-transition-group": "^1.1.0", + "@types/react-transition-group": "^1.1.2", "@types/xml2js": "0.0.33", "app-root-path": "^2.0.1", "autoprefixer": "7.1.0", @@ -48,19 +48,19 @@ "postcss-loader": "2.0.5", "promise": "7.1.1", "react-dev-utils": "^2.0.1", - "react-error-overlay": "^1.0.6", + "react-error-overlay": "^1.0.9", "source-map-loader": "^0.2.1", "style-loader": "0.17.0", "sw-precache-webpack-plugin": "0.9.1", - "ts-loader": "^2.0.3", - "tslint": "^5.2.0", + "ts-loader": "^2.3.2", + "tslint": "^5.5.0", "tslint-loader": "^3.5.3", - "tslint-react": "^3.0.0", - "typescript": "^2.3.3", + "tslint-react": "^3.1.0", + "typescript": "^2.4.2", "url-loader": "0.5.8", "webpack": "2.6.0", "webpack-dev-server": "2.4.5", - "webpack-manifest-plugin": "^1.1.0", + "webpack-manifest-plugin": "^1.2.1", "whatwg-fetch": "2.0.3", "write-file-webpack-plugin": "^4.1.0" }, diff --git a/src/LexAccessors.tsx b/src/LexAccessors.tsx index 9930836..dea30e0 100644 --- a/src/LexAccessors.tsx +++ b/src/LexAccessors.tsx @@ -91,13 +91,19 @@ function propListAttrAccessor(attrPred: any) { set: (li: any, value: any) => { let lexItem = _.cloneDeep(li); let allProps = _.get(lexItem, lens, []); + let setValue = value.map((v: any) => { + let ret = {}; + _.set(ret, '$.form', v.key); + _.set(ret, '_', v.value); + return ret; + }); if (allProps.length > 0) { let keepProps = _.filter(allProps, (m) => { return !pred(m); }); - _.set(lexItem, lens, _.concat(keepProps, value)); + _.set(lexItem, lens, _.concat(keepProps, setValue)); } else { - _.set(lexItem, lens, value); + _.set(lexItem, lens, setValue); } return lexItem; } @@ -190,6 +196,22 @@ const fieldMetaMap = { }, }; +function getSelectOptions(field: string, entries: any) { + let allOpts = entries.map((q: any) => { + return fieldMetaMap[field].get(q); + }); + switch (fieldMetaMap[field].type) { + case 'select': + return _.uniq(allOpts); + case 'list': + return _.uniq(_.flatten(allOpts)); + case 'proplist': + return _.uniq(_.map(_.flatten(allOpts), (v) => _.get(v, 'key'))); + default: + return []; + } +} + export const xmlToEntries = (xmlData: any) => { let allEntries = _.chain(xmlData) .get('document.lexicon[0].item') @@ -209,17 +231,18 @@ export const xmlToEntries = (xmlData: any) => { }); let langEntries = _.reduce(allEntries, langReducer, {}); let langs = _.keys(langEntries); + let selectableFields = ['select', 'list', 'proplist']; let selectFields = _.fromPairs(langs.map((lang) => { let langOpts = _.fromPairs(_.keys(fieldMetaMap).filter((s) => { - return _.includes(['select', 'list'], fieldMetaMap[s].type); + return _.includes(selectableFields, fieldMetaMap[s].type); }).map((s) => { let entries = _.get(langEntries, lang, 'en'); - let allOpts = entries.map((q: any) => { - return fieldMetaMap[s].get(q); - }); - let select = _.isEqual(fieldMetaMap[s].type, 'select'); - let selectOptions = select ? _.uniq(allOpts) : _.uniq(_.flatten(allOpts)); - return [s, selectOptions]; + // let allOpts = entries.map((q: any) => { + // return fieldMetaMap[s].get(q); + // }); + // let select = _.isEqual(fieldMetaMap[s].type, 'select'); + // let selectOptions = select ? _.uniq(allOpts) : _.uniq(_.flatten(allOpts)); + return [s, getSelectOptions(s, entries)]; })); return [lang, langOpts]; })); diff --git a/src/LexEdit.tsx b/src/LexEdit.tsx index 6f6b76c..ad67f2c 100644 --- a/src/LexEdit.tsx +++ b/src/LexEdit.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import * as _ from 'lodash'; -import { componentForType } from './LexSingleInput'; +import { componentForType } from './LexInputContainer'; import { Card, Button diff --git a/src/LexEditor.tsx b/src/LexEditor.tsx index 61f09e0..93a6056 100644 --- a/src/LexEditor.tsx +++ b/src/LexEditor.tsx @@ -77,7 +77,7 @@ function LexMatches(params: any) { if (props.searchText === '') { return ( -
Empty
+
Empty
Type something in the searchbar.
); diff --git a/src/LexInputContainer.tsx b/src/LexInputContainer.tsx new file mode 100644 index 0000000..9552257 --- /dev/null +++ b/src/LexInputContainer.tsx @@ -0,0 +1,265 @@ +import * as React from 'react'; +import * as _ from 'lodash'; +import { Label, Form } from 'semantic-ui-react'; +const { Flex, Box } = require('reflexbox'); +import { + Input, + Dropdown, + Image, + Modal, + Button, +} from 'semantic-ui-react'; + +class LexInputContainer extends React.Component { + public render() { + return ( +
+
+ + + {this.props.label} + + + {this.props.children} + + +
+
+ ); + } +} + +function changedLabel(changed: boolean, text: string) { + let labelClass = changed ? 'olive' : ''; + return ( + + ); +} + +function textInput(params: any) { + let { field, sh, value, changed } = params; + return ( + + { sh(d.value); }} + value={value} + placeholder={field} + type="text" + dir="auto" + style={{ width: '10em' }} + /> + + ); +} + +function selectInput(params: any) { + let { field, sh, value, options, langSelOpts, changed } = params; + let staticOpts = options; + let fieldOpts = _.get(langSelOpts, field, []); + let selOpts = staticOpts ? staticOpts : fieldOpts; + let dropOptions = selOpts.map((k: any, i: any, c: any) => { + return { key: i, value: k, text: k }; + }); + return ( + + { sh(d.value); }} + value={value} + compact={true} + selection={true} + search={true} + style={{ width: '10em' }} + /> + + ); +} + +function imagePreview(params: any) { + let { field, value, changed } = params; + let imageSrc = '/png/' + value; + return value !== '' ? ( + + + + ) : textInput(params); +} + +function listInput(params: any) { + let { field, sh, langSelOpts, value, changed } = params; + let fieldOpts = _.get(langSelOpts, field, []); + let renderLabel = (label: any) => ({ + content: `${label.value}`, + }); + let dropOptions = fieldOpts.map((k: any, i: any, c: any) => { + return { + key: i, + value: k, + text: k, + }; + }); + return ( + + { + sh(d.value); + }} + value={value} + compact={true} + selection={true} + search={true} + multiple={true} + fluid={true} + style={{ width: '10em' }} + renderLabel={renderLabel} + /> + + ); +} + +function propListInput(params: any) { + let { field, changed } = params; + return ( + + + + ); +} + +class PropListInput extends React.Component { + constructor(props: any) { + super(props); + let { value } = this.props.params; + let dropOptions = this.dropOptsForVal(value); + this.state = { value, dropOptions, modalOpen: false, exKey: '', exVal: '' }; + } + + dropOptsForVal(value: any) { + let { field, langSelOpts } = this.props.params; + let fieldOpts = _.get(langSelOpts, field, []); + function valueForKey(key: string) { + let match = _.find(value, (v: any) => _.isEqual(v.key, key)); + if (match) { + return match; + } else { + return { key, value: '' }; + } + } + return fieldOpts.map((k: any, i: any) => { + return { + key: i, + value: valueForKey(k), + text: k, + }; + }); + } + + public render() { + let { sh } = this.props.params; + let renderLabel = (label: any) => ({ + content: `${label.value.key}-${label.value.value}`, + }); + let value = _.filter(this.state.dropOptions, (o: any) => { + return _.some(this.state.value, (v: any) => { + return _.isEqual(v.key, o.value.key); + }); + }).map((so) => so.value); + let onCloseModal = (e: any) => { + let except = { key: this.state.exKey, value: this.state.exVal }; + let ns = _.concat(this.state.value, except); + this.setState({ + dropOptions: this.dropOptsForVal(ns), + value: ns, + modalOpen: false, + exKey: '', + exVal: '' + }); + sh(ns); + }; + let dropDownComp = ( + { + let newValue = d.value as any; + let addedValue = _.difference(newValue, this.state.value) as any; + console.log('added: ', addedValue); + let didAdd = _.size(addedValue) > 0; + let newState = didAdd ? { + exKey: addedValue[0].key, + } : { + exKey: '', + value: newValue + } as any; + this.setState({ ...newState, modalOpen: didAdd }); + if (!didAdd) { + sh(newValue); + } + }} + value={value} + compact={true} + selection={true} + search={true} + multiple={true} + fluid={true} + style={{ width: '10em' }} + renderLabel={renderLabel} + /> + ); + return ( + + + Enter the exception for {this.state.exKey} + + + { + this.setState({ exVal: d.value }); + }} + /> + + + + ); + } +} + +export function componentForType(type: string, params: any) { + switch (type) { + case 'text': { + return textInput(params); + } + case 'select': { + return selectInput(params); + } + case 'preview': { + return imagePreview(params); + } + case 'list': { + return listInput(params); + } + case 'proplist': { + return propListInput(params); + } + default: { + console.log('type discarded :', type); + return null; + } + } +} diff --git a/src/LexSetup.tsx b/src/LexSetup.tsx index 62ec9df..b94c8bc 100644 --- a/src/LexSetup.tsx +++ b/src/LexSetup.tsx @@ -63,7 +63,7 @@ export class LexXMLSelect extends React.Component { export class LexSetup extends React.Component { xmlBuilder = new XML.Builder(); - xmlFileName = 'new_es.xml'; + xmlFileName = 'new_es_orig.xml'; constructor(props: any) { super(props); this.state = { @@ -95,7 +95,7 @@ export class LexSetup extends React.Component { let editor = (
-
+
{saveButton} {loadButton} { - public render() { - return ( -
-
- - - {this.props.label} - - - {this.props.children} - - -
-
- ); - } -} - -function changedLabel(changed: boolean, text: string) { - let labelClass = changed ? 'olive' : ''; - return ( - - ); -} - -function textInput(params: any) { - let { field, sh, value, changed } = params; - return ( - - { sh(d.value); }} - value={value} - placeholder={field} - type="text" - dir="auto" - style={{ width: '10em' }} - /> - - ); -} - -function selectInput(params: any) { - let { field, sh, value, options, langSelOpts, changed } = params; - let staticOpts = options; - let fieldOpts = _.get(langSelOpts, field, []); - let selOpts = staticOpts ? staticOpts : fieldOpts; - let dropOptions = selOpts.map((k: any, i: any, c: any) => { - return { key: i, value: k, text: k }; - }); - return ( - - { sh(d.value); }} - value={value} - compact={true} - selection={true} - search={true} - style={{ width: '10em' }} - /> - - ); -} - -function imagePreview(params: any) { - let { field, value, changed } = params; - let imageSrc = '/png/' + value; - return value !== '' ? ( - - - - ) : textInput(params); -} - -function listInput(params: any) { - let { field, sh, langSelOpts, value, changed } = params; - let fieldOpts = _.get(langSelOpts, field, []); - let renderLabel = (label: any) => ({ - content: `${label.value}`, - }); - let dropOptions = fieldOpts.map((k: any, i: any, c: any) => { - return { - key: i, - value: k, - text: k, - }; - }); - return ( - - { - sh(d.value); - }} - value={value} - compact={true} - selection={true} - search={true} - multiple={true} - fluid={true} - style={{ width: '10em' }} - renderLabel={renderLabel} - /> - - ); -} - -export function componentForType(type: string, params: any) { - switch (type) { - case 'text': { - return textInput(params); - } - case 'select': { - return selectInput(params); - } - case 'preview': { - return imagePreview(params); - } - case 'list': { - // return (); - return listInput(params); - } - default: { - // console.log('type discarded :', type); - // console.log('values discarded :', fieldMeta.get(li)); - return null; - } - } -} diff --git a/walle_server.py b/walle_server.py index 8ea0299..5fe0508 100644 --- a/walle_server.py +++ b/walle_server.py @@ -6,7 +6,9 @@ import json import codecs import glob import os -xmlDir = 'public/' + +production = True if os.environ.get('NODE_ENV','') == 'production' else False +xmlDir = 'public/' if production else 'build/' # from flask_cors import CORS, cross_origin # CORS(app)