From 33492754881a27c88f6a1ed38e463bba15ecf837 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Wed, 21 Mar 2018 18:53:43 -0700 Subject: merge front and back --- backend/backend.py | 301 --------------------------------------- fatcat/backend.py | 301 +++++++++++++++++++++++++++++++++++++++ fatcat/static/robots.txt | 1 + fatcat/templates/base.html | 70 +++++++++ fatcat/templates/home.html | 32 +++++ fatcat/templates/work_add.html | 215 ++++++++++++++++++++++++++++ fatcat/templates/work_view.html | 37 +++++ fatcat/test_backend.py | 53 +++++++ fatcat/webface.py | 87 +++++++++++ webface/static/robots.txt | 1 - webface/templates/base.html | 70 --------- webface/templates/home.html | 32 ----- webface/templates/work_add.html | 215 ---------------------------- webface/templates/work_view.html | 37 ----- webface/webface.py | 87 ----------- 15 files changed, 796 insertions(+), 743 deletions(-) delete mode 100755 backend/backend.py create mode 100755 fatcat/backend.py create mode 100644 fatcat/static/robots.txt create mode 100644 fatcat/templates/base.html create mode 100644 fatcat/templates/home.html create mode 100644 fatcat/templates/work_add.html create mode 100644 fatcat/templates/work_view.html create mode 100644 fatcat/test_backend.py create mode 100755 fatcat/webface.py delete mode 100644 webface/static/robots.txt delete mode 100644 webface/templates/base.html delete mode 100644 webface/templates/home.html delete mode 100644 webface/templates/work_add.html delete mode 100644 webface/templates/work_view.html delete mode 100755 webface/webface.py diff --git a/backend/backend.py b/backend/backend.py deleted file mode 100755 index a39ae790..00000000 --- a/backend/backend.py +++ /dev/null @@ -1,301 +0,0 @@ - -import argparse -from flask import Flask, render_template, send_from_directory, request, \ - url_for, abort, g, redirect, jsonify -from sqlalchemy import create_engine, MetaData, Table - -app = Flask(__name__) -app.config.from_object(__name__) - -# Load default config and override config from an environment variable -app.config.update(dict( - DATABASE_URI='sqlite://:memory:', - SECRET_KEY='development-key', - USERNAME='admin', - PASSWORD='admin' -)) -app.config.from_envvar('FATCAT_BACKEND_CONFIG', silent=True) - -metadata = MetaData() - - -## SQL Schema ############################################################### - -import enum -from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, \ - Enum - -# TODO: http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/mixins.html - -class IdState(enum.Enum): - normal = 1 - redirect = 2 - removed = 3 - -work_id = Table('work_id', metadata, - Column('id', Integer, primary_key=True, autoincrement=False), - Column('revision', ForeignKey('work_revision.id')), - ) - -work_revision = Table('work_revision', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('previous', ForeignKey('work_revision.id'), nullable=True), - Column('state', Enum(IdState)), - Column('redirect_id', ForeignKey('work_id.id'), nullable=True), - Column('edit_id', ForeignKey('edit.id')), - Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), - - Column('title', String), - Column('work_type', String), - Column('date', String), - ) - -release_id = Table('release_id', metadata, - Column('id', Integer, primary_key=True, autoincrement=False), - Column('revision', ForeignKey('release_revision.id')), - ) - -release_revision = Table('release_revision', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('previous', ForeignKey('release_revision.id'), nullable=True), - Column('state', Enum(IdState)), - Column('redirect_id', ForeignKey('release_id.id'), nullable=True), - Column('edit_id', ForeignKey('edit.id')), - Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), - - #Column('work', ForeignKey('work_id.id')), - Column('container', ForeignKey('container_id.id')), - Column('title', String), - Column('license', String), # TODO: oa status foreign key - Column('release_type', String), # TODO: foreign key - Column('date', String), # TODO: datetime - Column('doi', String), # TODO: identifier table - ) - -creator_id = Table('creator_id', metadata, - Column('id', Integer, primary_key=True, autoincrement=False), - Column('revision', ForeignKey('creator_revision.id')), - ) - -creator_revision = Table('creator_revision', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('previous', ForeignKey('creator_revision.id'), nullable=True), - Column('state', Enum(IdState)), - Column('redirect_id', ForeignKey('creator_id.id'), nullable=True), - Column('edit_id', ForeignKey('edit.id')), - Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), - - Column('name', String), - Column('sortname', String), - Column('orcid', String), # TODO: identifier table - ) - -work_contrib = Table('work_contrib', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('work_rev', ForeignKey('work_revision.id'), nullable=False), - Column('creator_id', ForeignKey('creator_id.id'), nullable=False), - Column('stub', String, nullable=False), - ) - -release_contrib = Table('release_contrib', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('release_rev', ForeignKey('release_revision.id'), nullable=False), - Column('creator_id', ForeignKey('creator_id.id'), nullable=False), - ) - -container_id = Table('container_id', metadata, - Column('id', Integer, primary_key=True, autoincrement=False), - Column('revision', ForeignKey('container_revision.id')), - ) - -container_revision = Table('container_revision', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('previous', ForeignKey('container_revision.id'), nullable=True), - Column('state', Enum(IdState)), - Column('redirect_id', ForeignKey('container_id.id'), nullable=True), - Column('edit_id', ForeignKey('edit.id')), - Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), - - Column('name', String), - Column('container', ForeignKey('container_id.id')), - Column('publisher', String), # TODO: foreign key - Column('sortname', String), - Column('issn', String), # TODO: identifier table - ) - -file_id = Table('file_id', metadata, - Column('id', Integer, primary_key=True, autoincrement=False), - Column('revision', ForeignKey('container_revision.id')), - ) - -file_revision = Table('file_revision', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('previous', ForeignKey('file_revision.id'), nullable=True), - Column('state', Enum(IdState)), - Column('redirect_id', ForeignKey('file_id.id'), nullable=True), - Column('edit_id', ForeignKey('edit.id')), - Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), - - Column('size', Integer), - Column('sha1', Integer), # TODO: hash table... only or in addition? - Column('url', Integer), # TODO: URL table - ) - -release_file= Table('release_file', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('release_rev', ForeignKey('release_revision.id'), nullable=False), - Column('file_id', ForeignKey('file_id.id'), nullable=False), - ) - -edit = Table('edit', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('edit_group', ForeignKey('edit_group.id')), - Column('editor', ForeignKey('editor.id')), - Column('description', String), - ) - -edit_group = Table('edit_group', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('editor', ForeignKey('editor.id')), - Column('description', String), - ) - -editor = Table('editor', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('username', String), - ) - -changelog = Table('changelog', metadata, - Column('id', Integer, primary_key=True, autoincrement=True), - Column('edit_id', ForeignKey('edit.id')), - Column('timestamp', Integer), - ) - -extra_json = Table('extra_json', metadata, - Column('sha1', String, primary_key=True, autoincrement=True), - Column('json', String), - ) - -## Helpers ################################################################## - -def is_fcid(s): - return len(s) == 26 and s.isalnum() - -# XXX: why isn't this running? -def test_is_fcid(): - - for s in ("rzga5b9cd7efgh04iljk", "RZGA5B9CD7Efgh04iljk"): - assert is_fcid() is True - - for s in ("rzga59cd7efgh04iljk", "rzga.b9cd7efgh04iljk", "", - "rzga5b9cd7efgh04iljkz"): - assert is_fcid() is False - -def release_list(id_list): - # XXX: MOCK - l = [] - for i in id_list: - l.append({ - "id": i, - "rev": "8fkj28fjhqkjdhkjkj9s", - "previous": "0021jdfjhqkjdhkjkj9s", - "state": "normal", - "redirect_id": None, - "edit_id": "932582iuhckjvssk", - "extra_json": None, - - "container_id": "0021jdfjhqkjdhkjkj9s", - "title": "Mocks are great", - "license": "CC-0", - "release_type": "publication", - "date": "2017-11-22", - "doi": "10.1000/953kj.sdfkj", - }) - return l - -def release_hydrate(release_id): - e = release_list([release_id])[0] - e['container'] = container_hydrate(d['container_id']) - e.pop('container_id') - e['creators'] = [creator_hydrate(c['id']) for c in e['creator_ids']] - return e - -def work_list(id_list): - """This is the fast/light version: populates entity-specific lists (eg, - identifiers), and any primaries, but doesn't transclude all other - entities""" - if len(id_list) == 0: - return [] - - l = [] - for i in id_list: - l.append({ - "id": "rzga5b9cd7efgh04iljk", - "rev": "8fkj28fjhqkjdhkjkj9s", - "previous": "0021jdfjhqkjdhkjkj9s", - "state": "normal", - "redirect_id": None, - "edit_id": "932582iuhckjvssk", - "extra_json": None, - - "title": "Mocks are great", - "contributors": [], - "work_type": "journal-article", - "date": None, - - "primary_release": release_list(["8fkj28fjhqkjdhkjkj9s"])[0], - }) - return l - -def work_hydrate(work_id): - """This is the heavy/slowversion: everything from get_works(), but also - recursively transcludes single-linked entities""" - # XXX: - return work_list([work_id])[0] - -## API Methods ############################################################## - -@app.route('/health', methods=['GET']) -def health(): - return jsonify({'ok': True}) - - -@app.route('/v0/work/', methods=['GET']) -def work_get(work_id): - if not is_fcid(work_id): - print("not fcid: {}".format(work_id)) - return abort(404) - work = work_hydrate(work_id) - return jsonify(work) - -## Entry Point ############################################################## - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--debug', - action='store_true', - help="enable debugging interface") - parser.add_argument('--host', - default="127.0.0.1", - help="listen on this host/IP") - parser.add_argument('--port', - type=int, - default=8040, - help="listen on this port") - parser.add_argument('--database-uri', - default=app.config['DATABASE_URI'], - help="sqlalchemy database string") - args = parser.parse_args() - - app.config['DATABASE_URI'] = args.database_uri - app.conn = create_engine(app.config['DATABASE_URI'], convert_unicode=True) - metadata.create_all(bind=engine) - - # XXX: - db_test_data() - - app.run(debug=args.debug, host=args.host, port=args.port) - - -if __name__ == '__main__': - main() diff --git a/fatcat/backend.py b/fatcat/backend.py new file mode 100755 index 00000000..a39ae790 --- /dev/null +++ b/fatcat/backend.py @@ -0,0 +1,301 @@ + +import argparse +from flask import Flask, render_template, send_from_directory, request, \ + url_for, abort, g, redirect, jsonify +from sqlalchemy import create_engine, MetaData, Table + +app = Flask(__name__) +app.config.from_object(__name__) + +# Load default config and override config from an environment variable +app.config.update(dict( + DATABASE_URI='sqlite://:memory:', + SECRET_KEY='development-key', + USERNAME='admin', + PASSWORD='admin' +)) +app.config.from_envvar('FATCAT_BACKEND_CONFIG', silent=True) + +metadata = MetaData() + + +## SQL Schema ############################################################### + +import enum +from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey, \ + Enum + +# TODO: http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative/mixins.html + +class IdState(enum.Enum): + normal = 1 + redirect = 2 + removed = 3 + +work_id = Table('work_id', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('revision', ForeignKey('work_revision.id')), + ) + +work_revision = Table('work_revision', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('previous', ForeignKey('work_revision.id'), nullable=True), + Column('state', Enum(IdState)), + Column('redirect_id', ForeignKey('work_id.id'), nullable=True), + Column('edit_id', ForeignKey('edit.id')), + Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), + + Column('title', String), + Column('work_type', String), + Column('date', String), + ) + +release_id = Table('release_id', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('revision', ForeignKey('release_revision.id')), + ) + +release_revision = Table('release_revision', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('previous', ForeignKey('release_revision.id'), nullable=True), + Column('state', Enum(IdState)), + Column('redirect_id', ForeignKey('release_id.id'), nullable=True), + Column('edit_id', ForeignKey('edit.id')), + Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), + + #Column('work', ForeignKey('work_id.id')), + Column('container', ForeignKey('container_id.id')), + Column('title', String), + Column('license', String), # TODO: oa status foreign key + Column('release_type', String), # TODO: foreign key + Column('date', String), # TODO: datetime + Column('doi', String), # TODO: identifier table + ) + +creator_id = Table('creator_id', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('revision', ForeignKey('creator_revision.id')), + ) + +creator_revision = Table('creator_revision', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('previous', ForeignKey('creator_revision.id'), nullable=True), + Column('state', Enum(IdState)), + Column('redirect_id', ForeignKey('creator_id.id'), nullable=True), + Column('edit_id', ForeignKey('edit.id')), + Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), + + Column('name', String), + Column('sortname', String), + Column('orcid', String), # TODO: identifier table + ) + +work_contrib = Table('work_contrib', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('work_rev', ForeignKey('work_revision.id'), nullable=False), + Column('creator_id', ForeignKey('creator_id.id'), nullable=False), + Column('stub', String, nullable=False), + ) + +release_contrib = Table('release_contrib', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('release_rev', ForeignKey('release_revision.id'), nullable=False), + Column('creator_id', ForeignKey('creator_id.id'), nullable=False), + ) + +container_id = Table('container_id', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('revision', ForeignKey('container_revision.id')), + ) + +container_revision = Table('container_revision', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('previous', ForeignKey('container_revision.id'), nullable=True), + Column('state', Enum(IdState)), + Column('redirect_id', ForeignKey('container_id.id'), nullable=True), + Column('edit_id', ForeignKey('edit.id')), + Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), + + Column('name', String), + Column('container', ForeignKey('container_id.id')), + Column('publisher', String), # TODO: foreign key + Column('sortname', String), + Column('issn', String), # TODO: identifier table + ) + +file_id = Table('file_id', metadata, + Column('id', Integer, primary_key=True, autoincrement=False), + Column('revision', ForeignKey('container_revision.id')), + ) + +file_revision = Table('file_revision', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('previous', ForeignKey('file_revision.id'), nullable=True), + Column('state', Enum(IdState)), + Column('redirect_id', ForeignKey('file_id.id'), nullable=True), + Column('edit_id', ForeignKey('edit.id')), + Column('extra_json', ForeignKey('extra_json.sha1'), nullable=True), + + Column('size', Integer), + Column('sha1', Integer), # TODO: hash table... only or in addition? + Column('url', Integer), # TODO: URL table + ) + +release_file= Table('release_file', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('release_rev', ForeignKey('release_revision.id'), nullable=False), + Column('file_id', ForeignKey('file_id.id'), nullable=False), + ) + +edit = Table('edit', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('edit_group', ForeignKey('edit_group.id')), + Column('editor', ForeignKey('editor.id')), + Column('description', String), + ) + +edit_group = Table('edit_group', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('editor', ForeignKey('editor.id')), + Column('description', String), + ) + +editor = Table('editor', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('username', String), + ) + +changelog = Table('changelog', metadata, + Column('id', Integer, primary_key=True, autoincrement=True), + Column('edit_id', ForeignKey('edit.id')), + Column('timestamp', Integer), + ) + +extra_json = Table('extra_json', metadata, + Column('sha1', String, primary_key=True, autoincrement=True), + Column('json', String), + ) + +## Helpers ################################################################## + +def is_fcid(s): + return len(s) == 26 and s.isalnum() + +# XXX: why isn't this running? +def test_is_fcid(): + + for s in ("rzga5b9cd7efgh04iljk", "RZGA5B9CD7Efgh04iljk"): + assert is_fcid() is True + + for s in ("rzga59cd7efgh04iljk", "rzga.b9cd7efgh04iljk", "", + "rzga5b9cd7efgh04iljkz"): + assert is_fcid() is False + +def release_list(id_list): + # XXX: MOCK + l = [] + for i in id_list: + l.append({ + "id": i, + "rev": "8fkj28fjhqkjdhkjkj9s", + "previous": "0021jdfjhqkjdhkjkj9s", + "state": "normal", + "redirect_id": None, + "edit_id": "932582iuhckjvssk", + "extra_json": None, + + "container_id": "0021jdfjhqkjdhkjkj9s", + "title": "Mocks are great", + "license": "CC-0", + "release_type": "publication", + "date": "2017-11-22", + "doi": "10.1000/953kj.sdfkj", + }) + return l + +def release_hydrate(release_id): + e = release_list([release_id])[0] + e['container'] = container_hydrate(d['container_id']) + e.pop('container_id') + e['creators'] = [creator_hydrate(c['id']) for c in e['creator_ids']] + return e + +def work_list(id_list): + """This is the fast/light version: populates entity-specific lists (eg, + identifiers), and any primaries, but doesn't transclude all other + entities""" + if len(id_list) == 0: + return [] + + l = [] + for i in id_list: + l.append({ + "id": "rzga5b9cd7efgh04iljk", + "rev": "8fkj28fjhqkjdhkjkj9s", + "previous": "0021jdfjhqkjdhkjkj9s", + "state": "normal", + "redirect_id": None, + "edit_id": "932582iuhckjvssk", + "extra_json": None, + + "title": "Mocks are great", + "contributors": [], + "work_type": "journal-article", + "date": None, + + "primary_release": release_list(["8fkj28fjhqkjdhkjkj9s"])[0], + }) + return l + +def work_hydrate(work_id): + """This is the heavy/slowversion: everything from get_works(), but also + recursively transcludes single-linked entities""" + # XXX: + return work_list([work_id])[0] + +## API Methods ############################################################## + +@app.route('/health', methods=['GET']) +def health(): + return jsonify({'ok': True}) + + +@app.route('/v0/work/', methods=['GET']) +def work_get(work_id): + if not is_fcid(work_id): + print("not fcid: {}".format(work_id)) + return abort(404) + work = work_hydrate(work_id) + return jsonify(work) + +## Entry Point ############################################################## + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--debug', + action='store_true', + help="enable debugging interface") + parser.add_argument('--host', + default="127.0.0.1", + help="listen on this host/IP") + parser.add_argument('--port', + type=int, + default=8040, + help="listen on this port") + parser.add_argument('--database-uri', + default=app.config['DATABASE_URI'], + help="sqlalchemy database string") + args = parser.parse_args() + + app.config['DATABASE_URI'] = args.database_uri + app.conn = create_engine(app.config['DATABASE_URI'], convert_unicode=True) + metadata.create_all(bind=engine) + + # XXX: + db_test_data() + + app.run(debug=args.debug, host=args.host, port=args.port) + + +if __name__ == '__main__': + main() diff --git a/fatcat/static/robots.txt b/fatcat/static/robots.txt new file mode 100644 index 00000000..a168f11b --- /dev/null +++ b/fatcat/static/robots.txt @@ -0,0 +1 @@ +# Hello friends! diff --git a/fatcat/templates/base.html b/fatcat/templates/base.html new file mode 100644 index 00000000..4e9dcd4b --- /dev/null +++ b/fatcat/templates/base.html @@ -0,0 +1,70 @@ + + + + + + + {% block title %}fatcat!{% endblock %} + + + + + + + + + + +
+{% block body %}Nothing to see here.{% endblock %} +
+ + + + +{% block postscript %}{% endblock %} + + + diff --git a/fatcat/templates/home.html b/fatcat/templates/home.html new file mode 100644 index 00000000..d9cc34a2 --- /dev/null +++ b/fatcat/templates/home.html @@ -0,0 +1,32 @@ +{% extends "base.html" %} +{% block body %} + +

