mirror of
https://github.com/Alamantus/Lexiconga.git
synced 2025-04-01 17:22:07 +02:00
Start creating EditDictionaryModal and related pieces
Add Updater for saving new values. Add EditDictionaryForm and EditLinguisticsForm. Add helpful Array and Object functions to Helper.
This commit is contained in:
parent
24301cc7e6
commit
c8a7c1436f
8 changed files with 381 additions and 13 deletions
|
@ -15,6 +15,38 @@ class Helper {
|
|||
characterIsUppercase (character) {
|
||||
return character === character.toUpperCase();
|
||||
}
|
||||
|
||||
arraysAreEqual (array1, array2) {
|
||||
// if the other array2 is a falsy value, return
|
||||
if (!array1 || !array2)
|
||||
return false;
|
||||
|
||||
// compare lengths - can save a lot of time
|
||||
if (array1.length != array2.length)
|
||||
return false;
|
||||
|
||||
for (var i = 0, l=array1.length; i < l; i++) {
|
||||
// Check if we have nested arrays
|
||||
if (array1[i] instanceof Array && array2[i] instanceof Array) {
|
||||
// recurse into the nested arrays
|
||||
if (!array1[i].equals(array2[i]))
|
||||
return false;
|
||||
}
|
||||
else if (array1[i] != array2[i]) {
|
||||
// Warning - two different object instances will never be equal: {x:20} != {x:20}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
objectIsEmpty (obj) {
|
||||
for(var key in obj) {
|
||||
if(obj.hasOwnProperty(key))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Helper;
|
||||
|
|
58
src/Updater.js
Normal file
58
src/Updater.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
import helper from './Helper';
|
||||
|
||||
export class Updater {
|
||||
constructor (appWithDictionaryState, dictionary) {
|
||||
this.app = appWithDictionaryState;
|
||||
this.dictionary = dictionary;
|
||||
}
|
||||
|
||||
setDictionaryName (newName) {
|
||||
this.app.setState({
|
||||
name: newName,
|
||||
}, () => {
|
||||
this.dictionary.name = newName;
|
||||
});
|
||||
}
|
||||
|
||||
setDictionarySpecification (newSpecification) {
|
||||
this.app.setState({
|
||||
specification: newSpecification,
|
||||
}, () => {
|
||||
this.dictionary.specification = newSpecification;
|
||||
});
|
||||
}
|
||||
|
||||
updateDictionaryDetails (dicitonaryDetails = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const updatedDetails = {};
|
||||
|
||||
if (dicitonaryDetails.name) {
|
||||
updatedDetails['name'] = dicitonaryDetails.name;
|
||||
this.dictionary.name = dicitonaryDetails.name;
|
||||
}
|
||||
|
||||
if (dicitonaryDetails.specification) {
|
||||
updatedDetails['specification'] = dicitonaryDetails.specification;
|
||||
this.dicitonary.specification = dicitonaryDetails.specification;
|
||||
}
|
||||
|
||||
if (dicitonaryDetails.description) {
|
||||
updatedDetails['description'] = dicitonaryDetails.description;
|
||||
this.dictionary.description = dicitonaryDetails.description;
|
||||
}
|
||||
|
||||
if (dicitonaryDetails.partsOfSpeech) {
|
||||
updatedDetails['partsOfSpeech'] = dicitonaryDetails.partsOfSpeech;
|
||||
this.dictionary.partsOfSpeech = dicitonaryDetails.partsOfSpeech;
|
||||
}
|
||||
|
||||
if (helper.objectIsEmpty(updatedDetails)) {
|
||||
reject('No dictionary details have changed.');
|
||||
} else {
|
||||
this.app.setState(updatedDetails, () => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import { WordForm } from './management/WordForm';
|
|||
import { DictionaryDetails } from './display/DictionaryDetails';
|
||||
import { WordsList } from './display/WordsList';
|
||||
|
||||
export const MainDisplay = ({ dictionaryInfo, wordsToDisplay, updateDisplay, lastRender }) => {
|
||||
export const MainDisplay = ({ dictionaryInfo, wordsToDisplay, updateDisplay, updater, lastRender }) => {
|
||||
return (
|
||||
<section className='section'>
|
||||
<div className='container'>
|
||||
|
@ -22,9 +22,11 @@ export const MainDisplay = ({ dictionaryInfo, wordsToDisplay, updateDisplay, las
|
|||
|
||||
<RightColumn>
|
||||
<DictionaryDetails
|
||||
updater={ updater }
|
||||
name={ dictionaryInfo.name }
|
||||
specification={ dictionaryInfo.specification }
|
||||
description={ dictionaryInfo.description }
|
||||
partsOfSpeech={ dictionaryInfo.partsOfSpeech }
|
||||
details={{
|
||||
custom: [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import Inferno from 'inferno';
|
||||
import Component from 'inferno-component';
|
||||
|
||||
import dictionary from '../../../../managers/DictionaryData';
|
||||
|
||||
export const EditDictionaryForm = ({
|
||||
editDictionaryModal,
|
||||
name,
|
||||
specification,
|
||||
description,
|
||||
}) => {
|
||||
return (
|
||||
<div className='form'>
|
||||
<div className='field'>
|
||||
<label className='label'>Name</label>
|
||||
<div className='control'>
|
||||
<input className='input' type='text'
|
||||
placeholder={ `${ specification || 'Dictionary' } Name` }
|
||||
value={ name }
|
||||
onInput={ (event) => {
|
||||
editDictionaryModal.setState({
|
||||
name: event.target.value,
|
||||
hasChanged: event.target.value != editDictionaryModal.props.name,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='field'>
|
||||
<label className='label'>Specification</label>
|
||||
<div className='control'>
|
||||
<input className='input' type='text'
|
||||
placeholder='Dictionary'
|
||||
value={ specification }
|
||||
onInput={ (event) => {
|
||||
editDictionaryModal.setState({
|
||||
specification: event.target.value,
|
||||
hasChanged: event.target.value != editDictionaryModal.props.specification,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='field'>
|
||||
<label className='label' htmlFor='dictionaryDescription'>Description</label>
|
||||
<div className='control'>
|
||||
<textarea className='textarea' id='dictionaryDescription'
|
||||
placeholder={ `A description of your ${ specification }` }
|
||||
value={ description }
|
||||
onInput={ (event) => {
|
||||
editDictionaryModal.setState({
|
||||
description: event.target.value,
|
||||
hasChanged: event.target.value != editDictionaryModal.props.description,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import Inferno from 'inferno';
|
||||
import Component from 'inferno-component';
|
||||
|
||||
import dictionary from '../../../../managers/DictionaryData';
|
||||
|
||||
export const EditLinguisticsForm = ({
|
||||
editDictionaryModal,
|
||||
partsOfSpeech,
|
||||
}) => {
|
||||
return (
|
||||
<div className='form'>
|
||||
<div className='field'>
|
||||
<label className='label' htmlFor='dictionaryDescription'>Parts of Speech</label>
|
||||
<div className='control'>
|
||||
<textarea className='textarea' id='partsOfSpeech'
|
||||
placeholder={ `Put each part of speech on a separate line` }
|
||||
value={ partsOfSpeech }
|
||||
onInput={ (event) => {
|
||||
editDictionaryModal.setState({
|
||||
partsOfSpeech: event.target.value,
|
||||
hasChanged: event.target.value != editDictionaryModal.props.partsOfSpeech.join('\n'),
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
import Inferno from 'inferno';
|
||||
import Component from 'inferno-component';
|
||||
import marked from 'marked';
|
||||
|
||||
import helper from '../../../../Helper';
|
||||
|
||||
import { Modal } from '../../../structure/Modal';
|
||||
|
||||
import { EditDictionaryForm } from './EditDictionaryForm';
|
||||
import { EditLinguisticsForm } from './EditLinguisticsForm';
|
||||
|
||||
const DISPLAY = {
|
||||
DETAILS: 1,
|
||||
LINGUISTICS: 2,
|
||||
SETTINGS: 3,
|
||||
}
|
||||
|
||||
export class EditDictionaryModal extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
currentDisplay: DISPLAY.DETAILS,
|
||||
|
||||
name: props.name,
|
||||
specification: props.specification,
|
||||
description: props.description,
|
||||
partsOfSpeech: props.partsOfSpeech.join('\n'),
|
||||
|
||||
hasChanged: false,
|
||||
}
|
||||
}
|
||||
|
||||
hasChanged () {
|
||||
return (
|
||||
this.state.name != this.props.name
|
||||
|| this.state.specification != this.props.specification
|
||||
|| this.state.description != this.props.description
|
||||
|| this.state.partsOfSpeech != this.props.partsOfSpeech.join('\n')
|
||||
);
|
||||
}
|
||||
|
||||
toggleDisplay (display) {
|
||||
this.setState({
|
||||
currentDisplay: display,
|
||||
});
|
||||
}
|
||||
|
||||
displaySection () {
|
||||
let displayJSX;
|
||||
|
||||
switch(this.state.currentDisplay) {
|
||||
case DISPLAY.DETAILS : {
|
||||
displayJSX = (
|
||||
<EditDictionaryForm
|
||||
editDictionaryModal={ this }
|
||||
name={ this.state.name }
|
||||
specification={ this.state.specification }
|
||||
description={ this.state.description }
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case DISPLAY.LINGUISTICS : {
|
||||
displayJSX = (
|
||||
<EditLinguisticsForm
|
||||
editDictionaryModal={ this }
|
||||
partsOfSpeech={ this.state.partsOfSpeech }
|
||||
/>
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case DISPLAY.SETTINGS : {
|
||||
displayJSX = (
|
||||
<div className='content'>
|
||||
<p>Settings!</p>
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='box'>
|
||||
{ displayJSX }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
save () {
|
||||
const updatedDetails = {};
|
||||
|
||||
if (this.state.name !== this.props.name) {
|
||||
updatedDetails['name'] = this.state.name;
|
||||
}
|
||||
|
||||
if (this.state.specification !== this.props.specification) {
|
||||
updatedDetails['specification'] = this.state.specification;
|
||||
}
|
||||
|
||||
if (this.state.description !== this.props.description) {
|
||||
updatedDetails['description'] = this.state.description;
|
||||
}
|
||||
|
||||
if (this.state.partsOfSpeech !== this.props.partsOfSpeech.join('\n')) {
|
||||
updatedDetails['partsOfSpeech'] = this.state.partsOfSpeech.split('\n')
|
||||
.filter((value) => { return value !== '' })
|
||||
.map((value) => { return value.trim() });
|
||||
}
|
||||
|
||||
console.log(updatedDetails);
|
||||
|
||||
this.props.updater.updateDictionaryDetails(updatedDetails)
|
||||
.then(() => {
|
||||
this.setState({ hasChanged: false });
|
||||
})
|
||||
.catch(errorMessage => {
|
||||
console.error(errorMessage);
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
const { currentDisplay, hasChanged } = this.state;
|
||||
|
||||
return (
|
||||
<Modal title={ `Edit ${ this.props.specification }` }
|
||||
buttonText={ `Edit ${ this.props.specification }` }
|
||||
footerAlign='right'
|
||||
footerContent={
|
||||
(
|
||||
<div>
|
||||
<button className='button is-success'
|
||||
disabled={ !hasChanged }
|
||||
onClick={ this.save.bind(this) }
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
>
|
||||
|
||||
<div className='tabs'>
|
||||
<ul>
|
||||
<li className={ (currentDisplay === DISPLAY.DETAILS) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.DETAILS) }>
|
||||
Details
|
||||
</a>
|
||||
</li>
|
||||
<li className={ (currentDisplay === DISPLAY.LINGUISTICS) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.LINGUISTICS) }>
|
||||
Linguistics
|
||||
</a>
|
||||
</li>
|
||||
<li className={ (currentDisplay === DISPLAY.SETTINGS) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.SETTINGS) }>
|
||||
Settings
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{ this.displaySection() }
|
||||
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ import Inferno from 'inferno';
|
|||
import Component from 'inferno-component';
|
||||
import marked from 'marked';
|
||||
|
||||
import { EditDictionaryModal } from './EditDictionaryModal';
|
||||
|
||||
const DISPLAY = {
|
||||
NONE: false,
|
||||
DESCRIPTION: 1,
|
||||
|
@ -132,6 +134,8 @@ export class DictionaryDetails extends Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { currentDisplay } = this.state;
|
||||
|
||||
return (
|
||||
<div className='box'>
|
||||
|
||||
|
@ -146,30 +150,33 @@ export class DictionaryDetails extends Component {
|
|||
|
||||
<div className='level-right'>
|
||||
<div className='level-item'>
|
||||
<div className='field'>
|
||||
<p className='control'>
|
||||
<a className='button'>
|
||||
Edit Dictionary
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<EditDictionaryModal
|
||||
updater={ this.props.updater }
|
||||
name={ this.props.name }
|
||||
specification={ this.props.specification }
|
||||
description={ this.props.description }
|
||||
partsOfSpeech={ this.props.partsOfSpeech }
|
||||
details={ this.props.details }
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='tabs is-toggle'>
|
||||
<ul>
|
||||
<li className={ (this.state.currentDisplay === DISPLAY.DESCRIPTION) ? 'is-active' : null }>
|
||||
<li className={ (currentDisplay === DISPLAY.DESCRIPTION) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.DESCRIPTION) }>
|
||||
<span>Description</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className={ (this.state.currentDisplay === DISPLAY.DETAILS) ? 'is-active' : null }>
|
||||
<li className={ (currentDisplay === DISPLAY.DETAILS) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.DETAILS) }>
|
||||
<span>Details</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className={ (this.state.currentDisplay === DISPLAY.STATS) ? 'is-active' : null }>
|
||||
<li className={ (currentDisplay === DISPLAY.STATS) ? 'is-active' : null }>
|
||||
<a onClick={ this.toggleDisplay.bind(this, DISPLAY.STATS) }>
|
||||
<span>Stats</span>
|
||||
</a>
|
|
@ -6,6 +6,8 @@ import Component from 'inferno-component';
|
|||
|
||||
import dictionary from './managers/DictionaryData';
|
||||
|
||||
import { Updater } from './Updater';
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
require('inferno-devtools');
|
||||
}
|
||||
|
@ -26,6 +28,8 @@ class App extends Component {
|
|||
displayedWords: [],
|
||||
searchConfig: null,
|
||||
}
|
||||
|
||||
this.updater = new Updater(this, dictionary);
|
||||
}
|
||||
|
||||
get dictionaryInfo () {
|
||||
|
@ -68,12 +72,15 @@ class App extends Component {
|
|||
<div>
|
||||
<Header
|
||||
partsOfSpeech={ this.state.partsOfSpeech }
|
||||
search={ (searchConfig) => this.search(searchConfig) } />
|
||||
search={ (searchConfig) => this.search(searchConfig) }
|
||||
/>
|
||||
|
||||
<MainDisplay
|
||||
dictionaryInfo={ this.dictionaryInfo }
|
||||
wordsToDisplay={ this.state.displayedWords }
|
||||
updateDisplay={ this.updateDisplayedWords.bind(this) } />
|
||||
updateDisplay={ this.updateDisplayedWords.bind(this) }
|
||||
updater={ this.updater }
|
||||
/>
|
||||
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue