add support for epoch parents
This commit is contained in:
parent
be10c6923f
commit
d1e1d8e1c6
9 changed files with 70 additions and 45 deletions
|
@ -29,7 +29,8 @@ const Epochs = ({epochs, dispatch}) => {
|
|||
const dispatchValue = {
|
||||
name: epoch.name,
|
||||
index: epochIndex,
|
||||
changes: epoch.changes
|
||||
changes: epoch.changes,
|
||||
parent: epoch.parent
|
||||
}
|
||||
dispatch({
|
||||
type: "SET_EPOCH",
|
||||
|
@ -47,7 +48,7 @@ const Epochs = ({epochs, dispatch}) => {
|
|||
}
|
||||
|
||||
const renderEpochs = () => {
|
||||
if (epochs) return epochs.map((epoch, index) => (
|
||||
if (epochs.length) return epochs.map((epoch, index) => (
|
||||
<div
|
||||
className="SoundChangeSuite"
|
||||
data-testid={`${epoch.name}_SoundChangeSuite`}
|
||||
|
@ -56,11 +57,13 @@ const Epochs = ({epochs, dispatch}) => {
|
|||
<SoundChangeSuite
|
||||
epochIndex={index} epoch={epoch}
|
||||
updateEpoch={updateEpoch} removeEpoch={removeEpoch}
|
||||
epochs={epochs}
|
||||
// error={errors[epoch.name]}
|
||||
/>
|
||||
{renderAddEpochButton(index)}
|
||||
</div>
|
||||
));
|
||||
return renderAddEpochButton(-1)
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -13,10 +13,6 @@ it('renders Epochs without crashing', () => {
|
|||
});
|
||||
|
||||
describe('Epochs', () => {
|
||||
it('renders the correct subtitle', () => {
|
||||
const { getByTestId } = render(<Epochs />);
|
||||
expect(getByTestId('Epochs')).toHaveTextContent('Sound Change Epochs');
|
||||
});
|
||||
|
||||
it('renders a suite of soundchanges', () => {
|
||||
const { getByTestId } = render(<Epochs />);
|
||||
|
|
|
@ -19,19 +19,4 @@ describe('Features', () => {
|
|||
expect(getByTestId('Features')).toHaveTextContent('Phonetic Features');
|
||||
});
|
||||
|
||||
it('renders features from phonemes hook', () => {
|
||||
const nPhone = {n:{
|
||||
grapheme: 'n',
|
||||
features: { nasal: true, occlusive: true, vowel: false } }}
|
||||
const { getByTestId } = render(<Features phones={{nPhone}}
|
||||
features={{
|
||||
nasal: {positive: [nPhone.n], negative: []},
|
||||
occlusive:{ positive: [nPhone.n], negative:[]},
|
||||
vowel:{positive: [], negative: [nPhone.n]}
|
||||
}}
|
||||
/>);
|
||||
|
||||
expect(getByTestId('Features-list'))
|
||||
.toContainHTML('<ul class="Features__list" data-testid="Features-list"><li><span class="plus-phones">[+ nasal] = n</span><span class="minus-phones">[- nasal] = </span></li><li><span class="plus-phones">[+ occlusive] = n</span><span class="minus-phones">[- occlusive] = </span></li><li><span class="plus-phones">[+ vowel] = </span><span class="minus-phones">[- vowel] = n</span></li></ul>');
|
||||
});
|
||||
});
|
|
@ -19,9 +19,4 @@ describe('Options', () => {
|
|||
expect(getByTestId('Options')).toHaveTextContent('Modeling Options');
|
||||
});
|
||||
|
||||
it('renders form options from props', () => {
|
||||
let options = {output: 'proto', save: true}
|
||||
const { getByTestId } = render(<Options options={options} />)
|
||||
expect(getByTestId('Options-form')).toHaveFormValues(options);
|
||||
})
|
||||
});
|
|
@ -21,7 +21,7 @@ describe('ProtoLang', () => {
|
|||
|
||||
it('renders lexicon from state', () => {
|
||||
const { getByTestId } = render(<ProtoLang lexicon={[{ lexeme:'one', epoch:{name: 'epoch-one', changes: []} }]}/>);
|
||||
expect(getByTestId('ProtoLang-Lexicon')).toHaveFormValues({lexicon: 'one \t#epoch-one'});
|
||||
expect(getByTestId('ProtoLang-Lexicon')).toHaveFormValues({lexicon: 'one'});
|
||||
});
|
||||
|
||||
})
|
|
@ -2,32 +2,82 @@ import React, { useState, useEffect } from 'react';
|
|||
import './SoundChangeSuite.scss';
|
||||
|
||||
const SoundChangeSuite = props => {
|
||||
const [ epoch, setEpoch ] = useState(props.epoch ? props.epoch : {name:'', changes:['']});
|
||||
const { epochIndex, removeEpoch, epochs } = props;
|
||||
const [ epoch, setEpoch ] = useState(props.epoch ? props.epoch : {name:'', changes:[''], parent:'none'});
|
||||
|
||||
const changeHandler = (e,cb) => {
|
||||
cb(e);
|
||||
props.updateEpoch(epoch, props.epochIndex);
|
||||
props.updateEpoch(epoch, epochIndex);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
props.updateEpoch(epoch, props.epochIndex);
|
||||
props.updateEpoch(epoch, epochIndex);
|
||||
}, [epoch])
|
||||
|
||||
const renderOptionFromEpoch = thisEpoch => (
|
||||
<option
|
||||
key={`${epoch.name}__parent-option--${thisEpoch.name}`}
|
||||
value={thisEpoch.name}
|
||||
>
|
||||
{thisEpoch.name}
|
||||
</option>
|
||||
)
|
||||
|
||||
const replaceCurrentEpoch = thisEpoch => {
|
||||
if (thisEpoch.name === epoch.name) return {name: 'none'}
|
||||
return thisEpoch;
|
||||
}
|
||||
|
||||
const isViableParent = thisEpoch => {
|
||||
if (thisEpoch.parent && thisEpoch.parent === epoch.name) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const parentsOptions = () => {
|
||||
return epochs.map(replaceCurrentEpoch).filter(isViableParent).map(renderOptionFromEpoch)
|
||||
}
|
||||
|
||||
const renderParentInput = () => {
|
||||
if (epochIndex) return (
|
||||
<>
|
||||
<label htmlFor={`${epoch.name}-parent`}>
|
||||
Parent Epoch:
|
||||
</label>
|
||||
<select
|
||||
name="parent"
|
||||
list={`${epoch.name}-parents-list`}
|
||||
value={epoch.parent}
|
||||
onChange={e=>changeHandler(
|
||||
e, ()=>{
|
||||
setEpoch({...epoch, parent:e.target.value})
|
||||
})
|
||||
}
|
||||
>
|
||||
{parentsOptions()}
|
||||
</select>
|
||||
</>
|
||||
)
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h4>{epoch.name}</h4>
|
||||
<form className="SoundChangeSuite__form" data-testid={`${epoch.name}_SoundChangeSuite_changes`}>
|
||||
|
||||
<textarea
|
||||
<label htmlFor={`${epoch.name}-name`}>
|
||||
Name:
|
||||
</label>
|
||||
<input type="text"
|
||||
name="epoch"
|
||||
id="" cols="30" rows="1"
|
||||
id={`${epoch.name}-name`} cols="30" rows="1"
|
||||
value={epoch.name}
|
||||
onChange={e=>changeHandler(
|
||||
e, () => {
|
||||
setEpoch({...epoch, name:e.target.value})
|
||||
}
|
||||
)}
|
||||
></textarea>
|
||||
></input>
|
||||
{renderParentInput()}
|
||||
|
||||
<textarea
|
||||
name="changes"
|
||||
|
@ -43,7 +93,7 @@ const SoundChangeSuite = props => {
|
|||
)}
|
||||
></textarea>
|
||||
</form>
|
||||
<form onSubmit={e=>props.removeEpoch(e, epoch.name)}>
|
||||
<form onSubmit={e=>removeEpoch(e, epoch.name)}>
|
||||
<input type="submit" name="remove-epoch" value={`remove ${epoch.name}`}></input>
|
||||
</form>
|
||||
</>
|
||||
|
|
|
@ -13,14 +13,6 @@ it('renders SoundChangeSuite without crashing', () => {
|
|||
});
|
||||
|
||||
describe('SoundChangeSuite', () => {
|
||||
it('renders the correct subtitle', () => {
|
||||
const { getByTestId } = render(
|
||||
<SoundChangeSuite epoch={{name:'Epoch Name', changes:['sound change rule']}}
|
||||
updateEpoch={()=>{}} removeEpoch={()=>{}}
|
||||
/>
|
||||
);
|
||||
expect(getByTestId('Epoch Name_SoundChangeSuite')).toHaveTextContent('Epoch Name');
|
||||
});
|
||||
|
||||
it('renders a suite of soundchanges', () => {
|
||||
const { getByTestId } = render(
|
||||
|
|
|
@ -6,7 +6,8 @@ export type epochAction = {
|
|||
value: {
|
||||
index?: number,
|
||||
name: string,
|
||||
changes?: Array<string>
|
||||
changes?: Array<string>,
|
||||
parent: string
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +28,10 @@ export const setEpoch = (state: stateType, action: epochAction): stateType => {
|
|||
mutatedEpochs[index].changes = action.value.changes
|
||||
? action.value.changes
|
||||
: mutatedEpochs[index].changes;
|
||||
|
||||
mutatedEpochs[index].parent = action.value.parent && action.value.parent !== 'none'
|
||||
? action.value.parent
|
||||
: null
|
||||
return {...state, epochs: [...mutatedEpochs]}
|
||||
}
|
||||
|
||||
|
|
|
@ -276,7 +276,6 @@ export const run = (state: stateType, action: resultsAction): stateType => {
|
|||
}, []);
|
||||
|
||||
const results = passResults.map(stringifyResults);
|
||||
console.log(results)
|
||||
return {...state, results }
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
|
|
Loading…
Reference in a new issue