Salutations!

+ +Just mockups for now... + + + +{% endblock %} diff --git a/fatcat/templates/work_add.html b/fatcat/templates/work_add.html new file mode 100644 index 00000000..ac8a8169 --- /dev/null +++ b/fatcat/templates/work_add.html @@ -0,0 +1,215 @@ +{% extends "base.html" %} +{% block body %} +
+

Adding a New Thing

+ +
+ +

The Basics

+ +
+ + +
+ +
+ + +
+ + + + + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+ + +
+ + +

Primary Release / Edition

+ + + + + + + + + + + + + +

Anything Else?

+ + + + +
Create Work
+
+ +
+{% endblock %} + +{% block postscript %} + +{% endblock %} diff --git a/fatcat/templates/work_view.html b/fatcat/templates/work_view.html new file mode 100644 index 00000000..8c5e955d --- /dev/null +++ b/fatcat/templates/work_view.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% block body %} + +

{{ work.title }}

+ +

Work type: {{ work.type }} +

History +

Contributors: +{% for c in work.contributors %} {{ c.name }}; {% endfor %} + +{% if primary %} +

Primary Release/Edition

+

Title: {{ primary.title }} +

Date: {{ primary.date }} + +{% if primary.container %} +

Container: {{ primary.container.title }} +{% endif %} + +{% if primary.doi %} +

