diff --git a/gui/src/components/editQuantity/ActionEditQuantity.js b/gui/src/components/editQuantity/ActionEditQuantity.js new file mode 100644 index 0000000000000000000000000000000000000000..bb51d6a3828898daa6eeb2d54492a4894398f753 --- /dev/null +++ b/gui/src/components/editQuantity/ActionEditQuantity.js @@ -0,0 +1,58 @@ +/* + * Copyright The NOMAD Authors. + * + * This file is part of NOMAD. See https://nomad-lab.eu for further info. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, {useCallback} from 'react' +import { + Button, + Tooltip +} from '@material-ui/core' +import PropTypes from 'prop-types' +import {getFieldProps} from './StringEditQuantity' +import {getDisplayLabel} from "../../utils" +import {useErrors } from '../errors' +import {useEntryStore } from '../entry/EntryContext' +import {useRecoilValue} from "recoil" +import {configState} from "../archive/ArchiveBrowser" + +export const ActionEditQuantity = React.memo(function ButtonEditQuantity(props) { + const {quantityDef, value, onChange, ...otherProps} = props + const fieldProps = getFieldProps(quantityDef) + const {saveArchive} = useEntryStore() + const {raiseError} = useErrors() + const config = useRecoilValue(configState) + const label = getDisplayLabel(quantityDef, true, config?.showMeta) + + const handleClick = useCallback(() => { + onChange?.(true) + saveArchive().catch(raiseError) + }, [onChange, saveArchive, raiseError]) + + return <Tooltip title={fieldProps.helpDescription}> + <Button + variant="outlined" + disabled={value} + onClick={handleClick} + color="primary" + {...otherProps} + >{label}</Button> + </Tooltip> +}) +ActionEditQuantity.propTypes = { + quantityDef: PropTypes.object.isRequired, + value: PropTypes.bool, + onChange: PropTypes.func +} diff --git a/gui/src/components/editQuantity/EditQuantity.js b/gui/src/components/editQuantity/EditQuantity.js index b0522110d39f9ccd28394d73f0de3914aca28f1d..53f4c8b56b08f1b6c1bd8a1136df39568eedcf15 100644 --- a/gui/src/components/editQuantity/EditQuantity.js +++ b/gui/src/components/editQuantity/EditQuantity.js @@ -22,6 +22,7 @@ import {NumberEditQuantity} from './NumberEditQuantity' import {EnumEditQuantity} from './EnumEditQuantity' import {AutocompleteEditQuantity} from './AutocompleteEditQuantity' import {BoolEditQuantity} from './BoolEditQuantity' +import {ActionEditQuantity} from './ActionEditQuantity' import FileEditQuantity from './FileEditQuantity' import RichTextEditQuantity from './RichTextEditQuantity' import ReferenceEditQuantity from './ReferenceEditQuantity' @@ -38,6 +39,7 @@ export const editQuantityComponents = { RadioEnumEditQuantity: RadioEnumEditQuantity, AutocompleteEditQuantity: AutocompleteEditQuantity, BoolEditQuantity: BoolEditQuantity, + ActionEditQuantity: ActionEditQuantity, FileEditQuantity: FileEditQuantity, DateTimeEditQuantity: DateTimeEditQuantity, DateEditQuantity: DateEditQuantity, diff --git a/nomad/datamodel/metainfo/action.py b/nomad/datamodel/metainfo/action.py new file mode 100644 index 0000000000000000000000000000000000000000..a4c73d3de524f16e174415d663477c1bbde37261 --- /dev/null +++ b/nomad/datamodel/metainfo/action.py @@ -0,0 +1,69 @@ +# +# Copyright The NOMAD Authors. +# +# This file is part of NOMAD. See https://nomad-lab.eu for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from nomad.datamodel.data import ArchiveSection +from nomad.metainfo import Quantity, Package + +m_package = Package() + + +class ActionSection(ArchiveSection): + """ + Use this section to define actions that can be triggered from the ELN + interface. + + Usage: + - In any of your schemas, use a a section that inherits from this one. + - Provide a `description` and an eln annotation for the `action_trigger` + quantity. To show a button that sets the trigger and performs a save + operation, use the `ActionEditQuantity` component in the eln annotation . + - Define a `perform_action` function that contains the code to trigger. + + Example Usage: + ```python + class MyAction(ActionSection): + action_trigger = Quantity( + description='Description for this action. Will be shown as a tooltip.', + a_eln=dict(component='ActionEditQuantity', label='Button label'), + ) + + def perform_action(self, archive, logger): + # First check that was this action requested. Note that you do not + # have to modify this quantity: it will be set and reset + # automatically. + if self.action_trigger: + # Perform your action here + pass + ``` + """ + + action_trigger = Quantity(type=bool) + + def normalize(self, archive, logger): + try: + if self.action_trigger: + self.perform_action(archive, logger) + finally: + self.action_trigger = False + + def perform_action(self, archive, logger): + raise NotImplementedError( + 'No implementation provided for the perform_action function of an ActionSection.' + ) + + +m_package.__init_metainfo__() diff --git a/nomad/datamodel/metainfo/annotations.py b/nomad/datamodel/metainfo/annotations.py index 8f353097c43d4eb30510c60cdb34465612919d49..c5ae113ece24cda391eaf0c36172922f65efb882 100644 --- a/nomad/datamodel/metainfo/annotations.py +++ b/nomad/datamodel/metainfo/annotations.py @@ -48,6 +48,7 @@ class ELNComponentEnum(str, Enum): UserEditQuantity = 'UserEditQuantity' AuthorEditQuantity = 'AuthorEditQuantity' QueryEditQuantity = 'QueryEditQuantity' + ActionEditQuantity = 'ActionEditQuantity' valid_eln_types = { @@ -79,7 +80,7 @@ valid_eln_components = { ELNComponentEnum.RichTextEditQuantity, ELNComponentEnum.EnumEditQuantity, ], - 'bool': [ELNComponentEnum.BoolEditQuantity], + 'bool': [ELNComponentEnum.BoolEditQuantity, ELNComponentEnum.ActionEditQuantity], 'number': [ ELNComponentEnum.NumberEditQuantity, ELNComponentEnum.SliderEditQuantity,