diff --git a/CHANGELOG.md b/CHANGELOG.md index 14d78693..0f155d5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - Fix a freeze when opening a class tree in authoring mode when `MetadataProvider.filterConstructibleTypes()` returns without any delay. - Fix calling `MetadataProvider.canConnect()` with only source and without target when dragging over an element to establish a new link. - Fix `flushSync was called from inside a lifecycle method` React warning when calling `centerTo()`, `centerContent()`, `zoomToFit()` on `CanvasApi` from a lifecycle method. +- Fix labels not loading for element and link type selectors in `VisualAuthoring` dialogs unless already preloaded from the diagram. - Use default property editor for entities or relations when `VisualAuthoring.propertyEditor` returns `undefined`. - Fix `prepareLabels` option for `SparqlDataProvider` to be applied for `knownElementTypes()`, `knownLinkTypes()`, `elementTypes()`, `linkTypes()`, `propertyTypes()` and `elements`. - Fix `SparqlDataProvider.elements()` to always return entities with sorted types. diff --git a/examples/graphAuthoring.tsx b/examples/graphAuthoring.tsx index aa1ba294..5c29ca8f 100644 --- a/examples/graphAuthoring.tsx +++ b/examples/graphAuthoring.tsx @@ -69,6 +69,13 @@ function GraphAuthoringExample() { ? : undefined, }} + languages={[ + {code: 'en', label: 'English'}, + {code: 'es', label: 'Español'}, + {code: 'fr', label: 'Français'}, + {code: 'it', label: 'Italiano'}, + {code: 'ja', label: '日本語'}, + ]} /> ); diff --git a/src/forms/elementTypeSelector.tsx b/src/forms/elementTypeSelector.tsx index 5a910325..6c815a38 100644 --- a/src/forms/elementTypeSelector.tsx +++ b/src/forms/elementTypeSelector.tsx @@ -3,7 +3,9 @@ import * as React from 'react'; import { mapAbortedToNull } from '../coreUtils/async'; import { EventObserver } from '../coreUtils/events'; +import { useObservedProperty } from '../coreUtils/hooks'; import { Translation } from '../coreUtils/i18n'; +import { useKeyedSyncStore } from '../coreUtils/keyedObserver'; import { PlaceholderEntityType } from '../data/schema'; import type { ElementModel, ElementTypeIri } from '../data/model'; @@ -14,6 +16,7 @@ import { HtmlSpinner } from '../diagram/spinner'; import type { DataDiagramModel } from '../editor/dataDiagramModel'; import { EntityElement } from '../editor/dataElements'; +import { subscribeElementTypes } from '../editor/observedElement'; import { ListElementView } from '../widgets/utility/listElementView'; import { NoSearchResults } from '../widgets/utility/noSearchResults'; @@ -84,13 +87,6 @@ export class ElementTypeSelectorInner extends React.Component { - const {elementTypes} = this.state; - const changeEvent = data.changeData; - if (changeEvent && elementTypes && elementTypes.includes(changeEvent.source.id)) { - this.forceUpdate(); - } - }); this.listener.listen(searchStore.events, 'changeValue', ({source}) => { if (source.value.length === 0) { // Clear the search @@ -143,9 +139,7 @@ export class ElementTypeSelectorInner extends React.Component { - const {workspace: {model, translation: t}} = this.props; - const type = model.getElementType(elementType); - const label = t.formatLabel(type?.data?.label, elementType, model.language); - return ( - - ); - }; - private renderElementTypeSelector() { const {elementValue, workspace: {translation: t}} = this.props; const {elementTypes, elementTypesState} = this.state; @@ -249,9 +229,7 @@ export class ElementTypeSelectorInner extends React.Component {t.text('visual_authoring.select_entity.type.placeholder')} - { - elementTypes.map(this.renderPossibleElementType) - } + ) :
} @@ -349,12 +327,42 @@ export class ElementTypeSelectorInner extends React.Component model.language); + useKeyedSyncStore(subscribeElementTypes, elementTypes, model); + const sortedTypes = [...elementTypes].sort( + makeElementTypeComparatorByLabel(model, t, language) + ); + + return ( + <> + {sortedTypes.map(elementType => { + const type = model.getElementType(elementType); + const label = t.formatLabel(type?.data?.label, elementType, language); + return ( + + ); + })} + + ); +} + +function makeElementTypeComparatorByLabel(model: DataDiagramModel, t: Translation, language: string) { return (a: ElementTypeIri, b: ElementTypeIri) => { const typeA = model.getElementType(a); const typeB = model.getElementType(b); - const labelA = t.formatLabel(typeA?.data?.label, a, model.language); - const labelB = t.formatLabel(typeB?.data?.label, b, model.language); + const labelA = t.formatLabel(typeA?.data?.label, a, language); + const labelB = t.formatLabel(typeB?.data?.label, b, language); return labelA.localeCompare(labelB); }; } diff --git a/src/forms/input/formInputGroup.tsx b/src/forms/input/formInputGroup.tsx index 6db74d7e..1df5c5c4 100644 --- a/src/forms/input/formInputGroup.tsx +++ b/src/forms/input/formInputGroup.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; +import { useObservedProperty } from '../../coreUtils/hooks'; import { useKeyedSyncStore } from '../../coreUtils/keyedObserver'; -import { useTranslation } from '../../coreUtils/i18n'; import { PropertyTypeIri } from '../../data/model'; import * as Rdf from '../../data/rdf/rdfModel'; @@ -34,6 +34,7 @@ export function FormInputGroup(props: FormInputGroupProps) { className, languages, propertyShapes, extraPropertyShape, propertyValues, onChangeData, resolveInput, } = props; const {model, translation: t} = useWorkspace(); + const language = useObservedProperty(model.events, 'changeLanguage', () => model.language); const propertyIris: PropertyTypeIri[] = Array.from(propertyShapes.keys()); if (extraPropertyShape) { @@ -62,7 +63,7 @@ export function FormInputGroup(props: FormInputGroupProps) { ? propertyValues[iri] : undefined; labelledProperties.push({ iri, - label: t.formatLabel(property?.data?.label, iri, model.language), + label: t.formatLabel(property?.data?.label, iri, language), shape, values: values ?? [], }); @@ -108,7 +109,7 @@ function Property(props: { resolveInput: FormInputGroupProps['resolveInput']; }) { const {iri, label, shape, languages, values, onChange, factory, resolveInput} = props; - const t = useTranslation(); + const {model, translation: t} = useWorkspace(); const updateValues = React.useCallback((updater: FormInputMultiUpdater) => { onChange(iri, updater); @@ -130,7 +131,7 @@ function Property(props: {