Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f988899
feat(webgui): backend-tracked task queue with multi-task tray + foreg…
elibosley Jun 17, 2026
73fc6db
fix(task-tray): lift op-tray above fixed footer so it isn't clipped
elibosley Jun 18, 2026
6c6708e
fix(task-tray): open modal on create even before /sub/tasks broadcast
elibosley Jun 18, 2026
f6d8cfc
fix(task-tray): guard NchanSubscriber start/stop against wrong run-state
elibosley Jun 18, 2026
856cc7d
feat(task-tray): auto-expire finished tasks and add Clear finished ac…
elibosley Jun 18, 2026
97ef66f
revert(task-tray): drop daemon auto-expiry, keep Clear finished button
elibosley Jun 18, 2026
6811492
style(task-tray): use stop-circle instead of bomb for Abort
elibosley Jun 18, 2026
b771659
feat(task-tray): add indeterminate progress bar to running tasks
elibosley Jun 18, 2026
db7c8b1
style(task-tray): use a plain loader spinner for running tasks
elibosley Jun 18, 2026
3ae078d
fix(task-queue): address CodeRabbit review feedback on PR 2665
elibosley Jun 18, 2026
79f7c44
fix(task-queue): record terminal state from the task itself
elibosley Jun 22, 2026
49d12bb
feat(task-tray): backgroundable running ops + modal button polish (fo…
elibosley Jun 22, 2026
4c38213
feat(task-tray): show target name in background-task progress headings
elibosley Jun 18, 2026
0fe05ad
fix(task-queue): don't re-fire completion callback for pre-existing d…
elibosley Jul 8, 2026
de74806
feat(task-tray): user-resizable task sheet width, persisted per browser
elibosley Jul 9, 2026
0d5aa90
feat(task-tray): shared close control + resize across all .nchan sheets
elibosley Jul 9, 2026
5db13ad
fix(task-tray): clear stale state before ordinary dialogs
elibosley Jul 14, 2026
b7b7686
fix(task-queue): abort kills the whole process group, not just the wr…
elibosley Jul 21, 2026
42eae71
fix(task-tray): empty-plg callbacks, per-task output channel, replay/…
elibosley Jul 21, 2026
0b7e280
fix(task-tray): nchan channel DELETE requires the buffer_length arg
elibosley Jul 21, 2026
91eead4
fix(task-tray): capture output from legacy publishers
elibosley Aug 3, 2026
e000742
fix(task-tray): harden lifecycle and replay handoff
elibosley Aug 3, 2026
41dbf9a
fix(task-tray): serialize ordinary dialogs after minimize
elibosley Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions emhttp/plugins/dynamix.docker.manager/javascript/docker.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function updateContainer(container) {
swal({
title:_('Are you sure?'),text:_('Update container')+': '+container, type:'warning',html:true,showCancelButton:true,closeOnConfirm:false,confirmButtonText:_('Yes, update it!'),cancelButtonText:_('Cancel')
},function(){
openDocker('update_container '+encodeURIComponent(container),_('Updating the container'),'','loadlist');
openDocker('update_container '+encodeURIComponent(container),_('Update container')+': '+container,'','loadlist');
});
}
function rmContainer(container, image, id) {
Expand Down Expand Up @@ -182,7 +182,7 @@ function updateAll() {
$('input[type=button]').prop('disabled',true);
var ct = [];
for (var i=0,d; d=docker[i]; i++) if (d.update==1) ct.push(encodeURIComponent(d.name));
openDocker('update_container '+ct.join('*'),_('Updating all Containers'),'','loadlist');
openDocker('update_container '+ct.join('*'),_('Updating all Containers')+' ('+ct.length+')','','loadlist');
}
function rebuildAll() {
$('input[type=button]').prop('disabled',true);
Expand Down
18 changes: 18 additions & 0 deletions emhttp/plugins/dynamix.plugin.manager/Plugins.page
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Title="Installed Plugins"
Tag="icon-plugins"
Tabs="true"
Code="e944"
Markdown="false"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
Expand Down Expand Up @@ -204,6 +205,23 @@ function loadlist(id,check) {
$('#checkall').find('input').prop('disabled',false);
});
}
// Row buttons are rendered server-side (make_link) from the task queue: a plugin
// with an active/queued task shows "Upgrading" (disabled). Refresh the rows when
// the set of active plugin tasks changes, so that state appears/clears live —
// loadlist(null,1) re-renders just the status cells (no network re-check, no
// flickery full reload). The task queue is the single source of truth.
var _plgTaskSig = '';
function onPluginTasksChanged() {
var sig = '';
if (typeof taskList !== 'undefined') {
for (var i=0;i<taskList.length;i++) {
var t = taskList[i];
if (t && t.type=='plugins' && (t.status=='running'||t.status=='aborting'||t.status=='queued')) sig += t.id+';';
}
}
if (sig !== _plgTaskSig) { _plgTaskSig = sig; loadlist(null,1); }
}
window.onTaskListChanged = onPluginTasksChanged;
$(function() {
initlist();
$('.tabs-container').append("<span id='checkall' class='status vhshift'><input type='button' value=\"_(Check For Updates)_\" onclick='checkPlugins(true)' disabled></span>");
Expand Down
17 changes: 16 additions & 1 deletion emhttp/plugins/dynamix.plugin.manager/include/PluginHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@
<?
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix/include/TaskQueue.php";

// true when the backend task queue has an active/queued task targeting this .plg
// (the task queue is the source of truth for an in-flight install/update)
function plugin_task_busy($arg) {
if (!$arg) return false;
foreach (task_list() as $t) {
if ($t['type']==='plugins' && in_array($t['status'],['running','aborting','queued'],true)
&& in_array($arg, preg_split('/\s+/', trim($t['cmd'])), true)) return true;
}
return false;
}

// Invoke the plugin command with indicated method
function plugin($method, $arg = '', $dontCache = false) {
Expand Down Expand Up @@ -71,7 +83,10 @@ function make_link($method, $arg, $extra='') {
$cmd = "plugin $method $arg".($extra?" $extra":"");
$func = "loadlist";
}
if (is_file("/tmp/plugins/pluginPending/$arg") && !$check) {
if (in_array($method,['update','install']) && plugin_task_busy($arg)) {
$label = $method=='install' ? _('Installing') : _('Upgrading');
return "<span class='orange-text'><i class='fa fa-hourglass-o fa-fw'></i>&nbsp;$label</span>";
} elseif (is_file("/tmp/plugins/pluginPending/$arg") && !$check) {
return "<span class='orange-text'><i class='fa fa-hourglass-o fa-fw'></i>&nbsp;"._('pending')."</span>";
} else {
return "$check<input type='button' id='$id' data='$arg' class='$method' value=\""._(ucfirst($method))."\" onclick='openInstall(\"$cmd\",\""._(ucwords($method)." Plugin")."\",\"$plg\",\"$func\");'$disabled>";
Expand Down
5 changes: 4 additions & 1 deletion emhttp/plugins/dynamix/Apps.page
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Code="e942"
?>
<script>
function installPlugin(file) {
openPlugin("plugin install "+file,"_(Install Plugin)_","","refresh");
// show which plugin in the progress heading; sanitize to a safe display slug
// (the heading is rendered as HTML), derived from the .plg basename
var name = (file.split('/').pop()||'').replace(/\.[a-z0-9]+$/i,'').replace(/[^\w.\- ]+/g,' ').trim();
openPlugin("plugin install "+file,"_(Install Plugin)_"+(name?': '+name:''),"","refresh");
}
</script>

Expand Down
5 changes: 4 additions & 1 deletion emhttp/plugins/dynamix/Language.page
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ function getZIPfile(event,form) {
}
function installXML(name) {
var file = name.trim();
if (file) openPlugin('language install '+file, "_(Install Language)_");
// show which language pack in the progress heading; sanitize to a safe display
// slug (the heading is rendered as HTML), derived from the file basename
var disp = (file.split('/').pop()||'').replace(/\.[a-z0-9]+$/i,'').replace(/[^\w.\- ]+/g,' ').trim();
if (file) openPlugin('language install '+file, "_(Install Language)_"+(disp?': '+disp:''));
}
$(function() {
$('input.view').switchButton({labels_placement:'left', off_label:"_(User)_", on_label:"_(Developer)_"});
Expand Down
5 changes: 4 additions & 1 deletion emhttp/plugins/dynamix/Tailscale.page
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Title="Tailscale"
?>
<script>
function installPlugin(file) {
openPlugin("plugin install "+file,"_(Install Plugin)_","","refresh");
// show which plugin in the progress heading; sanitize to a safe display slug
// (the heading is rendered as HTML), derived from the .plg basename
var name = (file.split('/').pop()||'').replace(/\.[a-z0-9]+$/i,'').replace(/[^\w.\- ]+/g,' ').trim();
openPlugin("plugin install "+file,"_(Install Plugin)_"+(name?': '+name:''),"","refresh");
}
</script>

Expand Down
4 changes: 4 additions & 0 deletions emhttp/plugins/dynamix/include/DefaultPageLayout.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
if ($wlan0) {
$nchan[] = 'webGui/nchan/wlan0';
}
// keep the task scheduler alive while background operations exist (it exits when idle)
if (glob('/var/local/emhttp/tasks/*.json')) {
$nchan[] = 'plugins/dynamix/nchan/tasks';
}
// build nchan scripts from found pages
$allPages = array_merge($taskPages, $buttonPages, $pages);
foreach ($allPages as $page) {
Expand Down
Loading
Loading