mirror of
https://github.com/unraid/webgui.git
synced 2026-04-23 18:48:49 -05:00
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:
@@ -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> </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']), "<none>:<none>") === false):?>
|
||||
<div style="color:#888; width: 160px;"><?=implode("<br>", array_map('htmlspecialchars',$image['Tags']))?></div>
|
||||
<?endif;?>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
<td> </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']),"<none>:<none>")===false) echo "<div style='width:'160px'>".implode('<br>',array_map('htmlspecialchars',$image['Tags']))."</div>";
|
||||
echo "</td><td> </td><td> </td><td> </td><td> </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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user