Commit 05d2f050 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Various metainfo related fixes and imporvements.

parent 76ddd3ce
Pipeline #120856 passed with stages
in 29 minutes and 13 seconds
......@@ -71,7 +71,7 @@ const useBrowserStyles = makeStyles(theme => ({
width: 'fit-content'
}
}))
export default function Browser({adaptor, form}) {
export const Browser = React.memo(function Browser({adaptor, form}) {
const classes = useBrowserStyles()
const rootRef = useRef()
const outerRef = useRef()
......@@ -100,17 +100,24 @@ export default function Browser({adaptor, form}) {
next: null
}), [adaptor, url])
const lanes = [root]
archivePath.filter(segment => segment).forEach((segment, i) => {
const prev = lanes[i]
const lane = {
key: segment,
path: `${prev.path}/${segment}`,
adaptor: prev.adaptor.itemAdaptor(segment)
}
lanes.push(lane)
prev.next = lane
})
const memoedAdapters = useRef({})
const lanes = useMemo(() => {
const lanes = [root]
archivePath.filter(segment => segment).forEach((segment, i) => {
const prev = lanes[i]
const path = `${prev.path}/${segment}`
const adaptor = memoedAdapters.current[path] || prev.adaptor.itemAdaptor(segment)
memoedAdapters.current[path] = adaptor
const lane = {
key: segment,
path: path,
adaptor: adaptor
}
lanes.push(lane)
prev.next = lane
})
return lanes
}, [root, archivePath, memoedAdapters])
return <RecoilRoot>
{form}
......@@ -128,11 +135,12 @@ export default function Browser({adaptor, form}) {
</CardContent>
</Card>
</RecoilRoot>
}
})
Browser.propTypes = ({
adaptor: PropTypes.object.isRequired,
form: PropTypes.node
})
export default Browser
export const laneContext = React.createContext()
const useLaneStyles = makeStyles(theme => ({
......@@ -151,20 +159,25 @@ const useLaneStyles = makeStyles(theme => ({
margin: theme.spacing(1)
}
}))
function Lane({lane}) {
const Lane = React.memo(function Lane({lane}) {
const classes = useLaneStyles()
const { adaptor } = lane
return <div className={classes.root}>
<div className={classes.container}>
<laneContext.Provider value={lane}>
<ErrorHandler message='This section could not be rendered, due to an unexpected error.' className={classes.error}>
{adaptor.render()}
</ErrorHandler>
</laneContext.Provider>
const { key, selected, adaptor, next } = lane
const content = useMemo(() => {
return <div className={classes.root}>
<div className={classes.container}>
<laneContext.Provider value={lane}>
<ErrorHandler message='This section could not be rendered, due to an unexpected error.' className={classes.error}>
{adaptor.render()}
</ErrorHandler>
</laneContext.Provider>
</div>
</div>
</div>
}
// We deliberetly break the React rules here. The goal is to only update if the
// lanes contents change and not the lane object.
// eslint-disable-next-line
}, [key, selected, adaptor, next?.key, classes])
return content
})
Lane.propTypes = ({
lane: PropTypes.object.isRequired
})
......
......@@ -88,13 +88,14 @@ export function MetainfoPage() {
}
export default function MetainfoBrowser() {
const adaptor = useMemo(() => new MetainfoRootAdaptor(), [])
return <Browser
adaptor={new MetainfoRootAdaptor()}
adaptor={adaptor}
form={<MetainfoConfigForm />}
/>
}
function MetainfoConfigForm(props) {
const MetainfoConfigForm = React.memo(function MetainfoConfigForm(props) {
const [config, setConfig] = useRecoilState(metainfoConfigState)
const history = useHistory()
......@@ -150,7 +151,7 @@ function MetainfoConfigForm(props) {
</FormGroup>
</Box>
)
}
})
export function metainfoAdaptorFactory(obj) {
if (obj.m_def === 'Section') {
......@@ -250,7 +251,7 @@ export class PackagePrefixAdaptor extends MetainfoAdaptor {
}
}
function Metainfo(props) {
const Metainfo = React.memo(function Metainfo(props) {
return <Content>
<Compartment title="archive root section">
<Item itemKey="EntryArchive">
......@@ -258,8 +259,8 @@ function Metainfo(props) {
</Item>
</Compartment>
<Compartment title="other root sections">
{rootSections.filter(def => def.name !== 'EntryArchive').map(def => (
<Item key={def.name} itemKey={def.name}>
{rootSections.filter(def => def.name !== 'EntryArchive').map((def, i) => (
<Item key={i} itemKey={def.name}>
<Typography>
{def.name}
</Typography>
......@@ -272,7 +273,7 @@ function Metainfo(props) {
</Item>)}
</Compartment>
</Content>
}
})
export class SectionDefAdaptor extends MetainfoAdaptor {
itemAdaptor(key) {
......
......@@ -51,8 +51,7 @@ metainfo.packages.forEach(pkg => {
addDef(categoryDef)
})
const addSectionDef = (sectionDef, parentDef) => {
pkg._sections[sectionDef.name] = sectionDef
const initSection = sectionDef => {
sectionDef.base_sections = sectionDef.base_sections || []
sectionDef.quantities = sectionDef.quantities || []
sectionDef.sub_sections = sectionDef.sub_sections || []
......@@ -60,6 +59,33 @@ metainfo.packages.forEach(pkg => {
sectionDef._incomingRefs = sectionDef._incomingRefs || []
sectionDef._parentSections = sectionDef._parentSections || []
sectionDef._parentSubSections = sectionDef._parentSubSections || []
}
const computeAllProperties = sectionDef => {
const results = {}
function addProperties(sectionDef) {
sectionDef.quantities.concat(sectionDef.sub_sections).forEach(
property => {
results[property.name] = property
})
}
const baseSections = []
function addBaseSection(sectionDef) {
initSection(sectionDef)
if (!sectionDef.extends_base_section) {
sectionDef.base_sections.map(baseSectionRef => resolveRef(baseSectionRef)).forEach(addBaseSection)
}
baseSections.push(sectionDef)
}
addBaseSection(sectionDef)
baseSections.forEach(addProperties)
return Object.keys(results).sort().map(key => results[key])
}
const addSectionDef = (sectionDef, parentDef) => {
sectionDef._parent = parentDef
pkg._sections[sectionDef.name] = sectionDef
initSection(sectionDef)
sectionDef._qualifiedName = parentDef ? `${parentDef._qualifiedName || parentDef.name}.${sectionDef.name}` : sectionDef.name
sectionDef._package = pkg
......@@ -88,7 +114,6 @@ metainfo.packages.forEach(pkg => {
property._section = sectionDef
property._qualifiedName = `${sectionDef._qualifiedName}.${property.name}`
}
property._parentSections = [sectionDef]
property._package = pkg
addDef(property)
}
......@@ -102,10 +127,10 @@ metainfo.packages.forEach(pkg => {
referencedSection._incomingRefs.push(property)
}
} else if (property.m_def === 'SubSection') {
const subSectionsSectionDef = resolveRef(property.sub_section)
subSectionsSectionDef._parentSections = subSectionsSectionDef._parentSections || []
property._subSection = resolveRef(property.sub_section)
const subSectionsSectionDef = property._subSection
initSection(subSectionsSectionDef)
subSectionsSectionDef._parentSections.push(sectionDef)
subSectionsSectionDef._parentSubSections = subSectionsSectionDef._parentSubSections || []
subSectionsSectionDef._parentSubSections.push(property)
property._section = sectionDef
}
......@@ -115,26 +140,6 @@ metainfo.packages.forEach(pkg => {
pkg.section_definitions.forEach(sectionDef => addSectionDef(sectionDef, pkg))
})
function computeAllProperties(sectionDef) {
const results = {}
function addProperties(sectionDef) {
sectionDef.quantities.concat(sectionDef.sub_sections).forEach(
property => {
results[property.name] = property
})
}
const baseSections = []
function addBaseSection(sectionDef) {
if (!sectionDef.extends_base_section) {
sectionDef.base_sections.map(baseSectionRef => resolveRef(baseSectionRef)).forEach(addBaseSection)
}
baseSections.push(sectionDef)
}
addBaseSection(sectionDef)
baseSections.forEach(addProperties)
return Object.keys(results).sort().map(key => results[key])
}
export const rootSections = sortDefs(defs.filter(def => (
def.m_def === 'Section' && !def.extends_base_section && def._parentSections.length === 0)
))
......
......@@ -412,6 +412,21 @@ class ListTextInputUnstyled extends React.Component {
component: PropTypes.any
}
static styles = theme => ({
root: {},
row: {
display: 'flex'
},
buttonContainer: {
position: 'relative',
width: 52
},
button: {
position: 'absolute',
bottom: 0
}
})
render() {
const { classes, values, onChange, label, component, ...fieldProps } = this.props
......
......@@ -149,8 +149,13 @@ const FilterSubMenuArchive = React.memo(({
const root = useMemo(() => rootSections.find(def => def.name === 'EntryArchive'), [])
const options = useMemo(() => {
const options = []
const defsSet = new Set()
function addDef(def, prefix) {
const fullName = prefix ? `${prefix}.${def.name}` : def.name
if (defsSet.has(def)) {
return
}
defsSet.add(def)
options.push({value: fullName})
if (def.m_def === 'SubSection' && def.sub_section) {
def = resolveRef(def.sub_section)
......
......@@ -2872,7 +2872,7 @@ class Section(Definition):
def section_cls(self) -> Type[MSection]:
if self._section_cls is None:
# set a temporary to avoid endless recursion
self._section_cls = type(self.name, (MSection,), {})
self._section_cls = type(self.name, (MSection,), dict(do_init=False))
# Create a section class if this does not exist. This happens if the section
# is not created through a class definition.
......@@ -2884,7 +2884,11 @@ class Section(Definition):
attrs[name] = inner_section_def.section_cls
attrs.update(m_def=self, do_init=False)
self._section_cls = type(self.name, (MSection,), attrs)
if len(self.base_sections) > 0:
bases = tuple(base_section.section_cls for base_section in self.base_sections)
else:
bases = (MSection,)
self._section_cls = type(self.name, bases, attrs)
return self._section_cls
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment