Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions examples/graphAuthoring.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ function GraphAuthoringExample() {
? <Reactodia.FormInputList {...inputProps} valueInput={MultilineTextInput} />
: undefined,
}}
languages={[
{code: 'en', label: 'English'},
{code: 'es', label: 'Español'},
{code: 'fr', label: 'Français'},
{code: 'it', label: 'Italiano'},
{code: 'ja', label: '日本語'},
]}
/>
</Reactodia.Workspace>
);
Expand Down
68 changes: 38 additions & 30 deletions src/forms/elementTypeSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
Expand Down Expand Up @@ -84,13 +87,6 @@ export class ElementTypeSelectorInner extends React.Component<ElementTypeSelecto
componentDidMount() {
const {searchStore, workspace: {model}} = this.props;

this.listener.listen(model.events, 'elementTypeEvent', ({data}) => {
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
Expand Down Expand Up @@ -143,9 +139,7 @@ export class ElementTypeSelectorInner extends React.Component<ElementTypeSelecto
elementTypeSet.add(type);
}
}
const elementTypes = Array.from(elementTypeSet)
.sort(makeElementTypeComparatorByLabel(model, t));
this.setState({elementTypes});
this.setState({elementTypes: Array.from(elementTypeSet)});
}

private async searchExistingElements(searchString: string) {
Expand Down Expand Up @@ -212,20 +206,6 @@ export class ElementTypeSelectorInner extends React.Component<ElementTypeSelecto
});
};

private renderPossibleElementType = (elementType: ElementTypeIri) => {
const {workspace: {model, translation: t}} = this.props;
const type = model.getElementType(elementType);
const label = t.formatLabel(type?.data?.label, elementType, model.language);
return (
<option key={elementType} value={elementType}>
{t.text('visual_authoring.select_entity.entity_type.label', {
type: label,
typeIri: elementType,
})}
</option>
);
};

private renderElementTypeSelector() {
const {elementValue, workspace: {translation: t}} = this.props;
const {elementTypes, elementTypesState} = this.state;
Expand All @@ -249,9 +229,7 @@ export class ElementTypeSelectorInner extends React.Component<ElementTypeSelecto
<option value={PlaceholderEntityType} disabled={true}>
{t.text('visual_authoring.select_entity.type.placeholder')}
</option>
{
elementTypes.map(this.renderPossibleElementType)
}
<ElementTypeOptions elementTypes={elementTypes} />
</select>
) : <div><HtmlSpinner width={20} height={20} /></div>
}
Expand Down Expand Up @@ -349,12 +327,42 @@ export class ElementTypeSelectorInner extends React.Component<ElementTypeSelecto
}
}

function makeElementTypeComparatorByLabel(model: DataDiagramModel, t: Translation) {
function ElementTypeOptions(props: {
elementTypes: readonly ElementTypeIri[];
}) {
const {elementTypes} = props;
const {model, translation: t} = useWorkspace();

const language = useObservedProperty(model.events, 'changeLanguage', () => 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 (
<option key={elementType} value={elementType}>
{t.text('visual_authoring.select_entity.entity_type.label', {
type: label,
typeIri: elementType,
})}
</option>
);
})}
</>
);
}

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);
};
}
Expand Down
9 changes: 5 additions & 4 deletions src/forms/input/formInputGroup.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 ?? [],
});
Expand Down Expand Up @@ -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);
Expand All @@ -130,7 +131,7 @@ function Property(props: {
<label
title={t.text('visual_authoring.property.title', {
property: label,
propertyIri: iri,
propertyIri: model.locale.formatIri(iri),
})}>
<WithFetchStatus type='propertyType' target={iri}>
<span>
Expand Down
Loading