diff --git a/swh/web/ui/controller.py b/swh/web/ui/controller.py index baeb07884..9b66a0abd 100644 --- a/swh/web/ui/controller.py +++ b/swh/web/ui/controller.py @@ -1,339 +1,335 @@ # Copyright (C) 2015 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -import logging import json -from flask import redirect, render_template, url_for, jsonify, request +from flask import render_template, jsonify, request from flask import make_response from swh.core.hashutil import ALGORITHMS from swh.web.ui.main import app from swh.web.ui import service from swh.web.ui.decorators import jsonp hash_filter_keys = ALGORITHMS @app.route('/') def main(): - """Main application view. - At the moment, redirect to the content search view. - """ - return redirect(url_for('info')) + """Home page + """ + # return redirect(url_for('about')) + return render_template('home.html') -@app.route('/info') -def info(): - """A simple api to define what the server is all about. - """ - logging.info('Dev SWH UI') - return 'Dev SWH UI' +@app.route('/about') +def about(): + return render_template('about.html') @app.route('/search') def search(): """Search for hashes in swh-storage. """ q = request.args.get('q', '') env = {'q': q, 'message': '', 'found': None} try: if q: env['found'] = service.lookup_hash(q) except ValueError: env['message'] = 'Error: invalid query string' return render_template('search.html', **env) @app.route('/browse/revision/') def revision(sha1_git): """Show commit information. Args: sha1_git: the revision's sha1 Returns: Revision information """ return render_template('revision.html', sha1_git=sha1_git) @app.route('/browse/directory/') def directory(sha1_git): """Show directory information. Args: sha1_git: the directory's sha1 Returns: Directory information """ return render_template('directory.html', sha1_git=sha1_git) @app.route('/browse/directory//') def directory_at_path(sha1_git, p): """Show directory information for the sha1_git at path. Args: sha1_git: the directory's sha1 path: file or directory pointed to Returns: Directory information at sha1_git + path """ return render_template('directory.html', sha1_git=sha1_git, path=p) def _origin_seen(hash, data): """Given an origin, compute a message string with the right information. Args: origin: a dictionary with keys: - origin: a dictionary with type and url keys - occurrence: a dictionary with a validity range Returns: message as a string """ if data is None: return 'Content with hash %s is unknown as of now.' % hash origin_type = data['origin_type'] origin_url = data['origin_url'] revision = data['revision'] branch = data['branch'] path = data['path'] return """The content with hash %s has been seen on origin with type '%s' at url '%s'. The revision was identified at '%s' on branch '%s'. The file's path referenced was '%s'.""" % (hash, origin_type, origin_url, revision, branch, path) @app.route('/browse/content/:') def content(hash, sha): """Show content information. Args: hash: hash according to HASH_ALGO, where HASH_ALGO is one of: sha1, sha1_git, sha256. This means that several different URLs (at least one per HASH_ALGO) will point to the same content sha: the sha with 'hash' format Returns: The content's information at sha1_git """ if hash not in hash_filter_keys: message = 'The checksum must be one of sha1, sha1_git, sha256' else: q = "%s:%s" % (hash, sha) found = service.lookup_hash(q) if not found: message = "Hash %s was not found." % hash else: origin = service.lookup_hash_origin(q) message = _origin_seen(hash, origin) return render_template('content.html', hash=hash, sha=sha, message=message) @app.route('/browse/release/') def release(sha1_git): """Show release's information. Args: sha1_git: sha1_git for this particular release Returns: Release's information """ return 'Release information at %s' % sha1_git @app.route('/browse/person/') def person(id): """Show Person's information at id. Args: id: person's unique identifier Returns: Person's information """ return 'Person information at %s' % id @app.route('/browse/origin/') def origin(id): """Show origin's information at id. Args: id: origin's unique identifier Returns: Origin's information """ return 'Origin information at %s' % id @app.route('/browse/project/') def project(id): """Show project's information at id. Args: id: project's unique identifier Returns: Project's information """ return 'Project information at %s' % id @app.route('/browse/organization/') def organization(id): """Show organization's information at id. Args: id: organization's unique identifier Returns: Organization's information """ return 'Organization information at %s' % id @app.route('/browse/directory//' '+|/' '|/') def directory_at_origin(timestamp, origin_type, origin_url, branch, path): """Show directory information at timestamp, origin-type, origin-url, branch and path. Those parameters are separated by the `|` terminator. Args: timestamp: the timestamp to look for. can be latest or some iso8601 date format. (TODO: decide the time matching policy.) origin_type: origin's type origin_url: origin's url (can contain `/`) branch: branch name which can contain `/` path: path to directory or file Returns: Directory information at the given parameters. """ return 'Directory at (%s, %s, %s, %s, %s)' % (timestamp, origin_type, origin_url, branch, path) @app.route('/browse/revision//' '+|/') def revision_at_origin_and_branch(timestamp, origin_type, origin_url, branch): """Show revision information at timestamp, origin, and branch. Those parameters are separated by the `|` terminator. Args: timestamp: the timestamp to look for. can be latest or some iso8601 date format. (TODO: decide the time matching policy.) origin_type: origin's type origin_url: origin's url (can contain `/`) branch: branch name which can contain / Returns: Revision information at the given parameters. """ return 'Revision at (ts=%s, type=%s, url=%s, branch=%s)' % (timestamp, origin_type, origin_url, branch) @app.route('/browse/revision//' '+|') def revision_at_origin(timestamp, origin_type, origin_url): """Show revision information at timestamp, origin, and branch. Those parameters are separated by the `|` terminator. Args: timestamp: the timestamp to look for. can be latest or iso8601 date format. (TODO: decide the time matching policy.) origin_type: origin's type origin_url: origin's url (can contain `/`) Returns: Revision information at the given parameters. """ return 'Revision at (timestamp=%s, type=%s, url=%s)' % (timestamp, origin_type, origin_url) @app.route('/api/1/stat/counters') @jsonp def api_stats(): """Return statistics as a JSON object""" return jsonify(service.stat_counters()) @app.errorhandler(ValueError) def value_error_as_bad_request(error): """Compute a bad request and add body as payload. """ response = make_response( 'Bad request', 400) response.headers['Content-Type'] = 'application/json' response.data = json.dumps({"error": str(error)}) return response @app.route('/api/1/search//') @jsonp def api_search(q): """Return search results as a JSON object""" return jsonify({'found': service.lookup_hash(q)}) @app.route('/api/1/browse//') @jsonp def api_browse(q): """Return search results as a JSON object""" return jsonify({'origin': service.lookup_hash_origin(q)}) diff --git a/swh/web/ui/templates/about.html b/swh/web/ui/templates/about.html new file mode 100644 index 000000000..d3f9ab9c0 --- /dev/null +++ b/swh/web/ui/templates/about.html @@ -0,0 +1,8 @@ +{% extends "layout.html" %} +{% block title %}About{% endblock %} +{% block content %} +

