aboutsummaryrefslogtreecommitdiff
path: root/src_py/hatter/ui.py
diff options
context:
space:
mode:
authorbozo.kopic <bozo@kopic.xyz>2022-03-25 21:18:41 +0100
committerbozo.kopic <bozo@kopic.xyz>2022-03-25 21:18:41 +0100
commit17af1ae6ca22d3bf76d09705cb3f29b17dbfdab7 (patch)
tree34ace40ec3a433592f5b2157cb231217c8821043 /src_py/hatter/ui.py
parent130055c70ad2b062adf2c4df13dd2ed5ce062f97 (diff)
WIP server
Diffstat (limited to 'src_py/hatter/ui.py')
-rw-r--r--src_py/hatter/ui.py159
1 files changed, 140 insertions, 19 deletions
diff --git a/src_py/hatter/ui.py b/src_py/hatter/ui.py
index 525df6b..9368d63 100644
--- a/src_py/hatter/ui.py
+++ b/src_py/hatter/ui.py
@@ -1,4 +1,5 @@
from pathlib import Path
+import datetime
from hat import aio
import aiohttp.web
@@ -19,18 +20,18 @@ async def create(host: str,
ui._async_group = aio.Group()
app = aiohttp.web.Application()
- app.add_routes([
- aiohttp.web.get('/', ui._get_root_handler),
- aiohttp.web.get('/repo/{repo}', server._get_repo_handler),
- aiohttp.web.get('/repo/{repo}/commit/{commit}',
- server._get_commit_handler),
- aiohttp.web.post('/repo/{repo}/webhook',
- server._post_webhook_handler),
- aiohttp.web.post('/repo/{repo}/commit/{commit}/run',
- server._post_run_handler),
- aiohttp.web.post('/repo/{repo}/commit/{commit}/remove',
- server._post_remove_handler),
- aiohttp.web.static('/', static_dir)])
+ get_routes = (
+ aiohttp.web.get(path, handler) for path, handler in (
+ ('/', ui._get_root_handler),
+ ('/main.css', ui._get_style_handler),
+ ('/repo/{repo}', ui._get_repo_handler),
+ ('/repo/{repo}/commit/{commit}', ui._get_commit_handler)))
+ post_routes = (
+ aiohttp.web.post(path, handler) for path, handler in (
+ ('/repo/{repo}/webhook', ui._post_webhook_handler),
+ ('/repo/{repo}/commit/{commit}/rerun', ui._post_rerun_handler),
+ ('/repo/{repo}/commit/{commit}/remove', ui._post_remove_handler)))
+ app.add_routes([*get_routes, *post_routes])
runner = aiohttp.web.AppRunner(app)
await runner.setup()
@@ -58,19 +59,139 @@ class UI(aio.Resource):
return self._async_group
async def _get_root_handler(self, request):
- pass
+ repos = self._server.get_repos()
+ commits = await self._server.get_commits(None)
+ body = (f'{_generate_repos(repos)}\n'
+ f'{_generate_commits(commits)}')
+ return _create_html_response('hatter', body)
+
+ async def _get_style_handler(self, request):
+ return aiohttp.web.Response(content_type='text/css',
+ text=_main_css)
async def _get_repo_handler(self, request):
- pass
+ repo = request.match_info['repo']
+ commits = await self._server.get_commits(repo)
+ body = _generate_commits(commits)
+ return _create_html_response(f'hatter - {repo}', body)
async def _get_commit_handler(self, request):
- pass
+ repo = request.match_info['repo']
+ commit_hash = request.match_info['commit']
+ commit = await self._server.get_commit(repo, commit_hash)
+ body = _generate_commit(commit)
+ return _create_html_response(f'hatter - {repo}/{commit_hash}', body)
async def _post_webhook_handler(self, request):
- pass
+ repo = request.match_info['repo']
+ self._server.sync_repo(repo)
+ return aiohttp.web.Response()
- async def _post_run_handler(self, request):
- pass
+ async def _post_rerun_handler(self, request):
+ repo = request.match_info['repo']
+ commit_hash = request.match_info['commit']
+ await self._server.rerun_commit(repo, commit_hash)
+ raise aiohttp.web.HTTPFound(f'/repo/{repo}/commit/{commit_hash}')
async def _post_remove_handler(self, request):
- pass
+ repo = request.match_info['repo']
+ commit_hash = request.match_info['commit']
+ await self._server.remove_commit(repo, commit_hash)
+ raise aiohttp.web.HTTPFound(f'/repo/{repo}')
+
+
+def _create_html_response(title, body):
+ text = _html_template.format(title=title,
+ body=body)
+ return aiohttp.web.Response(content_type='text/html',
+ text=text)
+
+
+def _generate_repos(repos):
+ items = '\n'.join(f'<li><a href="/repo/{repo}">{repo}</a></li>'
+ for repo in repos)
+ return (f'<div class="repos">\n'
+ f'<ul>\n'
+ f'{items}\n'
+ f'</ul>\n'
+ f'</div>')
+
+
+def _generate_commits(commits):
+ thead = ('<tr>\n'
+ '<th class="col-change">Change</th>\n'
+ '<th class="col-repo">Repo</th>\n'
+ '<th class="col-hash">Commit</th>\n'
+ '<th class="col-status">Status</th>\n'
+ '</tr>')
+
+ tbody = '\n'.join(
+ (f'<tr>\n'
+ f'<td class="col-change">{_format_time(commit.change)}</td>\n'
+ f'<td class="col-repo"><a href="/repo/{commit.repo}">{commit.repo}</a></td>\n' # NOQA
+ f'<td class="col-hash"><a href="/repo/{commit.repo}/commit/{commit.hash}">{commit.hash}</a></td>\n' # NOQA
+ f'<td class="col-status">{commit.status.name}</td>\n'
+ f'</tr>')
+ for commit in commits)
+
+ return (f'<div class="commits">\n'
+ f'<table>\n'
+ f'<thead>\n'
+ f'{thead}\n'
+ f'</thead>\n'
+ f'<tbody>\n'
+ f'{tbody}\n'
+ f'</tbody>\n'
+ f'</table>\n'
+ f'</div>')
+
+
+def _generate_commit(commit):
+ buttons = '\n'.join(
+ (f'<form method="post" action="{action}">\n'
+ f'<input type="submit" value="{value}">\n'
+ f'</form>')
+ for value, action in (
+ ('Rerun', f'/repo/{commit.repo}/commit/{commit.hash}/rerun'),
+ ('Remove', f'/repo/{commit.repo}/commit/{commit.hash}/remove')))
+
+ return (f'<div class="commit">\n'
+ f'<label>Repo:</label><div><a href="/repo/{commit.repo}">{commit.repo}</a></div>\n' # NOQA
+ f'<label>Commit:</label><div>{commit.hash}</div>\n'
+ f'<label>Change:</label><div>{_format_time(commit.change)}</div>\n'
+ f'<label>Status:</label><div>{commit.status.name}</div>\n'
+ f'<label>Output:</label><pre>{commit.output}</pre>\n'
+ f'<label></label><div>{buttons}</div>\n'
+ f'</div>')
+
+
+def _format_time(t):
+ return datetime.datetime.fromtimestamp(t).strftime("%Y-%m-%d %H:%M:%S")
+
+
+_html_template = r"""<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>{title}</title>
+<link href="/main.css" rel="stylesheet">
+</head>
+<body>
+{body}
+</body>
+</html>
+"""
+
+_main_css = r"""
+.repos {
+
+}
+
+.commits {
+
+}
+
+.commit {
+
+}
+"""