From 0f3e4ef1de18dd8559f09870f4bfed270a788edb Mon Sep 17 00:00:00 2001 From: Markus Scheidgen <markus.scheidgen@gmail.com> Date: Sat, 25 Aug 2018 08:25:10 +0200 Subject: [PATCH] Added api and json gui for list all repo calcs. --- gui/src/api.js | 8 +++++- gui/src/components/App.js | 3 ++- gui/src/components/Repo.js | 55 ++++++++++++++++++++++++++++++++++++++ nomad/api.py | 42 ++++++++++++++++++++++++++--- nomad/search.py | 6 ++++- tests/test_api.py | 14 ++++++++-- 6 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 gui/src/components/Repo.js diff --git a/gui/src/api.js b/gui/src/api.js index f7dec4856d..1379c9b3f4 100644 --- a/gui/src/api.js +++ b/gui/src/api.js @@ -66,11 +66,17 @@ function repo(uploadHash, calcHash) { .then(response => response.json()) } +function repoAll(uploadHash, calcHash) { + return fetch(`${apiBase}/repo`) + .then(response => response.json()) +} + const api = { createUpload: createUpload, getUploads: getUploads, archive: archive, - repo: repo + repo: repo, + repoAll: repoAll, }; export default api; \ No newline at end of file diff --git a/gui/src/components/App.js b/gui/src/components/App.js index 23838bcc1e..b8781cfe30 100644 --- a/gui/src/components/App.js +++ b/gui/src/components/App.js @@ -6,6 +6,7 @@ import { BrowserRouter, Switch, Route } from 'react-router-dom'; import Uploads from './Uploads' import ArchiveCalc from './ArchiveCalc'; import RepoCalc from './RepoCalc'; +import Repo from './Repo'; function App() { return ( @@ -14,7 +15,7 @@ function App() { <Navigation> <Switch> <Route exact path="/" render={() => <div>Home</div>} /> - <Route exact path="/repo" render={() => <div>Browse</div>} /> + <Route exact path="/repo" component={Repo} /> <Route path="/repo/:uploadHash/:calcHash" component={RepoCalc} /> <Route path="/upload" component={Uploads} /> <Route exact path="/archive" render={() => <div>Archive</div>} /> diff --git a/gui/src/components/Repo.js b/gui/src/components/Repo.js new file mode 100644 index 0000000000..cb67835267 --- /dev/null +++ b/gui/src/components/Repo.js @@ -0,0 +1,55 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles, Paper, LinearProgress } from '@material-ui/core'; +import ReactJson from 'react-json-view' +import api from '../api'; +import Markdown from './Markdown'; + + +class Repo extends React.Component { + static propTypes = { + classes: PropTypes.object.isRequired + } + static styles = theme => ({ + root: {}, + calcData: { + padding: theme.spacing.unit + } + }); + + constructor(props) { + super(props) + this.state = { + data: null + } + } + + componentDidMount() { + api.repoAll().then(data => { + this.setState({data: data}) + }) + } + + render() { + const { classes } = this.props + const { data } = this.state + + return ( + <div className={classes.root}> + <Markdown>{` + ## The Repository – Raw Code Data + `}</Markdown> + <Paper className={classes.calcData}> + { + data ? + <ReactJson src={this.state.data} enableClipboard={false} collapsed={4} /> : + <LinearProgress variant="query" /> + } + </Paper> + </div> + + ) + } +} + +export default withStyles(Repo.styles)(Repo); \ No newline at end of file diff --git a/nomad/api.py b/nomad/api.py index 2e8a003ceb..cd25efbbef 100644 --- a/nomad/api.py +++ b/nomad/api.py @@ -76,10 +76,11 @@ class Upload(Resource): return Uploads._render(upload), 200 -class Repo(Resource): +class RepoCalc(Resource): @staticmethod def _render(data: dict): - if 'upload_time' in data: + upload_time = data.get('upload_time', None) + if upload_time is not None and isinstance(upload_time, datetime): data['upload_time'] = data['upload_time'].isoformat() return {key: value for key, value in data.items() if value is not None} @@ -92,7 +93,39 @@ class Repo(Resource): except Exception as e: abort(500, message=str(e)) - return Repo._render(data.to_dict()), 200 + return RepoCalc._render(data.to_dict()), 200 + + +class RepoCalcs(Resource): + def get(self): + page = request.args.get('page', 1) + per_page = request.args.get('per_page', 10) + + assert page >= 1 + assert per_page > 0 + + body = { + 'from': page - 1, + 'size': per_page, + 'query': { + 'match_all': {} + } + } + + try: + results = search.Calc.search(body=body) + except Exception as e: + get_logger(__name__).error('Could not execute repo calcs get.', exc_info=e) + abort(500, message=str(e)) + + return { + 'pagination': { + 'total': results['hits']['total'], + 'page': page, + 'per_page': per_page + }, + 'results': [RepoCalc._render(hit['_source']) for hit in results['hits']['hits']] + } @app.route('/archive/<string:upload_hash>/<string:calc_hash>', methods=['GET']) @@ -111,7 +144,8 @@ def get_calc(upload_hash, calc_hash): api.add_resource(Uploads, '/uploads') api.add_resource(Upload, '/uploads/<string:upload_id>') -api.add_resource(Repo, '/repo/<string:upload_hash>/<string:calc_hash>') +api.add_resource(RepoCalcs, '/repo') +api.add_resource(RepoCalc, '/repo/<string:upload_hash>/<string:calc_hash>') if __name__ == '__main__': diff --git a/nomad/search.py b/nomad/search.py index 994b19a2fc..9c096be20a 100644 --- a/nomad/search.py +++ b/nomad/search.py @@ -30,7 +30,7 @@ logger = logging.getLogger(__name__) # ensure elastic connection if 'sphinx' not in sys.modules: - connections.create_connection(hosts=[config.elastic.host]) + client = connections.create_connection(hosts=[config.elastic.host]) key_mappings = { @@ -66,6 +66,10 @@ class Calc(Document): class Index: name = config.elastic.calc_index + @staticmethod + def search(body): + return client.search(index=config.elastic.calc_index, body=body) + @staticmethod def add_from_backend(backend: LocalBackend, **kwargs) -> 'Calc': """ diff --git a/tests/test_api.py b/tests/test_api.py index 6e8f891608..d525bdec4f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -153,16 +153,26 @@ def test_processing(client, file, celery_session_worker): assert_exists(config.files.uploads_bucket, upload['upload_id']) -def test_get_repo(client, example_entry): +def test_get_repo_calc(client, example_entry): rv = client.get('/repo/%s/%s' % (example_entry.upload_hash, example_entry.calc_hash)) assert rv.status_code == 200 -def test_non_existing_repo(client): +def test_non_existing_repo_cals(client): rv = client.get('/repo/doesnt/exist') assert rv.status_code == 404 +def test_get_repo_calcs(client, example_entry): + rv = client.get('/repo') + assert rv.status_code == 200 + data = json.loads(rv.data) + results = data.get('results', None) + assert results is not None + assert isinstance(results, list) + assert len(results) >= 1 + + def test_get_archive(client, archive_id): rv = client.get('/archive/%s' % archive_id) assert rv.status_code == 302 -- GitLab