Merge remote-tracking branch 'origin/release'
This commit is contained in:
commit
de5ac9bee0
@ -0,0 +1,2 @@
|
|||||||
|
- [Feature] Only allow command cancellation from relevant page. (by @mlabeeb03)
|
||||||
|
- [Feature] Add link to developer panel while command is in progress. (by @mlabeeb03)
|
||||||
@ -9,7 +9,6 @@ from markdown import markdown
|
|||||||
from quart import (
|
from quart import (
|
||||||
Quart,
|
Quart,
|
||||||
Response,
|
Response,
|
||||||
abort,
|
|
||||||
g,
|
g,
|
||||||
jsonify,
|
jsonify,
|
||||||
make_response,
|
make_response,
|
||||||
@ -126,7 +125,6 @@ async def plugin_installed_list() -> str:
|
|||||||
@app.get("/plugin/<name>")
|
@app.get("/plugin/<name>")
|
||||||
async def plugin(name: str) -> Response:
|
async def plugin(name: str) -> Response:
|
||||||
# TODO check that plugin exists
|
# TODO check that plugin exists
|
||||||
show_logs = request.args.get("show_logs")
|
|
||||||
seq_command_executed = request.args.get("seq_command_executed")
|
seq_command_executed = request.args.get("seq_command_executed")
|
||||||
author = next(
|
author = next(
|
||||||
(
|
(
|
||||||
@ -151,7 +149,6 @@ async def plugin(name: str) -> Response:
|
|||||||
is_installed=name in g.installed_plugins,
|
is_installed=name in g.installed_plugins,
|
||||||
author_name=author,
|
author_name=author,
|
||||||
plugin_description=description,
|
plugin_description=description,
|
||||||
show_logs=show_logs,
|
|
||||||
seq_command_executed=seq_command_executed,
|
seq_command_executed=seq_command_executed,
|
||||||
plugin_config_unique=tutorclient.Client.plugin_config_unique(name),
|
plugin_config_unique=tutorclient.Client.plugin_config_unique(name),
|
||||||
plugin_config_defaults=tutorclient.Client.plugin_config_defaults(name),
|
plugin_config_defaults=tutorclient.Client.plugin_config_defaults(name),
|
||||||
@ -214,7 +211,6 @@ async def plugin_install(name: str) -> WerkzeugResponse:
|
|||||||
url_for(
|
url_for(
|
||||||
"plugin",
|
"plugin",
|
||||||
name=name,
|
name=name,
|
||||||
show_logs=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -226,14 +222,13 @@ async def plugin_upgrade(name: str) -> WerkzeugResponse:
|
|||||||
url_for(
|
url_for(
|
||||||
"plugin",
|
"plugin",
|
||||||
name=name,
|
name=name,
|
||||||
show_logs=True,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.post("/plugins/update")
|
@app.post("/plugins/update")
|
||||||
async def plugins_update() -> WerkzeugResponse:
|
async def plugins_update() -> WerkzeugResponse:
|
||||||
tutorclient.CliPool.run_parallel(app, ["plugins", "update"])
|
tutorclient.CliPool.run_sequential(["plugins", "update"])
|
||||||
return redirect(url_for("plugin_store"))
|
return redirect(url_for("plugin_store"))
|
||||||
|
|
||||||
|
|
||||||
@ -286,7 +281,6 @@ async def cli_local_launch() -> str:
|
|||||||
tutorclient.CliPool.run_parallel(app, ["local", "launch", "--non-interactive"])
|
tutorclient.CliPool.run_parallel(app, ["local", "launch", "--non-interactive"])
|
||||||
return await render_template(
|
return await render_template(
|
||||||
"local_launch.html",
|
"local_launch.html",
|
||||||
show_logs=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -349,7 +343,6 @@ async def cli_stop() -> Response:
|
|||||||
async def advanced() -> str:
|
async def advanced() -> str:
|
||||||
return await render_template(
|
return await render_template(
|
||||||
"advanced.html",
|
"advanced.html",
|
||||||
show_logs=True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -366,7 +359,5 @@ async def command() -> WerkzeugResponse:
|
|||||||
form = await request.form
|
form = await request.form
|
||||||
command_string = form.get("command", "")
|
command_string = form.get("command", "")
|
||||||
command_args = command_string.split()
|
command_args = command_string.split()
|
||||||
if tutorclient.CliPool.is_thread_alive():
|
|
||||||
abort(400, description="Command execution already in progress")
|
|
||||||
tutorclient.CliPool.run_parallel(app, command_args)
|
tutorclient.CliPool.run_parallel(app, command_args)
|
||||||
return redirect(url_for("advanced"))
|
return redirect(url_for("advanced"))
|
||||||
|
|||||||
@ -113,3 +113,40 @@ function setToastContent(cmd) {
|
|||||||
toastFooter.style.display = config.showFooter ? "flex" : "none";
|
toastFooter.style.display = config.showFooter ? "flex" : "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each page defines its own relevant commands, we use them to check
|
||||||
|
// if the currently running commands belong the currently opened page or not
|
||||||
|
let relevantCommands = [];
|
||||||
|
let onDeveloperPage = false;
|
||||||
|
function onRelevantPage(command) {
|
||||||
|
if (onDeveloperPage) {
|
||||||
|
// Developer page is relevant to all commands
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return relevantCommands.some((prefix) => command.startsWith(prefix));
|
||||||
|
}
|
||||||
|
|
||||||
|
function activateInputs() {
|
||||||
|
document.querySelectorAll("button").forEach((button) => {
|
||||||
|
button.disabled = false;
|
||||||
|
});
|
||||||
|
document.querySelectorAll("input").forEach((input) => {
|
||||||
|
input.disabled = false;
|
||||||
|
});
|
||||||
|
document.querySelectorAll(".form-switch").forEach((formSwitch) => {
|
||||||
|
formSwitch.style.opacity = 1;
|
||||||
|
});
|
||||||
|
document.getElementById("warning-command-running").style.display = "none";
|
||||||
|
}
|
||||||
|
function deactivateInputs() {
|
||||||
|
document.querySelectorAll("button").forEach((button) => {
|
||||||
|
button.disabled = true;
|
||||||
|
});
|
||||||
|
document.querySelectorAll("input").forEach((input) => {
|
||||||
|
input.disabled = true;
|
||||||
|
});
|
||||||
|
document.querySelectorAll(".form-switch").forEach((formSwitch) => {
|
||||||
|
formSwitch.style.opacity = 0.5;
|
||||||
|
});
|
||||||
|
document.getElementById("warning-command-running").style.display = "flex";
|
||||||
|
}
|
||||||
|
|||||||
@ -23,14 +23,21 @@ htmx.on("htmx:sseBeforeMessage", function (evt) {
|
|||||||
const data = JSON.parse(evt.detail.data);
|
const data = JSON.parse(evt.detail.data);
|
||||||
const command = data.command;
|
const command = data.command;
|
||||||
|
|
||||||
// This means a parallel command just started its execution
|
// This means a parallel command is executing
|
||||||
if (!executedNewCommand && data.thread_alive) {
|
if (data.thread_alive) {
|
||||||
|
// Check if we are on the same page on which the actual command was executed
|
||||||
|
// Each page defines its relevant commands which are sent to `onRelevantPage` function to check if we are on the relevant page
|
||||||
|
if (onRelevantPage(command)) {
|
||||||
ShowCancelCommandButton();
|
ShowCancelCommandButton();
|
||||||
|
logsElement.style.display = "block";
|
||||||
|
} else {
|
||||||
|
// If we are not on relevant page we don't show the cancel button and disable all inputs
|
||||||
|
deactivateInputs();
|
||||||
|
}
|
||||||
executedNewCommand = true;
|
executedNewCommand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parallelCommandCompleted =
|
const parallelCommandCompleted = executedNewCommand && !data.thread_alive;
|
||||||
executedNewCommand && !data.thread_alive;
|
|
||||||
|
|
||||||
const onPluginPage = typeof pluginName !== "undefined";
|
const onPluginPage = typeof pluginName !== "undefined";
|
||||||
// Note that sequential commands are only executed on the plugins page
|
// Note that sequential commands are only executed on the plugins page
|
||||||
@ -40,6 +47,7 @@ htmx.on("htmx:sseBeforeMessage", function (evt) {
|
|||||||
parallelCommandCompleted ||
|
parallelCommandCompleted ||
|
||||||
(onPluginPage && sequentialCommandExecuted)
|
(onPluginPage && sequentialCommandExecuted)
|
||||||
) {
|
) {
|
||||||
|
activateInputs();
|
||||||
// There are certain commands for which we do not show the toast message
|
// There are certain commands for which we do not show the toast message
|
||||||
// Only show the toast if it was set in the `setToastContent` function and if the command ran successfully
|
// Only show the toast if it was set in the `setToastContent` function and if the command ran successfully
|
||||||
if (data.stdout.includes("Success!")) {
|
if (data.stdout.includes("Success!")) {
|
||||||
|
|||||||
@ -23,6 +23,11 @@ $green-1: #edfff7;
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin command {
|
@mixin command {
|
||||||
width: 9em;
|
width: 9em;
|
||||||
height: 3em;
|
height: 3em;
|
||||||
@ -355,6 +360,26 @@ main {
|
|||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#warning-command-running {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: none;
|
||||||
|
border: 1px solid $gray-2;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1.25em;
|
||||||
|
color: $gray-4;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
span {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 2em;
|
width: 2em;
|
||||||
}
|
}
|
||||||
@ -689,6 +714,7 @@ main {
|
|||||||
|
|
||||||
.tutor-logs-container {
|
.tutor-logs-container {
|
||||||
#tutor-logs {
|
#tutor-logs {
|
||||||
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@ -34,6 +34,8 @@ Search for any tutor command and execute it with a single click.
|
|||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
|
onDeveloperPage = true;
|
||||||
|
logsElement.style.display = "block";
|
||||||
runCommandButton = document.querySelector('.run-command-button')
|
runCommandButton = document.querySelector('.run-command-button')
|
||||||
cancelCommandButton = document.querySelector('.cancel-command-button')
|
cancelCommandButton = document.querySelector('.cancel-command-button')
|
||||||
const toggleButtons = ({run = false, cancel = false} = {}) => {
|
const toggleButtons = ({run = false, cancel = false} = {}) => {
|
||||||
|
|||||||
@ -49,7 +49,13 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<header>{% block workspace_header %}{% endblock %}</header>
|
<header>
|
||||||
|
<div id="warning-command-running">
|
||||||
|
<img src="{{ url_for('static', filename='/img/Featured icon.svg')}}" alt="">
|
||||||
|
<span>Command execution in progress. <a href="{{ url_for('advanced') }}">Click here</a> to view details.</span>
|
||||||
|
</div>
|
||||||
|
{% block workspace_header %}{% endblock %}
|
||||||
|
</header>
|
||||||
<section>
|
<section>
|
||||||
{% block workspace_content %}
|
{% block workspace_content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -111,10 +117,6 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<script>
|
<script>
|
||||||
const logsElement = document.getElementById("tutor-logs");
|
const logsElement = document.getElementById("tutor-logs");
|
||||||
show_logs = '{{ show_logs }}' === 'True';
|
|
||||||
if (!show_logs){
|
|
||||||
logsElement.style.display = 'none';
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
{% block scripts %}{% endblock %}
|
{% block scripts %}{% endblock %}
|
||||||
<script src="{{ url_for('static', filename='js/logs.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/logs.js') }}"></script>
|
||||||
|
|||||||
@ -24,6 +24,7 @@ This will run Launch Platform to apply all plugin changes. This may take a few m
|
|||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script>
|
<script>
|
||||||
|
relevantCommands = ["tutor local launch --non-interactive"];
|
||||||
localLaunchButton = document.getElementById('local-launch-button')
|
localLaunchButton = document.getElementById('local-launch-button')
|
||||||
cancelLocalLaunchButton = document.getElementById('cancel-local-launch-button')
|
cancelLocalLaunchButton = document.getElementById('cancel-local-launch-button')
|
||||||
const toggleButtons = ({run = false, cancel = false} = {}) => {
|
const toggleButtons = ({run = false, cancel = false} = {}) => {
|
||||||
|
|||||||
@ -53,6 +53,8 @@
|
|||||||
pluginInstallButton = document.getElementById('plugin-install-button');
|
pluginInstallButton = document.getElementById('plugin-install-button');
|
||||||
cancelCommandButton = document.getElementById('cancel-command-button');
|
cancelCommandButton = document.getElementById('cancel-command-button');
|
||||||
|
|
||||||
|
relevantCommands = ["tutor plugins install", "tutor plugins upgrade"];
|
||||||
|
|
||||||
const toggleButtons = ({install = false, upgrade = false, cancel = false} = {}) => {
|
const toggleButtons = ({install = false, upgrade = false, cancel = false} = {}) => {
|
||||||
pluginInstallButton.style.display = install ? 'block' : 'none';
|
pluginInstallButton.style.display = install ? 'block' : 'none';
|
||||||
pluginUpgradeButton.style.display = upgrade ? 'block' : 'none';
|
pluginUpgradeButton.style.display = upgrade ? 'block' : 'none';
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user