Basic Table
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 1m44s
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 1m44s
This commit is contained in:
parent
e376956def
commit
a4d0803d20
@ -17,6 +17,14 @@ server {
|
|||||||
root /ums-agenten/plattform/web/public/;
|
root /ums-agenten/plattform/web/public/;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
|
location = / {
|
||||||
|
server_name_in_redirect off;
|
||||||
|
port_in_redirect off;
|
||||||
|
absolute_redirect off;
|
||||||
|
|
||||||
|
return 303 /index;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ @dynamic;
|
try_files $uri $uri/ @dynamic;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ class DB():
|
|||||||
|
|
||||||
with self.db:
|
with self.db:
|
||||||
for row in self.db.execute(
|
for row in self.db.execute(
|
||||||
"SELECT * FROM Messages {} LIMIT :lim OFFSET :off".format(where_clause),
|
"SELECT * FROM Messages {} ORDER BY time DESC LIMIT :lim OFFSET :off".format(where_clause),
|
||||||
params
|
params
|
||||||
):
|
):
|
||||||
yield self._create_row_object(row)
|
yield self._create_row_object(row)
|
||||||
@ -165,7 +165,7 @@ class DB():
|
|||||||
sender=row['sender'],
|
sender=row['sender'],
|
||||||
recipient=row['recipient'],
|
recipient=row['recipient'],
|
||||||
time=int(datetime.strptime(row['time'], self._DB_TIME_FORMAT).timestamp()),
|
time=int(datetime.strptime(row['time'], self._DB_TIME_FORMAT).timestamp()),
|
||||||
message=AgentMessage.model_construct(row['json']),
|
message=AgentMessage.model_validate_json(row['json']),
|
||||||
processed=row['processed']
|
processed=row['processed']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -8,28 +8,57 @@
|
|||||||
# source code released under the terms of GNU Public License Version 3
|
# source code released under the terms of GNU Public License Version 3
|
||||||
# https://www.gnu.org/licenses/gpl-3.0.txt
|
# https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
|
||||||
|
from urllib.parse import urlencode
|
||||||
|
|
||||||
from fastapi import APIRouter, Request
|
from fastapi import APIRouter, Request
|
||||||
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from ums.management.db import DB
|
from ums.management.db import DB
|
||||||
|
|
||||||
class Interface():
|
class Interface():
|
||||||
|
|
||||||
|
_PREFIX = "/app"
|
||||||
|
|
||||||
def __init__(self, template:Jinja2Templates, db:DB):
|
def __init__(self, template:Jinja2Templates, db:DB):
|
||||||
self.template = template
|
self.template = template
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
self.router = APIRouter(
|
self.router = APIRouter(
|
||||||
prefix="/app",
|
prefix=self._PREFIX,
|
||||||
tags=["app, gui"]
|
tags=["app, gui"]
|
||||||
)
|
)
|
||||||
|
|
||||||
self._add_routes()
|
self._add_routes()
|
||||||
|
|
||||||
def _add_routes(self):
|
def _add_routes(self):
|
||||||
@self.router.get("/", summary="Test")
|
@self.router.get("/", response_class=RedirectResponse, summary="Redirect")
|
||||||
def corpus(request: Request):
|
def index(request: Request) -> RedirectResponse:
|
||||||
|
return RedirectResponse(self._PREFIX + "/table")
|
||||||
|
|
||||||
|
@self.router.get("/table", response_class=HTMLResponse, summary="Table of messages")
|
||||||
|
def table(request: Request, limit:int=10, offset:int=0):
|
||||||
|
db_args = {
|
||||||
|
"limit" : limit,
|
||||||
|
"offset" : offset
|
||||||
|
}
|
||||||
|
|
||||||
print(self.db.by_count(3))
|
def pagination_link(**kwargs):
|
||||||
|
link_args = db_args.copy()
|
||||||
return {}
|
link_args.update(kwargs)
|
||||||
|
return urlencode(link_args)
|
||||||
|
|
||||||
|
return self.template.TemplateResponse(
|
||||||
|
'table.html',
|
||||||
|
{"request" : request,
|
||||||
|
"db" : self.db, "db_args" : db_args,
|
||||||
|
"pagination_link" : pagination_link
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@self.router.get("/new", response_class=HTMLResponse, summary="Add new riddle")
|
||||||
|
def new(request: Request):
|
||||||
|
return self.template.TemplateResponse(
|
||||||
|
'new.html',
|
||||||
|
{"request" : request}
|
||||||
|
)
|
@ -10,7 +10,10 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
|
from fastapi.responses import HTMLResponse
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
from ums.management.interface import Interface
|
from ums.management.interface import Interface
|
||||||
@ -44,13 +47,21 @@ class WebMain():
|
|||||||
directory=TEMPLATE_PATH,
|
directory=TEMPLATE_PATH,
|
||||||
auto_reload=True
|
auto_reload=True
|
||||||
)
|
)
|
||||||
|
self.template.env.globals["timestamp2date"] = lambda t: \
|
||||||
|
datetime.fromtimestamp(t).strftime("%H:%M:%S %d.%m.%Y")
|
||||||
|
|
||||||
def _add_routers(self):
|
def _add_routers(self):
|
||||||
interface_router = Interface(self.template, self.db)
|
interface_router = Interface(self.template, self.db)
|
||||||
self.app.include_router(interface_router.router)
|
self.app.include_router(interface_router.router)
|
||||||
|
|
||||||
|
|
||||||
def _add_routes(self):
|
def _add_routes(self):
|
||||||
|
|
||||||
|
@self.app.get("/index", response_class=HTMLResponse, summary="Link list")
|
||||||
|
def index(request: Request):
|
||||||
|
return self.template.TemplateResponse(
|
||||||
|
'index.html',
|
||||||
|
{"request" : request}
|
||||||
|
)
|
||||||
|
|
||||||
@self.app.get("/test", summary="Test")
|
@self.app.get("/test", summary="Test")
|
||||||
def huhu(request: Request) -> AgentMessage:
|
def huhu(request: Request) -> AgentMessage:
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>UMS-Agenten – Management</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>UMS-Agenten – Management</h1>
|
|
||||||
<ul>
|
|
||||||
<li><a href="/app/" target="_blank">Web App (small GUI)</a></li>
|
|
||||||
<li><a href="/app/new" target="_blank">Add Riddle via GUI</a></li>
|
|
||||||
<li><a href="/api/" target="_blank">API Documentations</a></li>
|
|
||||||
<li><a href="/docs/" target="_blank">Code Documentation</a></li>
|
|
||||||
</ul>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
7
web/public/static/bootstrap.bundle.min.js
vendored
Normal file
7
web/public/static/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
web/public/static/bootstrap.bundle.min.js.map
Normal file
1
web/public/static/bootstrap.bundle.min.js.map
Normal file
File diff suppressed because one or more lines are too long
6
web/public/static/bootstrap.min.css
vendored
Normal file
6
web/public/static/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
web/public/static/bootstrap.min.css.map
Normal file
1
web/public/static/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
web/public/static/jquery.min.js
vendored
Normal file
2
web/public/static/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
0
web/public/static/main.css
Normal file
0
web/public/static/main.css
Normal file
0
web/public/static/main.js
Normal file
0
web/public/static/main.js
Normal file
48
web/templates/base.html
Normal file
48
web/templates/base.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{#-
|
||||||
|
Agenten Plattform
|
||||||
|
(c) 2024 Magnus Bender
|
||||||
|
Institute of Humanities-Centered Artificial Intelligence (CHAI)
|
||||||
|
Universitaet Hamburg
|
||||||
|
https://www.chai.uni-hamburg.de/~bender
|
||||||
|
source code released under the terms of GNU Public License Version 3
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
-#}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/static/bootstrap.min.css" />
|
||||||
|
<link rel="stylesheet" href="/static/main.css" />
|
||||||
|
|
||||||
|
<script src="/static/jquery.min.js"></script>
|
||||||
|
<script src="/static/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="/static/main.js"></script>
|
||||||
|
|
||||||
|
<title>{{title}} – MGMT</title>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Agenten Plattform
|
||||||
|
|
||||||
|
(c) 2024 Magnus Bender
|
||||||
|
Institute of Humanities-Centered Artificial Intelligence (CHAI)
|
||||||
|
Universitaet Hamburg
|
||||||
|
https://www.chai.uni-hamburg.de/~bender
|
||||||
|
|
||||||
|
source code released under the terms of GNU Public License Version 3
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
-->
|
||||||
|
|
||||||
|
{% block morehead %}
|
||||||
|
{% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>{{title}} – MGMT</h1>
|
||||||
|
|
||||||
|
{% block maincontent %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
19
web/templates/index.html
Normal file
19
web/templates/index.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{#-
|
||||||
|
Agenten Plattform
|
||||||
|
(c) 2024 Magnus Bender
|
||||||
|
Institute of Humanities-Centered Artificial Intelligence (CHAI)
|
||||||
|
Universitaet Hamburg
|
||||||
|
https://www.chai.uni-hamburg.de/~bender
|
||||||
|
source code released under the terms of GNU Public License Version 3
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
-#}
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% set title = "Overview" %}
|
||||||
|
{% block maincontent %}
|
||||||
|
<ul>
|
||||||
|
<li><a href="/app/table" target="_blank">↗ Web App: Table</a></li>
|
||||||
|
<li><a href="/app/new" target="_blank">↗ Web App: New Riddle</a></li>
|
||||||
|
<li><a href="/api/" target="_blank">↗ Documentation: API </a></li>
|
||||||
|
<li><a href="/docs/" target="_blank">↗ Documentation: Code </a></li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
19
web/templates/new.html
Normal file
19
web/templates/new.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{#-
|
||||||
|
Agenten Plattform
|
||||||
|
(c) 2024 Magnus Bender
|
||||||
|
Institute of Humanities-Centered Artificial Intelligence (CHAI)
|
||||||
|
Universitaet Hamburg
|
||||||
|
https://www.chai.uni-hamburg.de/~bender
|
||||||
|
source code released under the terms of GNU Public License Version 3
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
-#}
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% set title = "New" %}
|
||||||
|
{% block maincontent %}
|
||||||
|
<div class="float-end">
|
||||||
|
<a href="/app/table" class="btn btn-secondary">← Back to Messages</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
109
web/templates/table.html
Normal file
109
web/templates/table.html
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
{#-
|
||||||
|
Agenten Plattform
|
||||||
|
(c) 2024 Magnus Bender
|
||||||
|
Institute of Humanities-Centered Artificial Intelligence (CHAI)
|
||||||
|
Universitaet Hamburg
|
||||||
|
https://www.chai.uni-hamburg.de/~bender
|
||||||
|
source code released under the terms of GNU Public License Version 3
|
||||||
|
https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
-#}
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% set title = "Messages" %}
|
||||||
|
{% macro pagination() %}
|
||||||
|
<nav>
|
||||||
|
<ul class="pagination justify-content-center">
|
||||||
|
<li class="page-item {% if db_args.offset-db_args.limit < 0 %}disabled{% endif %}">
|
||||||
|
<a class="page-link" href="?{{ pagination_link(offset=db_args.offset-db_args.limit) }}">Previous</a>
|
||||||
|
</li>
|
||||||
|
<li class="page-item active" aria-current="page">
|
||||||
|
<span class="page-link">Offset: {{db_args.offset}}</span>
|
||||||
|
</li>
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?{{ pagination_link(offset=db_args.offset+db_args.limit) }}">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{% endmacro %}
|
||||||
|
{% block maincontent %}
|
||||||
|
|
||||||
|
<div class="float-end">
|
||||||
|
<a href="/app/new" class="btn btn-secondary">→ Add a Riddle</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{pagination()}}
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
{% for item in db.iterate(**db_args) %}
|
||||||
|
{% if loop.index == 1 %}
|
||||||
|
<tr id="row_0">
|
||||||
|
{% for field in item.__fields__.keys() %}
|
||||||
|
<th>
|
||||||
|
{% if field == 'time' %}
|
||||||
|
<input type="text" class="value_filter" name="filter_time_before" value="{{db_args.time_before}}" class="form-control" placeholder="Before">
|
||||||
|
<input type="text" class="value_filter" name="filter_time_after" value="{{db_args.time_after}}" class="form-control" placeholder="After">
|
||||||
|
{% elif field not in ('message', 'count') %}
|
||||||
|
<input type="text" class="value_filter" name="filter_{{field}}" value="{{db_args[field]}}" class="form-control" placeholder="Filter">
|
||||||
|
{% endif %}
|
||||||
|
{{ field.title() }}
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead><tbody>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<tr id="row_{{loop.index}}">
|
||||||
|
{% for field in item.__fields__.keys() %}
|
||||||
|
{% if field == "message" %}
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-outline" data-bs-toggle="modal" data-bs-target="#row_message_{{loop.index}}">
|
||||||
|
Show Message
|
||||||
|
</button>
|
||||||
|
<div class="modal fade" id="row_message_{{loop.index}}" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5">Content of Message</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<pre>{{ item[field].model_dump_json(indent=2)|string }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{% elif field == "time" %}
|
||||||
|
<td ts="item[field]">{{ timestamp2date(item[field]) }}</td>
|
||||||
|
{% else %}
|
||||||
|
<td>{{ item[field] }}</td>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
No items found, reset offset, limit, filter, ...!
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="float-end">
|
||||||
|
<div class="input-group">
|
||||||
|
<label class="input-group-text" for="items-per-page">Items per page</label>
|
||||||
|
<select class="form-select" id="items-per-page" onchange="location = this.value;">
|
||||||
|
<option value="?{{ pagination_link(limit=5) }}" {% if db_args.limit == 5 %}selected{% endif %}>5</option>
|
||||||
|
<option value="?{{ pagination_link(limit=10) }}" {% if db_args.limit == 10 %}selected{% endif %}>10</option>
|
||||||
|
<option value="?{{ pagination_link(limit=25) }}" {% if db_args.limit == 25 %}selected{% endif %}>25</option>
|
||||||
|
<option value="?{{ pagination_link(limit=100) }}" {% if db_args.limit == 100 %}selected{% endif %}>100</option>
|
||||||
|
{% if db_args.limit not in (5, 10, 25, 100) %}
|
||||||
|
<option value="?{{ pagination_link(limit=db_args.limit) }}" selected>{{db_args.limit}}</option>
|
||||||
|
{% endif %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{pagination()}}
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user