diff options
| author | bozo.kopic <bozo@kopic.xyz> | 2022-03-25 21:18:41 +0100 |
|---|---|---|
| committer | bozo.kopic <bozo@kopic.xyz> | 2022-03-25 21:18:41 +0100 |
| commit | 17af1ae6ca22d3bf76d09705cb3f29b17dbfdab7 (patch) | |
| tree | 34ace40ec3a433592f5b2157cb231217c8821043 /src_py/hatter/ui.py | |
| parent | 130055c70ad2b062adf2c4df13dd2ed5ce062f97 (diff) | |
WIP server
Diffstat (limited to 'src_py/hatter/ui.py')
| -rw-r--r-- | src_py/hatter/ui.py | 159 |
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 { + +} +""" |
