diff --git a/src/client/resources/entity/entity.jsx b/src/client/resources/entity/entity.jsx index 0bb796c..f49584e 100644 --- a/src/client/resources/entity/entity.jsx +++ b/src/client/resources/entity/entity.jsx @@ -29,7 +29,7 @@ const EntityComponent = (props) => {
- +
); diff --git a/src/client/resources/entity/state.js b/src/client/resources/entity/state.js index 173d2b8..99975e0 100644 --- a/src/client/resources/entity/state.js +++ b/src/client/resources/entity/state.js @@ -46,7 +46,15 @@ export const selectEntityByUri = createSelector( const slice = createSlice({ name: 'entities', initialState: adapter.getInitialState({uris: {}}), - reducers: {}, + reducers: { + setTraitProperty: (state, {payload: {target, trait, type, key, value}}) => { + const {traits} = state.entities[target]; + traits[trait] = traits[trait] || {}; + traits[trait][type] = traits[trait][type] || {}; + traits[trait][type][key] = value; + state.entities[target].traits = traits; + }, + }, extraReducers: { [fetchEntity.fulfilled]: (state, action) => { adapter.upsertMany(state, action.payload.entities); @@ -56,4 +64,8 @@ const slice = createSlice({ }, }); +export const { + setTraitProperty, +} = slice.actions; + export default slice.reducer; diff --git a/src/client/resources/entity/traits.jsx b/src/client/resources/entity/traits.jsx index 868a030..8c3828c 100644 --- a/src/client/resources/entity/traits.jsx +++ b/src/client/resources/entity/traits.jsx @@ -6,6 +6,7 @@ import {produce} from 'immer'; import PropTypes from 'prop-types'; import React, {useEffect, useState} from 'react'; // import ReactMarkdown from 'react-markdown'; +import {useDispatch} from 'react-redux'; import { Tab, Tabs, @@ -17,6 +18,8 @@ import {deregisterHooks, registerHooks} from 'scwp'; import Value from '~/client/value'; +import {setTraitProperty} from './state'; + const SCROLL_MAG = 80; const decorate = compose( @@ -44,7 +47,7 @@ const ensureTraitComponents = () => { } }; -const makeTabSelector = (context, type) => createSelector( +const makeTabSelector = (context, dispatch, target, type) => createSelector( (_) => _, (trait) => { ensureTraitComponents(); @@ -55,7 +58,7 @@ const makeTabSelector = (context, type) => createSelector( const state = Trait ? {...Trait.defaultState(), ...stateRaw} : stateRaw; const paramsDescription = Trait?.describeParams() || {}; const stateDescription = Trait?.describeState() || {}; - const renderComponents = (description, values) => ( + const renderComponents = (traitHalf, description, values) => ( // eslint-disable-next-line no-shadow Object.values(mapObject(description, (description, key) => { const {label, options} = description; @@ -68,6 +71,13 @@ const makeTabSelector = (context, type) => createSelector(
dispatch(setTraitProperty({ + target, + trait: type, + type: traitHalf, + key, + value, + }))} options={options} value={values[key]} /> @@ -79,55 +89,56 @@ const makeTabSelector = (context, type) => createSelector( ? : (
- {renderComponents(paramsDescription, params)} - {renderComponents(stateDescription, state)} + {renderComponents('params', paramsDescription, params)} + {renderComponents('state', stateDescription, state)}
); }, ); const Traits = (props) => { - const {context, traits} = props; - const [tabSelectorMap, setTabSelectorMap] = useState({}); + const {context, target, traits} = props; + const dispatch = useDispatch(); + const [traitForms, setTraitForms] = useState({}); + const [mts, setMts] = useState(); useEffect(() => { + if (!mts) { + setMts(() => (type) => makeTabSelector(context, dispatch, target, type)); + } + }, [mts, setMts]); + useEffect(() => { + if (!mts) { + return; + } const entries = Object.entries(traits); - setTabSelectorMap(produce(tabSelectorMap, (draft) => { + setTraitForms(produce(traitForms, (draft) => { for (let i = 0; i < entries.length; i++) { const [type] = entries[i]; - if (!draft[type]) { - // eslint-disable-next-line no-param-reassign - draft[type] = new WeakMap(); - } - if (!draft[type].has(traits)) { - draft[type].set(traits, makeTabSelector(context, type)); - } + draft[type] = mts(type); } })); const M = { autoreg$accept: (type, M2) => { if ('trait' === type) { const {default: Trait} = M2; - setTabSelectorMap(produce(tabSelectorMap, (draft) => { - const traitType = Trait.type(); - if (!draft[traitType]) { - // eslint-disable-next-line no-param-reassign - draft[traitType] = new WeakMap(); - } - draft[traitType].set(traits, makeTabSelector(traitType)); + setTraitForms(produce(traitForms, (draft) => { + draft[Trait.type()] = mts(Trait.type()); })); } }, }; registerHooks(M, __filename); return () => deregisterHooks(M); - }, [context, tabSelectorMap, traits]); + }, [mts, traits]); const [tabIndex, setTabIndex] = useState(0); let listRef; const entries = Object.entries(traits); const tabs = []; for (let i = 0; i < entries.length; i++) { const [type, trait] = entries[i]; - tabs.push([type, tabSelectorMap[type]?.get(traits)(trait)]); + if (type in traitForms) { + tabs.push([type, traitForms[type](trait)]); + } } return (
diff --git a/src/client/types/literal.type-renderer.jsx b/src/client/types/literal.type-renderer.jsx index d3907a4..9f141a2 100644 --- a/src/client/types/literal.type-renderer.jsx +++ b/src/client/types/literal.type-renderer.jsx @@ -14,6 +14,7 @@ const decorate = compose( const Literal = ({ context, + onChange, value, }) => { const typeRenderers = useTypeRenderers(); @@ -36,7 +37,7 @@ const Literal = ({ .map((tierOption) => ) } - {Component ? : null} + {Component ? : null}
); }; diff --git a/src/client/types/string.type-renderer.jsx b/src/client/types/string.type-renderer.jsx index d7e1a24..e6f92f5 100644 --- a/src/client/types/string.type-renderer.jsx +++ b/src/client/types/string.type-renderer.jsx @@ -4,6 +4,7 @@ import React from 'react'; import propTypes from './prop-types'; const String = ({ + onChange, options, value, }) => ( @@ -17,7 +18,13 @@ const String = ({ ))} ) - : + : ( + onChange(event.target.value)} + type="text" + value={value} + /> + ) } ); diff --git a/src/client/value.jsx b/src/client/value.jsx index 1812182..a93c71e 100644 --- a/src/client/value.jsx +++ b/src/client/value.jsx @@ -14,6 +14,7 @@ const decorate = compose( const Value = ({ context, + onChange, options, value, }) => { @@ -25,7 +26,7 @@ const Value = ({ { Component - ? + ? :
?
}