DOI: {{ primary.doi }} +{% endif %} + +{% else %} +

No primary release +{% endif %} + +{% if releases %} +

    +{% for r in releases %} +
      {{ r.title }} ({{ y.date }} - {{ y.release_type }}) +{% endfor %} +
    +{% else %} +{% endif %} + +{% endblock %} diff --git a/fatcat/test_backend.py b/fatcat/test_backend.py new file mode 100644 index 00000000..429b5ae7 --- /dev/null +++ b/fatcat/test_backend.py @@ -0,0 +1,53 @@ + +import os +import json +import backend +import unittest +import tempfile +from nose.tools import * + +# TODO: replace all these "assert" with unit test version (which displays left +# and right on failure) + +# TODO: http://alextechrants.blogspot.com/2013/08/unit-testing-sqlalchemy-apps.html + +## Helpers ################################################################## + +def check_entity_fields(e): + for key in ('id', 'rev', 'previous', 'state', 'redirect_id', 'edit_id', + 'extra_json'): + assert_in(key, e) + for key in ('id', 'rev'): + assert_is_not_none(e[key]) + +## API Tests ################################################################ + +class BackendTestCase(unittest.TestCase): + + def setUp(self): + backend.app.config['DATABASE_URI'] = 'sqlite://:memory:' + backend.app.testing = True + self.app = backend.app.test_client() + + def test_health(self): + rv = self.app.get('/health') + obj = json.loads(rv.data.decode('utf-8')) + assert obj['ok'] + + def test_works(self): + + # Invalid Id + rv = self.app.get('/v0/work/_') + assert rv.status_code == 404 + + # Missing Id (TODO) + #rv = self.app.get('/v0/work/rzga5b9cd7efgh04iljk') + #assert rv.status is 404 + + # Valid Id + rv = self.app.get('/v0/work/r3zga5b9cd7ef8gh084714iljk') + assert rv.status_code == 200 + obj = json.loads(rv.data.decode('utf-8')) + check_entity_fields(obj) + assert obj['title'] + assert_equal(obj['work_type'], "journal-article") diff --git a/fatcat/webface.py b/fatcat/webface.py new file mode 100755 index 00000000..33833e25 --- /dev/null +++ b/fatcat/webface.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +import os +import argparse +import requests +from flask import Flask, render_template, send_from_directory, request, \ + url_for, abort, g, redirect, jsonify + +app = Flask(__name__) +app.config.from_object(__name__) + + +### Views ################################################################### + +@app.route('/health', methods=['GET']) +def health(): + return jsonify({'ok': True}) + +@app.route('/work/create', methods=['GET']) +def work_create(): + return render_template('work_add.html') + +@app.route('/work/random', methods=['GET']) +def work_random(): + work = { + "title": "Structure and Interpretation", + "work_type": "book", + "date": None, + "contributors": [ + {"name": "Alyssa P. Hacker"}, + ], + "primary": { + "title": "Structure and Interpretation", + "release_type": "online", + "date": "2000-01-01", + "doi": "10.491/599.sdo14", + }, + "releases": [ + ] + } + return render_template('work_view.html', work=work, primary=work['primary']) + +@app.route('/work//random', methods=['GET']) +def work_view(work_id): + return render_template('work_view.html') + + +### Static Routes ########################################################### + +@app.route('/', methods=['GET']) +def homepage(): + return render_template('home.html') + +@app.route('/about', methods=['GET']) +def aboutpage(): + return render_template('about.html') + +@app.route('/robots.txt', methods=['GET']) +def robots(): + return send_from_directory(os.path.join(app.root_path, 'static'), + 'robots.txt', + mimetype='text/plain') + + +### Entry Point ############################################################# + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--debug', + action='store_true', + help="enable debugging interface") + parser.add_argument('--host', + default="127.0.0.1", + help="listen on this host/IP") + parser.add_argument('--port', + type=int, + default=5050, + help="listen on this port") + parser.add_argument('--backend-api', + default="localhost:6060", + help="backend API to connect to") + args = parser.parse_args() + + app.run(debug=args.debug, host=args.host, port=args.port) + +if __name__ == '__main__': + main() diff --git a/webface/static/robots.txt b/webface/static/robots.txt deleted file mode 100644 index a168f11b..00000000 --- a/webface/static/robots.txt +++ /dev/null @@ -1 +0,0 @@ -# Hello friends! diff --git a/webface/templates/base.html b/webface/templates/base.html deleted file mode 100644 index 4e9dcd4b..00000000 --- a/webface/templates/base.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - {% block title %}fatcat!{% endblock %} - - - - - - - - - - -
    -{% block body %}Nothing to see here.{% endblock %} -
    - - - - -{% block postscript %}{% endblock %} - - - diff --git a/webface/templates/home.html b/webface/templates/home.html deleted file mode 100644 index d9cc34a2..00000000 --- a/webface/templates/home.html +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "base.html" %} -{% block body %} - -

    Salutations!

    - -Just mockups for now... - - - -{% endblock %} diff --git a/webface/templates/work_add.html b/webface/templates/work_add.html deleted file mode 100644 index ac8a8169..00000000 --- a/webface/templates/work_add.html +++ /dev/null @@ -1,215 +0,0 @@ -{% extends "base.html" %} -{% block body %} -
    -

    Adding a New Thing

    - -
    - -

    The Basics

    - -
    - - -
    - -
    - - -
    - - - - - -
    - -
    - - -
    -
    - - -
    - - -
    - - -
    - - -
    - - -

    Primary Release / Edition

    - - - - - - - - - - - - - -

    Anything Else?

    - - - - -
    Create Work
    -
    - -
    -{% endblock %} - -{% block postscript %} - -{% endblock %} diff --git a/webface/templates/work_view.html b/webface/templates/work_view.html deleted file mode 100644 index 8c5e955d..00000000 --- a/webface/templates/work_view.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "base.html" %} -{% block body %} - -

    {{ work.title }}

    - -

    Work type: {{ work.type }} -

    History -

    Contributors: -{% for c in work.contributors %} {{ c.name }}; {% endfor %} - -{% if primary %} -

    Primary Release/Edition

    -

    Title: {{ primary.title }} -

    Date: {{ primary.date }} - -{% if primary.container %} -

    Container: {{ primary.container.title }} -{% endif %} - -{% if primary.doi %} -

    DOI: {{ primary.doi }} -{% endif %} - -{% else %} -

    No primary release -{% endif %} - -{% if releases %} -

      -{% for r in releases %} -
        {{ r.title }} ({{ y.date }} - {{ y.release_type }}) -{% endfor %} -
      -{% else %} -{% endif %} - -{% endblock %} diff --git a/webface/webface.py b/webface/webface.py deleted file mode 100755 index 33833e25..00000000 --- a/webface/webface.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python3 - -import os -import argparse -import requests -from flask import Flask, render_template, send_from_directory, request, \ - url_for, abort, g, redirect, jsonify - -app = Flask(__name__) -app.config.from_object(__name__) - - -### Views ################################################################### - -@app.route('/health', methods=['GET']) -def health(): - return jsonify({'ok': True}) - -@app.route('/work/create', methods=['GET']) -def work_create(): - return render_template('work_add.html') - -@app.route('/work/random', methods=['GET']) -def work_random(): - work = { - "title": "Structure and Interpretation", - "work_type": "book", - "date": None, - "contributors": [ - {"name": "Alyssa P. Hacker"}, - ], - "primary": { - "title": "Structure and Interpretation", - "release_type": "online", - "date": "2000-01-01", - "doi": "10.491/599.sdo14", - }, - "releases": [ - ] - } - return render_template('work_view.html', work=work, primary=work['primary']) - -@app.route('/work//random', methods=['GET']) -def work_view(work_id): - return render_template('work_view.html') - - -### Static Routes ########################################################### - -@app.route('/', methods=['GET']) -def homepage(): - return render_template('home.html') - -@app.route('/about', methods=['GET']) -def aboutpage(): - return render_template('about.html') - -@app.route('/robots.txt', methods=['GET']) -def robots(): - return send_from_directory(os.path.join(app.root_path, 'static'), - 'robots.txt', - mimetype='text/plain') - - -### Entry Point ############################################################# - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--debug', - action='store_true', - help="enable debugging interface") - parser.add_argument('--host', - default="127.0.0.1", - help="listen on this host/IP") - parser.add_argument('--port', - type=int, - default=5050, - help="listen on this port") - parser.add_argument('--backend-api', - default="localhost:6060", - help="backend API to connect to") - args = parser.parse_args() - - app.run(debug=args.debug, host=args.host, port=args.port) - -if __name__ == '__main__': - main() -- cgit v1.2.3