+ This is the Software Heritage Web + interface.
It is heavily under development, stay tuned for more! +

+{% endblock %} diff --git a/swh/web/ui/templates/directory.html b/swh/web/ui/templates/directory.html index 47f75335e..04deefe16 100644 --- a/swh/web/ui/templates/directory.html +++ b/swh/web/ui/templates/directory.html @@ -1,9 +1,8 @@ {% extends "layout.html" %} -{% block body %} - +{% block title %}Home{% endblock %} +{% block content %} Directory {{ sha1_git }} - {% if path %} with path {{ path }} {% endif %} {% endblock %} diff --git a/swh/web/ui/templates/home.html b/swh/web/ui/templates/home.html new file mode 100644 index 000000000..2e462bc62 --- /dev/null +++ b/swh/web/ui/templates/home.html @@ -0,0 +1,8 @@ +{% extends "layout.html" %} +{% block title %}Home{% endblock %} +{% block content %} + +{% endblock %} diff --git a/swh/web/ui/templates/layout.html b/swh/web/ui/templates/layout.html index a3a721883..32aedba99 100644 --- a/swh/web/ui/templates/layout.html +++ b/swh/web/ui/templates/layout.html @@ -1,29 +1,32 @@ - Software Heritage Archive + {% block title %}{% endblock %} - The Software Heritage Archive -
-
+
+

{{ self.title() }}

+
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %} - {% block body %}{% endblock %} +
+
+ {% block content %}{% endblock %}
diff --git a/swh/web/ui/templates/revision.html b/swh/web/ui/templates/revision.html index ba9cdd67c..8e08a7573 100644 --- a/swh/web/ui/templates/revision.html +++ b/swh/web/ui/templates/revision.html @@ -1,4 +1,5 @@ {% extends "layout.html" %} -{% block body %} +{% block title %}Revision{% endblock %} +{% block content %} Revision {{ sha1_git }} {% endblock %} diff --git a/swh/web/ui/templates/search.html b/swh/web/ui/templates/search.html index f816e8209..3ad0711b0 100644 --- a/swh/web/ui/templates/search.html +++ b/swh/web/ui/templates/search.html @@ -1,16 +1,17 @@ {% extends "layout.html" %} -{% block body %} +{% block title %}Search{% endblock %} +{% block content %}
{% if message is not none %}
{{ message | safe }}
{% endif %} {% if found is not none %}
Found: {{ found | safe }}
{% endif %} {% endblock %}