Load docker and vm lists in background to speed up rendering

Add rotating animation when starting or stopping a container or vm
This commit is contained in:
bergware
2018-03-06 03:09:08 +01:00
parent 8eb2e1f756
commit e4c9710991
9 changed files with 653 additions and 923 deletions
@@ -4,44 +4,26 @@ Tag="cubes"
Cond="(pgrep('dockerd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2017, Lime Technology
* Copyright 2014-2017, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
// Add the Docker JSON client
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$DockerClient = new DockerClient();
$DockerUpdate = new DockerUpdate();
$DockerTemplates = new DockerTemplates();
?>
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.ui.css">
<link type="text/css" rel="stylesheet" href="/webGui/styles/jquery.switchbutton.css">
<style>
body {-webkit-overflow-scrolling: touch;}
img.started{opacity:1.0;}
img.stopped{opacity:0.3;}
.log{cursor:zoom-in;}
.exec{cursor:pointer;}
.fa-custom{font-size: 1.3em;}
.basic{display: block;}
.advanced{display:none;white-space: nowrap;}
.iconstatus{position:absolute;z-index:2;bottom:-4px;right:-4px;font-size:1.2em;text-shadow:0 0 2px #FFF;}
.iconstatus.started{font-size:1.3em;}
.iconstatus.stopped{font-size:1.2em;}
.started{color:#009900;}
.stopped{color:#EF3D47;}
.switch-button-label.off{color:inherit;}
.basic{display:block}
.advanced{display:none;white-space:nowrap}
body{-webkit-overflow-scrolling:touch}
img.started{opacity:1.0}
img.stopped{opacity:0.3}
.log{cursor:zoom-in}
.exec{cursor:pointer}
.fa-custom{font-size:1.3em}
.iconstatus{position:absolute;z-index:2;bottom:-4px;right:-4px;font-size:1.2em;text-shadow:0 0 2px #FFF}
.iconstatus.started{font-size:1.3em}
.iconstatus.stopped{font-size:1.2em}
.started{color:#009900}
.stopped{color:#EF3D47}
.switch-button-label.off{color:inherit}
</style>
<form id="formAutostart" method="POST" action="/plugins/dynamix.docker.manager/include/UpdateConfig.php" target="progressFrame">
<input type="hidden" name="action" value="autostart" />
<input type="hidden" name="container" value="none" />
@@ -53,165 +35,10 @@ img.stopped{opacity:0.3;}
</form>
<div id="dialog-confirm" style="display:none;" title="Dialog Title"></div>
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
<span class="status" style="margin-top: -44px;"><input type="checkbox" class="advancedview"></span>
<span class="status" style="margin-top:-44px"><input type="checkbox" class="advancedview"></span>
<table class="tablesorter shift" id="docker_containers">
<thead>
<tr>
<th>&nbsp;</th>
<th>Application</th>
<th>Version</th>
<th>Network</th>
<th>Port Mappings <small>(App to Host)</small></th>
<th>Volume Mappings <small>(App to Host)</small></th>
<th width="80px" style="text-align: center">Autostart</th>
<th>Log</th>
</tr>
</thead>
<tbody id="docker_list">
<?
$all_containers = $DockerClient->getDockerContainers();
if (!$all_containers) {
$all_containers = [];
echo "<tr><td></td><td colspan=\"7\">No Docker Containers Installed</td></tr>";
}
$info = $DockerTemplates->getAllInfo();
$contextMenus = [];
$IP = $eth0['IPADDR:0'];
foreach ($all_containers as $ct) {
$name = $ct['Name'];
$mode = $ct['NetworkMode'];
$is_autostart = ($info[$name]['autostart']) ? 'true' : 'false';
$updateStatus = $info[$name]['updated'];
$updateStatus = ($updateStatus == "true" || $updateStatus == "undef") ? 'true' : 'false';
$running = ($ct['Running']) ? 'true' : 'false';
$webGuiUrl = $info[$name]['url'];
$Support = $ct['Support'];
$Project = $ct['Project'];
$contextMenus[] = sprintf("addDockerContainerContext('%s', '%s', '%s', %s, %s, %s, '%s', '%s', '%s', '%s');", addslashes($name), addslashes($ct['ImageId']), addslashes($info[$name]['template']), $running, $updateStatus, $is_autostart, addslashes(html_entity_decode($webGuiUrl)), $ct["Id"], addslashes(html_entity_decode($info[$name]['Support'])),addslashes(html_entity_decode($info[$name]['Project'])));
$shape = ($ct["Running"]) ? "play" : "square";
$status = ($ct["Running"]) ? "started" : "stopped";
$Icon = $info[$name]['icon'];
if (!$Icon) {
$Icon = "/plugins/dynamix.docker.manager/images/question.png";
}
$ports = [];
if ($mode == 'bridge') {
$binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .HostConfig.PortBindings}}{{\$p}}:{{(index \$c 0).HostPort}}|{{end}}' $name 2>/dev/null"));
$ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null");
foreach ($binds as $bind) {
if (!$bind) continue;
list($container_port,$host_port) = explode(':',$bind);
$ports[] = sprintf('%s:%s<i class="fa fa-arrows-h" style="margin:0 6px"></i>%s:%s', $ip, $container_port, $IP, $host_port);
}
} else {
$binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .Config.ExposedPorts}}{{\$p}}|{{end}}' $name 2>/dev/null"));
$ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null") ?: $IP;
foreach ($binds as $bind) {
if (!$bind) continue;
$ports[] = sprintf('%s:%s<i class="fa fa-arrows-h" style="margin:0 6px"></i>%s:%s', $ip, $bind, $ip, str_replace(['/tcp','/udp'],'',$bind));
}
}
$paths = [];
$mounts = explode('|',exec("docker inspect --format='{{range \$c := .HostConfig.Binds}}{{\$c}}|{{end}}' $name 2>/dev/null"));
foreach ($mounts as $mount) {
if (!$mount) continue;
list($host_path,$container_path,$access_mode) = explode(':',$mount);
$paths[] = sprintf('%s<i class="fa fa-%s" style="margin:0 6px"></i>%s', htmlspecialchars($container_path), $access_mode=='ro'?'long-arrow-left':'arrows-h', htmlspecialchars($host_path));
}
?>
<tr>
<td style="width: 48px; padding: 4px">
<?
echo " <div id=\"context-".htmlspecialchars($name)."\" style=\"display:block; cursor:pointer\">
<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
<img src=\"".htmlspecialchars($Icon)."\" class=\"".htmlspecialchars($status)."\" style=\"position: absolute; z-index: 1; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
<i class=\"fa iconstatus fa-$shape $status\" title=\"".htmlspecialchars($status)."\"></i>
</div>
</div>";
?>
</td>
<td>
<?if($info[$ct['Name']]['template']):?>
<a class="exec" onclick="editContainer('<?=addslashes(htmlspecialchars($ct['Name']));?>','<?=addslashes(htmlspecialchars($info[$ct['Name']]['template']));?>');"><?=htmlspecialchars($ct['Name']);?></a>
<?else:?>
<?=htmlspecialchars($ct['Name']);?>
<?endif;?>
<div class="advanced" style="color:#888; width: 160px;">Container ID: <?=htmlspecialchars($ct['Id']);?></div>
<?if($ct['BaseImage']):?>
<div class="advanced" style="color:#888; width: 160px;"><i class="fa fa-cubes" style="margin-right: 5px"></i><?=htmlspecialchars(${ct[BaseImage]})?></div>
<?endif;?>
<div class="advanced" style="color:#888; width: 160px;">By:
<?if($Registry = $info[$ct['Name']]['registry']):?>
<a href="<?=htmlspecialchars($Registry)?>" target="_blank"><?=htmlspecialchars($ct['Image'])?></a>
<?else:?>
<?=htmlspecialchars($ct['Image']);?>
<?endif;?>
</div>
</td>
<td class="updatecolumn">
<?
$updateStatus = $info[$ct['Name']]['updated'];
if ($updateStatus == "false") {
echo "<a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> update ready</span></a>";
} elseif ($updateStatus == "true") {
echo "<span style=\"color:#44B012;white-space:nowrap;\"><i class=\"fa fa-check\"></i> up-to-date</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
} else {
echo "<span style=\"color:#FF2400;white-space:nowrap;\"><i class=\"fa fa-exclamation-triangle\"></i> not available</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('" . addslashes(htmlspecialchars($ct["Name"])) . "');\" style=\"color:#888;\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
}
?>
</td>
<td><?=$mode?></td>
<td style="white-space:nowrap;"><?= implode("<br>", $ports)?></td>
<td style="word-break:break-all;"><?= implode("<br>", $paths)?></td>
<td><input type="checkbox" class="autostart" container="<?=htmlspecialchars($ct['Name']);?>" <?=$info[$ct['Name']]['autostart'] ? "checked" : ""?>></td>
<td><a class="log" onclick="containerLogs('<?=addslashes(htmlspecialchars($ct['Name']));?>','<?=$ct['Id'];?>', false, false)"><img class="basic" src="/plugins/dynamix/icons/log.png"/><div class="advanced" style="width: 124px;"><?=htmlspecialchars($ct['Status'])?></div><div class="advanced" style="color:#888;">Created <?=htmlspecialchars($ct['Created'])?></div></a></td>
</tr>
<?}?>
<?
foreach ($DockerClient->getDockerImages() as $image) {
if (count($image['usedBy'])) {
continue;
}
$contextMenus[] = sprintf("addDockerImageContext('%s', '%s');", $image['Id'], implode(', ', $image['Tags']));
?>
<tr class="advanced">
<td style="width: 48px; padding: 4px">
<?
echo " <div id=\"context-".htmlspecialchars($image['Id'])."\" style=\"display:block; cursor:pointer\">
<div style=\"position: relative; width: 48px; height: 48px; margin: 0px auto;\">
<img src=\"/webGui/images/disk.png\" style=\"position: absolute; z-index: 1; opacity: 0.3; top: 0; bottom: 0; left: 0; right: 0; width: 48px; height: 48px;\"/>
</div>
</div>";
?>
</td>
<td data-sort-value="ZZZZZZZZZZZ">
<i>(orphan image)</i>
<div style="color:#888; width: 160px;">Image ID: <?=htmlspecialchars($image['Id'])?></div>
<?if(strpos(implode($image['Tags']), "&lt;none&gt;:&lt;none&gt;") === false):?>
<div style="color:#888; width: 160px;"><?=implode("<br>", array_map('htmlspecialchars',$image['Tags']))?></div>
<?endif;?>
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><div class="advanced" style="width: 124px; color:#888;">Created <?=htmlspecialchars($image['Created'])?></div></td>
</tr>
<?}?>
</tbody>
<thead><tr><th></th><th>Application</th><th>Version</th><th>Network</th><th>Port Mappings <small>(App to Host)</small></th><th>Volume Mappings <small>(App to Host)</small></th><th width="80px" style="text-align:center">Autostart</th><th>Log</th></tr></thead>
<tbody id="docker_list"><tr><td colspan='8' style='text-align:center;padding-top:12px'><i class='fa fa-spinner fa-spin icon'></i>Please wait... retrieving container information</td></tr></tbody>
</table>
<input type="button" onclick="addContainer()" value="Add Container"/>
<input type="button" onclick="reloadUpdate()" value="Check for Updates"/>
@@ -232,48 +59,34 @@ function resize(bind) {
}
}
<?endif;?>
$(function() {
if ($.cookie('docker_listview_mode') == 'advanced') {
$('.advanced').show();
$('.basic').hide();
}
$('.autostart').switchButton({
labels_placement: "right"
});
$('.autostart').change(function () {
$.post( "/plugins/dynamix.docker.manager/include/UpdateConfig.php", { action: "autostart", container: $(this).attr('container'), response: "json" }, function( data ) {
$(this).prop('checked', data.autostart );
}, "json");
});
$('.advancedview').switchButton({
labels_placement: "left",
on_label: 'Advanced View',
off_label: 'Basic View',
checked: $.cookie('docker_listview_mode') == 'advanced'
});
$('.advancedview').change(function () {
$('.advanced').toggle('slow');
$('.basic').toggle('slow');
$.cookie('docker_listview_mode', $('.advancedview').is(':checked') ? 'advanced' : 'basic', { expires: 3650 });
});
function loadlist() {
$.get('/plugins/dynamix.docker.manager/include/DockerContainers.php',function(d) {
var data = d.split(/\0/);
$('#docker_list').html(data[0]);
$('head').append('<script>'+data[1]+'<\/script>');
$('.autostart').switchButton({labels_placement:"right"});
$('.autostart').change(function() {
$.post( "/plugins/dynamix.docker.manager/include/UpdateConfig.php",{action:'autostart',container:$(this).attr('container'),response:'json'},function(data){$(this).prop('checked',data.autostart);},'json');
});
<?if ($display['resize']):?>
resize();
$(window).bind('resize',function(){resize(true);});
resize();
$(window).bind('resize',function(){resize(true);});
<?endif;?>
$('#docker_containers').tablesorter({
sortList: [[1,0]],
headers: {0: {sorter: false }, 6: {sorter: false }},
textExtraction: {
5: function(node, table, cellIndex){ return $(node).find("input").prop('checked')?1:0; }
}
});
$('#docker_containers tr:even').addClass('odd');
context.init({ preventDoubleContext: false });
<?=htmlspecialchars(implode("\n\t", $contextMenus));?>
$('#docker_containers').tablesorter({
sortList:[[1,0]],headers:{0:{sorter:false},4:{sorter:false},5:{sorter:false},7:{sorter:false}},
textExtraction:{6:function(node,table,cellIndex){return $(node).find('input').prop('checked')?1:0;}}
});
if ($.cookie('docker_listview_mode')=='advanced') {$('.advanced').show(); $('.basic').hide();}
context.init({preventDoubleContext:false});
});
}
$(function() {
$('.advancedview').switchButton({labels_placement:"left", on_label:'Advanced View', off_label:'Basic View', checked:$.cookie('docker_listview_mode')=='advanced'});
$('.advancedview').change(function() {
$('.advanced').toggle('slow');
$('.basic').toggle('slow');
$.cookie('docker_listview_mode', $('.advancedview').is(':checked')?'advanced':'basic', {expires:3650});
});
loadlist();
});
</script>
@@ -0,0 +1,126 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
// Add the Docker JSON client
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$DockerClient = new DockerClient();
$DockerTemplates = new DockerTemplates();
$all_containers = $DockerClient->getDockerContainers();
if (!$all_containers) {
echo "<tr><td colspan='8' style='text-align:center;padding-top:12px'>No Docker containers installed</td></tr>";
return;
}
// Read network settings
extract(parse_ini_file('state/network.ini',true));
// Read container info
$all = $DockerTemplates->getAllInfo();
$menu = [];
foreach ($all_containers as $ct) {
$name = $ct['Name'];
$info = &$all[$name];
$mode = $ct['NetworkMode'];
$id = $ct['Id'];
$imageID = $ct['ImageId'];
$is_autostart = $info['autostart'] ? 'true':'false';
$updateStatus = $info['updated']=='true'||$info['updated']=='undef' ? 'true':'false';
$running = $ct['Running'] ? 'true':'false';
$template = $info['template'];
$webGui = html_entity_decode($info['url']);
$support = html_entity_decode($info['Support']);
$project = html_entity_decode($info['Project']);
$menu[] = sprintf("addDockerContainerContext('%s','%s','%s',%s,%s,%s,'%s','%s','%s','%s');",addslashes($name),addslashes($imageID),addslashes($template),$running,$updateStatus,$is_autostart,addslashes($webGui),$id,addslashes($support),addslashes($project));
$shape = $ct['Running'] ? 'play':'square';
$status = $ct['Running'] ? 'started':'stopped';
$icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png';
$ports = [];
if ($mode=='bridge') {
$binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .HostConfig.PortBindings}}{{\$p}}:{{(index \$c 0).HostPort}}|{{end}}' $name 2>/dev/null"));
$ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null");
foreach ($binds as $bind) {
if (!$bind) continue;
list($container_port,$host_port) = explode(':',$bind);
$ports[] = sprintf('%s:%s<i class="fa fa-arrows-h" style="margin:0 6px"></i>%s:%s',$ip, $container_port, $eth0['IPADDR:0'], $host_port);
}
} else {
$binds = explode('|',exec("docker inspect --format='{{range \$p,\$c := .Config.ExposedPorts}}{{\$p}}|{{end}}' $name 2>/dev/null"));
$ip = exec("docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $name 2>/dev/null") ?: $eth0['IPADDR:0'];
foreach ($binds as $bind) {
if (!$bind) continue;
$ports[] = sprintf('%s:%s<i class="fa fa-arrows-h" style="margin:0 6px"></i>%s:%s',$ip, $bind, $ip, str_replace(['/tcp','/udp'],'',$bind));
}
}
$paths = [];
$mounts = explode('|',exec("docker inspect --format='{{range \$c := .HostConfig.Binds}}{{\$c}}|{{end}}' $name 2>/dev/null"));
foreach ($mounts as $mount) {
if (!$mount) continue;
list($host_path,$container_path,$access_mode) = explode(':',$mount);
$paths[] = sprintf('%s<i class="fa fa-%s" style="margin:0 6px"></i>%s', htmlspecialchars($container_path), $access_mode=='ro'?'long-arrow-left':'arrows-h', htmlspecialchars($host_path));
}
echo "<tr><td style='width:48px;padding:4px'>";
echo "<div id=\"$id\" style=\"display:block; cursor:pointer\"><div style=\"position:relative;width:48px;height:48px;margin:0px auto\">";
echo "<img src=\"".htmlspecialchars($icon)."\" class=\"".htmlspecialchars($status)."\" style=\"position:absolute;top:0;bottom:0;left:0;right:0;width:48px;height:48px\">";
echo "<i class=\"fa iconstatus fa-$shape $status\" title=\"".htmlspecialchars($status)."\"></i></div></div>";
echo "</td><td>";
if ($template) {
echo "<a class=\"exec\" onclick=\"editContainer('".addslashes(htmlspecialchars($name))."','".addslashes(htmlspecialchars($template))."')\">".htmlspecialchars($name)."</a>";
} else {
echo htmlspecialchars($name);
}
echo "<div class='advanced' style='width:160px'>Container ID: ".htmlspecialchars($id)."</div>";
if ($ct['BaseImage']) echo "<div class='advanced' style='width:160px;'><i class='fa fa-cubes' style='margin-right:5px'></i>".htmlspecialchars(${ct['BaseImage']})."</div>";
echo "<div class='advanced' style='width:160px'>By:";
$registry = $info['registry'];
if ($registry) {
echo "<a href=\"".htmlspecialchars($registry)."\" target=\"_blank\">".htmlspecialchars($ct['Image'])."</a>";
} else {
echo htmlspecialchars($ct['Image']);
}
echo "</div></td><td class='updatecolumn'>";
if ($updateStatus=='false') {
echo "<a class=\"exec\" onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> update ready</span></a>";
} elseif ($updateStatus=='true') {
echo "<span style=\"color:#44B012;white-space:nowrap;\"><i class=\"fa fa-check\"></i> up-to-date</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
} else {
echo "<span style=\"color:#FF2400;white-space:nowrap;\"><i class=\"fa fa-exclamation-triangle\"></i> not available</span>";
echo "<div class=\"advanced\"><a class=\"exec\" onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style=\"white-space:nowrap;\"><i class=\"fa fa-cloud-download\"></i> force update</span></a></div>";
}
echo "</td><td>$mode</td>";
echo "<td style='white-space:nowrap'>".implode('<br>',$ports)."</td>";
echo "<td style='word-break:break-all'>".implode('<br>',$paths)."</td>";
echo "<td><input type='checkbox' class='autostart' container=\"".htmlspecialchars($name)."\"".($info['autostart'] ? ' checked':'')."></td>";
echo "<td><a class='log' onclick=\"containerLogs('".addslashes(htmlspecialchars($name))."','$id',false,false)\"><img class='basic' src='/plugins/dynamix/icons/log.png'><div class='advanced' style='width:124px;'>".htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."</div><div class='advanced'>Created ".htmlspecialchars($ct['Created'])."</div></a></td></tr>";
}
foreach ($DockerClient->getDockerImages() as $image) {
if (count($image['usedBy'])) continue;
$menu[] = sprintf("addDockerImageContext('%s','%s');",$image['Id'],implode(', ',$image['Tags']));
echo "<tr class='advanced'><td style='width:48px;padding:4px'>";
echo "<div id=\"context-".htmlspecialchars($image['Id'])."\" style=\"display:block;cursor:pointer\">";
echo "<div style='position:relative;width:48px;height:48px;margin:0 auto'>";
echo "<img src='/webGui/images/disk.png' style='position:absolute;opacity:0.3;top:0;bottom:0;left:0;right:0;width:48px;height:48px'>";
echo "</div></div></td>";
echo "<td data-sort-value='ZZZZZZZZZZZ'><i>(orphan image)</i><div style='width:160px;'>Image ID: ".htmlspecialchars($image['Id'])."</div>";
if (strpos(implode($image['Tags']),"&lt;none&gt;:&lt;none&gt;")===false) echo "<div style='width:'160px'>".implode('<br>',array_map('htmlspecialchars',$image['Tags']))."</div>";
echo "</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>";
echo "<td><div class='advanced' style='width:124px'>Created ".htmlspecialchars($image['Created'])."</div></td></tr>";
}
echo "\0".implode($menu);
?>
@@ -1,43 +1,43 @@
var eventURL = "/plugins/dynamix.docker.manager/include/Events.php";
function addDockerContainerContext(container, image, template, started, update, autostart, webui, id, Support, Project) {
var opts = [{header: container, image: "/plugins/dynamix.docker.manager/images/dynamix.docker.manager.png"}];
var opts = [{header:container, image:"/plugins/dynamix.docker.manager/images/dynamix.docker.manager.png"}];
if (started && (webui !== "" && webui != "#")) {
opts.push({text: 'WebUI', icon: 'fa-globe', href: webui, target: '_blank'});
opts.push({divider: true});
opts.push({text:'WebUI', icon:'fa-globe', href:webui, target:'_blank'});
opts.push({divider:true});
}
if (!update) {
opts.push({text: 'Update', icon: 'fa-arrow-down', action: function(e){ e.preventDefault(); execUpContainer(container); }});
opts.push({divider: true});
opts.push({text:'Update', icon:'fa-arrow-down', action:function(e){e.preventDefault(); execUpContainer(container);}});
opts.push({divider:true});
}
if (started) {
opts.push({text: 'Stop', icon: 'fa-stop', action: function(e){ e.preventDefault(); eventControl({action: "stop", container: id}); }});
opts.push({text: 'Restart', icon: 'fa-refresh', action: function(e){ e.preventDefault(); eventControl({action: "restart", container: id}); }});
opts.push({text:'Stop', icon:'fa-stop', action:function(e){e.preventDefault(); eventControl({action:"stop", container:id}, 'loadlist');}});
opts.push({text:'Restart', icon:'fa-refresh', action:function(e){e.preventDefault(); eventControl({action:"restart", container:id});}});
} else {
opts.push({text: 'Start', icon: 'fa-play', action: function(e){ e.preventDefault(); eventControl({action: "start", container: id}); }});
opts.push({text:'Start', icon:'fa-play', action:function(e){e.preventDefault(); eventControl({action:"start", container:id}, 'loadlist');}});
}
opts.push({divider: true});
opts.push({divider:true});
if (location.pathname.indexOf("/Dashboard") === 0) {
opts.push({text: 'Logs', icon: 'fa-navicon', action: function(e){ e.preventDefault(); containerLogs(container, id); }});
opts.push({text:'Logs', icon:'fa-navicon', action:function(e){e.preventDefault(); containerLogs(container, id);}});
}
if (template) {
opts.push({text: 'Edit', icon: 'fa-wrench', action: function(e){ e.preventDefault(); editContainer(container, template); }});
opts.push({text:'Edit', icon:'fa-wrench', action:function(e){e.preventDefault(); editContainer(container, template);}});
}
opts.push({divider: true});
opts.push({text: 'Remove', icon: 'fa-trash', action: function(e){ e.preventDefault(); rmContainer(container, image, id); }});
if (Support) {
opts.push({divider: true});
opts.push({text: 'Support', icon: 'fa-question', href: Support, target: '_blank'});
}
if (Project) {
opts.push({text: 'Project Page', icon: 'fa-life-ring', href: Project, target: '_blank'});
}
context.attach('#context-'+container, opts);
opts.push({divider:true});
opts.push({text:'Remove', icon:'fa-trash', action:function(e){e.preventDefault(); rmContainer(container, image, id);}});
if (Support) {
opts.push({divider:true});
opts.push({text:'Support', icon:'fa-question', href:Support, target:'_blank'});
}
if (Project) {
opts.push({text:'Project Page', icon:'fa-life-ring', href:Project, target:'_blank'});
}
context.attach('#'+id, opts);
}
function addDockerImageContext(image, imageTag) {
var opts = [{header: '(orphan image)'}];
opts.push({text: "Remove", icon: "fa-trash", action: function(e){ e.preventDefault(); rmImage(image, imageTag); }});
var opts = [{header:'(orphan image)'}];
opts.push({text:"Remove", icon:"fa-trash", action:function(e){e.preventDefault(); rmImage(image, imageTag);}});
context.attach('#context-'+image, opts);
}
@@ -52,19 +52,19 @@ function popupWithIframe(title, cmd, reload) {
$("#iframe-popup").html('<iframe id="myIframe" frameborder="0" scrolling="yes" width="100%" height="99%"></iframe>');
$("#iframe-popup").dialog({
autoOpen: true,
title: title,
draggable: true,
width: 800,
height: ((screen.height / 5) * 4) || 0,
resizable: true,
modal: true,
show: {effect: "fade", duration: 250},
hide: {effect: "fade", duration: 250},
open: function(ev, ui) {
autoOpen:true,
title:title,
draggable:true,
width:800,
height:((screen.height / 5) * 4) || 0,
resizable:true,
modal:true,
show:{effect:"fade", duration:250},
hide:{effect:"fade", duration:250},
open:function(ev, ui) {
$("#myIframe").attr("src", cmd);
},
close: function(event, ui) {
close:function(event, ui) {
if (reload && !$("#myIframe").contents().find("#canvas").length) {
location = window.location.href;
} else {
@@ -75,7 +75,7 @@ function popupWithIframe(title, cmd, reload) {
$(".ui-dialog .ui-dialog-titlebar").addClass("menu");
$(".ui-dialog .ui-dialog-title").css("text-align", "center").css("width", "100%");
$(".ui-dialog .ui-dialog-content").css("padding", "0");
//$('.ui-widget-overlay').click(function() { $("#iframe-popup").dialog("close"); });
//$('.ui-widget-overlay').click(function() {$("#iframe-popup").dialog("close");});
}
function addContainer() {
@@ -98,35 +98,35 @@ function updateContainer(container) {
var body = "Update container: "+container;
swal({
title: "Are you sure?",
text: body,
type: "warning",
showCancelButton: true,
confirmButtonColor: "#8CD4F5",
confirmButtonText: "Yes, update it!"
title:"Are you sure?",
text:body,
type:"warning",
showCancelButton:true,
confirmButtonColor:"#8CD4F5",
confirmButtonText:"Yes, update it!"
}, function() {
execUpContainer(container);
});
}
function rmContainer(container, image, id) {
var body = "Remove container: "+container+"<br><br><label><input id=\"removeimagechk\" type=\"checkbox\" checked style=\"display: inline; width: unset; height: unset; margin-top: unset; margin-bottom: unset\">also remove image</label>";
var body = "Remove container: "+container+"<br><br><label><input id=\"removeimagechk\" type=\"checkbox\" checked style=\"display:inline; width:unset; height:unset; margin-top:unset; margin-bottom:unset\">also remove image</label>";
swal({
title: "Are you sure?",
text: body,
type: "warning",
html: true,
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!",
closeOnConfirm: false,
showLoaderOnConfirm: true
title:"Are you sure?",
text:body,
type:"warning",
html:true,
showCancelButton:true,
confirmButtonColor:"#DD6B55",
confirmButtonText:"Yes, delete it!",
closeOnConfirm:false,
showLoaderOnConfirm:true
}, function() {
if ($("#removeimagechk").prop('checked')) {
eventControl({action: "remove_all", container: id, image: image});
eventControl({action:"remove_all", container:id, image:image});
} else {
eventControl({action: "remove_container", container: id});
eventControl({action:"remove_container", container:id});
}
});
}
@@ -135,26 +135,27 @@ function rmImage(image, imageName) {
var body = "Remove image: "+$('<textarea />').html(imageName).text();
swal({
title: "Are you sure?",
text: body,
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!",
closeOnConfirm: false,
showLoaderOnConfirm: true
title:"Are you sure?",
text:body,
type:"warning",
showCancelButton:true,
confirmButtonColor:"#DD6B55",
confirmButtonText:"Yes, delete it!",
closeOnConfirm:false,
showLoaderOnConfirm:true
}, function() {
eventControl({action: "remove_image", image: image});
eventControl({action:"remove_image", image:image});
});
}
function eventControl(params, reload) {
if (typeof reload == "undefined") reload = true;
var spin = typeof reload != 'undefined';
if (spin) $('#'+params['container']).addClass('fa-spin');
$.post(eventURL, params, function(data) {
if (data.success === true) {
if (reload) location.reload();
if (spin) setTimeout(reload+'()',500); else location=window.location.href;
} else {
swal({title: "Execution error", text: data.success, type: "error"});
swal({title:"Execution error", text:data.success, type:"error"});
}
}, "json");
}
@@ -175,10 +176,9 @@ function autoStart(container, event) {
function containerLogs(container, id) {
var height = 600;
var width = 900;
var run = eventURL + "?action=log&container=" + id + "&title=Log for: " + container;
var run = eventURL + "?action=log&container=" + id + "&title=Log for:" + container;
var top = (screen.height-height) / 2;
var left = (screen.width-width) / 2;
var options = 'resizeable=yes,scrollbars=yes,height='+height+',width='+width+',top='+top+',left='+left;
window.open(run, 'log', options);
}