Create a metadata sidebar
This recipe covers a very basic metadata form for use in a sidebar. It's mostly meant to serve as an example for an editing roundtrip between an opened XML document and a custom form within a sidebar.
This is by no means an example for a be-all and end-all metadata sidebar. Assumptions have been made, and functionality has been omitted, in favour of brevity. It should be carefully evaluated and refined when building a production worthy metadata sidebar.
Recommended reading
-
The 'Create a sidebar' guide for instructions on creating and setting up a sidebar.
-
The 'Create a form' guide for detailed information about creating forms.
MetadataSidebar.jsx
JavaScript
import React, { useCallback, useMemo } from 'react';
// More information about each of the following imports can be found in the FontoXML Editor API
// section of the documentation (http://documentation.fontoxml.com/api/).
import { Flex, Form, FormRow, SidebarHeader, SidebarInlay, TextInput } from 'fds/components';
import documentsManager from 'fontoxml-documents/src/documentsManager.js';
import getNodeId from 'fontoxml-dom-identification/src/getNodeId.js';
import useManagerState from 'fontoxml-fx/src/useManagerState.js';
import useXPath, { XPATH_RETURN_TYPES } from 'fontoxml-fx/src/useXPath.js';
import t from 'fontoxml-localization/src/t.js';
import operationsManager from 'fontoxml-operations/src/operationsManager.js';
import selectionManager from 'fontoxml-selection/src/selectionManager.js';
export default function MetadataPanel() {
const focusedDocumentNode = useManagerState(selectionManager.selectionChangeNotifier, () =>
documentsManager.getNodeById(selectionManager.focusedDocumentId)
);
// This assumes an editor with a schema where in each loaded document file has xml like this:
// <document><metadata>Actual metadata content</metadata><content>...</content></document>
const metadataElement = useXPath('document/metadata', focusedDocumentNode, {
expectedResultType: XPATH_RETURN_TYPES.FIRST_NODE_TYPE
});
const metadataNodeId = useMemo(() => getNodeId(metadataElement), [metadataElement]);
const metadataTextContent = useXPath('string(.)', metadataElement, {
expectedResultType: XPATH_RETURN_TYPES.STRING_TYPE
});
const updateMetadataTextContentInXML = useCallback(
updatedMetadataContent => {
// Details about the 'replace-node' operation, and potential alternatives, can be found in
// the FontoXML Editor API section of the documentation. It's recommended to read through
// them to find out which operation is best suited for your usecase.
//
// Tip: make sure to only execute a single operation for an intuitive undo/redo stack.
//
// 'operationsManager.executeOperation' returns a Promise. It's recommended to implement
// 'then' and 'catch' handlers, and present users with some form of feedback when saving.
operationsManager.executeOperation('replace-node', {
contextNodeId: metadataNodeId,
replacementNodeStructure: [updatedMetadataContent]
});
},
[metadataNodeId]
);
return (
<Flex flex="1" flexDirection="column">
<SidebarHeader subtitle={t('Example metadata sidebar')} title={t('Metadata')} />
<SidebarInlay>
<Form labelPosition="before">
<FormRow key="text" label={t('Example field')}>
<TextInput
name="text"
onChange={updateMetadataTextContentInXML}
placeholder={t('type something here')}
tooltipContent={t('This field serves as an example.')}
value={metadataTextContent}
/>
</FormRow>
</Form>
</SidebarInlay>
</Flex>
);
}