Commit f576723a authored by Amir Golparvar's avatar Amir Golparvar
Browse files

new URL datatype is added to metainfo. new URLEditQuantity is added to the gui

parent 72a377e0
Pipeline #134764 failed with stages
in 43 minutes and 58 seconds
......@@ -5,7 +5,7 @@ import { useEntryContext } from '../entry/EntryContext'
import _ from 'lodash'
import ListEditQuantity from '../editQuantity/ListEditQuantity'
import {DateTimeEditQuantity} from '../editQuantity/DateTimeEditQuantity'
import {StringEditQuantity} from '../editQuantity/StringEditQuantity'
import { StringEditQuantity, URLEditQuantity } from '../editQuantity/StringEditQuantity'
import {NumberEditQuantity} from '../editQuantity/NumberEditQuantity'
import {EnumEditQuantity} from '../editQuantity/EnumEditQuantity'
import {AutocompleteEditQuantity} from '../editQuantity/AutocompleteEditQuantity'
......@@ -19,6 +19,7 @@ import { RadioEnumEditQuantity } from '../editQuantity/RadioEnumEditQuantity'
const editQuantityComponents = {
NumberEditQuantity: NumberEditQuantity,
StringEditQuantity: StringEditQuantity,
URLEditQuantity: URLEditQuantity,
EnumEditQuantity: EnumEditQuantity,
SelectEnumEditQuantity: EnumEditQuantity,
RadioEnumEditQuantity: RadioEnumEditQuantity,
......
......@@ -91,6 +91,9 @@ const useWithHelpStyles = makeStyles(theme => ({
display: 'none'
}
}
},
linkButton: {
width: '10%'
}
}))
......@@ -194,3 +197,73 @@ export const StringField = React.memo((props) => {
StringField.propTypes = {
onChange: PropTypes.func
}
export const TextFieldWithLinkButton = React.memo(React.forwardRef((props, ref) => {
const {withOtherAdornment, label, validateURL, value, helpDescription, 'data-testid': TestId, ...otherProps} = props
const classes = useWithHelpStyles()
return <TextField
value={value}
inputRef={ref}
className={classes.root}
InputProps={{endAdornment:
<>
{ helpDescription &&
<div id="help">
<HelpAdornment title={label} description={helpDescription} withOtherAdornment={withOtherAdornment}/>
</div>
}
{
validateURL(value) &&
<Button className={classes.linkButton} label={label} variant='contained' color='primary' onClick={() => window.open(value, '_blank')}>
link
</Button>
}
</>
}}
label={label}
data-testid={TestId}
{...otherProps}
/>
}))
TextFieldWithLinkButton.propTypes = {
withOtherAdornment: PropTypes.bool,
label: PropTypes.string,
value: PropTypes.string,
validateURL: PropTypes.func,
helpDescription: PropTypes.string,
'data-testid': PropTypes.string
}
export const URLEditQuantity = React.memo((props) => {
const {quantityDef, onChange, ...otherProps} = props
const validateURL = useCallback((value) => {
if (!value) { return false }
try {
let url = new URL(value)
if (url) { return true }
} catch (_) {
return false
}
}, [])
const handleChange = useCallback((value) => {
if (onChange && validateURL(value)) {
onChange(value === '' ? undefined : value)
}
}, [onChange, validateURL])
return <TextFieldWithLinkButton
fullWidth variant='filled' size='small'
validateURL={validateURL}
onChange={event => handleChange(event.target.value)}
{...getFieldProps(quantityDef)}
{...otherProps}
/>
})
URLEditQuantity.propTypes = {
quantityDef: PropTypes.object.isRequired,
value: PropTypes.string,
onChange: PropTypes.func
}
......@@ -39,6 +39,7 @@ import base64
import importlib
import email.utils
from urllib.parse import urlsplit, urlunsplit, SplitResult
import validators
from nomad.units import ureg as units
......@@ -787,6 +788,30 @@ class _File(DataType):
return value
class _URL(DataType):
def _test(self, url_str: str) -> str:
if url_str is None:
return None
if not isinstance(url_str, str):
raise TypeError('Links need to be given as URL strings')
if not validators.url(url_str):
raise ValueError('The given URL could not be fetched')
return url_str
def set_normalize(self, section: 'MSection', quantity_def: 'Quantity', value: Any) -> Any:
return self._test(value)
def serialize(self, section: 'MSection', quantity_def: 'Quantity', value: Any) -> Any:
if value is None:
return None
return self._test(value)
def deserialize(self, section: 'MSection', quantity_def: 'Quantity', value: Any) -> Any:
return self._test(value)
class _Datetime(DataType):
def _parse(self, datetime_str: str) -> datetime:
......@@ -897,10 +922,11 @@ JSON = _JSON()
Capitalized = _Capitalized()
Bytes = _Bytes()
File = _File()
URL = _URL()
predefined_datatypes = {
'Dimension': Dimension, 'Unit': Unit, 'Datetime': Datetime,
'JSON': JSON, 'Capitalized': Capitalized, 'bytes': Bytes, 'File': File}
'JSON': JSON, 'Capitalized': Capitalized, 'bytes': Bytes, 'File': File, 'URL': URL}
# Metainfo data storage and reflection interface
......
Supports Markdown
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