From a6a484ea37aeb91f848c11cb818e2d7d4351d391 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 22 Jun 2016 17:56:04 +0200 Subject: [locations/sysconfig] Implement location specific sysconfig --- modules-available/locations/inc/location.inc.php | 8 +- modules-available/locations/page.inc.php | 54 ++++- .../locations/templates/locations.html | 35 +++- modules-available/sysconfig/api.inc.php | 78 +++++++ modules-available/sysconfig/clientscript.js | 62 ++++++ modules-available/sysconfig/inc/sysconfig.inc.php | 17 ++ modules-available/sysconfig/install.inc.php | 6 + modules-available/sysconfig/page.inc.php | 160 +++++++++++---- modules-available/sysconfig/templates/_page.html | 227 --------------------- .../sysconfig/templates/list-configs.html | 115 +++++++++++ .../sysconfig/templates/list-legend.html | 44 ++++ .../sysconfig/templates/list-modules.html | 59 ++++++ style/default.css | 4 + 13 files changed, 589 insertions(+), 280 deletions(-) create mode 100644 modules-available/sysconfig/api.inc.php create mode 100644 modules-available/sysconfig/inc/sysconfig.inc.php create mode 100644 modules-available/sysconfig/templates/list-configs.html create mode 100644 modules-available/sysconfig/templates/list-legend.html create mode 100644 modules-available/sysconfig/templates/list-modules.html diff --git a/modules-available/locations/inc/location.inc.php b/modules-available/locations/inc/location.inc.php index 788fc588..b1474279 100644 --- a/modules-available/locations/inc/location.inc.php +++ b/modules-available/locations/inc/location.inc.php @@ -64,7 +64,7 @@ class Location return $output; } - public static function getLocations($selected = 0, $excludeId = 0, $addNoParent = false) + public static function getLocations($selected = 0, $excludeId = 0, $addNoParent = false, $keepArrayKeys = false) { if (is_string($selected)) { settype($selected, 'int'); @@ -99,6 +99,8 @@ class Location 'selected' => $selected === 0 )); } + if ($keepArrayKeys) + return $rows; return array_values($rows); } @@ -129,14 +131,14 @@ class Location } $output = array(); foreach ($tree as $node) { - $output[] = array( + $output[(int)$node['locationid']] = array( 'locationid' => $node['locationid'], 'locationname' => $node['locationname'], 'locationpad' => str_repeat('--', $depth), 'depth' => $depth ); if (!empty($node['children'])) { - $output = array_merge($output, self::flattenTree($node['children'], $depth + 1)); + $output += self::flattenTree($node['children'], $depth + 1); } } return $output; diff --git a/modules-available/locations/page.inc.php b/modules-available/locations/page.inc.php index 84bc11a9..de724350 100644 --- a/modules-available/locations/page.inc.php +++ b/modules-available/locations/page.inc.php @@ -166,7 +166,6 @@ class Page_Locations extends Page } } // Now actual updates - // TODO: Warn on mismatch/overlap (should lie entirely in parent's subnet, not overlap with others) $starts = Request::post('startaddr', false); $ends = Request::post('endaddr', false); if (!is_array($starts) || !is_array($ends)) { @@ -263,7 +262,8 @@ class Page_Locations extends Page { $overlapSelf = $overlapOther = true; $subnets = Location::getSubnetsByLocation($overlapSelf, $overlapOther); - $locs = Location::getLocations(); + $locs = Location::getLocations(0, 0, false, true); + // Statistics: Count machines for each subnet $unassigned = false; if (Module::get('statistics') !== false) { foreach ($locs as &$location) { @@ -289,15 +289,61 @@ class Page_Locations extends Page $unassigned = $res['cnt']; } unset($loc, $location); + // Show currently active sysconfig for each location + $defaultConfig = false; + if (Module::isAvailable('sysconfig')) { + $confs = SysConfig::getAll(); + foreach ($confs as $conf) { + $confLocs = explode(',', $conf['locs']); + foreach ($confLocs as $loc) { + settype($loc, 'int'); + if ($loc === 0) { + $defaultConfig = $conf['title']; + } + if (!isset($locs[$loc])) + continue; + $locs[$loc] += array('configName' => $conf['title'], 'configClass' => 'slx-bold'); + } + } + $depth = array(); + foreach ($locs as &$loc) { + $d = $loc['depth']; + if (!isset($loc['configName'])) { + // Has no explicit config assignment + if ($d === 0) { + $loc['configName'] = $defaultConfig; + } else { + $loc['configName'] = $depth[$d - 1]; + } + $loc['configClass'] = 'gray'; + } + $depth[$d] = $loc['configName']; + unset($depth[$d + 1]); + } + unset($loc); + } + // Count overridden config vars + if (Module::get('baseconfig') !== false) { + $res = Database::simpleQuery("SELECT locationid, Count(*) AS cnt FROM `setting_location` GROUP BY locationid"); + while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + $lid = (int)$row['locationid']; + if (isset($locs[$lid])) { + $locs[$lid]['overriddenVars'] = $row['cnt']; + } + } + } + // Output Render::addTemplate('locations', array( - 'list' => $locs, + 'list' => array_values($locs), 'havestatistics' => Module::get('statistics') !== false, 'havebaseconfig' => Module::get('baseconfig') !== false, + 'havesysconfig' => Module::get('sysconfig') !== false, 'overlapSelf' => $overlapSelf, 'overlapOther' => $overlapOther, 'haveOverlapSelf' => !empty($overlapSelf), 'haveOverlapOther' => !empty($overlapOther), - 'unassignedCount' => $unassigned + 'unassignedCount' => $unassigned, + 'defaultConfig' => $defaultConfig, )); } diff --git a/modules-available/locations/templates/locations.html b/modules-available/locations/templates/locations.html index e8b5d707..11142ef8 100644 --- a/modules-available/locations/templates/locations.html +++ b/modules-available/locations/templates/locations.html @@ -6,34 +6,59 @@ - + + + {{#havesysconfig}} + + {{/havesysconfig}} {{#list}} + + {{/list}} {{#unassignedCount}} - + + + {{/unassignedCount}}
{{lang_locationName}}{{#havestatistics}}{{lang_machineCount}}{{/havestatistics}}{{lang_editConfigVariables}} + {{#havebaseconfig}}{{lang_sysConfig}}{{/havebaseconfig}} +
- {{locationname}} + {{locationname}}
{{#havestatistics}} {{clientCount}} {{/havestatistics}} + {{#havebaseconfig}} - {{lang_editConfigVariables}} +
+ +
+ {{#overriddenVars}} + {{lang_overrideCount}}: {{overriddenVars}} + {{/overriddenVars}} {{/havebaseconfig}}
+
+ +
+ + {{configName}} + + {{#havesysconfig}} + {{/havesysconfig}} +
{{lang_unassignedMachines}} - {{lang_unassignedMachines}}: {{unassignedCount}} + {{unassignedCount}} {{defaultConfig}}
diff --git a/modules-available/sysconfig/api.inc.php b/modules-available/sysconfig/api.inc.php new file mode 100644 index 00000000..556e99f3 --- /dev/null +++ b/modules-available/sysconfig/api.inc.php @@ -0,0 +1,78 @@ +fetch(PDO::FETCH_ASSOC)) { + settype($r['locationid'], 'int'); + $index = array_search($r['locationid'], $locationChain); + if ($index === false || $index > $best) + continue; + if (!file_exists($r['filepath'])) { + if ($r['locationid'] === 0) { + EventLog::failure("The global config.tgz '{$r['title']}' was not found at '{$r['filepath']}'. Please regenerate the system configuration"); + } else { + EventLog::warning("config.tgz '{$r['title']}' for location $locationId not found at '{$r['filepath']}', trying fallback...."); + } + continue; + } + $best = $index; + $row = $r; +} + +if ($row === false) { + // TODO Not found in DB + deliverEmpty("No config.tgz for location $locationId found"); +} + +if (!file_exists($row['filepath'])) { + // TODO Does not exist + deliverEmpty(); +} + +Header('Content-Type: application/gzip'); +Header('Content-Disposition: attachment; filename=' . Util::sanitizeFilename($row['title']) . '.tgz'); +$ret = readfile($row['filepath']); + +if ($ret === false || $ret === 0) { + // TODO didn't send anything/everything + // Cannot deliver empty, don't know what has been send already + EventLog::warning("Could not deliver config.tgz to client $ip: readfile() returned " . ($ret === false ? 'false' : $ret)); +} + +exit; \ No newline at end of file diff --git a/modules-available/sysconfig/clientscript.js b/modules-available/sysconfig/clientscript.js index 2a133353..47761ea5 100644 --- a/modules-available/sysconfig/clientscript.js +++ b/modules-available/sysconfig/clientscript.js @@ -1,4 +1,6 @@ +// Ugly hack to get the ellipsisized fields to work + function forceTable(t) { var pwidth = t.parent().innerWidth(); @@ -19,3 +21,63 @@ function forceTable(t) w -= 3; } while (t.width() > pwidth); } + +// Mouseover and clicking + +var boldItem = false; + +function showmod(e, action) { + var list = $(e).attr('data-modlist'); + list = list.split(','); + if (action === 'bold') { + $(boldItem).removeClass("slx-bold"); + if (boldItem === e) { + action = 'fade'; + boldItem = false; + } + } else if (boldItem !== false) { + return; + } + $('.modrow').each(function () { + var elem = $(this); + elem.removeClass("slx-fade slx-bold"); + if (action === 'reset') + return; + if (action === 'bold' && list.indexOf(elem.attr('data-id')) !== -1) + elem.addClass("slx-bold"); + if (list.indexOf(elem.attr('data-id')) === -1) + elem.addClass("slx-fade"); + }); + if (action === 'bold') { + boldItem = e; + $(e).addClass("slx-bold"); + } +} + +// Polling for updated status (outdated, missing, ok) + +var statusChecks = 0; + +function checkBuildStatus() { + var mods = []; + var confs = []; + $(".refmod.btn-primary").each(function (index) { + mods.push($(this).val()); + }); + $(".refconf.btn-primary").each(function (index) { + confs.push($(this).val()); + }); + if (mods.length === 0 && confs.length === 0) return; + if (++statusChecks < 10) setTimeout(checkBuildStatus, 200 + 50 * statusChecks); + $.post('?do=SysConfig', { mods: mods.join(), confs: confs.join(), token: TOKEN, action: 'status' }, function (data) { + if (typeof data === 'undefined') return; + if (typeof data.mods === 'object') updateButtonColor($(".refmod.btn-primary"), data.mods); + if (typeof data.confs === 'object') updateButtonColor($(".refconf.btn-primary"), data.confs); + }, 'json'); +} + +function updateButtonColor(list,ids) { + list.each(function() { + if (ids.indexOf($(this).val()) >= 0) $(this).removeClass('btn-primary').addClass('btn-default'); + }); +} diff --git a/modules-available/sysconfig/inc/sysconfig.inc.php b/modules-available/sysconfig/inc/sysconfig.inc.php new file mode 100644 index 00000000..15bd4104 --- /dev/null +++ b/modules-available/sysconfig/inc/sysconfig.inc.php @@ -0,0 +1,17 @@ +fetch(PDO::FETCH_ASSOC)) { + $ret[] = $row; + } + return $ret; + } + +} \ No newline at end of file diff --git a/modules-available/sysconfig/install.inc.php b/modules-available/sysconfig/install.inc.php index 35697d1f..0cde39c2 100644 --- a/modules-available/sysconfig/install.inc.php +++ b/modules-available/sysconfig/install.inc.php @@ -30,6 +30,12 @@ $res[] = tableCreate('configtgz_x_module', " KEY `moduleid` (`moduleid`) "); +$res[] = tableCreate('configtgz_location', " + `locationid` int(11) NOT NULL, + `configid` int(10) unsigned NOT NULL, + PRIMARY KEY (`locationid`), + KEY `configid` (`configid`) +"); // Constraints if (in_array(UPDATE_DONE, $res)) { diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php index 121e4cee..9bf9cacd 100644 --- a/modules-available/sysconfig/page.inc.php +++ b/modules-available/sysconfig/page.inc.php @@ -9,6 +9,18 @@ class Page_SysConfig extends Page */ protected static $moduleTypes = array(); + /** + * @var int current locationid, 0 if global + */ + private $currentLoc; + + /** + * @var array Associative list of known locations + */ + private $locations; + + private $haveOverriddenLocations = false; + /** * Add a known configuration module. Every addmoule_* file should call this * for its module provided. @@ -51,6 +63,22 @@ class Page_SysConfig extends Page Util::redirect('?do=Main'); } + // Determine location we're editing + if (!Module::isAvailable('locations')) { + $this->locations = array(); + $this->currentLoc = 0; + } else { + $this->locations = Location::getLocationsAssoc(); + $this->currentLoc = Request::any('locationid', 0, 'int'); + } + // Location valid? + if ($this->currentLoc !== 0 && !isset($this->locations[$this->currentLoc])) { + Message::addError('locations.invalid-location-id', $this->currentLoc); + Util::redirect('?do=sysconfig'); + } + + // Action handling + $action = Request::any('action', 'list'); // Load all addmodule classes, as they populate the $moduleTypes array @@ -115,7 +143,13 @@ class Page_SysConfig extends Page AddConfig_Base::render(); return; case 'list': + Render::openTag('div', array('class' => 'row')); $this->listConfigs(); + if ($this->currentLoc === 0) { + $this->listModules(); + } + Render::closeTag('div'); + Render::addTemplate('list-legend', array('showLocationBadge' => $this->haveOverriddenLocations)); return; case 'module': $listid = Request::post('list'); @@ -135,27 +169,79 @@ class Page_SysConfig extends Page Message::addError('invalid-action', $action, 'main'); } + private function getLocationNames($locations, $ids) + { + $ret = array(); + foreach ($ids as $id) { + settype($id, 'int'); + if (isset($locations[$id])) { + $ret[] = $locations[$id]['locationname']; + } + } + return implode(', ', $ret); + } + /** * List all configurations and configuration modules. */ private function listConfigs() { // Configs - $res = Database::simpleQuery("SELECT configtgz.configid, configtgz.title, configtgz.filepath, configtgz.status, GROUP_CONCAT(configtgz_x_module.moduleid) AS modlist" - . " FROM configtgz" - . " INNER JOIN configtgz_x_module USING (configid)" + $res = Database::simpleQuery("SELECT c.configid, c.title, c.filepath, c.status," + . " GROUP_CONCAT(DISTINCT cl.locationid) AS loclist, GROUP_CONCAT(cxm.moduleid) AS modlist" + . " FROM configtgz c" + . " INNER JOIN configtgz_x_module cxm USING (configid)" + . " LEFT JOIN configtgz_location cl ON (c.configid = cl.configid)" . " GROUP BY configid" . " ORDER BY title ASC"); $configs = array(); + if ($this->currentLoc !== 0) { + $locationName = $this->locations[$this->currentLoc]['locationname']; + } else { + $locationName = false; + } + $hasDefault = false; while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + if (is_null($row['loclist'])) { + $locList = array(); + } else { + $locList = explode(',', $row['loclist']); + } + $isDefault = in_array((string)$this->currentLoc, $locList, true); + $hasDefault |= $isDefault; + if ($this->currentLoc !== 0) { + $locCount = 0; + } else { + $locCount = count($locList); + if ($isDefault) { + $locCount--; + } + } + if ($locCount > 0) { + $this->haveOverriddenLocations = true; + } $configs[] = array( 'configid' => $row['configid'], 'config' => $row['title'], 'modlist' => $row['modlist'], - 'current' => readlink(CONFIG_HTTP_DIR . '/default/config.tgz') === $row['filepath'], + 'current' => $isDefault, + 'loclist' => $row['loclist'], + 'readableLocList' => $this->getLocationNames($this->locations, $locList), + 'locationCount' => $locCount, 'needrebuild' => ($row['status'] !== 'OK') ); } + Render::addTemplate('list-configs', array( + 'locationid' => $this->currentLoc, + 'locationname' => $locationName, + 'havelocations' => Module::isAvailable('locations'), + 'configs' => $configs, + 'inheritConfig' => !$hasDefault, + )); + } + + private function listModules() + { // Config modules $res = Database::simpleQuery("SELECT moduleid, title, moduletype, status FROM configtgz_module ORDER BY moduletype ASC, title ASC"); $modules = array(); @@ -168,15 +254,10 @@ class Page_SysConfig extends Page 'needrebuild' => ($row['status'] !== 'OK') ); } - Render::addTemplate('_page', array( - 'configs' => $configs, + Render::addTemplate('list-modules', array( 'modules' => $modules, 'havemodules' => (count($modules) > 0) )); - Render::addFooter(''); } private function listModuleContents($moduleid) @@ -185,7 +266,7 @@ class Page_SysConfig extends Page $row = Database::queryFirst("SELECT title, filepath FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleid)); if ($row === false) { Message::addError('config-invalid', $moduleid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } // find files in that archive @@ -196,7 +277,7 @@ class Page_SysConfig extends Page $status = Taskmanager::waitComplete($status, 4000); if (!Taskmanager::isFinished($status) || Taskmanager::isFailed($status)) { Taskmanager::addErrorMessage($status); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } // Sort files for better display @@ -232,7 +313,7 @@ class Page_SysConfig extends Page $config = Database::queryFirst("SELECT title FROM configtgz WHERE configid = :configid LIMIT 1", array('configid' => $configid)); if ($config === false) { Message::addError('config-invalid', $configid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } // fetch the data $res = Database::simpleQuery("SELECT module.moduleid, module.title AS moduletitle" @@ -257,25 +338,22 @@ class Page_SysConfig extends Page private function activateConfig() { - $configid = Request::post('activate', 'MISSING'); - $row = Database::queryFirst("SELECT title, filepath FROM configtgz WHERE configid = :configid LIMIT 1", array('configid' => $configid)); - if ($row === false) { - Message::addError('config-invalid', $configid); - Util::redirect('?do=SysConfig'); + $configid = Request::post('activate', false, 'int'); + if ($configid === false) { + Message::addError('main.empty-field'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } - $task = Taskmanager::submit('LinkConfigTgz', array( - 'destination' => $row['filepath'] - )); - if (isset($task['statusCode']) && $task['statusCode'] === TASK_WAITING) { - $task = Taskmanager::waitComplete($task['id']); - } - if (!isset($task['statusCode']) || $task['statusCode'] === TASK_ERROR) { - Message::addError('main.task-error', $task['data']['error']); - } elseif ($task['statusCode'] === TASK_FINISHED) { - Message::addSuccess('config-activated', $row['title']); - Event::activeConfigChanged(); + if ($this->currentLoc === 0 || $configid !== 0) { + $row = Database::queryFirst("SELECT title, filepath FROM configtgz WHERE configid = :configid LIMIT 1", array('configid' => $configid)); + if ($row === false) { + Message::addError('config-invalid', $configid); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); + } } - Util::redirect('?do=SysConfig'); + $locationid = $this->currentLoc; + Database::exec("INSERT INTO configtgz_location (locationid, configid) VALUES (:locationid, :configid)" + . " ON DUPLICATE KEY UPDATE configid = :configid", compact('locationid', 'configid')); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } private function rebuildConfig() @@ -284,7 +362,7 @@ class Page_SysConfig extends Page $config = ConfigTgz::get($configid); if ($config === false) { Message::addError('config-invalid', $configid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } $ret = $config->generate(false, 350); // TODO if ($ret === true) @@ -293,7 +371,7 @@ class Page_SysConfig extends Page Message::addError('module-rebuild-failed', $config->title()); else Message::addInfo('module-rebuilding', $config->title()); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } private function delModule() @@ -302,14 +380,14 @@ class Page_SysConfig extends Page $row = Database::queryFirst("SELECT title, filepath FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleid)); if ($row === false) { Message::addError('config-invalid', $moduleid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } $existing = Database::queryFirst("SELECT title FROM configtgz_x_module" . " INNER JOIN configtgz USING (configid)" . " WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleid)); if ($existing !== false) { Message::addError('module-in-use', $row['title'], $existing['title']); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } $task = Taskmanager::submit('DeleteFile', array( 'file' => $row['filepath'] @@ -323,7 +401,7 @@ class Page_SysConfig extends Page Message::addSuccess('module-deleted', $row['title']); } Database::exec("DELETE FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleid)); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } private function downloadModule() @@ -332,10 +410,10 @@ class Page_SysConfig extends Page $row = Database::queryFirst("SELECT title, filepath FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleid)); if ($row === false) { Message::addError('config-invalid', $moduleid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } if (!Util::sendFile($row['filepath'], $row['title'] . '.tgz')) - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); exit(0); } @@ -345,7 +423,7 @@ class Page_SysConfig extends Page $module = ConfigModule::get($moduleid); if ($module === false) { Message::addError('config-invalid', $moduleid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } $ret = $module->generate(false, 250); if ($ret === true) @@ -354,7 +432,7 @@ class Page_SysConfig extends Page Message::addError('module-rebuild-failed', $module->title()); else Message::addInfo('module-rebuilding', $module->title()); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig'); } private function delConfig() @@ -363,10 +441,10 @@ class Page_SysConfig extends Page $config = ConfigTgz::get($configid); if ($config === false) { Message::addError('config-invalid', $configid); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } $config->delete(); - Util::redirect('?do=SysConfig'); + Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc); } private function initAddModule() diff --git a/modules-available/sysconfig/templates/_page.html b/modules-available/sysconfig/templates/_page.html index 1a2f64d6..e69de29b 100644 --- a/modules-available/sysconfig/templates/_page.html +++ b/modules-available/sysconfig/templates/_page.html @@ -1,227 +0,0 @@ -
-
-
-
- {{lang_availableSystem}} - -
-
-
- - - - {{#configs}} - - - - - - - {{/configs}} -
-
{{config}}
-
- {{^current}} - - {{/current}} - {{#current}} - - - {{lang_active}} - - {{/current}} - - - - - -
- {{^configs}} -
- {{lang_systemConfigurationNotFound}} -
- {{^modules}} -
- {{lang_systemConfigurationAlert}} -
- {{/modules}} - {{/configs}} -
-
- {{#havemodules}} - - {{/havemodules}} -
-
- -
-
-
- {{lang_availableModules}} - -
-
-
- - - - {{#modules}} - - - - - - - {{/modules}} -
{{moduletype}}
{{module}}
- {{#iscustom}} - - - - {{/iscustom}} - - - - -
- {{^modules}} -
{{lang_configurationModuleNotFound}}
- {{/modules}} -
-
- -
-
-
- -
-
{{lang_legend}}
-
-

- - {{lang_showLong}} -

-

- - {{lang_downloadLong}} -

-

- - {{lang_rebuildLong}} -

-

- - {{lang_rebuildOutdatedLong}} -

-

- - {{lang_editLong}} -

-
- - {{lang_deleteLong}} -
-
-
- - - - - - \ No newline at end of file diff --git a/modules-available/sysconfig/templates/list-configs.html b/modules-available/sysconfig/templates/list-configs.html new file mode 100644 index 00000000..ed027385 --- /dev/null +++ b/modules-available/sysconfig/templates/list-configs.html @@ -0,0 +1,115 @@ +{{#locationid}} +
+

{{locationname}}

+
+ + {{lang_editingLocationInfo}} +
+
+{{/locationid}} +
+
+
+ {{lang_availableSystem}} + +
+
+
+ + + + + {{#configs}} + + + + + + + + {{/configs}} + {{#locationid}} + + + + + + + {{/locationid}} +
+
{{config}}
+
+ {{^current}} + + {{/current}} + {{#current}} + + + {{lang_active}} + + {{/current}} + + {{#locationCount}} + + +{{locationCount}} + + {{/locationCount}} + + + + + +
Vererben von übergeordnetem Raum + {{^inheritConfig}} + + {{/inheritConfig}} + {{#inheritConfig}} + + + {{lang_active}} + + {{/inheritConfig}} +
+ {{^configs}} +
+ {{lang_systemConfigurationNotFound}} +
+ {{^modules}} +
+ {{lang_systemConfigurationAlert}} +
+ {{/modules}} + {{/configs}} +
+
+ +
+ + + +
\ No newline at end of file diff --git a/modules-available/sysconfig/templates/list-legend.html b/modules-available/sysconfig/templates/list-legend.html new file mode 100644 index 00000000..090ef526 --- /dev/null +++ b/modules-available/sysconfig/templates/list-legend.html @@ -0,0 +1,44 @@ +
+
{{lang_legend}}
+
+

+ + {{lang_showLong}} +

+

+ + {{lang_downloadLong}} +

+

+ + {{lang_rebuildLong}} +

+

+ + {{lang_rebuildOutdatedLong}} +

+

+ + {{lang_editLong}} +

+

+ + {{lang_deleteLong}} +

+ {{#showLocationBadge}} +

+ +4 + {{lang_configLocationLong}} +

+ {{/showLocationBadge}} +
+
+ + \ No newline at end of file diff --git a/modules-available/sysconfig/templates/list-modules.html b/modules-available/sysconfig/templates/list-modules.html new file mode 100644 index 00000000..c3e2d736 --- /dev/null +++ b/modules-available/sysconfig/templates/list-modules.html @@ -0,0 +1,59 @@ +
+
+
+ {{lang_availableModules}} + +
+
+
+ + + + {{#modules}} + + + + + + + {{/modules}} +
{{moduletype}}
{{module}}
+ {{#iscustom}} + + + {{/iscustom}} + + + + +
+ {{^modules}} +
{{lang_configurationModuleNotFound}}
+ {{/modules}} +
+
+ +
+ + + +
\ No newline at end of file diff --git a/style/default.css b/style/default.css index 9b93bfda..0fa8fe26 100644 --- a/style/default.css +++ b/style/default.css @@ -107,6 +107,10 @@ body { color: #0b0; } +.gray { + color: gray; +} + .slx-label { font-weight: bold; margin: auto; -- cgit v1.2.3-55-g7522