Config set/unset

Also, a little refactoring.
This commit is contained in:
Régis Behmo 2024-12-20 16:09:51 +01:00
parent a3361ed71f
commit db2b205ff7
5 changed files with 54 additions and 21 deletions

View File

@ -66,22 +66,38 @@ async def toggle_plugin(name: str) -> WerkzeugResponse:
return redirect(url_for("plugin", name=name))
@app.post("/config/<name>/set")
async def config_set(name: str) -> WerkzeugResponse:
form = await request.form
value = form.get("value", "")
tutorclient.CliPool.run_sequential(["config", "save", "--set", f"{name}={value}"])
# TODO error management
return redirect(request.args.get("next", "/"))
@app.post("/config/<name>/unset")
async def config_unset(name: str) -> WerkzeugResponse:
tutorclient.CliPool.run_sequential(["config", "save", f"--unset={name}"])
# TODO error management
return redirect(request.args.get("next", "/"))
# def tutor_cli(command: list[str]) -> WerkzeugResponse:
# # Run command asynchronously
# # if TutorCli.is_thread_alive():
# # TODO return 400 if thread is active
# # TODO parse command from JSON request body
# tutorclient.CliPool.run_parallel(app, command)
# return redirect(url_for("tutor_cli_logs"))
# return redirect(url_for("cli_logs"))
@app.get("/tutor/cli/logs")
async def tutor_cli_logs() -> str:
return await render_template("tutor_cli_logs.html", **shared_template_context())
@app.get("/cli/logs")
async def cli_logs() -> str:
return await render_template("cli_logs.html", **shared_template_context())
@app.get("/tutor/cli/logs/stream")
async def tutor_cli_logs_stream() -> ResponseTypes:
@app.get("/cli/logs/stream")
async def cli_logs_stream() -> ResponseTypes:
"""
We only need single-direction communication, so we use server-sent events, and not
websockets.
@ -122,10 +138,10 @@ async def tutor_cli_logs_stream() -> ResponseTypes:
return response
@app.post("/tutor/cli/stop")
async def tutor_cli_stop() -> WerkzeugResponse:
@app.post("/cli/stop")
async def cli_stop() -> WerkzeugResponse:
tutorclient.CliPool.stop()
return redirect(url_for("tutor_cli_logs"))
return redirect(url_for("cli_logs"))
def shared_template_context() -> dict[str, t.Any]:

View File

@ -2,14 +2,22 @@
{% for key, value in config.items() %}
<div class="item">
<span>{{ key }}:</span>
{% if value is boolean %}
<input type="checkbox" name="{{ key }}" {% if value %}checked{% endif %} />
{% else %}
<input type="text" value="{{ value }}" size="50"/>
{% endif %}
<form
action="{{ url_for('config_set', name=key, next=url_for('plugin', name=plugin_name)) }}"
method="POST"
oninput="this.querySelector('button[type=submit]').disabled = false">
{% if value is boolean %}
<input type="checkbox" name="value" {% if value %}checked{% endif %} />
{% else %}
<input type="text" name="value" value="{{ value }}" size="50"/>
{% endif %}
<button type="submit" disabled>update</button>
</form>
{% if key in user_config %}
<form method="POST"><input type="button" value="unset" /></form>
<form action="{{ url_for('config_unset', name=key, next=url_for('plugin', name=plugin_name)) }}" method="POST">
<button type="submit">unset</button>
</form>
{% endif %}
</div>
{% endfor %}

View File

@ -3,7 +3,7 @@
{% block workspace_header %}Tutor command logs{% endblock %}
{% block workspace_content %}
<pre id="tutor-log" hx-ext="sse" sse-connect="{{ url_for('tutor_cli_logs_stream') }}" sse-swap="logs"></pre>
<pre id="tutor-log" hx-ext="sse" sse-connect="{{ url_for('cli_logs_stream') }}" sse-swap="logs"></pre>
{% endblock %}
{% block scripts %}

View File

@ -30,7 +30,7 @@
<div class="content">
<ul>
<li>Configuration</li>
<li><a href="{{ url_for('tutor_cli_logs') }}">Command logs</a></li>
<li><a href="{{ url_for('cli_logs') }}">Command logs</a></li>
</ul>
</div>
</div>
@ -44,7 +44,7 @@
{% for plugin in installed_plugins %}
<li><a href="{{ url_for('plugin', name=plugin) }}">{{ plugin }} {% if plugin in enabled_plugins %} ✅{% endif %}</a></li>
{% endfor %}
<form action="{{ url_for('tutor_cli_stop') }}" method="POST">
<form action="{{ url_for('cli_stop') }}" method="POST">
<button type="submit">Stop</button>
</form>
</ul>

View File

@ -299,8 +299,17 @@ class Client:
@classmethod
def plugin_config_defaults(cls, name: str) -> Config:
config = hooks.Filters.CONFIG_DEFAULTS.iterate_from_context(
hooks.Contexts.app(name).name
"""
Return the plugin default settings, with values potentially overridden in the
user configuration.
"""
config_defaults = dict(
hooks.Filters.CONFIG_DEFAULTS.iterate_from_context(
hooks.Contexts.app(name).name
)
)
user_config = Project.get_user_config()
# TODO render default config values
return dict(config)
return {
key: user_config.get(key, value) for key, value in config_defaults.items()
}