From c6c8655649b6f049fe478c0cc265af79095c715b Mon Sep 17 00:00:00 2001 From: Malar Kannan Date: Wed, 19 Jul 2017 16:53:24 +0530 Subject: [PATCH] 1. refactored to use get/set instead of raw lens 2. updated webpack dev config to use python proxy api server --- config/webpack.config.flask.js | 1 + config/webpackDevServer.config.js | 4 +- scripts/flask.js | 16 ++--- src/App.tsx | 2 +- src/LexEdit.tsx | 40 +++++------ src/LexEditor.tsx | 9 ++- src/LexSetup.tsx | 106 +++++++++++++++++++++++------- src/LexSingleInput.tsx | 4 +- walle_server.py | 17 +++-- 9 files changed, 134 insertions(+), 65 deletions(-) diff --git a/config/webpack.config.flask.js b/config/webpack.config.flask.js index c94511e..b09d623 100644 --- a/config/webpack.config.flask.js +++ b/config/webpack.config.flask.js @@ -17,6 +17,7 @@ const getClientEnvironment = require('./env'); const paths = require('./paths'); // Webpack uses `publicPath` to determine where the app is being served from. // It requires a trailing slash, or the file assets will get an incorrect path. +// const publicPath = 'http://localhost:3000/'; const publicPath = paths.servedPath; // Some apps do not use client-side routing with pushState. // For these, "homepage" can be set to "." to enable relative asset paths. diff --git a/config/webpackDevServer.config.js b/config/webpackDevServer.config.js index 6563fb8..fc995cb 100644 --- a/config/webpackDevServer.config.js +++ b/config/webpackDevServer.config.js @@ -77,7 +77,9 @@ module.exports = function(proxy, allowedHost) { disableDotRule: true, }, public: allowedHost, - proxy, + proxy: { + "/api":"http://localhost:5000/" + }, setup(app) { // This lets us open files from the runtime error overlay. app.use(errorOverlayMiddleware()); diff --git a/scripts/flask.js b/scripts/flask.js index 07087bb..b8bdedb 100644 --- a/scripts/flask.js +++ b/scripts/flask.js @@ -113,13 +113,11 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { // } // ); startWebPackDevServer(()=>{ - // child_process.spawn('webpack',['--watch','--config','config/webpack.config.flask.js'],{ - // stdio:'inherit' - // }); child_process.spawn('python',['walle_server.py'],{ stdio:'inherit' }); }); + // Create the production build and print the deployment instructions. function build(previousFileSizes) { console.log('Creating an optimized production build...'); @@ -169,10 +167,11 @@ function copyPublicFolder() { function startWebPackDevServer(pyServer){ const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; const HOST = process.env.HOST || '0.0.0.0'; - fs.emptyDirSync(paths.appBuild); - fs.ensureSymlink(paths.appPng,path.resolve(paths.appBuild,'png')); - // Merge with the public folder - copyPublicFolder(); + // fs.emptyDirSync(paths.appBuild); + // fs.ensureSymlink(paths.appPng,path.resolve(paths.appBuild,'png')); + // // Merge with the public folder + // copyPublicFolder(); + // We attempt to use the default port but if it is busy, we offer the user to // run on a different port. `detect()` Promise resolves to the next free port. choosePort(HOST, DEFAULT_PORT) @@ -201,8 +200,9 @@ function startWebPackDevServer(pyServer){ } if (isInteractive) { clearConsole(); - const urls = prepareUrls(protocol, HOST, '5000'); + const pyurls = prepareUrls(protocol, HOST, '5000'); pyServer(); + // openBrowser(pyurls.localUrlForBrowser); openBrowser(urls.localUrlForBrowser); } }); diff --git a/src/App.tsx b/src/App.tsx index 7b7db8d..46a3fdd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,7 +27,7 @@ export class Main extends React.Component { - + ); } diff --git a/src/LexEdit.tsx b/src/LexEdit.tsx index 34953b4..1a223aa 100644 --- a/src/LexEdit.tsx +++ b/src/LexEdit.tsx @@ -13,7 +13,7 @@ const { Box } = require('reflexbox'); const serialize = function(obj: any) { var str = []; - for(var p in obj){ + for (var p in obj) { if (obj.hasOwnProperty(p)) { str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p])); } @@ -29,15 +29,14 @@ export class LexEdit extends React.Component { } public render() { let li = this.state.lexItem; - let editLang = _.get(li, this.props.fieldMetaMap.lang.lens, 'en'); + let editLang = this.props.fieldMetaMap.lang.get(li); let langSelOpts = _.get(this.props.selectionMeta, editLang, []); let lexFields = _.keys(this.props.fieldMetaMap).map(field => { - let lens = this.props.fieldMetaMap[field].lens; - let defaultText = _.get(li, lens, ''); - let originalText = _.get(this.props.lexItem, lens, ''); - let options = this.props.fieldMetaMap[field].options; + let fieldMeta = this.props.fieldMetaMap[field]; + let defaultText = fieldMeta.get(li); + let originalText = fieldMeta.get(this.props.lexItem); + let options = fieldMeta.options; let changed = defaultText !== originalText && this.props.existing; - // console.log('changed:',changed); let sh = (e: any) => { let eventData = {}; eventData[field] = e.target.value; @@ -48,10 +47,10 @@ export class LexEdit extends React.Component { return textInput(params); } else if (this.props.fieldMetaMap[field].type === 'select') { return selectInput(params); - } else if (this.props.fieldMetaMap[field].type === 'preview' - && defaultText !== '') { + } else if (this.props.fieldMetaMap[field].type === 'preview') { return imagePreview(params); } else { + console.log('field discarded :', field); return null; } }); @@ -103,14 +102,18 @@ export class LexEdit extends React.Component { private handleOnLoad(event: any) { // this.props.load(this.state.lexItem) - let lexItem = this.props.lexItem; - let word = _.get(lexItem, this.props.fieldMetaMap.label.lens, ''); - let pos = _.get(lexItem, this.props.fieldMetaMap.pos.lens, ''); - let args = serialize({word,pos}); - fetch('/morph?'+args) + let li = this.state.lexItem; + let word = this.props.fieldMetaMap.label.get(li); + let pos = this.props.fieldMetaMap.pos.get(li); + let args = serialize({ word, pos }); + let morphQuery = '/api/morph?' + args; + fetch(morphQuery) .then((response) => response.text()) .then((jsonMorph) => { - console.log(jsonMorph); + let morphDict = JSON.parse(jsonMorph); + let morphMeta = this.props.fieldMetaMap.morphclass; + let lexItem = morphMeta.set(this.state.lexItem, morphDict.morphclass); + this.setState({ lexItem }); }) .catch((e) => { console.log('errored :', e); @@ -119,10 +122,9 @@ export class LexEdit extends React.Component { private handleOnChange(event: any) { let type = _.keys(event)[0]; - let value = _.values(event)[0]; - let lens = this.props.fieldMetaMap[type].lens; - let lexItem = _.cloneDeep(this.state.lexItem); - _.set(lexItem, lens, value); + let value = _.values(event)[0] as string; + let meta = this.props.fieldMetaMap[type]; + let lexItem = meta.set(this.state.lexItem, value); this.setState({ lexItem }); } diff --git a/src/LexEditor.tsx b/src/LexEditor.tsx index 63c25ff..39a2b31 100644 --- a/src/LexEditor.tsx +++ b/src/LexEditor.tsx @@ -10,10 +10,10 @@ const { Flex } = require('reflexbox'); // container component export class LexEditor extends React.Component { public render() { - let searchLens = this.props.fieldMetaMap[this.props.searchState.searchType].lens; + let searchMeta = this.props.fieldMetaMap[this.props.searchState.searchType]; let searchText = this.props.searchState.searchValue; let matchedEntries = _.chain(this.props.allEntries) - .filter((q: any) => _.get(q, searchLens, '') === searchText) + .filter((q: any) => searchMeta.get(q) === searchText) .take(10) .value(); let { fieldMetaMap: fieldMetaMap, save: save } = this.props; @@ -27,7 +27,7 @@ export class LexEditor extends React.Component { matchedEntries={matchedEntries} selectionMeta={this.props.selectFields} searchText={searchText} - searchLens={searchLens} + searchMeta={searchMeta} /> ); @@ -91,8 +91,7 @@ function LexMatches(params: any) { /> ); }); - let addProps = {}; - _.set(addProps, props.searchLens, props.searchText); + let addProps = props.searchMeta.set({}, props.searchText); let addEntry = ( { + let val = _.get(li, lens, def); + return val; + }, + set: (li: any, value: string) => { + let lexItem = _.cloneDeep(li); + let ret = _.set(lexItem, lens, value); + return ret; + } + }; +} + const fieldMetaMap = { - label: { lens: 'label[0]', type: 'text' }, - unl: { lens: 'unl[0]', type: 'text' }, - synset: { lens: 'lexprops[0].wnsynset[0]', type: 'text' }, - guid: { lens: 'guid[0]', type: 'text' }, - pos: { lens: 'pos[0]', type: 'select' }, - image: { lens: 'image[0]', type: 'preview' }, - relations: { lens: 'relations[0]', type: 'text' }, - frame: { lens: 'syntacticprops[0].property[0]._', type: 'select' }, - morphclass: { - lens: 'lexprops[0].morphology[0].morph[0]._', - type: 'select' + label: { + type: 'text', + ...simpleAccessor('label[0]'), }, - stats: { lens: 'stats[0].property[0]._', type: 'text' }, - lang: { lens: '$.id', type: 'select', options: ['en', 'es'] }, + unl: { type: 'text', ...simpleAccessor('unl[0]'), }, + synset: { type: 'text', ...simpleAccessor('lexprops[0].wnsynset[0]'), }, + guid: { type: 'text', ...simpleAccessor('guid[0]'), }, + pos: { type: 'select', ...simpleAccessor('pos[0]'), }, + image: { type: 'text', ...simpleAccessor('image[0]'), }, + relations: { type: 'text', ...simpleAccessor('relations[0]'), }, + frame: { type: 'select', ...simpleAccessor('syntacticprops[0].property[0]._'), }, + morphclass: { + type: 'select', + get: (li: any) => { + let lens = 'lexprops[0].morphology[0].morph'; + let def = [{ _: '', $: { form: 'morphclass' } }]; + let morphProps = _.get(li, lens, def); + let prop = _.filter(morphProps, (m) => { + return m.$.form === 'morphclass'; + }); + let mcls = _.get(prop, '[0]._', ''); + return mcls; + }, + set: (li: any, value: string) => { + let lexItem = _.cloneDeep(li); + let lens = 'lexprops[0].morphology[0].morph'; + let morphProps = _.get(lexItem, lens, []); + if (morphProps.length > 0) { + let prop = _.filter(morphProps, (m) => { + return m.$.form === 'morphclass'; + }); + if (prop.length > 0) { + _.set(prop[0], '_', value); + } else { + let def = { _: value, $: { form: 'morphclass' } }; + morphProps.push(def); + } + } else { + let def = [{ _: value, $: { form: 'morphclass' } }]; + _.set(lexItem, lens, def); + } + return lexItem; + } + }, + morphexceptions: { + type: 'list', + get: (li: any) => { + let lens = 'lexprops[0].morphology[0].morph'; + let def = [{ _: 'M0', $: { form: 'morphclass' } }]; + let morphProps = _.get(li, lens, def); + let morphExps = _.filter(morphProps, (m) => { + return m.$.form !== 'morphclass'; + }); + return morphExps; + } + }, + stats: { type: 'text', ...simpleAccessor('stats[0].property[0]._'), }, + lang: { type: 'select', options: ['en', 'es'], ...simpleAccessor('$.id', 'en'), }, }; const xmlToEntries = (xmlData: any) => { @@ -34,7 +92,7 @@ const xmlToEntries = (xmlData: any) => { ) .value(); let langReducer = ((result: any, q: any) => { - let lang = _.get(q, fieldMetaMap.lang.lens, 'en'); + let lang = fieldMetaMap.lang.get(q); (result[lang] || (result[lang] = [])).push(q); return result; }); @@ -44,10 +102,9 @@ const xmlToEntries = (xmlData: any) => { let langOpts = _.fromPairs(_.keys(fieldMetaMap).filter((s) => { return fieldMetaMap[s].type === 'select'; }).map((s) => { - let lens = fieldMetaMap[s].lens; let entries = _.get(langEntries, lang, 'en'); let selectOptions = _.uniq(entries.map((q: any) => { - return _.get(q, lens, ''); + return fieldMetaMap[s].get(q); })); return [s, selectOptions]; })); @@ -78,12 +135,15 @@ export class LexSetup extends React.Component { } render() { - return this.state.xmlLoaded ? ( - - ) : ( - - Loading - - ); + let dimmer = ( + + Loading + + ); + let xmlEntries = xmlToEntries(this.props.xmlData); + let editor = ( + + ); + return this.state.xmlLoaded ? editor : dimmer; } } diff --git a/src/LexSingleInput.tsx b/src/LexSingleInput.tsx index e459b40..99e7d0b 100644 --- a/src/LexSingleInput.tsx +++ b/src/LexSingleInput.tsx @@ -82,9 +82,9 @@ export function selectInput(params: any) { export function imagePreview(params: any) { let { field, defaultText, changed } = params; let imageSrc = imageRoot + defaultText; - return ( + return defaultText !== '' ? ( - ); + ) : null; } diff --git a/walle_server.py b/walle_server.py index ab2b838..64f9f56 100644 --- a/walle_server.py +++ b/walle_server.py @@ -1,22 +1,27 @@ from flask import Flask,send_from_directory,request app = Flask(__name__,static_url_path='',static_folder='build') -from freespeech_walle.get_morph_rule import get_morph +# from freespeech_walle.get_morph_rule import get_morph +from freespeech_walle.wizard_helpers import get_morph_rule,get_frequency import json +# from flask_cors import CORS, cross_origin +# CORS(app) + @app.route('/') def walle_index(): return app.send_static_file('index.html') -@app.route('/test') +@app.route('/api/test') def walle_test(): return "test" -@app.route('/morph') +@app.route('/api/morph') def walle_morph(): - word = request.args.get('word') - pos = request.args.get('pos') - return json.dumps(get_morph(word,pos)) + word = request.args.get('word','water') + pos_req = request.args.get('pos','N') + pos = pos_req if pos_req != '' else 'N'; + return json.dumps(get_morph_rule.get_morph(word,pos)) # hmr streaming # import requests