Commit cbce84c9 authored by Markus Scheidgen's avatar Markus Scheidgen
Browse files

Add URLs to parsers/codes. Added code list and mini doc to upload page. #343

parent 6f9b20b5
Pipeline #75113 passed with stages
in 22 minutes and 15 seconds
......@@ -9,6 +9,26 @@ import { domains } from './domains'
import { Grid, Card, CardContent, Typography, makeStyles, Link } from '@material-ui/core'
import { Link as RouterLink, useHistory } from 'react-router-dom'
export const CodeList = () => {
const {info} = useContext(apiContext)
if (!info) {
return '...'
}
return info.codes.reduce((result, code, index) => {
if (index !== 0) {
result.push(', ')
}
if (code.code_homepage) {
result.push(<Link target="external" key={code.code_name} href={code.code_homepage}>{code.code_name}</Link>)
} else {
result.push(code.code_name)
}
return result
}, [])
}
const useCardStyles = makeStyles(theme => ({
title: {
marginBottom: theme.spacing(1)
......@@ -173,7 +193,7 @@ export default function About() {
You can inspect the Archive form and extracted metadata before
publishing your data.
</p>
<p>NOMAD supports most community codes: {info ? info.codes.join(', ') : '...'}</p>
<p>NOMAD supports most community codes: <CodeList/></p>
<p>
To use NOMAD&apos;s parsers and normalizers outside of NOMAD.
Read <Link href="">here</Link> on how to install
......
import React from 'react'
import PropTypes, { instanceOf } from 'prop-types'
import Markdown from '../Markdown'
import { withStyles, Paper, IconButton, FormGroup, FormLabel, Tooltip } from '@material-ui/core'
import { withStyles, Paper, IconButton, FormGroup, FormLabel, Tooltip, Typography } from '@material-ui/core'
import UploadIcon from '@material-ui/icons/CloudUpload'
import Dropzone from 'react-dropzone'
import Upload from './Upload'
......@@ -16,6 +16,7 @@ import Pagination from 'material-ui-flat-pagination'
import { CopyToClipboard } from 'react-copy-to-clipboard'
import { guiBase } from '../../config'
import qs from 'qs'
import { CodeList } from '../About'
export const help = `
NOMAD allows you to upload data. After upload, NOMAD will process your data: it will
......@@ -126,7 +127,8 @@ class UploadPage extends React.Component {
'& svg': {
marginLeft: 'auto',
marginRight: 'auto'
}
},
marginTop: theme.spacing(3)
},
dropzoneAccept: {
background: theme.palette.primary.main,
......@@ -267,6 +269,16 @@ class UploadPage extends React.Component {
return (
<div className={classes.root}>
<Typography>
To prepare your data, simply use <b>zip</b> or <b>tar</b> to create a single file that contains
all your files as they are. These .zip/.tar files can contain subdirectories and additional files.
NOMAD will search through all files and identify the relevant files automatically.
Each uploaded file can be <b>up to 32GB</b> in size, you can have <b>up to 10 unpublished
uploads</b> simultaneously. Your uploaded data is not published right away.
</Typography>
<Typography>
The following codes are supported: <CodeList/>.
</Typography>
<Paper className={classes.dropzoneContainer}>
<Dropzone
accept={[
......@@ -288,7 +300,7 @@ class UploadPage extends React.Component {
rejectClassName={classes.dropzoneReject}
onDrop={this.onDrop.bind(this)}
>
<p>drop .tar.gz or .zip files here</p>
<p>click or drop .tar.gz/.zip files here</p>
<UploadIcon style={{fontSize: 36}}/>
</Dropzone>
</Paper>
......
......@@ -54,10 +54,15 @@ statistics_info_model = api.model('StatisticsInfo', {
# 'archive_file_size': fields.Integer(description='Total amount of binary archive data in TB')
})
code_info_model = api.model('CodeInfo', {
'code_name': fields.String(description='Name of the code or input format', allow_null=True),
'code_homepage': fields.String(description='Homepage of the code or input format', allow_null=True)
}, allow_null=True, skip_none=True)
info_model = api.model('Info', {
'parsers': fields.List(fields.String),
'metainfo_packages': fields.List(fields.String),
'codes': fields.List(fields.String),
'codes': fields.List(fields.Nested(code_info_model)),
'normalizers': fields.List(fields.String),
'domains': fields.List(fields.Nested(model=domain_model)),
'statistics': fields.Nested(model=statistics_info_model, description='General NOMAD statistics'),
......@@ -88,10 +93,14 @@ class InfoResource(Resource):
@api.marshal_with(info_model, skip_none=True, code=200, description='Info send')
def get(self):
''' Return information about the nomad backend and its configuration. '''
codes = [
parser.code_name
for parser in parsing.parser_dict.values()
if isinstance(parser, parsing.MatchingParser) and parser.domain == 'dft']
codes_dict = {}
for parser in parsing.parser_dict.values():
if isinstance(parser, parsing.MatchingParser) and parser.domain == 'dft':
code_name = parser.code_name
if code_name in codes_dict:
continue
codes_dict[code_name] = dict(code_name=code_name, code_homepage=parser.code_homepage)
codes = sorted(list(codes_dict.values()), key=lambda code_info: code_info['code_name'].lower())
return {
'parsers': [
......@@ -100,7 +109,7 @@ class InfoResource(Resource):
'metainfo_packages': ['general', 'general.experimental', 'common', 'public'] + sorted([
key[key.index('/') + 1:]
for key in parsing.parser_dict.keys()]),
'codes': sorted(set(codes), key=lambda x: x.lower()),
'codes': codes,
'normalizers': [normalizer.__name__ for normalizer in normalizing.normalizers],
'statistics': statistics(),
'domains': [
......
......@@ -178,7 +178,7 @@ parsers = [
mainfile_name_re=(r'.*/phonopy-FHI-aims-displacement-0*1/control.in$')
),
LegacyParser(
name='parsers/vasp', code_name='VASP',
name='parsers/vasp', code_name='VASP', code_homepage='https://www.vasp.at/',
parser_class_name='vaspparser.VASPRunParser',
mainfile_mime_re=r'(application/.*)|(text/.*)',
mainfile_contents_re=(
......
......@@ -99,6 +99,8 @@ class MatchingParser(Parser):
A parser implementation that used regular experessions to match mainfiles.
Arguments:
code_name: The name of the code or input format
code_homepage: The homepage of the code or input format
mainfile_mime_re: A regexp that is used to match against a files mime type
mainfile_contents_re: A regexp that is used to match the first 1024 bytes of a
potential mainfile.
......@@ -107,7 +109,7 @@ class MatchingParser(Parser):
supported_compressions: A list of [gz, bz2], if the parser supports compressed files
'''
def __init__(
self, name: str, code_name: str,
self, name: str, code_name: str, code_homepage: str = None,
mainfile_contents_re: str = None,
mainfile_binary_header: bytes = None,
mainfile_mime_re: str = r'text/.*',
......@@ -118,6 +120,7 @@ class MatchingParser(Parser):
super().__init__()
self.name = name
self.code_name = code_name
self.code_homepage = code_homepage
self.domain = domain
self._mainfile_binary_header = mainfile_binary_header
self._mainfile_mime_re = re.compile(mainfile_mime_re)
......
Markdown is supported
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