summaryrefslogtreecommitdiffstats
path: root/modules-available/dozmod
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/dozmod')
-rw-r--r--modules-available/dozmod/api.inc.php60
-rw-r--r--modules-available/dozmod/inc/pagedozmodlog.inc.php156
-rw-r--r--modules-available/dozmod/inc/pagedozmodusers.inc.php115
-rw-r--r--modules-available/dozmod/inc/pagemailtemplates.inc.php79
-rw-r--r--modules-available/dozmod/lang/de/messages.json8
-rw-r--r--modules-available/dozmod/lang/de/module.json11
-rw-r--r--modules-available/dozmod/lang/de/template-tags.json47
-rw-r--r--modules-available/dozmod/lang/en/messages.json8
-rw-r--r--modules-available/dozmod/lang/en/module.json8
-rw-r--r--modules-available/dozmod/lang/en/template-tags.json41
-rw-r--r--modules-available/dozmod/page.inc.php213
-rw-r--r--modules-available/dozmod/style.css51
-rw-r--r--modules-available/dozmod/templates/actionlog-header.html1
-rw-r--r--modules-available/dozmod/templates/actionlog-image.html30
-rw-r--r--modules-available/dozmod/templates/actionlog-lecture.html30
-rw-r--r--modules-available/dozmod/templates/actionlog-log.html41
-rw-r--r--modules-available/dozmod/templates/actionlog-user.html23
-rw-r--r--modules-available/dozmod/templates/blockstats-details.html16
-rw-r--r--modules-available/dozmod/templates/blockstats.html33
-rw-r--r--modules-available/dozmod/templates/images-delete.html12
-rw-r--r--modules-available/dozmod/templates/mailconfig.html2
-rw-r--r--modules-available/dozmod/templates/orglist.html36
-rw-r--r--modules-available/dozmod/templates/runtimeconfig.html93
-rw-r--r--modules-available/dozmod/templates/templates.html95
-rw-r--r--modules-available/dozmod/templates/userlist.html40
25 files changed, 911 insertions, 338 deletions
diff --git a/modules-available/dozmod/api.inc.php b/modules-available/dozmod/api.inc.php
index dc9788fc..accfe813 100644
--- a/modules-available/dozmod/api.inc.php
+++ b/modules-available/dozmod/api.inc.php
@@ -99,18 +99,66 @@ function xmlToLectureIds($responseXML)
return $uuids;
}
+function sendExamModeMismatch()
+{
+ Header('Content-Type: text/xml; charset=utf-8');
+ echo
+ <<<BLA
+ <settings>
+ <eintrag>
+ <image_name param="null"/>
+ <priority param="100"/>
+ <creator param="Ernie Esslingen"/>
+ <short_description param="Klausurmodus geändert, bitte PC neustarten"/>
+ <long_description param="Der Klausurmodus wurde ein- oder ausgeschaltet, bitte starten Sie den PC neu"/>
+ <uuid param="exam-mode-warning"/>
+ <virtualmachine param="exam-mode-warning"/>
+ <os param="debian8"/>
+ <virtualizer_name param="null"/>
+ <os_name param="null"/>
+ <for_location param="0"/>
+ <is_template param="0"/>
+ </eintrag>
+ <eintrag>
+ <image_name param="null"/>
+ <priority param="200"/>
+ <creator param="Ernie Esslingen"/>
+ <short_description param="Exam mode changed, please reboot PC"/>
+ <long_description param="Exam mode has been activated or deactivated since this PC was booted; please reboot the PC"/>
+ <uuid param="exam-mode-warning"/>
+ <virtualmachine param="exam-mode-warning"/>
+ <os param="debian8"/>
+ <virtualizer_name param="null"/>
+ <os_name param="null"/>
+ <for_location param="0"/>
+ <is_template param="0"/>
+ </eintrag>
+ </settings>
+BLA;
+ exit(0);
+}
+
/** Caching wrapper around _getLecturesForLocations() */
function getListForLocations($locationIds, $raw)
{
/* if in any of the locations there is an exam active, consider the client
to be in "exam-mode" and only offer him exams (no lectures) */
$key = 'lectures_' . cache_hash($locationIds);
- $examMode = false;
+ $examMode = Request::get('exams', 'normal-mode', 'string') !== 'normal-mode';
+ $clientServerMismatch = false;
if (Module::isAvailable('exams')) {
- $examMode = Exams::isInExamMode($locationIds);
- if ($examMode) {
- $key .= '_exams';
- }
+ // If we have the exam mode module, we can enforce a server side check and make sure it agrees with the client
+ $serverExamMode = Exams::isInExamMode($locationIds);
+ $clientServerMismatch = ($serverExamMode !== $examMode);
+ $examMode = $serverExamMode;
+ }
+ // Only enforce exam mode validity check if the client requests the raw xml data
+ if ($raw && $clientServerMismatch) {
+ sendExamModeMismatch(); // does not return
+ }
+ // Proceed normally from here on
+ if ($examMode) {
+ $key .= '_exams';
}
$rawKey = $key . '_raw';
if ($raw) {
@@ -189,7 +237,7 @@ function outputNetrules($lecture_uuid)
function outputRunscript($lecture_uuid)
{
- $key = 'netrules_' . $lecture_uuid;
+ $key = 'runscript_' . $lecture_uuid;
if (cache_has($key)) {
cache_get_passthru($key);
} else {
diff --git a/modules-available/dozmod/inc/pagedozmodlog.inc.php b/modules-available/dozmod/inc/pagedozmodlog.inc.php
new file mode 100644
index 00000000..f31edf5b
--- /dev/null
+++ b/modules-available/dozmod/inc/pagedozmodlog.inc.php
@@ -0,0 +1,156 @@
+<?php
+
+class Page_dozmod_log extends Page
+{
+
+ private $action;
+ private $uuid;
+
+ protected function doPreprocess()
+ {
+ $this->action = Request::get('action', '', 'string');
+ if ($this->action !== '' && $this->action !== 'showtarget' && $this->action !== 'showuser') {
+ Util::traceError('Invalid action for actionlog: "' . $this->action . '"');
+ }
+ $this->uuid = Request::get('uuid', '', 'string');
+ }
+
+ protected function doRender()
+ {
+ Render::addTemplate('actionlog-header');
+ if ($this->action === '') {
+ $this->generateLog("SELECT al.dateline, al.targetid, al.description,"
+ . " img.displayname AS imgname, tu.firstname AS tfirstname, tu.lastname AS tlastname, l.displayname AS lecturename,"
+ . " al.userid AS uuserid, usr.firstname AS ufirstname, usr.lastname AS ulastname"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.imagebase img ON (img.imagebaseid = targetid)"
+ . " LEFT JOIN sat.user usr ON (usr.userid = al.userid)"
+ . " LEFT JOIN sat.user tu ON (tu.userid = al.targetid)"
+ . " LEFT JOIN sat.lecture l ON (l.lectureid = targetid)"
+ . " ORDER BY al.dateline DESC LIMIT 500", array(), true, true);
+ } elseif ($this->action === 'showuser') {
+ $this->listUser();
+ } else {
+ $this->listTarget();
+ }
+ }
+
+ private function listUser()
+ {
+ // Query user
+ $user = Database::queryFirst('SELECT userid, firstname, lastname, email, lastlogin,'
+ . ' organization.displayname AS orgname FROM sat.user'
+ . ' LEFT JOIN sat.organization USING (organizationid)'
+ . ' WHERE userid = :uuid'
+ . ' LIMIT 1', array('uuid' => $this->uuid));
+ if ($user === false) {
+ Message:addError('unknown-userid', $this->uuid);
+ Util::redirect('?do=dozmod&section=actionlog');
+ }
+ // Mangle date and render
+ $user['lastlogin_s'] = date('d.m.Y H:i', $user['lastlogin']);
+ Render::addTemplate('actionlog-user', $user);
+ // Finally add the actionlog
+ $this->generateLog("SELECT al.dateline, al.targetid, al.description,"
+ . " img.displayname AS imgname, usr.firstname AS tfirstname, usr.lastname AS tlastname, l.displayname AS lecturename"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.imagebase img ON (img.imagebaseid = targetid)"
+ . " LEFT JOIN sat.user usr ON (usr.userid = targetid)"
+ . " LEFT JOIN sat.lecture l ON (l.lectureid = targetid)"
+ . " WHERE al.userid = :uuid"
+ . " ORDER BY al.dateline DESC LIMIT 500", array('uuid' => $this->uuid), false, true);
+ }
+
+ private function listTarget()
+ {
+ // We have to guess what kind of target it is
+ if (!$this->addImageHeader()
+ && !$this->addLectureHeader()) {
+ Message:addError('unknown-targetid', $this->uuid);
+ // Keep going, there might still be log entries for a deleted uuid
+ }
+
+ // Finally add the actionlog
+ $this->generateLog("SELECT al.dateline, al.userid AS uuserid, al.description,"
+ . " usr.firstname AS ufirstname, usr.lastname AS ulastname"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.user usr ON (usr.userid = al.userid)"
+ . " WHERE al.targetid = :uuid"
+ . " ORDER BY al.dateline DESC LIMIT 500", array('uuid' => $this->uuid), true, false);
+ }
+
+ private function addImageHeader()
+ {
+ $image = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname,'
+ . ' u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname,'
+ . ' img.displayname, img.description, img.createtime, img.updatetime,'
+ . ' os.displayname AS osname'
+ . ' FROM sat.imagebase img'
+ . ' LEFT JOIN sat.user o ON (img.ownerid = o.userid)'
+ . ' LEFT JOIN sat.user u ON (img.updaterid = u.userid)'
+ . ' LEFT JOIN sat.operatingsystem os ON (img.osid = os.osid)'
+ . ' WHERE img.imagebaseid = :uuid'
+ . ' LIMIT 1', array('uuid' => $this->uuid));
+ if ($image !== false) {
+ // Mangle date and render
+ $image['createtime_s'] = date('d.m.Y H:i', $image['createtime']);
+ $image['updatetime_s'] = date('d.m.Y H:i', $image['updatetime']);
+ $image['descriptionHtml'] = nl2br(htmlspecialchars($image['description']));
+ Render::addTemplate('actionlog-image', $image);
+ }
+ return $image !== false;
+ }
+
+ private function addLectureHeader()
+ {
+ $lecture = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname,'
+ . ' u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname,'
+ . ' l.displayname, l.description, l.createtime, l.updatetime,'
+ . ' img.displayname AS imgname, img.imagebaseid'
+ . ' FROM sat.lecture l'
+ . ' LEFT JOIN sat.user o ON (l.ownerid = o.userid)'
+ . ' LEFT JOIN sat.user u ON (l.updaterid = u.userid)'
+ . ' LEFT JOIN sat.imageversion ver ON (ver.imageversionid = l.imageversionid)'
+ . ' LEFT JOIN sat.imagebase img ON (img.imagebaseid = ver.imagebaseid)'
+ . ' WHERE l.lectureid = :uuid'
+ . ' LIMIT 1', array('uuid' => $this->uuid));
+ if ($lecture !== false) {
+ // Mangle date and render
+ $lecture['createtime_s'] = date('d.m.Y H:i', $lecture['createtime']);
+ $lecture['updatetime_s'] = date('d.m.Y H:i', $lecture['updatetime']);
+ $lecture['descriptionHtml'] = nl2br(htmlspecialchars($lecture['description']));
+ Render::addTemplate('actionlog-lecture', $lecture);
+ }
+ return $lecture !== false;
+ }
+
+ private function generateLog($query, $params, $showActor, $showTarget)
+ {
+ // query action log
+ $res = Database::simpleQuery($query, $params);
+ $events = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['dateline_s'] = date('d.m.Y H:i', $row['dateline']);
+ if (isset($row['imgname'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showtarget&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['imgname'];
+ } elseif (isset($row['tlastname'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showuser&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['tlastname'] . ', ' . $row['tfirstname'];
+ } elseif (isset($row['lecturename'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showtarget&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['lecturename'];
+ }
+ $events[] = $row;
+ }
+ $data = array('events' => $events);
+ if ($showActor) {
+ $data['showActor'] = true;
+ }
+ if ($showTarget) {
+ $data['showTarget'] = true;
+ }
+ Render::addTemplate('actionlog-log', $data);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/dozmod/inc/pagedozmodusers.inc.php b/modules-available/dozmod/inc/pagedozmodusers.inc.php
new file mode 100644
index 00000000..8da07923
--- /dev/null
+++ b/modules-available/dozmod/inc/pagedozmodusers.inc.php
@@ -0,0 +1,115 @@
+<?php
+
+class Page_dozmod_users extends Page
+{
+
+ protected function doPreprocess()
+ {
+
+ }
+
+ protected function doRender()
+ {
+ $this->listUsers();
+ $this->listOrganizations();
+ }
+
+ protected function doAjax()
+ {
+ $action = Request::post('action', '', 'string');
+ if ($action === 'setmail' || $action === 'setsu' || $action == 'setlogin') {
+ $this->setUserOption($action);
+ } elseif ($action === 'setorglogin') {
+ $this->setOrgOption($action);
+ } else {
+ die('No such action');
+ }
+ }
+
+ // Helpers
+
+ private function listUsers()
+ {
+ $res = Database::simpleQuery('SELECT userid, firstname, lastname, email, lastlogin, user.canlogin, issuperuser, emailnotifications,'
+ . ' organization.displayname AS orgname FROM sat.user'
+ . ' LEFT JOIN sat.organization USING (organizationid)'
+ . ' ORDER BY lastname ASC, firstname ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['canlogin'] = $this->checked($row['canlogin']);
+ $row['issuperuser'] = $this->checked($row['issuperuser']);
+ $row['emailnotifications'] = $this->checked($row['emailnotifications']);
+ $row['lastlogin'] = date('d.m.Y', $row['lastlogin']);
+ $rows[] = $row;
+ }
+ Render::addTemplate('userlist', array('users' => $rows));
+ }
+
+ private function listOrganizations()
+ {
+ $res = Database::simpleQuery('SELECT organizationid, displayname, canlogin FROM sat.organization'
+ . ' ORDER BY displayname ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['canlogin'] = $this->checked($row['canlogin']);
+ $rows[] = $row;
+ }
+ Render::addTemplate('orglist', array('organizations' => $rows));
+ }
+
+ private function checked($val)
+ {
+ if ($val)
+ return 'checked="checked"';
+ return '';
+ }
+
+ private function setUserOption($option)
+ {
+ $val = (string) Request::post('value', '-');
+ if ($val !== '1' && $val !== '0')
+ die('Nein');
+ if ($option === 'setmail') {
+ $field = 'emailnotifications';
+ } elseif ($option === 'setsu') {
+ $field = 'issuperuser';
+ } elseif ($option === 'setlogin') {
+ $field = 'canlogin';
+ } else {
+ die('Unknown');
+ }
+ $user = (string) Request::post('userid', '?');
+ $ret = Database::exec("UPDATE sat.user SET $field = :onoff WHERE userid = :userid", array(
+ 'userid' => $user,
+ 'onoff' => $val
+ ));
+ error_log("Setting $field to $val for $user - affected: $ret");
+ if ($ret === false)
+ die('Error');
+ if ($ret === 0)
+ die(1 - $val);
+ die($val);
+ }
+
+ private function setOrgOption($option)
+ {
+ $val = (string) Request::post('value', '-');
+ if ($val !== '1' && $val !== '0')
+ die('Nein');
+ if ($option === 'setorglogin') {
+ $field = 'canlogin';
+ } else {
+ die('Unknown');
+ }
+ $ret = Database::exec("UPDATE sat.organization SET $field = :onoff WHERE organizationid = :organizationid", array(
+ 'organizationid' => (string) Request::post('organizationid', ''),
+ 'onoff' => $val
+ ));
+ if ($ret === false)
+ die('Error');
+ if ($ret === 0)
+ die(1 - $val);
+ die($val);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/dozmod/inc/pagemailtemplates.inc.php b/modules-available/dozmod/inc/pagemailtemplates.inc.php
index fedb13c8..ef52ec12 100644
--- a/modules-available/dozmod/inc/pagemailtemplates.inc.php
+++ b/modules-available/dozmod/inc/pagemailtemplates.inc.php
@@ -7,19 +7,16 @@ class Page_mail_templates extends Page
protected function doPreprocess()
{
- User::load();
-
- if (!User::hasPermission('superadmin')) {
- Message::addError('main.no-permission');
- Util::redirect('?do=Main');
- }
-
- $action = Request::get('action', 'show', 'string');
-
+ $action = Request::post('action', 'show', 'string');
if ($action === 'show') {
$this->fetchTemplates();
} elseif ($action === 'save') {
$this->handleSave();
+ } elseif ($action === 'reset') {
+ $this->handleReset();
+ } else {
+ Message::addError('main.invalid-action', $action);
+ Util::redirect('?do=dozmod&section=templates');
}
}
@@ -54,32 +51,41 @@ class Page_mail_templates extends Page
}
protected function doRender()
{
- //echo '<pre>';
- //var_dump($this->templates);
- //echo '</pre>';
- //die();
$this->enrichHtml();
Render::addTemplate('templates', ['templates' => $this->templates]);
}
private function handleSave() {
- $data = [];
- $data['templates'] = Request::post('templates');
- $data = $this->cleanTemplateArray($data);
- if ($data!= NULL) {
- $data = json_encode($data, JSON_PRETTY_PRINT);
- //echo '<pre>';
- //print_r($data);
- //echo '</pre>';
- //die();
+ $data = Request::post('templates');
+ if (is_array($data)) {
+ $this->fetchTemplates();
+ foreach ($this->templates as &$template) {
+ if (isset($data[$template['name']])) {
+ $template['template'] = $data[$template['name']]['template'];
+ }
+ }
+ unset($template);
+ $data = json_encode(array('templates' => $this->templates));
Database::exec("UPDATE sat.configuration SET value = :value WHERE parameter = 'templates'", array('value' => $data));
Message::addSuccess('templates-saved');
- Util::redirect('?do=dozmod&section=templates&action=show');
} else {
- die('error while encoding');
+ Message::addError('nothing-submitted');
}
+ Util::redirect('?do=dozmod&section=templates');
+ }
+ private function handleReset()
+ {
+ $result = Download::asStringPost('http://127.0.0.1:9080/do/reset-mail-templates', array(), 10, $code);
+ if ($code == 999) {
+ Message::addError('timeout');
+ } elseif ($code != 200) {
+ Message::addError('dozmod-error', $code);
+ } else {
+ Message::addSuccess('all-templates-reset', $result);
+ }
+ Util::redirect('?do=dozmod&section=templates');
}
private function fetchTemplates() {
@@ -87,33 +93,12 @@ class Page_mail_templates extends Page
if ($templates != null) {
$templates = @json_decode($templates['value'], true);
if (is_array($templates)) {
+ $names = array_map(function ($e) { return $e['name']; }, $templates['templates']);
+ array_multisort($names, SORT_ASC, $templates['templates']);
$this->templates = $templates['templates'];
}
}
}
- private function cleanTemplateArray($in) {
- $out = [];
- foreach ($in['templates'] as $t) {
- $tcopy = $t;
- $tcopy['mandatory_variables'] = $this->toArray($t['mandatory_variables']);
- $tcopy['optional_variables'] = $this->toArray($t['optional_variables']);
- $tcopy['description'] = $t['description'];
- $tcopy['name'] = $t['name'];
-
- $out['templates'][] = $tcopy;
- }
- return $out;
- }
-
- private function toArray($value) {
- if (empty($value)) {
- return [];
- } else if(is_array($value)) {
- return $value;
- } else {
- return array($value);
- }
- }
}
diff --git a/modules-available/dozmod/lang/de/messages.json b/modules-available/dozmod/lang/de/messages.json
index 7944ffae..e72fb1be 100644
--- a/modules-available/dozmod/lang/de/messages.json
+++ b/modules-available/dozmod/lang/de/messages.json
@@ -1,5 +1,11 @@
{
+ "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 Abbilder: {{0}}",
- "mail-config-saved": "Mail-Konfiguration gespeichert"
+ "mail-config-saved": "Mail-Konfiguration gespeichert",
+ "nothing-submitted": "Es wurde nichts \u00fcbermittelt",
+ "runtimelimits-config-saved": "Einstellungen gespeichert",
+ "templates-saved": "Templates wurden gespeichert",
+ "timeout": "Zeit\u00fcberschreitung"
} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/de/module.json b/modules-available/dozmod/lang/de/module.json
index df2b5d4b..5840d8af 100644
--- a/modules-available/dozmod/lang/de/module.json
+++ b/modules-available/dozmod/lang/de/module.json
@@ -1,8 +1,9 @@
{
- "module_name": "Dozentenmodul",
- "page_title": "Verwalten des Dozentenmoduls",
+ "module_name": "bwLehrpool-Suite",
+ "page_title": "Verwalten der bwLehrpool-Suite",
+ "submenu_actionlog": "Aktions-Log",
"submenu_mailconfig": "Email-Konfiguration",
- "submenu_runtime": "Laufzeit",
- "submenu_templates": "Vorlagen E-Mail",
- "submenu_users": "Benutzer"
+ "submenu_runtime": "Limits und Standardwerte",
+ "submenu_templates": "Textbausteine f\u00fcr E-Mails",
+ "submenu_users": "Benutzer und Berechtigungen"
} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/de/template-tags.json b/modules-available/dozmod/lang/de/template-tags.json
index f123db5b..fe558ed5 100644
--- a/modules-available/dozmod/lang/de/template-tags.json
+++ b/modules-available/dozmod/lang/de/template-tags.json
@@ -1,37 +1,54 @@
{
+ "lang_actionTarget": "Aktionsziel",
"lang_asteriskRequired": "Felder mit (*) sind erforderlich",
"lang_canLogin": "Nutzer dieser Einrichtung k\u00f6nnen sich am Satelliten anmelden",
- "lang_defaultImagePermissionAdmin": "Administration",
+ "lang_createTime": "Erstellt",
+ "lang_currentFilter": "Aktueller Filter",
+ "lang_defaultImagePermissionAdmin": "Administrieren",
"lang_defaultImagePermissionDownload": "Download",
"lang_defaultImagePermissionEdit": "Bearbeiten",
- "lang_defaultImagePermissionLink": "Verkn\u00fcpfen",
- "lang_defaultImagePermissions": "Standard-Berechtigungen f\u00fcr Images",
- "lang_defaultLecturePermissions": "Standard-Berechtigungen f\u00fcr Vorlesungen",
- "lang_delButton": "Gew\u00e4hlte Images endg\u00fcltig l\u00f6schen",
+ "lang_defaultImagePermissionLink": "Veranstaltung Verkn\u00fcpfen",
+ "lang_defaultImagePermissions": "F\u00fcr VMs",
+ "lang_defaultLecturePermissions": "F\u00fcr Veranstaltungen",
+ "lang_defaultPermissions": "Standardberechtigungen",
+ "lang_delButton": "Gew\u00e4hlte VMs endg\u00fcltig l\u00f6schen",
"lang_description": "Beschreibung",
- "lang_descriptionRuntimeConfig": "Blah blah blah",
- "lang_description_delete_images": "Diese Liste zeigt Images, 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.",
+ "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.",
+ "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.",
+ "lang_dozmodLogHeading": "bwLehrpool-Suite Aktionslog",
"lang_email": "EMail",
"lang_emailNotifications": "EMail-Benachrichtigungen aktiviert",
+ "lang_error": "Fehler",
+ "lang_event": "Ereignis",
+ "lang_followingPlaceholdersUnused": "Folgende Platzhalter m\u00fcssen im Template verwendet werden",
"lang_hasNewer": "Neuere Version existiert",
- "lang_heading": "Zu l\u00f6schende Image-Versionen",
+ "lang_heading": "Zu l\u00f6schende VM-Versionen",
"lang_host": "Host",
"lang_image": "VM",
+ "lang_lastEditor": "Zuletzt bearbeitet von",
"lang_lastLogin": "Letzte Anmeldung",
+ "lang_lecture": "Veranstaltung",
"lang_lecturePermissionAdmin": "Administration",
"lang_lecturePermissionEdit": "Bearbeiten",
+ "lang_loadDefaults": "Alle Texte auf Auslieferungszustand zur\u00fccksetzen",
"lang_mailConfig": "SMTP-Konfiguration zum Versenden von Mails",
"lang_mailConfigHeadline": "EMail-Konfiguration",
"lang_mailDescription": "F\u00fcllen Sie die folgenden Felder aus, wenn sie m\u00f6chten, dass Dozenten Benachrichtigungen per Mail bekommen, falls eine von ihnen genutzte oder erstellte VM oder Veranstaltung abl\u00e4uft. Um diese Funktion zu deaktivieren, lassen Sie eines der mit (*) gekennzeichneten Felder leer. Wenn das hier angegebene E-Mail-Konto nur zum Versenden von Mails genutzt wird, sollten Sie einen Auto-Responder einrichten f\u00fcr den Fall, dass ein Dozent auf eine der automatisch generierten Mails antwortet (bzw. eine explizit angegebene Reply-To Adresse ignoriert).",
- "lang_maxImageValidity": "Maximale G\u00fcltigkeit",
- "lang_maxLectureVisibility": "Maximale Sichtbarkeit",
- "lang_maxTransfers": "Maximale Anzahl an Uploads",
+ "lang_mailTemplates": "E-Mail Templates",
+ "lang_maxImageValidity": "G\u00fcltigkeitsdauer neuer VM-Versionen (Tage)",
+ "lang_maxLectureVisibility": "Sp\u00e4testes Enddatum einer Veranstaltung (Tage in der Zukunft)",
+ "lang_maxTransfers": "Maximale Zahl gleichzeitiger Up-\/Downloads pro Benutzer",
+ "lang_name": "Name",
"lang_organization": "Einrichtung",
"lang_organizationList": "Liste der Einrichtungen",
"lang_organizationListHeader": "Nutzungsrechte f\u00fcr den Satelliten festlegen",
+ "lang_os": "Betriebssystem",
"lang_owner": "Besitzer",
"lang_password": "Passwort",
+ "lang_placeholders": "Platzhalter",
"lang_port": "Port",
+ "lang_reallyResetTemplates": "Sind Sie sicher, dass Sie alle Texte l\u00f6schen und auf die Standardwerte zur\u00fccksetzen wollen?",
"lang_replyTo": "Reply-To Adresse (z.B. Helpdesk)",
"lang_runtimeConfig": "Laufzeit-Konfiguration",
"lang_runtimeConfigHeadline": "Laufzeit-Konfiguration",
@@ -45,13 +62,19 @@
"lang_sslNone": "Kein SSL",
"lang_subHeading": "Images, die abgelaufen oder besch\u00e4digt sind",
"lang_superUser": "Ist SuperUser (darf alle Veranstaltungen und VMs bearbeiten\/l\u00f6schen)",
+ "lang_system": "System",
+ "lang_template": "Template",
+ "lang_templatePageDescription": "Hier k\u00f6nnen Sie die Textbausteine bearbeiten, aus denen die Mails generiert werden, die der bwLehrpool-Server bez\u00fcglich Virtueller Maschinen und Veranstaltungen versendet. Diese Funktionalit\u00e4t unterst\u00fctzt zur Zeit keine Internationalisierung.",
"lang_test": "Test-Mail senden",
"lang_testConfiguration": "Um die Konfiguration zu testen, geben Sie hier eine Empf\u00e4ngeradresse ein",
"lang_testRecipient": "Empf\u00e4nger",
+ "lang_updateTime": "Letzte Bearbeitung",
"lang_user": "Benutzername",
+ "lang_userId": "Benutzer-ID",
"lang_userList": "Benutzerliste",
"lang_userListDescription": "Hier k\u00f6nnen Sie individuelle Nutzer zu \"Super-Usern\" machen. Diese haben im Dozentenmodul auf alle Veranstaltungen und VMs Vollzugriff, unabh\u00e4ngig von den gesetzten Berechtigungen. Au\u00dferdem k\u00f6nnen Sie hier Benutzer vom Zugriff mittels des Dozentenmoduls ausschlie\u00dfen.",
"lang_userListHeader": "Dem Satelliten bekannte Benutzer",
"lang_username": "Benutzername (SMTP-Auth)",
- "lang_version": "Version vom"
+ "lang_version": "Version vom",
+ "lang_when": "Wann"
} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/en/messages.json b/modules-available/dozmod/lang/en/messages.json
index 6651e32e..e1b5eea6 100644
--- a/modules-available/dozmod/lang/en/messages.json
+++ b/modules-available/dozmod/lang/en/messages.json
@@ -1,5 +1,11 @@
{
+ "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": "Images marked for deletion: {{0}}",
- "mail-config-saved": "Mail config saved"
+ "mail-config-saved": "Mail config saved",
+ "nothing-submitted": "There was nothing submitted",
+ "runtimelimits-config-saved": "Configuration saved successfully",
+ "templates-saved": "Templates saved successfully",
+ "timeout": "Timeout"
} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/en/module.json b/modules-available/dozmod/lang/en/module.json
index e42d21ea..742aa848 100644
--- a/modules-available/dozmod/lang/en/module.json
+++ b/modules-available/dozmod/lang/en/module.json
@@ -1,3 +1,9 @@
{
- "module_name": "Tutor Module"
+ "module_name": "bwLehrpool-Suite",
+ "page_title": "Manage the bwLehrpool-Suite",
+ "submenu_actionlog": "action log",
+ "submenu_mailconfig": "email configuration",
+ "submenu_runtime": "limits and defaults",
+ "submenu_templates": "templates",
+ "submenu_users": "users and permissions"
} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/en/template-tags.json b/modules-available/dozmod/lang/en/template-tags.json
index 2ed11a2a..6a0434a3 100644
--- a/modules-available/dozmod/lang/en/template-tags.json
+++ b/modules-available/dozmod/lang/en/template-tags.json
@@ -1,25 +1,58 @@
{
+ "lang_actionTarget": "Action target",
"lang_asteriskRequired": "Fields marked with (*) are required",
"lang_canLogin": "Members of this organization can login",
+ "lang_createTime": "Created",
+ "lang_currentFilter": "Current filter",
+ "lang_defaultImagePermissionAdmin": "Administrate",
+ "lang_defaultImagePermissionDownload": "Download",
+ "lang_defaultImagePermissionEdit": "Edit",
+ "lang_defaultImagePermissionLink": "Link lecture",
+ "lang_defaultImagePermissions": "For VMs",
+ "lang_defaultLecturePermissions": "For lectures",
+ "lang_defaultPermissions": "Default permissions",
"lang_delButton": "Permanently delete selected images",
"lang_description": "This list shows images that reached their expire date, or where the image file in the file system is damaged or missing. You need to manually confirm the deletion of these files for safety reasons (software bugs, wrong system time, etc.).",
+ "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.",
+ "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.)",
+ "lang_dozmodLogHeading": "bwLehrpool-Suite action log",
"lang_email": "E-Mail",
"lang_emailNotifications": "E-Mail notifications enabled",
+ "lang_error": "Error",
+ "lang_event": "Event",
+ "lang_followingPlaceholdersUnused": "The following placeholders are not being used",
"lang_hasNewer": "Newer version exists",
"lang_heading": "Images marked for deletion",
"lang_host": "Host",
"lang_image": "VM",
+ "lang_lastEditor": "Edited by",
"lang_lastLogin": "Last login",
+ "lang_lecture": "Lecture",
+ "lang_lecturePermissionAdmin": "Administrate",
+ "lang_lecturePermissionEdit": "Edit",
+ "lang_loadDefaults": "Reset all templates to their defaults",
"lang_mailConfig": "SMTP configuration for sending mails",
"lang_mailConfigHeadline": "email configuration",
"lang_mailDescription": "Fill in the following fields if you want to notify tutors\/professors\/lecturers about expiring VMs and lectures. If you leave one of the required fields blank, the feature will be disabled.",
+ "lang_mailTemplates": "E-Mail templates",
+ "lang_maxImageValidity": "New VM validity (days)",
+ "lang_maxLectureVisibility": "Max time lecture end date may lie in the future (days)",
+ "lang_maxTransfers": "Max concurrent transfers per user",
+ "lang_name": "Name",
"lang_organization": "Organization",
"lang_organizationList": "List of organizations",
"lang_organizationListHeader": "Set access permissions for organizations",
+ "lang_os": "Operating System",
"lang_owner": "Owner",
"lang_password": "Password",
+ "lang_placeholders": "Placeholders",
"lang_port": "Port",
+ "lang_reallyResetTemplates": "Are you sure you want to reset all texts to their default values?",
"lang_replyTo": "Reply-To address",
+ "lang_runtimeConfig": "Limits and Defaults",
+ "lang_runtimeConfigHeadline": "Configure limits and defaults for bwLehrpool-Suite",
+ "lang_runtimeConfigLimits": "Limitations",
"lang_senderAddress": "Sender address",
"lang_senderName": "Sender's display name",
"lang_size": "Size",
@@ -29,13 +62,19 @@
"lang_sslNone": "No SSL",
"lang_subHeading": "Expired or damaged images",
"lang_superUser": "Is super user (can edit\/delete all lectures and VMs)",
+ "lang_system": "System",
+ "lang_template": "Template",
+ "lang_templatePageDescription": "Here you can edit text fragments that are used to compose the information and reminder mails sent by the bwLehrpool server, e.g. when a lecture or VM is about to expire.",
"lang_test": "Send test mail",
"lang_testConfiguration": "To test the configuration, enter a recipient address here",
"lang_testRecipient": "Recipient",
+ "lang_updateTime": "Last update",
"lang_user": "User name",
+ "lang_userId": "User id",
"lang_userList": "User list",
"lang_userListDescription": "Here you can promote \"super users\", which will have all permissions in the \"Dozenzenmodul\". You can also ban users from accessing this server via the \"Dozentenmodul\".",
"lang_userListHeader": "Users known to this satellite",
"lang_username": "User name (SMTP auth)",
- "lang_version": "Version timestamp"
+ "lang_version": "Version timestamp",
+ "lang_when": "When"
} \ No newline at end of file
diff --git a/modules-available/dozmod/page.inc.php b/modules-available/dozmod/page.inc.php
index c1c19b15..dfb49e0b 100644
--- a/modules-available/dozmod/page.inc.php
+++ b/modules-available/dozmod/page.inc.php
@@ -2,8 +2,26 @@
class Page_DozMod extends Page
{
- /* sub page classes */
- private $mail_templates;
+ /** @var \Page sub page classes */
+ private $subPage = false;
+
+ private function setupSubPage()
+ {
+ if ($this->subPage !== false)
+ return;
+ /* different pages for different sections */
+ $section = Request::any('section', 'mailconfig', 'string');
+ /* instantiate sub pages */
+ if ($section === 'templates') {
+ $this->subPage = new Page_mail_templates();
+ }
+ if ($section === 'users') {
+ $this->subPage = new Page_dozmod_users();
+ }
+ if ($section === 'actionlog') {
+ $this->subPage = new Page_dozmod_log();
+ }
+ }
protected function doPreprocess()
{
@@ -15,20 +33,15 @@ class Page_DozMod extends Page
}
/* add sub-menus */
- Dashboard::addSubmenu('?do=dozmod&section=mailconfig', Dictionary::translate('submenu_mailconfig'));
- Dashboard::addSubmenu('?do=dozmod&section=templates', Dictionary::translate('submenu_templates'));
- Dashboard::addSubmenu('?do=dozmod&section=runtimeconfig', Dictionary::translate('submenu_runtime'));
- Dashboard::addSubmenu('?do=dozmod&section=users', Dictionary::translate('submenu_users'));
-
- /* instantiate sub pages */
- $this->mail_templates = new Page_mail_templates();
-
-
-
- /* different pages for different sections */
- $section = Request::get('section', 'mailconfig', 'string');
- if ($section == 'templates') {
- $this->mail_templates->doPreprocess();
+ Dashboard::addSubmenu('?do=dozmod&section=mailconfig', Dictionary::translate('submenu_mailconfig', true));
+ Dashboard::addSubmenu('?do=dozmod&section=templates', Dictionary::translate('submenu_templates', true));
+ Dashboard::addSubmenu('?do=dozmod&section=runtimeconfig', Dictionary::translate('submenu_runtime', true));
+ Dashboard::addSubmenu('?do=dozmod&section=users', Dictionary::translate('submenu_users', true));
+ Dashboard::addSubmenu('?do=dozmod&section=actionlog', Dictionary::translate('submenu_actionlog', true));
+
+ $this->setupSubPage();
+ if ($this->subPage !== false) {
+ $this->subPage->doPreprocess();
return;
}
@@ -52,15 +65,15 @@ class Page_DozMod extends Page
protected function doRender()
{
+ $this->listDeletePendingImages();
+
/* different pages for different sections */
- $section = Request::get('section', 'mailconfig', 'string');
- if ($section == 'templates') {
- $this->mail_templates->doRender();
+ if ($this->subPage !== false) {
+ $this->subPage->doRender();
return;
}
-
- $this->listDeletePendingImages();
+ $section = Request::get('section', 'mailconfig', 'string');
if ($section === 'mailconfig') {
// Mail config
@@ -102,12 +115,23 @@ class Page_DozMod extends Page
}
Render::addTemplate('runtimeconfig', $runtimeConf);
}
+ if ($section === 'blockstats') {
+ $this->showBlockStats();
+ }
- // User list for making people admin
- if ($section === 'users') {
- $this->listUsers();
- $this->listOrganizations();
+ }
+
+ private function showBlockStats()
+ {
+ $res = Database::simpleQuery("SELECT blocksha1, blocksize, Count(*) AS blockcount FROM sat.imageblock"
+ . " GROUP BY blocksha1, blocksize HAVING blockcount > 1 ORDER BY blockcount DESC, blocksha1 ASC");
+ $data = array('hashes' => array());
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['hash_hex'] = bin2hex($row['blocksha1']);
+ $row['blocksize_s'] = Util::readableFileSize($row['blocksize']);
+ $data['hashes'][] = $row;
}
+ Render::addTemplate('blockstats', $data);
}
private function listDeletePendingImages()
@@ -159,21 +183,55 @@ class Page_DozMod extends Page
protected function doAjax()
{
+ User::load();
if (!User::hasPermission('superadmin'))
return;
+ $this->setupSubPage();
+ if ($this->subPage !== false) {
+ $this->subPage->doAjax();
+ return;
+ }
+
$action = Request::post('action');
if ($action === 'mail') {
$this->handleTestMail();
- } elseif ($action === 'setmail' || $action === 'setsu' || $action == 'setlogin') {
- $this->setUserOption($action);
- } elseif ($action === 'setorglogin') {
- $this->setOrgOption($action);
} elseif ($action === 'delimages') {
die($this->handleDeleteImages());
+ } elseif ($action === 'getblockinfo') {
+ $this->ajaxGetBlockInfo();
}
}
+ private function ajaxGetBlockInfo()
+ {
+ $hash = Request::any('hash', false, 'string');
+ $size = Request::any('size', false, 'string');
+ if ($hash === false || $size === false) {
+ die('Missing parameter');
+ }
+ if (!is_numeric($size) || strlen($hash) !== 40 || !preg_match('/^[a-f0-9]+$/i', $hash)) {
+ die('Malformed parameter');
+ }
+ $res = Database::simpleQuery("SELECT i.displayname, v.createtime, v.filesize, Count(*) AS blockcount FROM sat.imageblock ib"
+ . " INNER JOIN sat.imageversion v USING (imageversionid)"
+ . " INNER JOIN sat.imagebase i USING (imagebaseid)"
+ . " WHERE ib.blocksha1 = :hash AND ib.blocksize = :size"
+ . " GROUP BY ib.imageversionid"
+ . " ORDER BY i.displayname ASC, v.createtime ASC",
+ array('hash' => hex2bin($hash), 'size' => $size), true);
+ if ($res === false) {
+ die('Database error: ' . Database::lastError());
+ }
+ $data = array('rows' => array());
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['createtime_s'] = date('d.m.Y H:i', $row['createtime']);
+ $row['filesize_s'] = Util::readableFileSize($row['filesize']);
+ $data['rows'][] = $row;
+ }
+ die(Render::parse('blockstats-details', $data));
+ }
+
private function handleDeleteImages()
{
$images = Request::post('images', false);
@@ -234,6 +292,8 @@ class Page_DozMod extends Page
'value' => $data
));
Message::addSuccess('mail-config-saved');
+ } else {
+ Message::addError('main.invalid-action', $do);
}
Util::redirect('?do=DozMod&section=mailconfig');
}
@@ -247,9 +307,14 @@ class Page_DozMod extends Page
$data['defaultLecturePermissions'] = Request::post('defaultLecturePermissions', NULL, "array");
$data['defaultImagePermissions'] = Request::post('defaultImagePermissions', NULL, "array");
- foreach(['maxImageValidityDays', 'maxLectureValidityDays', 'maxTransfers'] as $field) {
- $value = Request::post($field);
- $data[$field] = $value;
+ $intParams = [
+ 'maxImageValidityDays' => array('min' => 7, 'max' => 999),
+ 'maxLectureValidityDays' => array('min' => 7, 'max' => 999),
+ 'maxTransfers' => array('min' => 1, 'max' => 10),
+ ];
+ foreach($intParams as $field => $limits) {
+ $value = Request::post($field, 0, 'int');
+ $data[$field] = max(min($value, $limits['max']), $limits['min']);
}
/* ensure types */
@@ -275,88 +340,4 @@ class Page_DozMod extends Page
Util::redirect('?do=DozMod&section=runtimeconfig');
}
- private function listUsers()
- {
- $res = Database::simpleQuery('SELECT userid, firstname, lastname, email, lastlogin, user.canlogin, issuperuser, emailnotifications,'
- . ' organization.displayname AS orgname FROM sat.user'
- . ' LEFT JOIN sat.organization USING (organizationid)'
- . ' ORDER BY lastname ASC, firstname ASC');
- $rows = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $row['canlogin'] = $this->checked($row['canlogin']);
- $row['issuperuser'] = $this->checked($row['issuperuser']);
- $row['emailnotifications'] = $this->checked($row['emailnotifications']);
- $row['lastlogin'] = date('d.m.Y', $row['lastlogin']);
- $rows[] = $row;
- }
- Render::addTemplate('userlist', array('users' => $rows));
- }
-
- private function listOrganizations()
- {
- $res = Database::simpleQuery('SELECT organizationid, displayname, canlogin FROM sat.organization'
- . ' ORDER BY displayname ASC');
- $rows = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $row['canlogin'] = $this->checked($row['canlogin']);
- $rows[] = $row;
- }
- Render::addTemplate('orglist', array('organizations' => $rows));
- }
-
- private function checked($val)
- {
- if ($val)
- return 'checked="checked"';
- return '';
- }
-
- private function setUserOption($option)
- {
- $val = (string) Request::post('value', '-');
- if ($val !== '1' && $val !== '0')
- die('Nein');
- if ($option === 'setmail') {
- $field = 'emailnotifications';
- } elseif ($option === 'setsu') {
- $field = 'issuperuser';
- } elseif ($option === 'setlogin') {
- $field = 'canlogin';
- } else {
- die('Unknown');
- }
- $user = (string) Request::post('userid', '?');
- $ret = Database::exec("UPDATE sat.user SET $field = :onoff WHERE userid = :userid", array(
- 'userid' => $user,
- 'onoff' => $val
- ));
- error_log("Setting $field to $val for $user - affected: $ret");
- if ($ret === false)
- die('Error');
- if ($ret == 0)
- die(1 - $val);
- die($val);
- }
-
- private function setOrgOption($option)
- {
- $val = (string) Request::post('value', '-');
- if ($val !== '1' && $val !== '0')
- die('Nein');
- if ($option === 'setorglogin') {
- $field = 'canlogin';
- } else {
- die('Unknown');
- }
- $ret = Database::exec("UPDATE sat.organization SET $field = :onoff WHERE organizationid = :organizationid", array(
- 'organizationid' => (string) Request::post('organizationid', ''),
- 'onoff' => $val
- ));
- if ($ret === false)
- die('Error');
- if ($ret === 0)
- die(1 - $val);
- die($val);
- }
-
}
diff --git a/modules-available/dozmod/style.css b/modules-available/dozmod/style.css
index c6975d3e..8cc5548d 100644
--- a/modules-available/dozmod/style.css
+++ b/modules-available/dozmod/style.css
@@ -1,9 +1,3 @@
-
-
-input[type=checkbox] {
- border: 2px solid green !important;
-}
-
/* this is based on https://github.com/flatlogic/awesome-bootstrap-checkbox */
.checkbox {
@@ -47,6 +41,7 @@ input[type=checkbox] {
.checkbox input[type="radio"] {
opacity: 0;
z-index: 1;
+ top: -6px;
}
@@ -58,18 +53,44 @@ input[type=checkbox] {
}
.checkbox input[type="checkbox"]:checked + label::after,
.checkbox input[type="radio"]:checked + label::after {
- font-family: "FontAwesome";
- content: "\f00c";
+ font-family: "Glyphicons Halflings";
+ content: "\E013";
+}
+
+.witherror {
+ border: 1px solid red;
+}
+
+/*
+.table-input-group tr:first-child {
+ background: #EEEEEE url("./style/bg.png");
+ border-style: solid none solid solid;
+ border-radius: 4px 0px 0px 4px;
+ border-color: #CCCCCC #555555 #CCCCCC #CCCCCC;
+ border-width: 1px 0px 1px 1px;
+ color: #555555;
}
+*/
+.table-input-group {
+ border-collapse: separate;
+}
-input[type="checkbox"].styled:checked + label:after {
- font-family: 'FontAwesome';
- content: "\f00c";
+.table-input-group tr.input-group {
+ display: table-row;
+ width: auto;
+ border-collapse: separate;
}
-input[type="checkbox"] .styled:checked + label::before {
- color: #fff;
+
+.table-input-group tr.input-group td.input-group-addon {
+ text-align: left;
+ border-collapse: separate;
}
-input[type="checkbox"] .styled:checked + label::after {
- color: #fff;
+
+.table-input-group tr.input-group input.form-control {
+ width: auto;
+}
+
+.table-input-group tr.input-group td:last-child input {
+ border-radius: 0px 4px 4px 0px;
}
diff --git a/modules-available/dozmod/templates/actionlog-header.html b/modules-available/dozmod/templates/actionlog-header.html
new file mode 100644
index 00000000..bb32efda
--- /dev/null
+++ b/modules-available/dozmod/templates/actionlog-header.html
@@ -0,0 +1 @@
+<h2>{{lang_dozmodLogHeading}}</h2> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/actionlog-image.html b/modules-available/dozmod/templates/actionlog-image.html
new file mode 100644
index 00000000..cd8c8d1d
--- /dev/null
+++ b/modules-available/dozmod/templates/actionlog-image.html
@@ -0,0 +1,30 @@
+<h3>{{lang_currentFilter}}</h3>
+<table class="table table-bordered table-striped" style="width: auto">
+ <tr>
+ <th class="text-nowrap">{{lang_image}}</th>
+ <td>{{displayname}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_os}}</th>
+ <td>{{osname}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_owner}}</th>
+ <td><a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{ouserid}}">{{ofirstname}} {{olastname}}</a></td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_lastEditor}}</th>
+ <td><a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{uuserid}}">{{ufirstname}} {{ulastname}}</a></td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_createTime}}</th>
+ <td>{{createtime_s}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_updateTime}}</th>
+ <td>{{updatetime_s}}</td>
+ </tr>
+ <tr>
+ <td colspan="2">{{{descriptionHtml}}}</td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/actionlog-lecture.html b/modules-available/dozmod/templates/actionlog-lecture.html
new file mode 100644
index 00000000..4fb2b4d0
--- /dev/null
+++ b/modules-available/dozmod/templates/actionlog-lecture.html
@@ -0,0 +1,30 @@
+<h3>{{lang_currentFilter}}</h3>
+<table class="table table-bordered table-striped" style="width: auto">
+ <tr>
+ <th class="text-nowrap">{{lang_lecture}}</th>
+ <td>{{displayname}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_owner}}</th>
+ <td><a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{ouserid}}">{{ofirstname}} {{olastname}}</a></td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_lastEditor}}</th>
+ <td><a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{uuserid}}">{{ufirstname}} {{ulastname}}</a></td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_createTime}}</th>
+ <td>{{createtime_s}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_updateTime}}</th>
+ <td>{{updatetime_s}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_image}}</th>
+ <td><a href="?do=dozmod&amp;section=actionlog&amp;action=showtarget&amp;uuid={{imagebaseid}}">{{imgname}}</a></td>
+ </tr>
+ <tr>
+ <td colspan="2">{{{descriptionHtml}}}</td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/actionlog-log.html b/modules-available/dozmod/templates/actionlog-log.html
new file mode 100644
index 00000000..3b523899
--- /dev/null
+++ b/modules-available/dozmod/templates/actionlog-log.html
@@ -0,0 +1,41 @@
+<table class="table table-striped table-bordered">
+ <tr>
+ <th class="text-nowrap">{{lang_when}}</th>
+ {{#showActor}}
+ <th class="text-nowrap">{{lang_user}}</th>
+ {{/showActor}}
+ {{#showTarget}}
+ <th class="text-nowrap">{{lang_actionTarget}}</th>
+ {{/showTarget}}
+ <th class="text-nowrap">{{lang_event}}</th>
+ </tr>
+ {{#events}}
+ <tr>
+ <td>{{dateline_s}}</td>
+ {{#showActor}}
+ <td>
+ {{#uuserid}}
+ <a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{uuserid}}">{{ulastname}}, {{ufirstname}}</a>
+ {{/uuserid}}
+ {{^uuserid}}
+ {{lang_system}}
+ {{/uuserid}}
+ </td>
+ {{/showActor}}
+ {{#showTarget}}
+ <td>
+ {{#targeturl}}
+ <a href="{{targeturl}}">{{targetname}}</a>
+ {{/targeturl}}
+ {{^targeturl}}
+ {{targetname}}
+ {{^targetname}}
+ <span class="small">{{targetid}}</span>
+ {{/targetname}}
+ {{/targeturl}}
+ </td>
+ {{/showTarget}}
+ <td>{{description}}</td>
+ </tr>
+ {{/events}}
+</table> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/actionlog-user.html b/modules-available/dozmod/templates/actionlog-user.html
new file mode 100644
index 00000000..eefe1386
--- /dev/null
+++ b/modules-available/dozmod/templates/actionlog-user.html
@@ -0,0 +1,23 @@
+<h3>{{lang_currentFilter}}</h3>
+<table class="table table-bordered table-striped" style="width: auto">
+ <tr>
+ <th class="text-nowrap">{{lang_user}}</th>
+ <td>{{firstname}} {{lastname}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_userId}}</th>
+ <td>{{userid}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_organization}}</th>
+ <td>{{orgname}}</td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_email}}</th>
+ <td><a href="mailto:{{email}}">{{email}}</a></td>
+ </tr>
+ <tr>
+ <th class="text-nowrap">{{lang_lastLogin}}</th>
+ <td>{{lastlogin_s}}</td>
+ </tr>
+</table> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/blockstats-details.html b/modules-available/dozmod/templates/blockstats-details.html
new file mode 100644
index 00000000..68e03fbc
--- /dev/null
+++ b/modules-available/dozmod/templates/blockstats-details.html
@@ -0,0 +1,16 @@
+<table class="table table-bordered table-striped">
+ <tr>
+ <th>{{lang_imageName}}</th>
+ <th>{{lang_createTime}}</th>
+ <th>{{lang_fileSize}}</th>
+ <th>{{lang_blockCount}}</th>
+ </tr>
+ {{#rows}}
+ <tr>
+ <td>{{displayname}}</td>
+ <td>{{createtime_s}}</td>
+ <td>{{filesize_s}}</td>
+ <td>{{blockcount}}</td>
+ </tr>
+ {{/rows}}
+</table> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/blockstats.html b/modules-available/dozmod/templates/blockstats.html
new file mode 100644
index 00000000..82a66146
--- /dev/null
+++ b/modules-available/dozmod/templates/blockstats.html
@@ -0,0 +1,33 @@
+<table class="table table-condensed table-striped" style="width: auto">
+ <tr>
+ <th>{{lang_hash}}</th>
+ <th>{{lang_size}}</th>
+ <th>{{lang_count}}</th>
+ </tr>
+ {{#hashes}}
+ <tr>
+ <td>{{hash_hex}}</td>
+ <td>{{blocksize_s}}</td>
+ <td>{{blockcount}} <button class="btn btn-xs btn-default" onclick="slxLoadBlocks('{{hash_hex}}', '{{blocksize}}')"><span class="glyphicon glyphicon-eye-open"></span></button></td>
+ </tr>
+ {{/hashes}}
+</table>
+
+<div class="modal fade" id="block-details" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header"></div>
+ <div class="modal-body"></div>
+ <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div>
+ </div>
+ </div>
+</div>
+
+<script type="application/javascript"><!--
+function slxLoadBlocks(hash, size) {
+ $('#block-details .modal-header').text(hash + '/' + size);
+ $('#block-details .modal-body').html('<div class="slx-rotation"><span class="glyphicon glyphicon-refresh"></span></div>');
+ $('#block-details').modal('show');
+ $('#block-details .modal-body').load('?do=dozmod&section=blockstats', { token: TOKEN, action: 'getblockinfo', hash: hash, size: size });
+}
+//--></script> \ No newline at end of file
diff --git a/modules-available/dozmod/templates/images-delete.html b/modules-available/dozmod/templates/images-delete.html
index f8836b83..0ee90835 100644
--- a/modules-available/dozmod/templates/images-delete.html
+++ b/modules-available/dozmod/templates/images-delete.html
@@ -27,11 +27,11 @@
<tbody>
{{#images}}
<tr>
- <td class="text-left slx-nowrap {{name_extra_class}}">{{displayname}}<br><span class="small">{{imageversionid}}</span></td>
- <td class="text-left slx-nowrap">{{version}}</td>
- <td class="text-left slx-nowrap"><a href="mailto:{{email}}">{{lastname}}, {{firstname}}</a></td>
- <td class="text-left slx-nowrap"><span class="glyphicon {{hasNewerClass}}"></span></td>
- <td class="text-right slx-nowrap">{{filesize}}</td>
+ <td class="text-left text-nowrap {{name_extra_class}}">{{displayname}}<br><span class="small">{{imageversionid}}</span></td>
+ <td class="text-left text-nowrap">{{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-right text-nowrap">{{filesize}}</td>
<td><input class="del-check" name="images[{{imageversionid}}]" type="checkbox" {{checked}}></td>
</tr>
{{/images}}
@@ -85,4 +85,4 @@ document.addEventListener("DOMContentLoaded", function() {
slxChangeSingle();
}, false);
---> </script>
+//--> </script>
diff --git a/modules-available/dozmod/templates/mailconfig.html b/modules-available/dozmod/templates/mailconfig.html
index 56850637..69622796 100644
--- a/modules-available/dozmod/templates/mailconfig.html
+++ b/modules-available/dozmod/templates/mailconfig.html
@@ -6,8 +6,6 @@
</div>
<div class="panel-body">
<p>{{lang_mailDescription}}</p>
- <p>[BETA] Diese Funktionalität ist neu. Wir bitten um Nachsicht, falls es Situationen gibt, in denen zu viele
- oder zu wenige Nachrichten verschickt werden.</p>
<form action="?do=DozMod" method="post" id="mailconf">
<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-200px" tabindex="-1">
<input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-200px" tabindex="-1">
diff --git a/modules-available/dozmod/templates/orglist.html b/modules-available/dozmod/templates/orglist.html
index 34fa039c..482864de 100644
--- a/modules-available/dozmod/templates/orglist.html
+++ b/modules-available/dozmod/templates/orglist.html
@@ -16,7 +16,7 @@
<tbody>
{{#organizations}}
<tr>
- <td class="text-left slx-nowrap">{{displayname}}</td>
+ <td class="text-left text-nowrap">{{displayname}}</td>
<td class="text-nowrap">
<input onclick="seto('setorglogin', this, '{{organizationid}}')" type="checkbox" {{{canlogin}}}>
</td>
@@ -35,33 +35,35 @@ function seto(action, el, orgid) {
var v = el.checked ? '1' : '0';
var old = el.checked == true;
box.css('display', 'none');
- $.post('?do=DozMod', { token: TOKEN, action: action, organizationid: orgid, value: v }).done(function (data) {
- if (data != 1 && data != 0) {
+ $.post('?do=DozMod', { token: TOKEN, section: 'users', action: action, organizationid: orgid, value: v }).done(function (data) {
+
+ if (data !== '1' && data !== '0') {
el.checked = !old;
box.parent().css('background-color', 'red !important');
} else {
el.checked = (data == 1);
+ box.parent().css('background-color', '');
+ /* show success notification */
+ $notification = $('<span></span>')
+ .addClass('glyphicon glyphicon-saved')
+ .css('color', '#2ecc71')
+ .css('width', '0px')
+ .css('position', 'relative')
+ .css('right', '20px')
+ .hide();
+ box.before($notification);
+ $notification.fadeIn('fast', function () {
+ $notification.fadeOut('slow', function () { $notification.remove() });
+ });
}
box.css('display', '');
- /* show success notification */
- $notification = $('<span></span>')
- .addClass('glyphicon glyphicon-saved')
- .css('color', '#2ecc71')
- .css('width', '0px')
- .css('position', 'relative')
- .css('right', '20px')
- .hide();
- box.before($notification);
- $notification.fadeIn('slow', function () {$notification.fadeOut('fast');});
-
-
-
-
}).fail(function() {
+
el.checked = !old;
box.parent().css('background-color', 'red !important');
box.css('display', '');
+
});
}
diff --git a/modules-available/dozmod/templates/runtimeconfig.html b/modules-available/dozmod/templates/runtimeconfig.html
index eced5784..011fcac4 100644
--- a/modules-available/dozmod/templates/runtimeconfig.html
+++ b/modules-available/dozmod/templates/runtimeconfig.html
@@ -5,90 +5,97 @@
{{lang_runtimeConfig}}
</div>
<div class="panel-body">
- <p> {{lang_descriptionRuntimeConfig}}</p>
+ <h3>{{lang_defaultPermissions}}</h3>
+ <p><i>{{lang_descriptionPermissionConfig}}</i></p>
<form action="?do=DozMod" method="post" id="runtimeconf" role="form">
<input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="position:absolute;top:-200px" tabindex="-1">
<input type="password" name="password_fake" id="password_fake" value="" style="position:absolute;top:-200px" tabindex="-1">
<fieldset class="form-group">
- <h4>{{lang_defaultLecturePermissions}}</h4>
+ <legend>{{lang_defaultLecturePermissions}}</legend>
- <input type="hidden" name="defaultLecturePermissions[edit]" value="0"/>
- <input type="hidden" name="defaultLecturePermissions[admin]" value="0"/>
+ <input type="hidden" name="defaultLecturePermissions[edit]" value="0"/>
+ <input type="hidden" name="defaultLecturePermissions[admin]" value="0"/>
- <div class="checkbox">
- <input type="checkbox" name="defaultLecturePermissions[edit]" value="1" {{defaultLecturePermissions.edit}} id ="lecture_edit" class="form-control"/>
- <label>
- {{lang_lecturePermissionEdit}}*
- </label>
- </div>
<div class="checkbox">
- <input type="checkbox" name="defaultLecturePermissions[admin]" value="1" {{defaultLecturePermissions.admin}} id ="lecture_admin" class="form-control"/>
- <label>
- {{lang_lecturePermissionAdmin}}*
+ <input type="checkbox" name="defaultLecturePermissions[admin]" value="1" {{defaultLecturePermissions.admin}} id ="lecture_admin" class="form-control">
+ <label>
+ {{lang_lecturePermissionAdmin}}
+ </label>
+ </div>
+ <div class="checkbox">
+ <input type="checkbox" name="defaultLecturePermissions[edit]" value="1" {{defaultLecturePermissions.edit}} id ="lecture_edit" class="form-control">
+ <label>
+ {{lang_lecturePermissionEdit}}
</label>
</div>
</fieldset>
- <fieldset class="xform-group">
- <h4>{{lang_defaultImagePermissions}}</h4>
+ <fieldset class="form-group">
+ <legend>{{lang_defaultImagePermissions}}</legend>
<input type="hidden" name="defaultImagePermissions[edit]" value="0"/>
<input type="hidden" name="defaultImagePermissions[admin]" value="0"/>
<input type="hidden" name="defaultImagePermissions[download]" value="0"/>
<input type="hidden" name="defaultImagePermissions[link]" value="0"/>
<div class="checkbox">
- <input type="checkbox" name="defaultImagePermissions[edit]" value="1" {{defaultImagePermissions.edit}} id ="image_edit" class="form-control"/>
- <label>
- {{lang_defaultImagePermissionEdit}} *
+ <input type="checkbox" name="defaultImagePermissions[admin]" value="1" {{defaultImagePermissions.admin}} id ="image_admin" class="form-control">
+ <label class="" for="image_admin">
+ {{lang_defaultImagePermissionAdmin}}
</label>
</div>
<div class="checkbox">
- <input type="checkbox" name="defaultImagePermissions[admin]" value="1" {{defaultImagePermissions.admin}} id ="image_admin" class="form-control"/ >
- <label class="" for="image_admin">
- {{lang_defaultImagePermissionAdmin}} *
+ <input type="checkbox" name="defaultImagePermissions[edit]" value="1" {{defaultImagePermissions.edit}} id ="image_edit" class="form-control">
+ <label>
+ {{lang_defaultImagePermissionEdit}}
</label>
</div>
-
<div class="checkbox">
- <input type="checkbox" name="defaultImagePermissions[download]" value="1" {{defaultImagePermissions.download}} id ="image_download" class="form-control"/ >
+ <input type="checkbox" name="defaultImagePermissions[download]" value="1" {{defaultImagePermissions.download}} id ="image_download" class="form-control">
<label>
- {{lang_defaultImagePermissionDownload}} *
+ {{lang_defaultImagePermissionDownload}}
</label>
</div>
<div class="checkbox">
- <input type="checkbox" name="defaultImagePermissions[link]" value="1" {{defaultImagePermissions.link}} id ="image_link" class="form-control"/ >
+ <input type="checkbox" name="defaultImagePermissions[link]" value="1" {{defaultImagePermissions.link}} id ="image_link" class="form-control">
<label>
- {{lang_defaultImagePermissionLink}} *
+ {{lang_defaultImagePermissionLink}}
</label>
</div>
-
-
</fieldset>
- <fieldset>
- <h4>{{lang_runtimeConfigLimits}}</h4>
- <div class="input-group">
- <label class="input-group-addon slx-ga2" for="max_image_validity">{{lang_maxImageValidity}} *</label>
- <input name="maxImageValidityDays" id ="max_image_validity" class="form-control" type="number" value="{{maxImageValidityDays}}"></input>
- </div>
- <div class="input-group">
- <label class="input-group-addon slx-ga2" for="max_lecture_validity">{{lang_maxLectureVisibility}} *</label>
- <input name="maxLectureValidityDays" id ="max_lecture_validity" class="form-control" type="number" value="{{maxLectureValidityDays}}"></input>
- </div>
- <div class="input-group">
- <label class="input-group-addon slx-ga2" for="max_transfers">{{lang_maxTransfers}} *</label>
- <input name="maxTransfers" id ="max_transfers" class="form-control" type="number" value="{{maxTransfers}}"></input>
- </div>
+ <fieldset>
+ <h3>{{lang_runtimeConfigLimits}}</h3>
+ <p><i>{{lang_descriptionRuntimeLimits}}</i></p>
+ <table class="table-input-group">
+ <tr class="input-group">
+ <td class="input-group-addon" for="max_image_validity">{{lang_maxImageValidity}}</td>
+ <td>
+ <input name="maxImageValidityDays" id="max_image_validity" class="form-control" type="number" value="{{maxImageValidityDays}}" min="7" max="999" pattern="^\d+$">
+ </td>
+ </tr>
+ <tr class="input-group">
+ <td class="input-group-addon" for="max_lecture_validity">{{lang_maxLectureVisibility}}</td>
+ <td>
+ <input name="maxLectureValidityDays" id="max_lecture_validity" class="form-control" type="number" value="{{maxLectureValidityDays}}" min="1" max="999" pattern="^\d+$">
+ </td>
+ </tr>
+ <tr class="input-group">
+ <td class="input-group-addon" for="max_transfers">{{lang_maxTransfers}}</td>
+ <td>
+ <input name="maxTransfers" id="max_transfers" class="form-control" type="number" value="{{maxTransfers}}" min="1" max="10" pattern="^\d+$">
+ </td>
+ </tr>
+ </table>
</fieldset>
<br>
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="runtime">
- <button class="btn btn-primary btn-sm" type="submit" name="button" value="save">{{lang_save}}</button>
+ <button class="btn btn-primary" type="submit" name="button" value="save">{{lang_save}}</button>
</form>
</div>
</div>
diff --git a/modules-available/dozmod/templates/templates.html b/modules-available/dozmod/templates/templates.html
index e8e3f592..3b2a003f 100644
--- a/modules-available/dozmod/templates/templates.html
+++ b/modules-available/dozmod/templates/templates.html
@@ -1,15 +1,18 @@
-<h1> Templates</h1>
+<h1>{{lang_mailTemplates}}</h1>
-<form id="templateForm" role="form" method="POST" action="?do=dozmod&section=templates&action=save">
+<p><i>{{lang_templatePageDescription}}</i></p>
+
+<form id="templateForm" role="form" method="POST" action="?do=dozmod&amp;section=templates">
<input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="save">
<div class="panel-group" id="accordion">
{{#templates}}
- <div class="panel panel-default">
- <div id="heading_{{name}}" class="panel-heading">
+ <div id="frame_{{name}}" class="panel panel-default">
+ <div class="panel-heading">
<div class="panel-title">
<h4>
<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#panel_{{name}}">
@@ -24,21 +27,26 @@
<div class="panel-body">
<div id="msgbox_{{name}}">
</div>
+ <!--
<label for="n_{{name}}">{{lang_name}}</label>
- <input name="templates[{{name}}][name]" value="{{name}}" class="form-control"/>
-
- <label for="n_{{description}}">{{lang_description}}</label>
- <input name="templates[{{name}}][description]" value="{{description}}" class="form-control"/>
-
+ <div class="form-group">
+ <input id="n_{{name}}" name="templates[{{name}}][name]" value="{{name}}" class="form-control"/>
+ </div>
+ <label for="d_{{name}}">{{lang_description}}</label>
+ <div class="form-group">
+ <input id="d_{{name}}" name="templates[{{name}}][description]" value="{{description}}" class="form-control"/>
+ </div>
+ -->
<label for="ta_{{name}}">{{lang_template}}</label>
- <br/>
- <textarea data-mandatory="{{list_mandatoryVariables}}" name="templates[{{name}}][template]" data-setting="{{name}}" id="ta_{{name}}"
- class="form-control templateEditor" style="min-height:200px"
- >{{template}}</textarea>
+ <div class="form-group">
+ <textarea data-mandatory="{{list_mandatoryVariables}}" name="templates[{{name}}][template]"
+ data-setting="{{name}}" id="ta_{{name}}"
+ class="form-control templateEditor" style="min-height:200px">{{template}}</textarea>
+ </div>
- <h3>{{lang_placeholders}}</h3>
+ <h4>{{lang_placeholders}}</h4>
<select name="templates[{{name}}][mandatory_variables]" multiple="multiple" class="hidden">
{{{html_mandatoryVariables}}}
</select>
@@ -56,16 +64,25 @@
{{/templates}}
</div>
- <div class="btn-group">
- <button type="button" onclick="sendForm()" class="btn btn-primary">{{lang_save}}</button>
+ <div class="pull-left">
+ <button type="submit" onclick="return validateForm()" class="btn btn-primary">{{lang_save}}</button>
</div>
</form>
+<form method="POST" action="?do=dozmod&amp;section=templates">
+ <input type="hidden" name="token" value="{{token}}">
+ <input type="hidden" name="action" value="reset">
+ <div>
+ <button type="submit" onclick="return confirm('{{lang_reallyResetTemplates}}')" class="btn btn-danger">{{lang_loadDefaults}}</button>
+ </div>
+</form>
+<div class="clearfix"></div>
<script type="application/javascript"><!--
/* check that all necessary placeholders are used */
function validateForm() {
var ok = true;
+ var $toppest = false;
$('.templateEditor').each(function (i, editor) {
@@ -76,7 +93,7 @@ function validateForm() {
/* ? */
- if (mandatory.length == 1 && mandatory[0] == "") {
+ if (mandatory.length === 1 && mandatory[0] === "") {
mandatory = [];
}
@@ -87,54 +104,36 @@ function validateForm() {
missing.push(v);
}
});
- console.log("missing are");
- console.log(missing);
var $msgBox = $("#msgbox_" + setting);
- var $panel = $("#panel_" + setting);
- var $header = $("#heading_" + setting);
-
+ var $frame = $("#frame_" + setting);
if (missing.length > 0) {
/* add errors */
var missingL = missing.join(", ");
- var msg="<strong>Fehler:</strong> Folgende wichtige Platzhalter wurden nicht verwendet: " +missingL;
- console.log("msg box has " + $msgBox.size());
+ var msg="<strong>{{lang_error}}:</strong> {{lang_followingPlaceholdersUnused}}: " +missingL;
$msgBox.html('<div class="alert alert-danger">' + msg + '</div>');
- $panel.addClass('witherror');
- $header.addClass('witherror');
+ $frame.addClass('witherror');
+ if ($toppest === false || $toppest.offset().top > $frame.offset().top) {
+ $toppest = $frame;
+ }
/* overall result */
ok = false;
} else {
$msgBox.html("");
- $panel.removeClass('witherror');
- $header.removeClass('witherror');
+ $frame.removeClass('witherror');
}
});
- return ok;
-}
-
-function submitForm() {
- console.log('sending form');
- $('#templateForm').submit();
-}
-
-
-function sendForm() {
- var ok = validateForm();
- if (ok) {
- console.log("is ok");
- submitForm();
- } else {
- console.log("form is not ok");
+ if ($toppest !== false) {
+ $toppest[0].scrollIntoView();
}
+ return ok;
}
document.addEventListener("DOMContentLoaded", function () {
-
-
-
+ validateForm(); // Do once in case invalid templates are in DB
});
-</script>
+
+//--></script>
diff --git a/modules-available/dozmod/templates/userlist.html b/modules-available/dozmod/templates/userlist.html
index 79d4848b..93ef7b41 100644
--- a/modules-available/dozmod/templates/userlist.html
+++ b/modules-available/dozmod/templates/userlist.html
@@ -22,10 +22,10 @@
<tbody>
{{#users}}
<tr>
- <td class="text-left slx-nowrap">{{lastname}}, {{firstname}}</td>
- <td class="text-left slx-nowrap">{{orgname}}</td>
- <td class="text-left slx-nowrap">{{lastlogin}}</td>
- <td class="text-left slx-nowrap"><a href="mailto:{{email}}">{{email}}</a></td>
+ <td class="text-left text-nowrap"><a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{userid}}">{{lastname}}, {{firstname}}</a></td>
+ <td class="text-left text-nowrap">{{orgname}}</td>
+ <td class="text-left text-nowrap">{{lastlogin}}</td>
+ <td class="text-left text-nowrap"><a href="mailto:{{email}}">{{email}}</a></td>
<td><input onclick="setu('setmail', this, '{{userid}}')" type="checkbox" {{{emailnotifications}}}></td>
<td><input onclick="setu('setsu', this, '{{userid}}')" type="checkbox" {{{issuperuser}}}></td>
<td><input onclick="setu('setlogin', this, '{{userid}}')" type="checkbox" {{{canlogin}}}></td>
@@ -44,29 +44,35 @@ function setu(action, el, uid) {
var v = el.checked ? '1' : '0';
var old = el.checked == true;
box.css('display', 'none');
- $.post('?do=DozMod', { token: TOKEN, action: action, userid: uid, value: v }).done(function (data) {
- if (data != 1 && data != 0) {
+ $.post('?do=DozMod', { token: TOKEN, section: 'users', action: action, userid: uid, value: v }).done(function (data) {
+
+ if (data !== '1' && data !== '0') {
el.checked = !old;
box.parent().css('background-color', 'red !important');
} else {
el.checked = (data == 1);
+ box.parent().css('background-color', '');
+ /* show success notification */
+ $notification = $('<span></span>')
+ .addClass('glyphicon glyphicon-saved')
+ .css('color', '#2ecc71')
+ .css('width', '0px')
+ .css('position', 'relative')
+ .css('right', '20px')
+ .hide();
+ box.before($notification);
+ $notification.fadeIn('fast', function () {
+ $notification.fadeOut('slow', function () { $notification.remove() });
+ });
}
- /* show success notification */
- $notification = $('<span></span>')
- .addClass('glyphicon glyphicon-saved')
- .css('color', '#2ecc71')
- .css('width', '0px')
- .css('position', 'relative')
- .css('right', '20px')
- .hide();
- box.before($notification);
- $notification.fadeIn('slow', function () {$notification.fadeOut('fast');});
-
box.css('display', '');
+
}).fail(function() {
+
el.checked = !old;
box.parent().css('background-color', 'red !important');
box.css('display', '');
+
});
}