summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2020-09-28 15:25:58 +0200
committerSimon Rettberg2020-09-28 15:25:58 +0200
commit39354a0cc0ef32ddd432d8421dc8483002cd855b (patch)
tree7b3975bc77ce6899fd128080c2e0035485ef1bb8
parent[remoteaccess/exams] Disable screen-saver timeout for these modes (diff)
downloadslx-admin-39354a0cc0ef32ddd432d8421dc8483002cd855b.tar.gz
slx-admin-39354a0cc0ef32ddd432d8421dc8483002cd855b.tar.xz
slx-admin-39354a0cc0ef32ddd432d8421dc8483002cd855b.zip
[dozmod] Implement deleting orphaned files from vm store
This is the UI part that communicates with dmsd to show or delete all files on the vm store that don't belong to a known VM. Might be dangerous, use wisely. Closes #3321
-rw-r--r--modules-available/dozmod/lang/de/messages.json3
-rw-r--r--modules-available/dozmod/lang/de/permissions.json2
-rw-r--r--modules-available/dozmod/lang/de/template-tags.json9
-rw-r--r--modules-available/dozmod/lang/en/messages.json1
-rw-r--r--modules-available/dozmod/lang/en/permissions.json2
-rw-r--r--modules-available/dozmod/lang/en/template-tags.json9
-rw-r--r--modules-available/dozmod/pages/expiredimages.inc.php105
-rw-r--r--modules-available/dozmod/permissions/permissions.json6
-rw-r--r--modules-available/dozmod/templates/images-delete.html172
-rw-r--r--modules-available/dozmod/templates/images-orphaned.html25
-rw-r--r--script/slx-fixes.js3
11 files changed, 231 insertions, 106 deletions
diff --git a/modules-available/dozmod/lang/de/messages.json b/modules-available/dozmod/lang/de/messages.json
index a2d6a0ae..7eba0b2d 100644
--- a/modules-available/dozmod/lang/de/messages.json
+++ b/modules-available/dozmod/lang/de/messages.json
@@ -1,6 +1,5 @@
{
"all-templates-reset": "Alle Templates wurden zur\u00fcckgesetzt",
- "delete-images": "L\u00f6schung: {{0}}",
"dozmod-error": "Fehler bei der Kommunikation mit dem bwLehrpool-Suite server: {{0}}",
"images-pending-delete-exist": "Zur L\u00f6schung markierte VM-Versionen: {{0}}",
"ldap-filter-created": "LDAP Filter wurde erfolgreich erstellt",
@@ -33,4 +32,4 @@
"timeout": "Zeit\u00fcberschreitung",
"unknown-targetid": "Target {{0}} nicht bekannt",
"unknown-userid": "Unbekannter Nutzer, {{0}}"
-}
+} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/de/permissions.json b/modules-available/dozmod/lang/de/permissions.json
index 8e743e5c..6159362d 100644
--- a/modules-available/dozmod/lang/de/permissions.json
+++ b/modules-available/dozmod/lang/de/permissions.json
@@ -8,6 +8,8 @@
"networkrules.view": "Netzwerk-Regeln einsehen.",
"networkshares.save": "\u00c4nderungen an den Netzlaufwerken speichern.",
"networkshares.view": "Netzlaufwerke einsehen.",
+ "orphaned.delete": "Verwaiste Dateien vom VM-Store l\u00f6schen.",
+ "orphaned.scan": "Nach Verwaisten Dateien auf VM-Store suchen.",
"runscripts.save": "Startkripte erstellen\/bearbeiten.",
"runscripts.view": "Startscripte auflisten.",
"runtimeconfig.save": "\u00c4nderungen an der Laufzeit-Konfiguration speichern.",
diff --git a/modules-available/dozmod/lang/de/template-tags.json b/modules-available/dozmod/lang/de/template-tags.json
index f03fd7b6..9b2b5653 100644
--- a/modules-available/dozmod/lang/de/template-tags.json
+++ b/modules-available/dozmod/lang/de/template-tags.json
@@ -11,6 +11,7 @@
"lang_bwlehrpoolsuite": "bwLehrpool-Suite",
"lang_canLoginOrganization": "Nutzer dieser Einrichtung k\u00f6nnen sich am Satelliten anmelden",
"lang_canLoginUser": "Nutzer kann sich am Satelliten anmelden",
+ "lang_confirmDeleteOrphanedFiles": "Sind Sie sicher, dass Sie alle aufgelisteten Dateien unwiderruflich vom VM-Store l\u00f6schen wollen?",
"lang_createTime": "Erstellt",
"lang_currentFilter": "Aktueller Filter",
"lang_defaultImagePermissionAdmin": "Administrieren",
@@ -21,6 +22,7 @@
"lang_defaultLecturePermissions": "F\u00fcr Veranstaltungen",
"lang_defaultPermissions": "Standardberechtigungen",
"lang_delButton": "Gew\u00e4hlte VMs endg\u00fcltig l\u00f6schen",
+ "lang_deleteExpiredHeading": "Zu l\u00f6schende VM-Versionen",
"lang_descriptionPermissionConfig": "Dies sind die Berechtigungen, die ein Benutzer standardm\u00e4\u00dfig f\u00fcr fremde VMs\/Veranstaltungen hat. Sie werden angewandt, wenn der Besitzer keine anderweitigen Berechtigungen w\u00e4hlt.",
"lang_descriptionRuntimeLimits": "Hier k\u00f6nnen Sie verschiedene Limits festlegen, z.B. wie lange eine VM nach dem Hochladen g\u00fcltig ist. Nach Ablauf dieses Zeitraums ist der Verantwortliche gezwungen, eine neue Version der VM hochzuladen. Damit k\u00f6nnen Sie das Ansammeln nicht mehr ben\u00f6tigter VMs eind\u00e4mmen. Weiterhin k\u00f6nnen Sie die maximale Anzahl gleichzeitiger Transfers pro Benutzer einschr\u00e4nken.\r\n\r\nVer\u00e4nderte Einstellungen wirken sich nicht auf bereits bestehende VMs aus.",
"lang_description_delete_images": "Diese Liste zeigt VMs, die entweder abgelaufen sind, oder deren Datei besch\u00e4digt, verschoben oder gel\u00f6scht wurde. Diese Images sind zur Zeit im Lehrpool nicht verf\u00fcgbar, ihre endg\u00fcltige L\u00f6schung muss aber manuell best\u00e4tigt werden, um gr\u00f6\u00dfere Katastrophen durch Softwarefehler, verstellte Systemuhren etc. zu vermeiden.",
@@ -33,11 +35,11 @@
"lang_emailNotifications": "EMail-Benachrichtigungen aktiviert",
"lang_error": "Fehler",
"lang_event": "Ereignis",
+ "lang_fileName": "Dateiname",
"lang_fileSize": "Dateigr\u00f6\u00dfe",
"lang_followingPlaceholdersUnused": "Folgende Platzhalter m\u00fcssen im Template verwendet werden",
"lang_hasNewer": "Neuere Version existiert",
"lang_hash": "Hash",
- "lang_heading": "Zu l\u00f6schende VM-Versionen",
"lang_hidden": "Versteckt",
"lang_host": "Host",
"lang_image": "VM",
@@ -77,6 +79,9 @@
"lang_normal": "Normal",
"lang_organization": "Einrichtung",
"lang_organizationListHeader": "Nutzungsrechte f\u00fcr den Satelliten festlegen",
+ "lang_orphanDeleteButton": "Dateien l\u00f6schen",
+ "lang_orphanedFilesDesc": "Hier aufgelistete Dateien geh\u00f6ren zu keiner aus der Datenbank bekannten VM. Sollten Sie sich sicher sein, dass diese Dateien nicht anderweitig verwendet werden, oder h\u00e4ndisch auf dem VM-Store abgelegt wurden, k\u00f6nnen Sie diese Dateien l\u00f6schen, um Speicherplatz zu gewinnen. Wenn Sie sich nicht sicher sind, untersuchen Sie die Situation auf dem VM-Store h\u00e4ndisch.",
+ "lang_orphanedFilesHeading": "Verwaiste Images und Dateien auf dem VM-Store",
"lang_os": "Betriebssystem",
"lang_owner": "Besitzer",
"lang_passwordCleartextHint": "Bitte beachten Sie, dass ein hier explizit angegebenes Passwort im Klartext an das Poolsystem \u00fcbergeben wird. Sie sollten also nur dedizierte Funktionsaccounts nutzen, die keinen Zugriff auf weitere Systeme erm\u00f6glichen.",
@@ -93,6 +98,7 @@
"lang_runScriptDeleteConfirmation": "Skript wirklich l\u00f6schen?",
"lang_runtimeConfig": "Laufzeit-Konfiguration",
"lang_runtimeConfigLimits": "Beschr\u00e4nkungen",
+ "lang_scanButton": "VM-Store durchsuchen",
"lang_scriptContent": "Skriptinhalt",
"lang_scriptExtension": "Dateinamenerweiterung",
"lang_scriptExtensionHead": "Erweiterung",
@@ -121,6 +127,7 @@
"lang_sslExplicit": "Explizites SSL (\"STARTTLS\")",
"lang_sslImplicit": "Implizites SSL",
"lang_sslNone": "Kein SSL",
+ "lang_status": "Status",
"lang_superUser": "Ist SuperUser (darf alle Veranstaltungen und VMs bearbeiten\/l\u00f6schen)",
"lang_system": "System",
"lang_target": "Ziel",
diff --git a/modules-available/dozmod/lang/en/messages.json b/modules-available/dozmod/lang/en/messages.json
index 84677402..1b46339b 100644
--- a/modules-available/dozmod/lang/en/messages.json
+++ b/modules-available/dozmod/lang/en/messages.json
@@ -1,6 +1,5 @@
{
"all-templates-reset": "All templates have been reset",
- "delete-images": "Delete: {{0}}",
"dozmod-error": "Error communicating with the bwLehrpool-Suite server: {{0}}",
"images-pending-delete-exist": "VMs marked for deletion: {{0}}",
"ldap-filter-created": "LDAP filter was successfully created",
diff --git a/modules-available/dozmod/lang/en/permissions.json b/modules-available/dozmod/lang/en/permissions.json
index 3d82bdda..479b150b 100644
--- a/modules-available/dozmod/lang/en/permissions.json
+++ b/modules-available/dozmod/lang/en/permissions.json
@@ -8,6 +8,8 @@
"networkrules.view": "View network rules.",
"networkshares.save": "Save network drives.",
"networkshares.view": "View network drives.",
+ "orphaned.delete": "Delete orphaned files from VM store.",
+ "orphaned.scan": "Scan for orphaned files on VM store.",
"runscripts.save": "Save startup scripts.",
"runscripts.view": "View startup scripts.",
"runtimeconfig.save": "Save limits and defaults of a runtime configuration.",
diff --git a/modules-available/dozmod/lang/en/template-tags.json b/modules-available/dozmod/lang/en/template-tags.json
index 1ab25a06..425ceefa 100644
--- a/modules-available/dozmod/lang/en/template-tags.json
+++ b/modules-available/dozmod/lang/en/template-tags.json
@@ -11,6 +11,7 @@
"lang_bwlehrpoolsuite": "bwLehrpool-Suite",
"lang_canLoginOrganization": "Users from this organization can login",
"lang_canLoginUser": "This user can login",
+ "lang_confirmDeleteOrphanedFiles": "Are you sure you want to permanently delete the files listed below?",
"lang_createTime": "Created",
"lang_currentFilter": "Current filter",
"lang_defaultImagePermissionAdmin": "Administrate",
@@ -21,6 +22,7 @@
"lang_defaultLecturePermissions": "For lectures",
"lang_defaultPermissions": "Default permissions",
"lang_delButton": "Permanently delete selected images",
+ "lang_deleteExpiredHeading": "Images marked for deletion",
"lang_descriptionPermissionConfig": "These are the default permissions being used for VMs and lectures if the owner does not specify any.",
"lang_descriptionRuntimeLimits": "Here you can define some limits, e.g. how long a newly uploaded VM will be valid. This should make sure that you don't end up with a lot of old, unused VMs over time.\r\n\r\nModified settings won't apply for already existing VMs.",
"lang_description_delete_images": "This is a list of VMs that either expired, or where the disk image is damaged or missing. These VMs are not available in bwLehrpool currently, but you have to manually confirm the deletion of the disk images for safety reasons (clock skew etc.)",
@@ -33,11 +35,11 @@
"lang_emailNotifications": "E-Mail notifications enabled",
"lang_error": "Error",
"lang_event": "Event",
+ "lang_fileName": "File name",
"lang_fileSize": "File size",
"lang_followingPlaceholdersUnused": "The following placeholders are not being used",
"lang_hasNewer": "newer version exists",
"lang_hash": "Hash",
- "lang_heading": "Images Marked for Deletion",
"lang_hidden": "Hidden",
"lang_host": "Host",
"lang_image": "VM",
@@ -77,6 +79,9 @@
"lang_normal": "Normal",
"lang_organization": "Organization",
"lang_organizationListHeader": "Set access permissions for organizations",
+ "lang_orphanDeleteButton": "Delete files",
+ "lang_orphanedFilesDesc": "Files listed here could not be matched to any VM from the database. If you're sure that these files aren't used for anything else (e.g. shared VM store), you can delete these files to free up space. If you're not sure, leave them alone or manually examine the situation on the file system.",
+ "lang_orphanedFilesHeading": "Orphaned files on VM store",
"lang_os": "Operating System",
"lang_owner": "Owner",
"lang_passwordCleartextHint": "Please not that explicitly provided credentials will be passed in clear text. You should only use dedicated accounts that don't give access to anything else than the desired network share(s).",
@@ -93,6 +98,7 @@
"lang_runScriptDeleteConfirmation": "Do you want to delete this run-script?",
"lang_runtimeConfig": "Limits and Defaults",
"lang_runtimeConfigLimits": "Limitations",
+ "lang_scanButton": "Scan VM store",
"lang_scriptContent": "Script content",
"lang_scriptExtension": "Script extension",
"lang_scriptExtensionHead": "Extension",
@@ -121,6 +127,7 @@
"lang_sslExplicit": "Explicit SSL (\"STARTTLS\")",
"lang_sslImplicit": "Implicit SSL",
"lang_sslNone": "No SSL",
+ "lang_status": "Status",
"lang_superUser": "Is super user (can edit\/delete all lectures and VMs)",
"lang_system": "System",
"lang_target": "Target",
diff --git a/modules-available/dozmod/pages/expiredimages.inc.php b/modules-available/dozmod/pages/expiredimages.inc.php
index 2b5a2274..ffd7b026 100644
--- a/modules-available/dozmod/pages/expiredimages.inc.php
+++ b/modules-available/dozmod/pages/expiredimages.inc.php
@@ -5,40 +5,7 @@ class SubPage
public static function doPreprocess()
{
- $action = Request::post('action', false, 'string');
- if ($action === 'delimages') {
- if (User::hasPermission("expiredimages.delete")) {
- $result = self::handleDeleteImages();
- if (!empty($result)) {
- Message::addInfo('delete-images', $result);
- }
- Util::redirect('?do=DozMod');
- }
- }
- }
-
- private static function handleDeleteImages()
- {
- $images = Request::post('images', false);
- if (is_array($images)) {
- foreach ($images as $image => $val) {
- if (strtolower($val) !== 'on')
- continue;
- Database::exec("UPDATE sat.imageversion SET deletestate = 'WANT_DELETE'"
- . " WHERE deletestate = 'SHOULD_DELETE' AND imageversionid = :imageversionid", array(
- 'imageversionid' => $image
- ));
- }
- if (!empty($images)) {
- $ret = Download::asStringPost('http://127.0.0.1:9080/do/delete-images', false, 10, $code);
- if ($code == 999) {
- $ret .= "\nConnection to DMSD failed.";
- }
- return $ret;
- }
- }
- return false;
}
private static function loadExpiredImages()
@@ -80,7 +47,9 @@ class SubPage
if (empty($expiredImages)) {
Message::addSuccess('no-expired-images');
} else {
- Render::addTemplate('images-delete', array('images' => $expiredImages, 'allowedDelete' => User::hasPermission("expiredimages.delete")));
+ $data = ['images' => $expiredImages];
+ Permission::addGlobalTags($data['perm'], null, ['expiredimages.delete', 'orphaned.scan']);
+ Render::addTemplate('images-delete', $data);
}
}
@@ -88,10 +57,72 @@ class SubPage
{
$action = Request::post('action');
if ($action === 'delimages') {
- User::assertPermission("expiredimages.delete");
- die(self::handleDeleteImages());
+ self::handleDeleteImages();
+ } elseif ($action === 'orphaned') {
+ self::handleOrphaned();
+ } else {
+ echo 'Huh?';
+ }
+ }
+
+ private static function handleDeleteImages()
+ {
+ User::assertPermission("expiredimages.delete");
+ $images = Request::post('images', false);
+ $result = false;
+ if (is_array($images)) {
+ foreach ($images as $image => $val) {
+ if (strtolower($val) !== 'on')
+ continue;
+ Database::exec("UPDATE sat.imageversion SET deletestate = 'WANT_DELETE'"
+ . " WHERE deletestate = 'SHOULD_DELETE' AND imageversionid = :imageversionid", array(
+ 'imageversionid' => $image
+ ));
+ }
+ if (!empty($images)) {
+ $result = Download::asStringPost('http://127.0.0.1:9080/do/delete-images', false, 10, $code);
+ if ($code == 999) {
+ $result .= "\nConnection to DMSD failed.";
+ }
+ }
+ }
+ if (!empty($result)) {
+ echo $result;
+ }
+ }
+
+ private static function handleOrphaned()
+ {
+ if (Request::post('delete', 0, 'int') !== 0) {
+ User::assertPermission("orphaned.delete");
+ $action = 'delete';
+ } else {
+ User::assertPermission("orphaned.scan");
+ $action = 'scan';
+ }
+ // Talk to dmsd
+ $result = Download::asStringPost('http://127.0.0.1:9080/do/scan-orphaned-files', ['action' => $action],
+ 10, $code);
+ if ($code == 999) {
+ $result = '<div class="alert alert-warning">'
+ . $result . ' - Connection to DMSD failed.</div>';
+ } else {
+ $json = json_decode($result, true);
+ if (is_array($json)) {
+ $result = [];
+ $showDelete = false;
+ foreach ($json as $k => $v) {
+ $result[] = ['file' => $k, 'status' => $v];
+ if ($v === 'EXISTS') {
+ $showDelete = true;
+ }
+ }
+ $data = ['files' => $result, 'show_delete' => $showDelete];
+ Permission::addGlobalTags($data['perm'], null, ['orphaned.delete']);
+ $result = Render::parse('images-orphaned', $data);
+ }
}
- die('Huh?');
+ echo $result;
}
}
diff --git a/modules-available/dozmod/permissions/permissions.json b/modules-available/dozmod/permissions/permissions.json
index c8958089..12d0acd3 100644
--- a/modules-available/dozmod/permissions/permissions.json
+++ b/modules-available/dozmod/permissions/permissions.json
@@ -2,6 +2,12 @@
"expiredimages.delete": {
"location-aware": false
},
+ "orphaned.scan": {
+ "location-aware": false
+ },
+ "orphaned.delete": {
+ "location-aware": false
+ },
"actionlog.view": {
"location-aware": false
},
diff --git a/modules-available/dozmod/templates/images-delete.html b/modules-available/dozmod/templates/images-delete.html
index 78690426..9d61559f 100644
--- a/modules-available/dozmod/templates/images-delete.html
+++ b/modules-available/dozmod/templates/images-delete.html
@@ -2,96 +2,142 @@
<div class="panel panel-default">
<div class="panel-heading">
- {{lang_heading}}
+ {{lang_deleteExpiredHeading}}
</div>
<div class="panel-body">
<p>{{lang_description_delete_images}}</p>
<div class="table-responsive">
- <form id="delform" method="post" action="?do=DozMod" onsubmit="return slxPostdel()">
+ <form id="delform" method="post" action="?do=dozmod">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="section" value="expiredimages">
<input type="hidden" name="action" value="delimages">
<table class="table table-stripped table-condensed stupidtable">
<thead>
- <tr>
- <th data-sort="string">{{lang_image}}</th>
- <th data-sort="int">{{lang_version}}</th>
- <th data-sort="string">{{lang_owner}}</th>
- <th><span class="glyphicon glyphicon-upload" title="{{lang_hasNewer}}"></span></th>
- <th data-sort="int">{{lang_size}}</th>
- <th>
- <div class="checkbox">
- <input id="del-all" type="checkbox" onclick="slxChangeAll()">
- <label for="del-all"></label>
- <span class="glyphicon glyphicon-trash" title="{{lang_delete}}"></span>
- </div>
- </th>
- </tr>
+ <tr>
+ <th data-sort="string">{{lang_image}}</th>
+ <th data-sort="int">{{lang_version}}</th>
+ <th data-sort="string">{{lang_owner}}</th>
+ <th><span class="glyphicon glyphicon-upload" title="{{lang_hasNewer}}"></span></th>
+ <th data-sort="int">{{lang_size}}</th>
+ <th>
+ <div class="checkbox">
+ <input id="del-all" type="checkbox">
+ <label for="del-all"></label>
+ <span class="glyphicon glyphicon-trash" title="{{lang_delete}}"></span>
+ </div>
+ </th>
+ </tr>
</thead>
<tbody>
- {{#images}}
- <tr>
- <td class="text-left text-nowrap {{name_extra_class}}">{{displayname}}<br><span class="small">{{imageversionid}}</span></td>
- <td class="text-left text-nowrap" data-sort-value="{{createtime}}" >{{version}}</td>
- <td class="text-left text-nowrap"><a href="mailto:{{email}}">{{lastname}}, {{firstname}}</a></td>
- <td class="text-left text-nowrap"><span class="glyphicon {{hasNewerClass}}"></span></td>
- <td class="text-left text-nowrap" data-sort-value="{{rawfilesize}}">{{filesize}}</td>
- <td>
- <div class="checkbox">
- <input type="checkbox" id="images[{{imageversionid}}]" class="del-check" name="images[{{imageversionid}}]" {{checked}}>
- <label for="images[{{imageversionid}}]"></label>
- </div>
- </td>
- </tr>
- {{/images}}
+ {{#images}}
+ <tr>
+ <td class="text-left text-nowrap {{name_extra_class}}">{{displayname}}<br><span class="small">{{imageversionid}}</span>
+ </td>
+ <td class="text-left text-nowrap" data-sort-value="{{createtime}}">{{version}}</td>
+ <td class="text-left text-nowrap"><a href="mailto:{{email}}">{{lastname}}, {{firstname}}</a></td>
+ <td class="text-left text-nowrap"><span class="glyphicon {{hasNewerClass}}"></span></td>
+ <td class="text-left text-nowrap" data-sort-value="{{rawfilesize}}">{{filesize}}</td>
+ <td>
+ <div class="checkbox">
+ <input type="checkbox" id="images[{{imageversionid}}]" class="del-check"
+ name="images[{{imageversionid}}]" {{checked}}>
+ <label for="images[{{imageversionid}}]"></label>
+ </div>
+ </td>
+ </tr>
+ {{/images}}
</tbody>
</table>
- <button {{^allowedDelete}}disabled{{/allowedDelete}} style="margin-left: 20px" id="delbtn" class="btn btn-danger pull-right" type="submit" name="button" value="save"><span class="glyphicon glyphicon-trash"></span> {{lang_delButton}}</button>
+ <button {{perm.expiredimages.delete.disabled}} id="expired-delete"
+ class="btn btn-danger pull-right" type="submit">
+ <span class="glyphicon glyphicon-trash"></span>
+ {{lang_delButton}}
+ </button>
</form>
<pre style="display:none" id="deloutput"></pre>
</div>
</div>
</div>
-<script type="text/javascript"><!--
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_orphanedFilesHeading}}
+ </div>
+ <div class="panel-body">
+ <p>{{lang_orphanedFilesDesc}}</p>
+ <div id="orphan-ajax">
+ <button {{perm.orphaned.scan.disabled}} id="orphan-scan"
+ class="btn btn-default pull-right" type="button">
+ <span class="glyphicon glyphicon-search"></span>
+ {{lang_scanButton}}
+ </button>
+ </div>
+ </div>
+</div>
-function slxPostdel() {
- var f = $('#delform');
- $('#delbtn').prop('disabled', true);
- $.post('?do=DozMod', f.serialize()).done(function (data) {
- $('#deloutput').text(data).css('display', '');
- }).fail(function () {
- $('#deloutput').text('ERROR').css('display', '');
- });
- return false;
-}
+<div class="hidden" id="confirm-orphan-delete">
+ {{lang_confirmDeleteOrphanedFiles}}
+</div>
-function slxChangeAll()
-{
- if ($('#del-all').is(':checked')) {
- $('.del-check').prop('checked', true);
- } else {
- $('.del-check').prop('checked', false);
- }
-}
+<script type="text/javascript"><!--
-function slxChangeSingle()
-{
- var ons = 0;
- var offs = 0;
- $('.del-check').each(function(idx, elem) {
- if (elem.checked) {
- ons++;
+document.addEventListener("DOMContentLoaded", function () {
+ $('#del-all').click(function () {
+ if ($(this).is(':checked')) {
+ $('.del-check').prop('checked', true);
} else {
- offs++;
+ $('.del-check').prop('checked', false);
}
});
- $('#del-all').prop('checked', offs === 0).prop('indeterminate', ons > 0 && offs > 0);
-}
-
-document.addEventListener("DOMContentLoaded", function() {
+ var slxChangeSingle = function () {
+ var ons = 0;
+ var offs = 0;
+ $('.del-check').each(function (idx, elem) {
+ if (elem.checked) {
+ ons++;
+ } else {
+ offs++;
+ }
+ });
+ // TODO indeterminate doesn't work with styled checkbox
+ $('#del-all').prop('checked', offs === 0).prop('indeterminate', ons > 0 && offs > 0);
+ };
$('.del-check').click(slxChangeSingle);
slxChangeSingle();
+ // Handler for delete expired images button
+ var delform = $('#delform');
+ delform.submit(function (e) {
+ e.preventDefault();
+ $('#expired-delete').prop('disabled', true);
+ $.post('?do=dozmod', delform.serialize()).done(function (data) {
+ $('#deloutput').text(data).css('display', '');
+ }).fail(function () {
+ $('#deloutput').text('ERROR').css('display', '');
+ });
+ });
+ // Handler for scanning/deleting orphaned files
+ var slxOrphans = function (del) {
+ $.post('?do=dozmod', {
+ token: TOKEN, section: 'expiredimages', action: 'orphaned', delete: del
+ }).done(function (data) {
+ $('#orphan-ajax').html(data).find('#orphan-delete')
+ .click(slxModalConfirmHandler)
+ .click(function () {
+ slxOrphans(1);
+ });
+ }).fail(function () {
+ $('#orphan-ajax').text('ERROR');
+ });
+ };
+ // Handler for scanning for orphaned files
+ $('#orphan-scan').click(function () {
+ $('#orphan-scan').prop('disabled', true);
+ slxOrphans(0);
+ });
+ window.addEventListener('unload', function () {
+ // Do something here that forces browsers to throw away any JS state on nav.back
+ $('input[type=checkbox]').prop('checked', false);
+ });
}, false);
//--> </script>
diff --git a/modules-available/dozmod/templates/images-orphaned.html b/modules-available/dozmod/templates/images-orphaned.html
new file mode 100644
index 00000000..d1b74a42
--- /dev/null
+++ b/modules-available/dozmod/templates/images-orphaned.html
@@ -0,0 +1,25 @@
+<table class="table">
+ <thead>
+ <tr>
+ <th>{{lang_fileName}}</th>
+ <th>{{lang_status}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#files}}
+ <tr>
+ <td>{{file}}</td>
+ <td>{{status}}</td>
+ </tr>
+ {{/files}}
+ </tbody>
+</table>
+
+{{#show_delete}}
+<button {{perm.orphaned.delete.disabled}} id="orphan-delete"
+ class="btn btn-danger pull-right" type="button"
+ data-confirm="#confirm-orphan-delete">
+ <span class="glyphicon glyphicon-search"></span>
+ {{lang_orphanDeleteButton}}
+</button>
+{{/show_delete}} \ No newline at end of file
diff --git a/script/slx-fixes.js b/script/slx-fixes.js
index 992ca337..a06761e4 100644
--- a/script/slx-fixes.js
+++ b/script/slx-fixes.js
@@ -61,6 +61,7 @@ $(document).ready(function() {
var $title, $body, $button, $modal = null, $cache = {};
slxModalConfirmHandler = function (e) {
e.preventDefault();
+ e.stopImmediatePropagation();
var $this = $(this);
if ($modal === null) {
$modal = $('<div class="modal fade" id="modal-autogen" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal">&times;</button>'
@@ -74,7 +75,7 @@ $(document).ready(function() {
$title.text($this.data('title') || $this.text());
$button.html($this.data('close') || $this.html()).attr('class', $this.attr('class')).removeClass('btn-xs btn-sm btn-lg').off('click').click(function() {
// Click and reconnect click handler so pressing "back" on the next page works
- $this.off('click').click().click(slxModalConfirmHandler);
+ $this.off('click', slxModalConfirmHandler).click().click(slxModalConfirmHandler);
});
var $wat, str = $this.data('confirm');
if (str.substr(0, 9) === '#confirm-') {