summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Klinger2016-06-15 16:43:17 +0200
committerChristian Klinger2016-06-15 16:43:17 +0200
commit2b18d0d0c49c3a75bd221ab86b7315f7bae98008 (patch)
tree7d44e103224c1a79e8ccdd5d0313f76180847303
parentsmall style changes (diff)
parent[sysconfignew] Move css from global file to module specific one (diff)
downloadslx-admin-2b18d0d0c49c3a75bd221ab86b7315f7bae98008.tar.gz
slx-admin-2b18d0d0c49c3a75bd221ab86b7315f7bae98008.tar.xz
slx-admin-2b18d0d0c49c3a75bd221ab86b7315f7bae98008.zip
Merge branch 'modularization' of git.openslx.org:openslx-ng/slx-admin into modularization
Conflicts: install/content.sql install/schema.sql
-rw-r--r--doc/baseconfig_-_config-variables42
-rw-r--r--doc/dashboard20
-rw-r--r--doc/enabling_modules16
-rw-r--r--doc/installation28
-rw-r--r--doc/javascript_css19
-rw-r--r--doc/main_page_warnings17
-rw-r--r--doc/module-dependencies31
-rw-r--r--inc/dashboard.inc.php17
-rw-r--r--inc/dictionary.inc.php3
-rw-r--r--inc/module.inc.php5
-rw-r--r--inc/property.inc.php2
-rw-r--r--inc/taskmanagercallback.inc.php19
-rwxr-xr-xinstall-all53
-rw-r--r--modules-available/adduser/page.inc.php2
-rw-r--r--modules-available/backup/page.inc.php5
-rw-r--r--modules-available/baseconfig/api.inc.php22
-rw-r--r--modules-available/baseconfig/install.inc.php2
-rw-r--r--modules-available/baseconfig/lang/de/template-tags.json4
-rw-r--r--modules-available/baseconfig/lang/en/template-tags.json19
-rw-r--r--modules-available/baseconfig/lang/pt/template-tags.json20
-rw-r--r--modules-available/baseconfig/page.inc.php86
-rw-r--r--modules-available/baseconfig/templates/_page.html87
-rw-r--r--modules-available/baseconfig_partitions_cdn/install.inc.php31
-rw-r--r--modules-available/baseconfig_partitions_cdn/lang/de/template-tags.json1
-rw-r--r--modules-available/bootstrap_switch/README19
-rw-r--r--modules-available/bootstrap_switch/clientscript.js25
-rw-r--r--modules-available/bootstrap_switch/config.json1
-rw-r--r--modules-available/bootstrap_switch/style.css22
-rw-r--r--modules-available/citymanagement/config.json2
-rw-r--r--modules-available/citymanagement/install.inc.php22
-rw-r--r--modules-available/citymanagement/lang/de/categories.json3
-rw-r--r--modules-available/citymanagement/lang/en/categories.json3
-rw-r--r--modules-available/eventlog/page.inc.php1
-rw-r--r--modules-available/locations/baseconfig/getconfig.inc.php9
-rw-r--r--modules-available/locations/lang/de/template-tags.json6
-rw-r--r--modules-available/locations/lang/en/template-tags.json6
-rw-r--r--modules-available/locations/page.inc.php8
-rw-r--r--modules-available/main/hooks/translation.inc.php17
-rw-r--r--modules-available/main/templates/main-menu.html3
-rw-r--r--modules-available/minilinux/page.inc.php5
-rw-r--r--modules-available/news/lang/de/template-tags.json1
-rw-r--r--modules-available/news/lang/en/template-tags.json1
-rw-r--r--modules-available/news/lang/pt/template-tags.json1
-rw-r--r--modules-available/serversetup-bwlp/lang/de/template-tags.json1
-rw-r--r--modules-available/serversetup-bwlp/lang/en/template-tags.json14
-rw-r--r--modules-available/session/page.inc.php1
-rw-r--r--modules-available/statistics/lang/de/template-tags.json1
-rw-r--r--modules-available/statistics/lang/en/template-tags.json1
-rw-r--r--modules-available/statistics/page.inc.php1
-rw-r--r--modules-available/sysconfig/addmodule_adauth.inc.php2
-rw-r--r--modules-available/sysconfig/addmodule_ldapauth.inc.php2
-rw-r--r--modules-available/sysconfig/addmodule_sshconfig.inc.php6
-rw-r--r--modules-available/sysconfig/install.inc.php3
-rw-r--r--modules-available/sysconfig/page.inc.php2
-rw-r--r--modules-available/sysconfignew/style.css59
-rw-r--r--modules-available/translation/lang/de/template-tags.json1
-rw-r--r--modules-available/translation/lang/en/template-tags.json1
-rw-r--r--modules-available/translation/page.inc.php68
-rw-r--r--modules-available/translation/templates/menu-category-list.html23
-rw-r--r--modules-available/vmstore/page.inc.php4
-rw-r--r--style/default.css80
61 files changed, 715 insertions, 261 deletions
diff --git a/doc/baseconfig_-_config-variables b/doc/baseconfig_-_config-variables
new file mode 100644
index 00000000..6c85b7de
--- /dev/null
+++ b/doc/baseconfig_-_config-variables
@@ -0,0 +1,42 @@
+The baseconfig module (configuration variables) is now modularized in two
+ways.
+
+
+1) The definition of configuration variables has moved from the database to
+dedicated .json files, which can be defined by one or multiple additional
+modules. This means the database table "settings" is no longer in use.
+As an example, see the module "baseconfig_bwlp".
+If you only enable the module "baseconfig", you will find that visiting
+the "configuration variables" menu entry in slx-admin shows a pretty empty
+page. However, if you additionally enable the baseconfig_bwlp module, many
+configuration variables will be shown.
+baseconfig_bwlp doesn't contain any config.json or page.inc.php, as its
+sole purpose is to supply wanted configuration variables. This is achieved
+by supplying two .json files.
+
+./modules/<module>/baseconfig/categories.json: Defines categories for
+configuration variables. Syntax is <id>:<sort-order>
+
+./modules/<module>/baseconfig/settings.json: Defines configuration variables
+to be shown by the baseconfig page. This has taken the place of the settings
+table from the database and contains pretty much the same information.
+
+Note that you can have multiple modules that supply categories.json or
+settings.json files. They will all be honored by the baseconfig module.
+
+2) You can hook into the baseconfig API mechanism (previously known as
+the "getconfig" API) which creates the plain text output intended for
+the clients. This way you can create more sophisticated output logic, or
+simply have a nicer guy for some values you want to generate.
+To hook into the API, you need a hook:
+./modules/<module>/baseconfig/getconfig.inc.php
+This code will run directly in the context of the baseconfig API request,
+so you write code straight away that should add any configuration variables
+to the associative array called $configVars, e.g.
+$configVars['SLX_FOO'] = 'bar';
+These values can be static, or queried from anywhere in the database, etc.
+For an example of this, see the module "baseconfig_partitions_cdn"
+Which is basically a normal slx-admin module with a GUI for creating a
+partitioning config that get stored in the database.
+It also contains the .../baseconfig/getconfig.inc.php hook that adds
+the partition configuration to the output of the baseconfig API.
diff --git a/doc/dashboard b/doc/dashboard
new file mode 100644
index 00000000..3040bb6f
--- /dev/null
+++ b/doc/dashboard
@@ -0,0 +1,20 @@
+The dashboard is usually created automatically and doesn't require any
+special setup. The order of the settings and categories in the menu
+can be influenced by the two variables $MENU_CAT_SORT_ORDER and
+$MENU_SETTING_SORT_ORDER in config.php (see config.php.example)
+
+Menu categories can be defined implicitly in the form of
+modulename.catname, i.e. main.content
+
+To assign an icon to the category, create a file called category-icons.json
+in the module's root dir (i.e. ./modules/main/category-icons.json)
+and add a key value pair of the form "catname":"glyphicon", i.e.
+{ "content":"th" }. Notice the module name is not prefixed again.
+
+To translate the category's name, visit the translation page and go
+to the module in which the category is defined (in this example, main).
+You'll see a panel dedicated to menu categories, it should contain the
+Note: The menu section will only appear in the translation list of the
+module if any active module is assigned to this category. However, you
+can still manually create the entry by using the "create tag" button.
+As an example, see the "main" or the "citymanagement" module.
diff --git a/doc/enabling_modules b/doc/enabling_modules
new file mode 100644
index 00000000..dd36d000
--- /dev/null
+++ b/doc/enabling_modules
@@ -0,0 +1,16 @@
+As a convention, modules should be placed in another directory and then
+get selectively enabled by symlinking.
+Currently, all modules are placed in ./modules-available, and the symlinks
+reside in ./modules
+Note that you can name the symlink differently. The name of the symlink
+will define by what identifier the module is referred to. This way
+you can have different implementations or versions of the same module
+and switch them out.
+An example of this is the module "serversetup-bwlp" which is symlinked
+as just "serversetup", so we can have "serversetup-cdn" in the future,
+as it seems the two locations have quite different requirements for this
+module's functionality.
+
+Note that a module identifier cannot contain dashes (-), so this is an
+easy way to hint that a module is supposed to be aliased when being
+activated.
diff --git a/doc/installation b/doc/installation
new file mode 100644
index 00000000..14fba625
--- /dev/null
+++ b/doc/installation
@@ -0,0 +1,28 @@
+Installation of slx-admin is modularized, that means there is no central,
+global SQL dump, but every module can provide an install hook, that is
+supposed to install everything it needs to the database (or anything else).
+
+The hook file is called install.inc.php and needs to reside in the module's
+root directory. Some modules might not have an install hook.
+
+A few simple helper functions are provided to make it easier to create
+tables, check for their existence, and create feedback of the installation
+process.
+
+It is important to make as little assumptions as possible about what is
+already present in the database, so try not to call functions like
+User::load() in your install hook. There might be no user table yet.
+
+The installation hook should be written in a way that it is non-destructive,
+and can recognize if an old version of the module's schema is already
+present in the database, in which case it should update the table(s)
+instead of erroring out or losing data. See the install hook of the
+'main' module for an example.
+
+Installation/Upgrading can be triggered manually through the browser
+by accessing "install.php" in slx-admin's root. Please note that this
+page does not require any form of authentication. While any actions
+this page can perform should not be destructive, you might want to
+consider moving the file away after each install/upgrade.
+The other way of triggering the process is running 'install-all' from
+the command line. This comes in handy for automated install scripts.
diff --git a/doc/javascript_css b/doc/javascript_css
new file mode 100644
index 00000000..de4896d5
--- /dev/null
+++ b/doc/javascript_css
@@ -0,0 +1,19 @@
+In order to prevent the global ./style/default.css from growing until
+it's a complete mess, it is also possible to modularize css stylesheets
+and javascript files.
+
+If a module contains a file called style.css, it is automatically included
+in the generated HTML page of the module, or any module that declared this
+module as a dependency.
+The same goes for a file called clientscript.js. Any module containing such
+a file will have this script included in the generated HTML.
+
+This way you can have module specific CSS definitions. Some of the
+definitions in ./style/default.css should be moved into modules over
+time (TODO :)), since they are only used in one module.
+
+Thanks to the dependency mechanism it is possible to have dedicated css/js
+modules, like "js_chart" or "js_circles". An example is the module
+"statistics", which defines js_chart as a dependency in its config.json.
+The result is that js_chart/clientscript.js is automatically included
+in the HTML output of the statistics module.
diff --git a/doc/main_page_warnings b/doc/main_page_warnings
new file mode 100644
index 00000000..e69a6125
--- /dev/null
+++ b/doc/main_page_warnings
@@ -0,0 +1,17 @@
+The warning messages that can appear on the main site (after logging in)
+can be added by hooks now, too, so the page.inc.php of the "main" module
+doesn't contain code specific to a dozen other modules.
+
+If you want to add a hook, create a file in your module:
+./modules/<module>/hooks/main-warning.inc.php
+The file contains flat code, no classes or functions. You should
+do your checks, and then call Message::addError (or the likes).
+You could also render your own template if you feel fancy.
+Remember you're running in the context of the main module, so your
+message ID should use the full syntax module.id, or add your
+module's name to the Render::addTemplate call.
+
+If you also want to enable the "configuration incomplete" global
+warning, set $needSetup to true.
+
+See modules "vmstore", "minilinux" or "sysconfig" for an example.
diff --git a/doc/module-dependencies b/doc/module-dependencies
new file mode 100644
index 00000000..3da27b16
--- /dev/null
+++ b/doc/module-dependencies
@@ -0,0 +1,31 @@
+Modules can define other modules as dependencies. You should do this
+whenever you require resources (like database tables) that belong
+to module A in module B, if you want to use automatic css/js
+inclusion (see javascript_css doc), or if you just feel like your
+module should not be accessible if another module is not present.
+
+"baseconfig_partitions_cdn" has "baseconfig" as a dependency; it
+does not directly access any tables of the module "baseconfig", but
+since it depends on the getconfig-API of the baseconfig module, one
+might argue that having the partition setup feature is of limited
+use if the clients can't fetch it.
+
+"statistics" module has "js_chart" as a dependency, since it
+makes use of the automatic clientscript.js inclusion. The statistics
+module uses the chart javascript library to draw, well, charts.
+
+
+You can write modules that can optionally interact or take advantage
+of other modules if they are present. The statistics module can
+make use of the locations module to show which location a client
+belongs to, but it would still work without the locations module
+being present. You can check for the availability of a module
+by calling Module::isAvailable('<module_name>')
+If the module is available, the call will return true, and
+the class autoloader for the requested module is also installed,
+so you can use any classes from ./modules/<module_name>/inc/*.inc.php
+Again, see how the statistics module calls Location::getFromIp()
+and other functions after calling Module::isAvailable().
+If you'd try to access Location::* without doing so, you'd get
+a class not found error.
+
diff --git a/inc/dashboard.inc.php b/inc/dashboard.inc.php
index ddea6166..3c913b76 100644
--- a/inc/dashboard.inc.php
+++ b/inc/dashboard.inc.php
@@ -4,6 +4,7 @@ class Dashboard
{
private static $iconCache = array();
+ private static $subMenu = array();
public static function createMenu()
{
@@ -16,6 +17,7 @@ class Dashboard
continue;
$modByCategory[$cat][] = $module;
}
+ $currentPage = Page::getModule()->getIdentifier();
$categories = array();
$catSort = array();
foreach ($modByCategory as $catId => $modList) {
@@ -23,11 +25,15 @@ class Dashboard
$sectionSort = array();
foreach ($modList as $module) {
$modId = $module->getIdentifier();
- $modules[] = array(
+ $newEntry = array(
'displayName' => $module->getDisplayName(),
- 'identifier' => $module->getIdentifier(),
- 'className' => ($module->getIdentifier() === Page::getModule()->getIdentifier()) ? 'active' : ''
+ 'identifier' => $module->getIdentifier()
);
+ if ($module->getIdentifier() === $currentPage) {
+ $newEntry['className'] = 'active';
+ $newEntry['subMenu'] = self::$subMenu;
+ }
+ $modules[] = $newEntry;
if (isset($MENU_SETTING_SORT_ORDER[$modId])) {
$sectionSort[] = (string)($MENU_SETTING_SORT_ORDER[$modId] + 1000);
} else {
@@ -82,5 +88,10 @@ class Dashboard
}
return 'glyphicon glyphicon-' . self::$iconCache[$module][$icon];
}
+
+ public static function addSubmenu($url, $name)
+ {
+ self::$subMenu[] = array('url' => $url, 'name' => $name);
+ }
} \ No newline at end of file
diff --git a/inc/dictionary.inc.php b/inc/dictionary.inc.php
index 6ae8fb9b..01651b88 100644
--- a/inc/dictionary.inc.php
+++ b/inc/dictionary.inc.php
@@ -79,7 +79,8 @@ class Dictionary
public static function translateFile($path, $tag)
{
- // TODO: Handle case where we have no active module/no page class
+ if (!class_exists('Page') || Page::getModule() === false)
+ return false; // We have no page - return false for now, as we're most likely running in api or install mode
return self::translateFileModule(Page::getModule()->getIdentifier(), $path, $tag);
}
diff --git a/inc/module.inc.php b/inc/module.inc.php
index 13d9c1e4..58484f34 100644
--- a/inc/module.inc.php
+++ b/inc/module.inc.php
@@ -197,7 +197,10 @@ class Module
public function getPageTitle()
{
- return Dictionary::translateFileModule($this->name, 'module', 'page_title');
+ $val = Dictionary::translateFileModule($this->name, 'module', 'page_title');
+ if ($val !== false)
+ return $val;
+ return $this->getDisplayName();
}
public function getCategory()
diff --git a/inc/property.inc.php b/inc/property.inc.php
index eae5033c..4a6c3720 100644
--- a/inc/property.inc.php
+++ b/inc/property.inc.php
@@ -100,7 +100,7 @@ class Property
if (!isset($task['id']))
return 'Could not start list download (' . Message::asString() . ')';
if ($task['statusCode'] !== TASK_FINISHED) {
- $task = Taskmanager::waitComplete($task['id'], 4000);
+ $task = Taskmanager::waitComplete($task['id'], 5000);
}
if ($task['statusCode'] !== TASK_FINISHED || !isset($task['data']['content'])) {
return $task['data']['error'];
diff --git a/inc/taskmanagercallback.inc.php b/inc/taskmanagercallback.inc.php
index f40db297..c2a05609 100644
--- a/inc/taskmanagercallback.inc.php
+++ b/inc/taskmanagercallback.inc.php
@@ -29,15 +29,16 @@ class TaskmanagerCallback
'task' => $task,
'callback' => $callback,
);
- if (Property::getCurrentSchemaVersion() >= 9) {
- if (is_null($args))
- $data['args'] = '';
- else
- $data['args'] = serialize($args);
- Database::exec("INSERT INTO callback (taskid, dateline, cbfunction, args) VALUES (:task, UNIX_TIMESTAMP(), :callback, :args)", $data);
+ if (is_null($args)) {
+ $data['args'] = '';
} else {
- Database::exec("INSERT INTO callback (taskid, dateline, cbfunction) VALUES (:task, UNIX_TIMESTAMP(), :callback)", $data);
+ $data['args'] = serialize($args);
}
+ if (Database::exec("INSERT INTO callback (taskid, dateline, cbfunction, args)"
+ . " VALUES (:task, UNIX_TIMESTAMP(), :callback, :args)", $data, true) !== false) {
+ return;
+ }
+ Database::exec("INSERT INTO callback (taskid, dateline, cbfunction) VALUES (:task, UNIX_TIMESTAMP(), :callback)", $data);
}
/**
@@ -47,10 +48,10 @@ class TaskmanagerCallback
*/
public static function getPendingCallbacks()
{
- if (Property::getCurrentSchemaVersion() < 9)
+ $res = Database::simpleQuery("SELECT taskid, cbfunction, args FROM callback", array(), true);
+ if ($res === false)
return array();
$retval = array();
- $res = Database::simpleQuery("SELECT taskid, cbfunction, args FROM callback");
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
$retval[$row['taskid']][] = $row;
}
diff --git a/install-all b/install-all
new file mode 100755
index 00000000..42f8e5e4
--- /dev/null
+++ b/install-all
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+FILE=$(mktemp)
+if [ -z "$FILE" ]; then
+ echo "Something's fishy: No temp file!"
+ exit 1
+fi
+
+trap "rm -f -- '$FILE'" EXIT SIGINT SIGTERM
+
+START=$(php install.php | grep -m1 '^MODULE=' | cut -d= -f2-)
+
+if [ -z "$START" ]; then
+ echo "Cannot install slxadmin - did you configure the DB access properly?"
+ exit 1
+fi
+
+echo "Started with $START"
+
+declare -A COUNTER
+
+COUNTER["$START"]=1
+
+NEXT=$START
+RETRY=0
+while true; do
+ php install.php "$NEXT" > "$FILE"
+ MODULE=$(grep -m1 '^MODULE=' "$FILE" | cut -d= -f2-)
+ if [ -z "$MODULE" ]; then
+ echo "Barfed after $NEXT - no module name found in next run"
+ exit 1
+ fi
+ echo "Next module was ${MODULE}..."
+ (( COUNTER["$MODULE"]++ ))
+ if [ ${COUNTER["$MODULE"]} -gt 3 ]; then
+ echo "Iterated too many times"
+ exit 1
+ fi
+ STATUS=$(grep -m1 '^STATUS=' "$FILE" | cut -d= -f2-)
+ echo "Result: $STATUS"
+ if [ -z "$STATUS" ] || [ "$STATUS" = "UPDATE_RETRY" ]; then
+ RETRY=1
+ fi
+ if [ "$MODULE" = "$START" ]; then
+ if [ "$RETRY" = "0" ]; then
+ break
+ fi
+ RETRY=0
+ fi
+ NEXT=$MODULE
+done
+echo "Done."
+
diff --git a/modules-available/adduser/page.inc.php b/modules-available/adduser/page.inc.php
index cb2987bd..87aaeef1 100644
--- a/modules-available/adduser/page.inc.php
+++ b/modules-available/adduser/page.inc.php
@@ -51,8 +51,6 @@ class Page_AddUser extends Page
if (!User::hasPermission('superadmin') && Database::queryFirst('SELECT userid FROM user LIMIT 1') !== false) {
Message::addError('adduser-disabled');
} else {
-
- Render::setTitle(Dictionary::translate('lang_createUser'));
Render::addTemplate('page-adduser', $_POST);
}
}
diff --git a/modules-available/backup/page.inc.php b/modules-available/backup/page.inc.php
index 3f2388a5..34777db8 100644
--- a/modules-available/backup/page.inc.php
+++ b/modules-available/backup/page.inc.php
@@ -23,7 +23,6 @@ class Page_Backup extends Page
protected function doRender()
{
- Render::setTitle(Dictionary::translate('lang_titleBackup'));
if ($this->action === 'restore') {
Render::addTemplate('restore', $this->templateData);
} else {
@@ -51,7 +50,7 @@ class Page_Backup extends Page
Util::redirect('?do=Backup');
}
Header('Content-Type: application/octet-stream', true);
- Header('Content-Disposition: attachment; filename=' . 'satellite-backup_v' . Database::getExpectedSchemaVersion() . '_' . date('Y.m.d-H.i.s') . '.tgz');
+ Header('Content-Disposition: attachment; filename=' . 'satellite-backup_v16_' . date('Y.m.d-H.i.s') . '.tgz');
Header('Content-Length: ' . @filesize($task['data']['backupFile']));
while (!feof($fh)) {
$data = fread($fh, 16000);
@@ -96,7 +95,7 @@ class Page_Backup extends Page
$this->templateData['mountid'] = $task['id'];
$parent = $task['id'];
}
- EventLog::info('Creating backup, v' . Database::getExpectedSchemaVersion() . ' on ' . Property::getServerIp());
+ EventLog::info('Creating backup on ' . Property::getServerIp());
// Finally run restore
$task = Taskmanager::submit('BackupRestore', array(
'mode' => 'restore',
diff --git a/modules-available/baseconfig/api.inc.php b/modules-available/baseconfig/api.inc.php
index 3aac322f..000015f5 100644
--- a/modules-available/baseconfig/api.inc.php
+++ b/modules-available/baseconfig/api.inc.php
@@ -45,18 +45,28 @@ foreach (glob('modules/*/baseconfig/getconfig.inc.php') as $file) {
$defaults = BaseConfigUtil::getVariables();
// Dump global config from DB
-$res = Database::simpleQuery('SELECT setting, value FROM setting_global');
+$res = Database::simpleQuery('SELECT setting, value, enabled FROM setting_global');
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- if (isset($configVars[$row['setting']]) || !isset($defaults[$row['setting']]))
+ if (isset($configVars[$row['setting']]) // Already set by a hook above, ignore
+ || !isset($defaults[$row['setting']])) // Setting is not defined in any <module>/baseconfig/settings.json
continue;
- $configVars[$row['setting']] = $row['value'];
+ if ($row['enabled'] != 1) {
+ // Setting is disabled
+ $configVars[$row['setting']] = false;
+ } else {
+ $configVars[$row['setting']] = $row['value'];
+ }
}
// Fallback to default values from json files
foreach ($defaults as $setting => $value) {
- if (isset($configVars[$setting]))
- continue;
- $configVars[$setting] = $value;
+ if (isset($configVars[$setting])) {
+ if ($configVars[$setting] === false) {
+ unset($configVars[$setting]);
+ }
+ } else {
+ $configVars[$setting] = $value['defaultvalue'];
+ }
}
// All done, now output
diff --git a/modules-available/baseconfig/install.inc.php b/modules-available/baseconfig/install.inc.php
index 8f1cb1e7..b4eada5d 100644
--- a/modules-available/baseconfig/install.inc.php
+++ b/modules-available/baseconfig/install.inc.php
@@ -6,7 +6,7 @@ $res[] = tableCreate('setting_global', "
`setting` varchar(28) NOT NULL,
`value` text NOT NULL,
`displayvalue` text NOT NULL,
- `enabled` tinyint(1) UNSIGNED NOT NULL DEFAULT '1'
+ `enabled` tinyint(1) UNSIGNED NOT NULL DEFAULT '1',
PRIMARY KEY (`setting`)
");
diff --git a/modules-available/baseconfig/lang/de/template-tags.json b/modules-available/baseconfig/lang/de/template-tags.json
index 34163ca9..cdd54f6a 100644
--- a/modules-available/baseconfig/lang/de/template-tags.json
+++ b/modules-available/baseconfig/lang/de/template-tags.json
@@ -1,5 +1,7 @@
{
"lang_basicConfiguration": "Basiskonfiguration",
"lang_clientRelatedConfig": "Die Optionen auf dieser Seite beziehen sich auf das Verhalten der bwLehrpool-Clients.",
- "lang_enableOverride": "\u00dcberschreiben"
+ "lang_editOverrideNotice": "Sie bearbeiten die Einstellungen f\u00fcr einen Unterbereich",
+ "lang_enableOverride": "\u00dcberschreiben",
+ "lang_settingActive": "Einstellung aktiv"
} \ No newline at end of file
diff --git a/modules-available/baseconfig/lang/en/template-tags.json b/modules-available/baseconfig/lang/en/template-tags.json
index 6adfd682..8e75e5ac 100644
--- a/modules-available/baseconfig/lang/en/template-tags.json
+++ b/modules-available/baseconfig/lang/en/template-tags.json
@@ -1,22 +1,7 @@
{
"lang_basicConfiguration": "Basic Configuration",
- "lang_catPartition": "Partition Managment",
- "lang_catUser": "User Managment",
"lang_clientRelatedConfig": "The options on this page are related to the bwLehrpool client machines.",
- "lang_confirm": "Would you like to save the settings on [ \/srv\/openslx\/www\/boot\/config ] ?",
+ "lang_editOverrideNotice": "You're editing the settings of a sub-section",
"lang_enableOverride": "Override",
- "lang_helpId": "Partition Id",
- "lang_helpMountPoint": "Must be a directory: \/example\/directory\/",
- "lang_helpOptions": "Currently, only option 'bootable' is available",
- "lang_helpSize": "Must be in Gigabytes e.g. 15G",
- "lang_newPartition": "New Partition",
- "lang_newUser": "New User",
- "lang_partitionId": "Id",
- "lang_partitionMountPoint": "Mount Point",
- "lang_partitionOptions": "Options",
- "lang_partitionSize": "Size",
- "lang_resetConfirm": "Do you really wish to reset the variable to their default values?",
- "lang_resetDefault": "Reset Default",
- "lang_userName": "Username",
- "lang_userPasswd": "Password"
+ "lang_settingActive": "Setting active"
} \ No newline at end of file
diff --git a/modules-available/baseconfig/lang/pt/template-tags.json b/modules-available/baseconfig/lang/pt/template-tags.json
index 28b9cb76..14367665 100644
--- a/modules-available/baseconfig/lang/pt/template-tags.json
+++ b/modules-available/baseconfig/lang/pt/template-tags.json
@@ -1,21 +1,3 @@
{
- "lang_basicConfiguration": "Configura\u00e7\u00e3o B\u00e1sica",
- "lang_catPartition": "Gerenciamento de Parti\u00e7\u00f5es",
- "lang_catUser": "Gerenciamente de Usu\u00e1rios",
- "lang_confirm": "Voc\u00ea deseja salvar configura\u00e7\u00f5es em [ \/srv\/openslx\/www\/boot\/default\/config ] ?",
- "lang_create": "Criar",
- "lang_helpId": "Id da parti\u00e7\u00e3o",
- "lang_helpMountPoint": "Precisa ser um diret\u00f3rio: \/exemplo\/diret\u00f3rio\/",
- "lang_helpOptions": "Atualmente, apenas a op\u00e7\u00e3o 'bootable' est\u00e1 dispon\u00edvel",
- "lang_helpSize": "Precisa estar em Gigabytes, por exemplo 15G",
- "lang_newPartition": "Nova Parti\u00e7\u00e3o",
- "lang_newUser": "Novo Usu\u00e1rio",
- "lang_partitionId": "Id",
- "lang_partitionMountPoint": "Mount Point",
- "lang_partitionOptions": "Op\u00e7\u00f5es",
- "lang_partitionSize": "Tamanho",
- "lang_resetConfirm": "Voc\u00ea realmente deseja restaurar as vari\u00e1veis para seus valores padr\u00f5es?",
- "lang_resetDefault": "Restaurar Padr\u00e3o",
- "lang_userName": "Nome",
- "lang_userPasswd": "Senha"
+ "lang_basicConfiguration": "Configura\u00e7\u00e3o B\u00e1sica"
} \ No newline at end of file
diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php
index d14c64ac..056dbab1 100644
--- a/modules-available/baseconfig/page.inc.php
+++ b/modules-available/baseconfig/page.inc.php
@@ -3,6 +3,7 @@
class Page_BaseConfig extends Page
{
private $qry_extra = array();
+ private $categories;
/**
* @var bool|string in case we're in module mode, set to the id of the module
@@ -23,36 +24,47 @@ class Page_BaseConfig extends Page
Util::redirect('?do=baseconfig');
}
// Build variables for specific sub-settings
- if (empty($this->qry_extra['field'])) {
+ if ($this->targetModule === false) {
+ // We're editing global settings - use the 'enabled' field
+ $qry_insert = ', enabled';
+ $qry_values = ', :enabled';
+ $qry_update = ', enabled = :enabled';
+ $params = array();
+ } elseif (empty($this->qry_extra['field'])) {
+ // Module specific, but module doesn't have an extra field
$qry_insert = '';
$qry_values = '';
- $params = array();
+ $qry_update = '';
} else {
+ // Module with extra field
$qry_insert = ', ' . $this->qry_extra['field'];
$qry_values = ', :field_value';
+ $qry_update = '';
$params = array('field_value' => $this->qry_extra['field_value']);
$delExtra = " AND {$this->qry_extra['field']} = :field_value ";
$delParams = array('field_value' => $this->qry_extra['field_value']);
- }
- if ($this->targetModule === false) {
- $override = false;
- } else {
// Not editing global settings
if ($this->getCurrentModuleName() === false) {
Message::addError('main.value-invalid', $this->qry_extra['field'], $this->qry_extra['field_value']);
Util::redirect('?do=BaseConfig');
}
- // Honor override checkbox
- $override = Request::post('override', array());
}
+ // Honor override/enabled checkbox
+ $override = Request::post('override', array());
// Load all existing config options to validate input
$vars = BaseConfigUtil::getVariables();
foreach ($vars as $key => $var) {
- if (is_array($override) && (!isset($override[$key]) || $override[$key] !== 'on')) {
- // module mode - override not set - delete
- $delParams['key'] = $key;
- Database::exec("DELETE FROM {$this->qry_extra['table']} WHERE setting = :key $delExtra", $delParams);
- continue;
+ if ($this->targetModule === false) {
+ // Global mode
+ $params['enabled'] = (is_array($override) && isset($override[$key]) && $override[$key] === 'on') ? 1 : 0;
+ } else {
+ // Module mode
+ if (is_array($override) && (!isset($override[$key]) || $override[$key] !== 'on')) {
+ // override not set - delete
+ $delParams['key'] = $key;
+ Database::exec("DELETE FROM {$this->qry_extra['table']} WHERE setting = :key $delExtra", $delParams);
+ continue;
+ }
}
$validator = $var['validator'];
$displayValue = (isset($newValues[$key]) ? $newValues[$key] : '');
@@ -65,7 +77,7 @@ class Page_BaseConfig extends Page
// Now put into DB
Database::exec("INSERT INTO {$this->qry_extra['table']} (setting, value, displayvalue $qry_insert)"
. " VALUES (:key, :value, :displayvalue $qry_values)"
- . " ON DUPLICATE KEY UPDATE value = :value, displayvalue = :displayvalue",
+ . " ON DUPLICATE KEY UPDATE value = :value, displayvalue = :displayvalue $qry_update",
array(
'key' => $key,
'value' => $mangledValue,
@@ -82,6 +94,15 @@ class Page_BaseConfig extends Page
Util::redirect('?do=BaseConfig&module=' . $this->targetModule . '&' . $this->qry_extra['field'] . '=' . $this->qry_extra['field_value']);
}
}
+ // Load categories so we can define them as sub menu items
+ $this->categories = BaseConfigUtil::getCategories();
+ asort($this->categories, SORT_DESC);
+ foreach ($this->categories as $catid => $val) {
+ Dashboard::addSubmenu(
+ '#category_' . $catid,
+ Dictionary::translateFileModule($this->categories[$catid]['module'], 'config-variable-categories', $catid)
+ );
+ }
}
protected function doRender()
@@ -101,17 +122,22 @@ class Page_BaseConfig extends Page
// List config options
$settings = array();
$vars = BaseConfigUtil::getVariables();
- $cats = BaseConfigUtil::getCategories();
// Get stuff that's set in DB already
- if (isset($this->qry_extra['field'])) {
+ if ($this->targetModule === false) {
+ $fields = ', enabled';
+ $where = '';
+ $params = array();
+ } elseif (isset($this->qry_extra['field'])) {
+ $fields = '';
$where = " WHERE {$this->qry_extra['field']} = :field_value";
$params = array('field_value' => $this->qry_extra['field_value']);
} else {
+ $fields = '';
$where = '';
$params = array();
}
// Populate structure with existing config from db
- $res = Database::simpleQuery("SELECT setting, value, displayvalue FROM {$this->qry_extra['table']} "
+ $res = Database::simpleQuery("SELECT setting, value, displayvalue $fields FROM {$this->qry_extra['table']} "
. " {$where} ORDER BY setting ASC", $params);
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if (!isset($vars[$row['setting']]) || !is_array($vars[$row['setting']])) {
@@ -119,9 +145,6 @@ class Page_BaseConfig extends Page
continue;
}
$row += $vars[$row['setting']];
- if (is_null($row['displayvalue'])) {
- $row['displayvalue'] = $row['defaultvalue'];
- }
if (!isset($row['catid'])) {
$row['catid'] = 'unknown';
}
@@ -129,39 +152,48 @@ class Page_BaseConfig extends Page
}
// Add entries that weren't in the db (global), setup override checkbox (module specific)
foreach ($vars as $key => $var) {
- if (isset($settings[$var['catid']]['settings'][$key])) {
- // Value is set in DB
+ if (isset($settings[$var['catid']]['settings'][$key]['enabled'])) {
+ // Global settings - honor enabled field in db
+ if ($settings[$var['catid']]['settings'][$key]['enabled'] == 1) {
+ $settings[$var['catid']]['settings'][$key]['checked'] = 'checked';
+ }
+ } elseif (isset($settings[$var['catid']]['settings'][$key])) {
+ // Module specific - value is set in DB
$settings[$var['catid']]['settings'][$key]['checked'] = 'checked';
} else {
- // Value is not set in DB
+ // Module specific - value is not set in DB
$settings[$var['catid']]['settings'][$key] = $var + array(
'setting' => $key
);
}
+ if (!isset($settings[$var['catid']]['settings'][$key]['displayvalue'])) {
+ $settings[$var['catid']]['settings'][$key]['displayvalue'] = $var['defaultvalue'];
+ }
$settings[$var['catid']]['settings'][$key] += array(
- 'item' => $this->makeInput($var['validator'], $key, $var['defaultvalue']),
+ 'item' => $this->makeInput($var['validator'], $key, $settings[$var['catid']]['settings'][$key]['displayvalue']),
'description' => Util::markup(Dictionary::translateFileModule($var['module'], 'config-variables', $key))
);
}
// Sort categories
$sortvals = array();
foreach ($settings as $catid => &$setting) {
- $sortvals[] = isset($cats[$catid]) ? (int)$cats[$catid]['sortpos'] : 99999;
+ $sortvals[] = isset($this->categories[$catid]) ? (int)$this->categories[$catid]['sortpos'] : 99999;
$setting['category_id'] = $catid;
- $setting['category_name'] = Dictionary::translateFileModule($cats[$catid]['module'], 'config-variable-categories', $catid);
+ $setting['category_name'] = Dictionary::translateFileModule($this->categories[$catid]['module'], 'config-variable-categories', $catid);
if ($setting['category_name'] === false) {
$setting['category_name'] = $catid;
}
+ ksort($setting['settings']);
$setting['settings'] = array_values($setting['settings']);
}
unset($setting);
array_multisort($sortvals, SORT_ASC, SORT_NUMERIC, $settings);
Render::addTemplate('_page', array(
- 'userid' => User::getId(),
'override' => $this->targetModule !== false,
'categories' => array_values($settings),
'target_module' => $this->targetModule,
) + $this->qry_extra);
+ Module::isAvailable('bootstrap_switch');
}
private function getCurrentModuleName()
diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html
index d5548ae9..4d4c05aa 100644
--- a/modules-available/baseconfig/templates/_page.html
+++ b/modules-available/baseconfig/templates/_page.html
@@ -10,58 +10,59 @@
<input name="module" type="hidden" value="{{target_module}}">
<input name="{{field}}" type="hidden" value="{{field_value}}">
{{/override}}
- <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
- <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;">
- <input type="password" name="password_fake" id="password_fake" value="" style="display:none;">
- {{#categories}}
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="heading{{category_id}}">
- <a data-toggle="collapse" data-parent="#accordion" href="#collapse{{category_id}}" aria-expanded="false" aria-controls="collapse{{category_id}}">
- {{category_name}}
- </a>
- </div>
- <div id="collapse{{category_id}}" class="accordion-body collapse" role="tabpanel" aria-labelledby="heading{{category_id}}">
- <div class="panel-body">
- <div class="list-group">
- {{#settings}}
- <div class="list-group-item">
- <div class="row">
- <div class="col-md-5 slx-cfg-toggle">
- <div>{{setting}}</div>
- {{^override}}
- <div class="slx-default">
- {{defaultvalue}}
- </div>
- {{/override}}
- {{#override}}
- <input name="override[{{setting}}]" id="CB_{{setting}}" type="checkbox" {{checked}}> <label for="CB_{{setting}}">{{lang_enableOverride}}</label>
- {{/override}}
- </div>
- <div class="col-md-5">
- {{{item}}}
- </div>
- <div class="col-md-2">
- <a class="btn btn-default" data-toggle="modal" data-target="#help-{{setting}}"><span class="glyphicon glyphicon-question-sign"></span></a>
- </div>
+ <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;">
+ <input type="password" name="password_fake" id="password_fake" value="" style="display:none;">
+ {{#categories}}
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab" id="heading{{category_id}}">
+ <a name="category_{{category_id}}"></a>
+ {{category_name}}
+ </div>
+ <div class="panel-body">
+ <div class="list-group">
+ {{#settings}}
+ <div class="list-group-item">
+ <div class="row">
+ <div class="col-md-5 slx-cfg-toggle">
+ <div>{{setting}}</div>
+ {{^override}}
+ <div class="slx-default">
+ {{defaultvalue}}
</div>
+ <input class="bs-switch" name="override[{{setting}}]" id="CB_{{setting}}" type="checkbox" {{checked}}> <label for="CB_{{setting}}">{{lang_settingActive}}</label>
+ {{/override}}
+ {{#override}}
+ <input class="bs-switch" name="override[{{setting}}]" id="CB_{{setting}}" type="checkbox" {{checked}}> <label for="CB_{{setting}}">{{lang_enableOverride}}</label>
+ {{/override}}
</div>
- <div class="modal fade" id="help-{{setting}}" tabindex="-1" role="dialog">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">{{setting}}</div>
- <div class="modal-body">{{{description}}}</div>
- <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div>
- </div>
- </div>
+ <div class="col-md-5">
+ {{{item}}}
+ </div>
+ <div class="col-md-2">
+ <a class="btn btn-default" data-toggle="modal" data-target="#help-{{setting}}"><span class="glyphicon glyphicon-question-sign"></span></a>
+ </div>
+ </div>
+ </div>
+ <div class="modal fade" id="help-{{setting}}" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">{{setting}}</div>
+ <div class="modal-body">{{{description}}}</div>
+ <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div>
</div>
- {{/settings}}
</div>
</div>
+ {{/settings}}
</div>
</div>
- {{/categories}}
</div>
+ {{/categories}}
<button class="btn btn-primary" type="submit">{{lang_save}}</button>
<button class="btn btn-default" type="reset">{{lang_reset}}</button>
+ {{^override}}
<a class="btn btn-default" href="api.php?do=baseconfig&amp;user={{userid}}">Download</a>
+ {{/override}}
+ {{#override}}
+ <a class="btn btn-default" href="api.php?do=baseconfig&amp;user={{userid}}&amp;module={{target_module}}&amp;value={{field_value}}&amp;force=1">Download</a>
+ {{/override}}
</form>
diff --git a/modules-available/baseconfig_partitions_cdn/install.inc.php b/modules-available/baseconfig_partitions_cdn/install.inc.php
new file mode 100644
index 00000000..f4092078
--- /dev/null
+++ b/modules-available/baseconfig_partitions_cdn/install.inc.php
@@ -0,0 +1,31 @@
+<?php
+
+$res = array();
+
+$res[] = tableCreate('setting_partition', "
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `partition_id` varchar(110) NOT NULL,
+ `size` varchar(110) NOT NULL,
+ `mount_point` varchar(110) NOT NULL,
+ `options` varchar(110) NOT NULL,
+ `user` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `user` (`user`)
+");
+
+if (in_array(UPDATE_DONE, $res)) {
+ Database::exec("ALTER TABLE `setting_partition`
+ ADD CONSTRAINT `setting_partition_ibfk_1` FOREIGN KEY (`user`) REFERENCES `user` (`userid`)");
+}
+
+// Update path
+
+// -- none --
+
+// Create response for browser
+
+if (in_array(UPDATE_DONE, $res)) {
+ finalResponse(UPDATE_DONE, 'Tables created successfully');
+}
+
+finalResponse(UPDATE_NOOP, 'Everything already up to date');
diff --git a/modules-available/baseconfig_partitions_cdn/lang/de/template-tags.json b/modules-available/baseconfig_partitions_cdn/lang/de/template-tags.json
index 91cca0db..ea4f9f5c 100644
--- a/modules-available/baseconfig_partitions_cdn/lang/de/template-tags.json
+++ b/modules-available/baseconfig_partitions_cdn/lang/de/template-tags.json
@@ -1,5 +1,4 @@
{
- "lang_addPartition": "Partition anlegen",
"lang_confirm": "Wollen Sie die Einstellungen unter \/srv\/openslx\/www\/boot\/config speichern?",
"lang_create": "Anlegen",
"lang_explanationText": "Hier k\u00f6nnen Sie bestimmen, welche Partitionen auf dem Client angelegt werden.",
diff --git a/modules-available/bootstrap_switch/README b/modules-available/bootstrap_switch/README
new file mode 100644
index 00000000..405ce13a
--- /dev/null
+++ b/modules-available/bootstrap_switch/README
@@ -0,0 +1,19 @@
+This is basically just bootstrap-switch (js + css), with
+the addition of these three lines in the .js file:
+<snip>
+// SLX-Admin: Enable for class bs-switch
+$.fn.bootstrapSwitch.defaults.size = 'mini';
+$("input.bs-switch").bootstrapSwitch();
+</snip>
+
+This makes sure any checkboxes or radio buttons with the
+class "bs-switch" will automatically be turned into
+bootstrap switches.
+
+To apply bootstrap-switch to your checkboxes you need to
+a) give them the class bs-switch
+b) either make bootstrap_switch a dependency of your module (config.json)
+ or, as a "soft dependency", just call
+ Module::isAvailable('boostrap_switch')
+ somewhere in your code. If bootstrap_switch is not activated, your
+ page will still load and show old fashioned checkboxes \ No newline at end of file
diff --git a/modules-available/bootstrap_switch/clientscript.js b/modules-available/bootstrap_switch/clientscript.js
new file mode 100644
index 00000000..43259451
--- /dev/null
+++ b/modules-available/bootstrap_switch/clientscript.js
@@ -0,0 +1,25 @@
+/* ========================================================================
+ * bootstrap-switch - v3.3.2
+ * http://www.bootstrap-switch.org
+ * ========================================================================
+ * Copyright 2012-2013 Mattia Larentis
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+(function(){var t=[].slice;!function(e,i){"use strict";var n;return n=function(){function t(t,i){null==i&&(i={}),this.$element=e(t),this.options=e.extend({},e.fn.bootstrapSwitch.defaults,{state:this.$element.is(":checked"),size:this.$element.data("size"),animate:this.$element.data("animate"),disabled:this.$element.is(":disabled"),readonly:this.$element.is("[readonly]"),indeterminate:this.$element.data("indeterminate"),inverse:this.$element.data("inverse"),radioAllOff:this.$element.data("radio-all-off"),onColor:this.$element.data("on-color"),offColor:this.$element.data("off-color"),onText:this.$element.data("on-text"),offText:this.$element.data("off-text"),labelText:this.$element.data("label-text"),handleWidth:this.$element.data("handle-width"),labelWidth:this.$element.data("label-width"),baseClass:this.$element.data("base-class"),wrapperClass:this.$element.data("wrapper-class")},i),this.prevOptions={},this.$wrapper=e("<div>",{"class":function(t){return function(){var e;return e=[""+t.options.baseClass].concat(t._getClasses(t.options.wrapperClass)),e.push(t.options.state?t.options.baseClass+"-on":t.options.baseClass+"-off"),null!=t.options.size&&e.push(t.options.baseClass+"-"+t.options.size),t.options.disabled&&e.push(t.options.baseClass+"-disabled"),t.options.readonly&&e.push(t.options.baseClass+"-readonly"),t.options.indeterminate&&e.push(t.options.baseClass+"-indeterminate"),t.options.inverse&&e.push(t.options.baseClass+"-inverse"),t.$element.attr("id")&&e.push(t.options.baseClass+"-id-"+t.$element.attr("id")),e.join(" ")}}(this)()}),this.$container=e("<div>",{"class":this.options.baseClass+"-container"}),this.$on=e("<span>",{html:this.options.onText,"class":this.options.baseClass+"-handle-on "+this.options.baseClass+"-"+this.options.onColor}),this.$off=e("<span>",{html:this.options.offText,"class":this.options.baseClass+"-handle-off "+this.options.baseClass+"-"+this.options.offColor}),this.$label=e("<span>",{html:this.options.labelText,"class":this.options.baseClass+"-label"}),this.$element.on("init.bootstrapSwitch",function(e){return function(){return e.options.onInit.apply(t,arguments)}}(this)),this.$element.on("switchChange.bootstrapSwitch",function(i){return function(n){return!1===i.options.onSwitchChange.apply(t,arguments)?i.$element.is(":radio")?e("[name='"+i.$element.attr("name")+"']").trigger("previousState.bootstrapSwitch",!0):i.$element.trigger("previousState.bootstrapSwitch",!0):void 0}}(this)),this.$container=this.$element.wrap(this.$container).parent(),this.$wrapper=this.$container.wrap(this.$wrapper).parent(),this.$element.before(this.options.inverse?this.$off:this.$on).before(this.$label).before(this.options.inverse?this.$on:this.$off),this.options.indeterminate&&this.$element.prop("indeterminate",!0),this._init(),this._elementHandlers(),this._handleHandlers(),this._labelHandlers(),this._formHandler(),this._externalLabelHandler(),this.$element.trigger("init.bootstrapSwitch",this.options.state)}return t.prototype._constructor=t,t.prototype.setPrevOptions=function(){return this.prevOptions=e.extend(!0,{},this.options)},t.prototype.state=function(t,i){return"undefined"==typeof t?this.options.state:this.options.disabled||this.options.readonly?this.$element:this.options.state&&!this.options.radioAllOff&&this.$element.is(":radio")?this.$element:(this.$element.is(":radio")?e("[name='"+this.$element.attr("name")+"']").trigger("setPreviousOptions.bootstrapSwitch"):this.$element.trigger("setPreviousOptions.bootstrapSwitch"),this.options.indeterminate&&this.indeterminate(!1),t=!!t,this.$element.prop("checked",t).trigger("change.bootstrapSwitch",i),this.$element)},t.prototype.toggleState=function(t){return this.options.disabled||this.options.readonly?this.$element:this.options.indeterminate?(this.indeterminate(!1),this.state(!0)):this.$element.prop("checked",!this.options.state).trigger("change.bootstrapSwitch",t)},t.prototype.size=function(t){return"undefined"==typeof t?this.options.size:(null!=this.options.size&&this.$wrapper.removeClass(this.options.baseClass+"-"+this.options.size),t&&this.$wrapper.addClass(this.options.baseClass+"-"+t),this._width(),this._containerPosition(),this.options.size=t,this.$element)},t.prototype.animate=function(t){return"undefined"==typeof t?this.options.animate:(t=!!t,t===this.options.animate?this.$element:this.toggleAnimate())},t.prototype.toggleAnimate=function(){return this.options.animate=!this.options.animate,this.$wrapper.toggleClass(this.options.baseClass+"-animate"),this.$element},t.prototype.disabled=function(t){return"undefined"==typeof t?this.options.disabled:(t=!!t,t===this.options.disabled?this.$element:this.toggleDisabled())},t.prototype.toggleDisabled=function(){return this.options.disabled=!this.options.disabled,this.$element.prop("disabled",this.options.disabled),this.$wrapper.toggleClass(this.options.baseClass+"-disabled"),this.$element},t.prototype.readonly=function(t){return"undefined"==typeof t?this.options.readonly:(t=!!t,t===this.options.readonly?this.$element:this.toggleReadonly())},t.prototype.toggleReadonly=function(){return this.options.readonly=!this.options.readonly,this.$element.prop("readonly",this.options.readonly),this.$wrapper.toggleClass(this.options.baseClass+"-readonly"),this.$element},t.prototype.indeterminate=function(t){return"undefined"==typeof t?this.options.indeterminate:(t=!!t,t===this.options.indeterminate?this.$element:this.toggleIndeterminate())},t.prototype.toggleIndeterminate=function(){return this.options.indeterminate=!this.options.indeterminate,this.$element.prop("indeterminate",this.options.indeterminate),this.$wrapper.toggleClass(this.options.baseClass+"-indeterminate"),this._containerPosition(),this.$element},t.prototype.inverse=function(t){return"undefined"==typeof t?this.options.inverse:(t=!!t,t===this.options.inverse?this.$element:this.toggleInverse())},t.prototype.toggleInverse=function(){var t,e;return this.$wrapper.toggleClass(this.options.baseClass+"-inverse"),e=this.$on.clone(!0),t=this.$off.clone(!0),this.$on.replaceWith(t),this.$off.replaceWith(e),this.$on=t,this.$off=e,this.options.inverse=!this.options.inverse,this.$element},t.prototype.onColor=function(t){var e;return e=this.options.onColor,"undefined"==typeof t?e:(null!=e&&this.$on.removeClass(this.options.baseClass+"-"+e),this.$on.addClass(this.options.baseClass+"-"+t),this.options.onColor=t,this.$element)},t.prototype.offColor=function(t){var e;return e=this.options.offColor,"undefined"==typeof t?e:(null!=e&&this.$off.removeClass(this.options.baseClass+"-"+e),this.$off.addClass(this.options.baseClass+"-"+t),this.options.offColor=t,this.$element)},t.prototype.onText=function(t){return"undefined"==typeof t?this.options.onText:(this.$on.html(t),this._width(),this._containerPosition(),this.options.onText=t,this.$element)},t.prototype.offText=function(t){return"undefined"==typeof t?this.options.offText:(this.$off.html(t),this._width(),this._containerPosition(),this.options.offText=t,this.$element)},t.prototype.labelText=function(t){return"undefined"==typeof t?this.options.labelText:(this.$label.html(t),this._width(),this.options.labelText=t,this.$element)},t.prototype.handleWidth=function(t){return"undefined"==typeof t?this.options.handleWidth:(this.options.handleWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.labelWidth=function(t){return"undefined"==typeof t?this.options.labelWidth:(this.options.labelWidth=t,this._width(),this._containerPosition(),this.$element)},t.prototype.baseClass=function(t){return this.options.baseClass},t.prototype.wrapperClass=function(t){return"undefined"==typeof t?this.options.wrapperClass:(t||(t=e.fn.bootstrapSwitch.defaults.wrapperClass),this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(" ")),this.$wrapper.addClass(this._getClasses(t).join(" ")),this.options.wrapperClass=t,this.$element)},t.prototype.radioAllOff=function(t){return"undefined"==typeof t?this.options.radioAllOff:(t=!!t,t===this.options.radioAllOff?this.$element:(this.options.radioAllOff=t,this.$element))},t.prototype.onInit=function(t){return"undefined"==typeof t?this.options.onInit:(t||(t=e.fn.bootstrapSwitch.defaults.onInit),this.options.onInit=t,this.$element)},t.prototype.onSwitchChange=function(t){return"undefined"==typeof t?this.options.onSwitchChange:(t||(t=e.fn.bootstrapSwitch.defaults.onSwitchChange),this.options.onSwitchChange=t,this.$element)},t.prototype.destroy=function(){var t;return t=this.$element.closest("form"),t.length&&t.off("reset.bootstrapSwitch").removeData("bootstrap-switch"),this.$container.children().not(this.$element).remove(),this.$element.unwrap().unwrap().off(".bootstrapSwitch").removeData("bootstrap-switch"),this.$element},t.prototype._width=function(){var t,e;return t=this.$on.add(this.$off),t.add(this.$label).css("width",""),e="auto"===this.options.handleWidth?Math.max(this.$on.width(),this.$off.width()):this.options.handleWidth,t.width(e),this.$label.width(function(t){return function(i,n){return"auto"!==t.options.labelWidth?t.options.labelWidth:e>n?e:n}}(this)),this._handleWidth=this.$on.outerWidth(),this._labelWidth=this.$label.outerWidth(),this.$container.width(2*this._handleWidth+this._labelWidth),this.$wrapper.width(this._handleWidth+this._labelWidth)},t.prototype._containerPosition=function(t,e){return null==t&&(t=this.options.state),this.$container.css("margin-left",function(e){return function(){var i;return i=[0,"-"+e._handleWidth+"px"],e.options.indeterminate?"-"+e._handleWidth/2+"px":t?e.options.inverse?i[1]:i[0]:e.options.inverse?i[0]:i[1]}}(this)),e?setTimeout(function(){return e()},50):void 0},t.prototype._init=function(){var t,e;return t=function(t){return function(){return t.setPrevOptions(),t._width(),t._containerPosition(null,function(){return t.options.animate?t.$wrapper.addClass(t.options.baseClass+"-animate"):void 0})}}(this),this.$wrapper.is(":visible")?t():e=i.setInterval(function(n){return function(){return n.$wrapper.is(":visible")?(t(),i.clearInterval(e)):void 0}}(this),50)},t.prototype._elementHandlers=function(){return this.$element.on({"setPreviousOptions.bootstrapSwitch":function(t){return function(e){return t.setPrevOptions()}}(this),"previousState.bootstrapSwitch":function(t){return function(e){return t.options=t.prevOptions,t.options.indeterminate&&t.$wrapper.addClass(t.options.baseClass+"-indeterminate"),t.$element.prop("checked",t.options.state).trigger("change.bootstrapSwitch",!0)}}(this),"change.bootstrapSwitch":function(t){return function(i,n){var o;return i.preventDefault(),i.stopImmediatePropagation(),o=t.$element.is(":checked"),t._containerPosition(o),o!==t.options.state?(t.options.state=o,t.$wrapper.toggleClass(t.options.baseClass+"-off").toggleClass(t.options.baseClass+"-on"),n?void 0:(t.$element.is(":radio")&&e("[name='"+t.$element.attr("name")+"']").not(t.$element).prop("checked",!1).trigger("change.bootstrapSwitch",!0),t.$element.trigger("switchChange.bootstrapSwitch",[o]))):void 0}}(this),"focus.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.addClass(t.options.baseClass+"-focused")}}(this),"blur.bootstrapSwitch":function(t){return function(e){return e.preventDefault(),t.$wrapper.removeClass(t.options.baseClass+"-focused")}}(this),"keydown.bootstrapSwitch":function(t){return function(e){if(e.which&&!t.options.disabled&&!t.options.readonly)switch(e.which){case 37:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!1);case 39:return e.preventDefault(),e.stopImmediatePropagation(),t.state(!0)}}}(this)})},t.prototype._handleHandlers=function(){return this.$on.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!1),t.$element.trigger("focus.bootstrapSwitch")}}(this)),this.$off.on("click.bootstrapSwitch",function(t){return function(e){return e.preventDefault(),e.stopPropagation(),t.state(!0),t.$element.trigger("focus.bootstrapSwitch")}}(this))},t.prototype._labelHandlers=function(){return this.$label.on({click:function(t){return t.stopPropagation()},"mousedown.bootstrapSwitch touchstart.bootstrapSwitch":function(t){return function(e){return t._dragStart||t.options.disabled||t.options.readonly?void 0:(e.preventDefault(),e.stopPropagation(),t._dragStart=(e.pageX||e.originalEvent.touches[0].pageX)-parseInt(t.$container.css("margin-left"),10),t.options.animate&&t.$wrapper.removeClass(t.options.baseClass+"-animate"),t.$element.trigger("focus.bootstrapSwitch"))}}(this),"mousemove.bootstrapSwitch touchmove.bootstrapSwitch":function(t){return function(e){var i;if(null!=t._dragStart&&(e.preventDefault(),i=(e.pageX||e.originalEvent.touches[0].pageX)-t._dragStart,!(i<-t._handleWidth||i>0)))return t._dragEnd=i,t.$container.css("margin-left",t._dragEnd+"px")}}(this),"mouseup.bootstrapSwitch touchend.bootstrapSwitch":function(t){return function(e){var i;if(t._dragStart)return e.preventDefault(),t.options.animate&&t.$wrapper.addClass(t.options.baseClass+"-animate"),t._dragEnd?(i=t._dragEnd>-(t._handleWidth/2),t._dragEnd=!1,t.state(t.options.inverse?!i:i)):t.state(!t.options.state),t._dragStart=!1}}(this),"mouseleave.bootstrapSwitch":function(t){return function(e){return t.$label.trigger("mouseup.bootstrapSwitch")}}(this)})},t.prototype._externalLabelHandler=function(){var t;return t=this.$element.closest("label"),t.on("click",function(e){return function(i){return i.preventDefault(),i.stopImmediatePropagation(),i.target===t[0]?e.toggleState():void 0}}(this))},t.prototype._formHandler=function(){var t;return t=this.$element.closest("form"),t.data("bootstrap-switch")?void 0:t.on("reset.bootstrapSwitch",function(){return i.setTimeout(function(){return t.find("input").filter(function(){return e(this).data("bootstrap-switch")}).each(function(){return e(this).bootstrapSwitch("state",this.checked)})},1)}).data("bootstrap-switch",!0)},t.prototype._getClasses=function(t){var i,n,o,s;if(!e.isArray(t))return[this.options.baseClass+"-"+t];for(n=[],o=0,s=t.length;s>o;o++)i=t[o],n.push(this.options.baseClass+"-"+i);return n},t}(),e.fn.bootstrapSwitch=function(){var i,o,s;return o=arguments[0],i=2<=arguments.length?t.call(arguments,1):[],s=this,this.each(function(){var t,a;return t=e(this),a=t.data("bootstrap-switch"),a||t.data("bootstrap-switch",a=new n(this,o)),"string"==typeof o?s=a[o].apply(a,i):void 0}),s},e.fn.bootstrapSwitch.Constructor=n,e.fn.bootstrapSwitch.defaults={state:!0,size:null,animate:!0,disabled:!1,readonly:!1,indeterminate:!1,inverse:!1,radioAllOff:!1,onColor:"primary",offColor:"default",onText:"ON",offText:"OFF",labelText:"&nbsp;",handleWidth:"auto",labelWidth:"auto",baseClass:"bootstrap-switch",wrapperClass:"wrapper",onInit:function(){},onSwitchChange:function(){}}}(window.jQuery,window)}).call(this);
+// SLX-Admin: Enable for class bs-switch
+$.fn.bootstrapSwitch.defaults.size = 'mini';
+$("input.bs-switch").bootstrapSwitch(); \ No newline at end of file
diff --git a/modules-available/bootstrap_switch/config.json b/modules-available/bootstrap_switch/config.json
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/modules-available/bootstrap_switch/config.json
@@ -0,0 +1 @@
+{} \ No newline at end of file
diff --git a/modules-available/bootstrap_switch/style.css b/modules-available/bootstrap_switch/style.css
new file mode 100644
index 00000000..c63cfe2f
--- /dev/null
+++ b/modules-available/bootstrap_switch/style.css
@@ -0,0 +1,22 @@
+/* ========================================================================
+ * bootstrap-switch - v3.3.2
+ * http://www.bootstrap-switch.org
+ * ========================================================================
+ * Copyright 2012-2013 Mattia Larentis
+ *
+ * ========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================================
+ */
+
+.bootstrap-switch{display:inline-block;direction:ltr;cursor:pointer;border-radius:4px;border:1px solid #ccc;position:relative;text-align:left;overflow:hidden;line-height:8px;z-index:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.bootstrap-switch .bootstrap-switch-container{display:inline-block;top:0;border-radius:4px;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on,.bootstrap-switch .bootstrap-switch-label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:inline-block!important;height:100%;padding:6px 12px;font-size:14px;line-height:20px}.bootstrap-switch .bootstrap-switch-handle-off,.bootstrap-switch .bootstrap-switch-handle-on{text-align:center;z-index:1}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary{color:#fff;background:#337ab7}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info{color:#fff;background:#5bc0de}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success{color:#fff;background:#5cb85c}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning{background:#f0ad4e;color:#fff}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger{color:#fff;background:#d9534f}.bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default,.bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default{color:#000;background:#eee}.bootstrap-switch .bootstrap-switch-label{text-align:center;margin-top:-1px;margin-bottom:-1px;z-index:100;color:#333;background:#fff}.bootstrap-switch .bootstrap-switch-handle-on{border-bottom-left-radius:3px;border-top-left-radius:3px}.bootstrap-switch .bootstrap-switch-handle-off{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch input[type=radio],.bootstrap-switch input[type=checkbox]{position:absolute!important;top:0;left:0;margin:0;z-index:-1;opacity:0;filter:alpha(opacity=0)}.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label{padding:1px 5px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label{padding:5px 10px;font-size:12px;line-height:1.5}.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label{padding:6px 16px;font-size:18px;line-height:1.3333333}.bootstrap-switch.bootstrap-switch-disabled,.bootstrap-switch.bootstrap-switch-indeterminate,.bootstrap-switch.bootstrap-switch-readonly{cursor:default!important}.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on,.bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label{opacity:.5;filter:alpha(opacity=50);cursor:default!important}.bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container{-webkit-transition:margin-left .5s;-o-transition:margin-left .5s;transition:margin-left .5s}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on{border-radius:0 3px 3px 0}.bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off{border-radius:3px 0 0 3px}.bootstrap-switch.bootstrap-switch-focused{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label{border-bottom-right-radius:3px;border-top-right-radius:3px}.bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label,.bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label{border-bottom-left-radius:3px;border-top-left-radius:3px} \ No newline at end of file
diff --git a/modules-available/citymanagement/config.json b/modules-available/citymanagement/config.json
index 2eb2d680..e87cbf7d 100644
--- a/modules-available/citymanagement/config.json
+++ b/modules-available/citymanagement/config.json
@@ -1,4 +1,4 @@
{
- "category":"main.settings-server",
+ "category":"citymanagement.cities",
"permission":"0"
}
diff --git a/modules-available/citymanagement/install.inc.php b/modules-available/citymanagement/install.inc.php
new file mode 100644
index 00000000..b051ca5c
--- /dev/null
+++ b/modules-available/citymanagement/install.inc.php
@@ -0,0 +1,22 @@
+<?php
+
+$res = array();
+
+$res[] = tableCreate('cities', "
+ `cityid` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `ip` varchar(10) NOT NULL,
+ PRIMARY KEY (`cityid`)
+");
+
+// Update path
+
+// -- none --
+
+// Create response for browser
+
+if (in_array(UPDATE_DONE, $res)) {
+ finalResponse(UPDATE_DONE, 'Tables created successfully');
+}
+
+finalResponse(UPDATE_NOOP, 'Everything already up to date');
diff --git a/modules-available/citymanagement/lang/de/categories.json b/modules-available/citymanagement/lang/de/categories.json
new file mode 100644
index 00000000..0c348a06
--- /dev/null
+++ b/modules-available/citymanagement/lang/de/categories.json
@@ -0,0 +1,3 @@
+{
+ "cities": "St\u00e4dte"
+} \ No newline at end of file
diff --git a/modules-available/citymanagement/lang/en/categories.json b/modules-available/citymanagement/lang/en/categories.json
new file mode 100644
index 00000000..2233db93
--- /dev/null
+++ b/modules-available/citymanagement/lang/en/categories.json
@@ -0,0 +1,3 @@
+{
+ "cities": "Cities"
+} \ No newline at end of file
diff --git a/modules-available/eventlog/page.inc.php b/modules-available/eventlog/page.inc.php
index 0e56c82d..87957479 100644
--- a/modules-available/eventlog/page.inc.php
+++ b/modules-available/eventlog/page.inc.php
@@ -15,7 +15,6 @@ class Page_EventLog extends Page
protected function doRender()
{
- Render::setTitle(Dictionary::translate('lang_titleEventLog'));
$today = date('d.m.Y');
$yesterday = date('d.m.Y', time() - 86400);
$lines = array();
diff --git a/modules-available/locations/baseconfig/getconfig.inc.php b/modules-available/locations/baseconfig/getconfig.inc.php
index d4a4f40b..2cf5495d 100644
--- a/modules-available/locations/baseconfig/getconfig.inc.php
+++ b/modules-available/locations/baseconfig/getconfig.inc.php
@@ -1,7 +1,14 @@
<?php
// Location handling: figure out location
-$locationId = false; // TODO: machine specific mapping
+$locationId = false;
+if (Request::any('force', 0, 'int') === 1 && Request::any('module', false, 'string') === 'locations') {
+ // Force location for testing, but require logged in admin
+ if (User::load()) {
+ $locationId = Request::any('value', 0, 'int');
+ }
+}
+// TODO: machine specific mapping
if ($locationId === false) {
// Fallback to subnets
$locationId = Location::getFromIp($ip);
diff --git a/modules-available/locations/lang/de/template-tags.json b/modules-available/locations/lang/de/template-tags.json
index 13e21217..09ee8a35 100644
--- a/modules-available/locations/lang/de/template-tags.json
+++ b/modules-available/locations/lang/de/template-tags.json
@@ -6,11 +6,14 @@
"lang_deleteChildLocations": "Untergeordnete Orte ebenfalls l\u00f6schen",
"lang_deleteLocation": "Ort l\u00f6schen",
"lang_deleteSubnet": "Bereich l\u00f6schen",
+ "lang_editConfigVariables": "Konfiguration anpassen",
"lang_endAddress": "Endadresse",
"lang_listOfSubnets": "Liste der Subnetze",
"lang_location": "Ort",
"lang_locationInfo": "Details zu diesem Ort",
"lang_locationName": "Name",
+ "lang_locationOtherOverlap": "Achtung! Folgende Orte haben sich \u00fcberlappende Netzbereiche",
+ "lang_locationSelfOverlap": "Folgender Ort hat mehrere sich \u00fcberschneidende Netzbereiche",
"lang_locationSettings": "Raum\/Ort bearbeiten",
"lang_locationsMainHeading": "Verwaltung von R\u00e4umen\/Orten",
"lang_matchingMachines": "Enthaltene Rechner",
@@ -21,5 +24,6 @@
"lang_startAddress": "Startadresse",
"lang_subnet": "IP-Bereich",
"lang_thisListByLocation": "Zur Ortsansicht",
- "lang_thisListBySubnet": "Nach Subnetzen auflisten"
+ "lang_thisListBySubnet": "Nach Subnetzen auflisten",
+ "lang_unassignedMachines": "Rechner, die in keinen definierten Ort fallen"
} \ No newline at end of file
diff --git a/modules-available/locations/lang/en/template-tags.json b/modules-available/locations/lang/en/template-tags.json
index 1ea0f56e..bd64554f 100644
--- a/modules-available/locations/lang/en/template-tags.json
+++ b/modules-available/locations/lang/en/template-tags.json
@@ -6,11 +6,14 @@
"lang_deleteChildLocations": "Delete child locations aswell",
"lang_deleteLocation": "Delete location",
"lang_deleteSubnet": "Delete range",
+ "lang_editConfigVariables": "Edit config variables",
"lang_endAddress": "End address",
"lang_listOfSubnets": "List of subnets",
"lang_location": "Ort",
"lang_locationInfo": "Location details",
"lang_locationName": "Name",
+ "lang_locationOtherOverlap": "Warning! These locations have overlapping address ranges",
+ "lang_locationSelfOverlap": "The following location has multiple address ranges that are overlapping",
"lang_locationSettings": "Edit this room or location",
"lang_locationsMainHeading": "Manage rooms and locations",
"lang_matchingMachines": "Matching clients",
@@ -21,5 +24,6 @@
"lang_startAddress": "Start address",
"lang_subnet": "IP range",
"lang_thisListByLocation": "List by location",
- "lang_thisListBySubnet": "List by subnet"
+ "lang_thisListBySubnet": "List by subnet",
+ "lang_unassignedMachines": "Machines not matching any location"
} \ No newline at end of file
diff --git a/modules-available/locations/page.inc.php b/modules-available/locations/page.inc.php
index 9de5e521..84bc11a9 100644
--- a/modules-available/locations/page.inc.php
+++ b/modules-available/locations/page.inc.php
@@ -80,9 +80,9 @@ class Page_Locations extends Page
$this->deleteLocation($location);
}
// Update subnets
- $this->updateLocationSubnets($location);
+ $this->updateLocationSubnets();
// Insert subnets
- $this->addNewLocationSubnets($location); // TODO
+ $this->addNewLocationSubnets($location);
// Update location!
$this->updateLocationData($location);
Util::redirect('?do=Locations');
@@ -148,9 +148,8 @@ class Page_Locations extends Page
}
}
- private function updateLocationSubnets($location)
+ private function updateLocationSubnets()
{
- $locationId = (int)$location['locationid'];
// Deletion first
$dels = Request::post('deletesubnet', false);
if (is_array($dels)) {
@@ -240,7 +239,6 @@ class Page_Locations extends Page
protected function doRender()
{
- //Render::setTitle(Dictionary::translate('lang_titleBackup'));
$getAction = Request::get('action');
if (empty($getAction)) {
// Until we have a main landing page?
diff --git a/modules-available/main/hooks/translation.inc.php b/modules-available/main/hooks/translation.inc.php
index c831cbfd..03fa5f79 100644
--- a/modules-available/main/hooks/translation.inc.php
+++ b/modules-available/main/hooks/translation.inc.php
@@ -6,7 +6,7 @@ $HANDLER = array();
* List of valid subsections
*/
$HANDLER['subsections'] = array(
- 'categories', 'global-tags'
+ 'global-tags'
);
/*
@@ -15,21 +15,6 @@ $HANDLER['subsections'] = array(
*/
/**
- * Configuration categories
- */
-$HANDLER['grep_categories'] = function($module) {
- $skip = strlen($module->getIdentifier()) + 1;
- $want = array();
- foreach (Module::getAll() as $module) {
- $cat = $module->getCategory();
- if (is_string($cat)) {
- $want[substr($cat, $skip)] = true;
- }
- }
- return $want;
-};
-
-/**
* Global tags.
* This just returns the union of global tags of all languages, as there is no
* way to define a definite set of required global tags.
diff --git a/modules-available/main/templates/main-menu.html b/modules-available/main/templates/main-menu.html
index b14d1ace..7c104e92 100644
--- a/modules-available/main/templates/main-menu.html
+++ b/modules-available/main/templates/main-menu.html
@@ -33,6 +33,9 @@
<ul class="dropdown-menu sidebar-visible-block" role="menu">
{{#modules}}
<li class="{{className}}"><a href="?do={{identifier}}">{{displayName}}</a></li>
+ {{#subMenu}}
+ <li class="slx-submenu"><a href="{{url}}">{{name}}</a></li>
+ {{/subMenu}}
{{/modules}}
</ul>
</li>
diff --git a/modules-available/minilinux/page.inc.php b/modules-available/minilinux/page.inc.php
index a7a70d13..2623500b 100644
--- a/modules-available/minilinux/page.inc.php
+++ b/modules-available/minilinux/page.inc.php
@@ -27,9 +27,10 @@ class Page_MiniLinux extends Page
{
$data = Property::getVersionCheckInformation();
if (!is_array($data) || !isset($data['systems'])) {
- echo Render::parse('messagebox-error', array(
+ echo Render::parse('messagebox', array(
+ 'type' => 'danger',
'message' => 'Failed to retrieve the list: ' . print_r($data, true)
- ),'main');
+ ), 'main');
return;
}
$action = Request::any('action');
diff --git a/modules-available/news/lang/de/template-tags.json b/modules-available/news/lang/de/template-tags.json
index 94aee385..7bd4c0e0 100644
--- a/modules-available/news/lang/de/template-tags.json
+++ b/modules-available/news/lang/de/template-tags.json
@@ -1,5 +1,4 @@
{
- "lang_activeNews": "Aktive News",
"lang_content": "Inhalt",
"lang_date": "Datum",
"lang_editNews": "News bearbeiten",
diff --git a/modules-available/news/lang/en/template-tags.json b/modules-available/news/lang/en/template-tags.json
index 8630e8e8..e33f6945 100644
--- a/modules-available/news/lang/en/template-tags.json
+++ b/modules-available/news/lang/en/template-tags.json
@@ -1,5 +1,4 @@
{
- "lang_activeNews": "News",
"lang_content": "Content",
"lang_date": "Date",
"lang_editNews": "Edit news",
diff --git a/modules-available/news/lang/pt/template-tags.json b/modules-available/news/lang/pt/template-tags.json
index 127aeec9..f1d71682 100644
--- a/modules-available/news/lang/pt/template-tags.json
+++ b/modules-available/news/lang/pt/template-tags.json
@@ -1,5 +1,4 @@
{
- "lang_activeNews": "Novidades",
"lang_content": "Conte\u00fado",
"lang_date": "Data",
"lang_latestUpdate": "\u00daltima Atualiza\u00e7\u00e3o",
diff --git a/modules-available/serversetup-bwlp/lang/de/template-tags.json b/modules-available/serversetup-bwlp/lang/de/template-tags.json
index 12881540..593eb9e8 100644
--- a/modules-available/serversetup-bwlp/lang/de/template-tags.json
+++ b/modules-available/serversetup-bwlp/lang/de/template-tags.json
@@ -7,7 +7,6 @@
"lang_bootMenu": "Bootmen\u00fc",
"lang_bootMenuCreate": "Bootmen\u00fc erzeugen",
"lang_chooseIP": "Bitte w\u00e4hlen Sie die IP-Adresse, \u00fcber die der Server von den Clients zum Booten angesprochen werden soll.",
- "lang_compile": "Kompilieren",
"lang_customEntry": "Eigener Eintrag",
"lang_downloadImage": "USB-Image herunterladen",
"lang_example": "Beispiel",
diff --git a/modules-available/serversetup-bwlp/lang/en/template-tags.json b/modules-available/serversetup-bwlp/lang/en/template-tags.json
index 61ac6ade..f2c8aa41 100644
--- a/modules-available/serversetup-bwlp/lang/en/template-tags.json
+++ b/modules-available/serversetup-bwlp/lang/en/template-tags.json
@@ -7,18 +7,10 @@
"lang_bootMenu": "Boot Menu",
"lang_bootMenuCreate": "Create Boot Menu",
"lang_chooseIP": "Please select the IP address that the client server will use to boot.",
- "lang_compile": "Compile",
- "lang_compilingIpxe": "Compiling iPXE",
"lang_customEntry": "Custom entry",
- "lang_customScript": "Custom script",
- "lang_download": "Download",
"lang_downloadImage": "Download USB image",
"lang_example": "Example",
- "lang_extension": "Extension",
"lang_generationFailed": "Could not generate boot menu. The bwLehrpool-System might not work properly. If you can't fix the problem, please report the error message above to the bwLehrpool project.",
- "lang_ipxeInfo": "Here it is possible to compile iPXE using a custom script.",
- "lang_ipxeWarning": "If this is your first time compiling, it may take 1 to 4 minutes to finish.",
- "lang_loading": "Loading",
"lang_localHDD": "Local HDD",
"lang_masterPassword": "Master password",
"lang_masterPasswordHelp": "The master password is required to edit a boot menu entry. This should be set for security reasons.",
@@ -28,10 +20,6 @@
"lang_menuCustomHint3": "and select as the default boot behavior custom as well.",
"lang_menuDisplayTime": "Menu Display Time",
"lang_menuGeneration": "Generating boot menu...",
- "lang_mountIpxe": "Mount iPXE",
- "lang_restoreDefault": "Restore Default",
- "lang_saveScript": "Save Script",
"lang_seconds": "Seconds",
- "lang_set": "Set",
- "lang_success": "Successfully create file:"
+ "lang_set": "Set"
} \ No newline at end of file
diff --git a/modules-available/session/page.inc.php b/modules-available/session/page.inc.php
index ef135f9d..853f20e4 100644
--- a/modules-available/session/page.inc.php
+++ b/modules-available/session/page.inc.php
@@ -29,7 +29,6 @@ class Page_Session extends Page
protected function doRender()
{
- Render::setTitle(Dictionary::translate('lang_login'));
Render::addTemplate('page-login');
}
diff --git a/modules-available/statistics/lang/de/template-tags.json b/modules-available/statistics/lang/de/template-tags.json
index bd4785c0..40f3dbc4 100644
--- a/modules-available/statistics/lang/de/template-tags.json
+++ b/modules-available/statistics/lang/de/template-tags.json
@@ -6,6 +6,7 @@
"lang_cpuCores": "CPU-Kerne",
"lang_cpuModel": "CPU",
"lang_details": "Details",
+ "lang_devices": "Ger\u00e4te",
"lang_event": "Ereignis",
"lang_firstSeen": "Erste Aktivit\u00e4t",
"lang_gbRam": "RAM",
diff --git a/modules-available/statistics/lang/en/template-tags.json b/modules-available/statistics/lang/en/template-tags.json
index aae26ae6..beb9f4f6 100644
--- a/modules-available/statistics/lang/en/template-tags.json
+++ b/modules-available/statistics/lang/en/template-tags.json
@@ -6,6 +6,7 @@
"lang_cpuCores": "CPU cores",
"lang_cpuModel": "CPU",
"lang_details": "Details",
+ "lang_devices": "Devices",
"lang_event": "Event",
"lang_firstSeen": "First seen",
"lang_gbRam": "RAM",
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index 266c4277..1e6f7400 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -37,7 +37,6 @@ class Page_Statistics extends Page
protected function doRender()
{
- Render::setTitle(Dictionary::translate('lang_titleClientStatistics'));
$uuid = Request::get('uuid', false, 'string');
if ($uuid !== false) {
$this->showMachine($uuid);
diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php
index b855761a..2949928b 100644
--- a/modules-available/sysconfig/addmodule_adauth.inc.php
+++ b/modules-available/sysconfig/addmodule_adauth.inc.php
@@ -108,7 +108,7 @@ class AdAuth_SelfSearch extends AddModule_Base
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
- Message::addError('error-read', 'fingerprint');
+ Message::addError('main.error-read', 'fingerprint');
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php
index a6ac145c..d7122001 100644
--- a/modules-available/sysconfig/addmodule_ldapauth.inc.php
+++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php
@@ -96,7 +96,7 @@ class LdapAuth_CheckCredentials extends AddModule_Base
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
- Message::addError('error-read', 'fingerprint');
+ Message::addError('main.error-read', 'fingerprint');
AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render()
return;
}
diff --git a/modules-available/sysconfig/addmodule_sshconfig.inc.php b/modules-available/sysconfig/addmodule_sshconfig.inc.php
index 79857085..19272c32 100644
--- a/modules-available/sysconfig/addmodule_sshconfig.inc.php
+++ b/modules-available/sysconfig/addmodule_sshconfig.inc.php
@@ -45,7 +45,11 @@ class SshConfig_Finish extends AddModule_Base
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
}
$module->setData('allowPasswordLogin', Request::post('allowPasswordLogin') === 'yes');
- if (!$module->setData('listenPort', Request::post('listenPort'))) {
+ $port = Request::post('listenPort', '');
+ if ($port === '') {
+ $port = 22;
+ }
+ if (!$module->setData('listenPort', $port)) {
Message::addError('main.value-invalid', 'port', Request::post('listenPort'));
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
}
diff --git a/modules-available/sysconfig/install.inc.php b/modules-available/sysconfig/install.inc.php
index 0b7bbc1b..35697d1f 100644
--- a/modules-available/sysconfig/install.inc.php
+++ b/modules-available/sysconfig/install.inc.php
@@ -34,7 +34,8 @@ $res[] = tableCreate('configtgz_x_module', "
// Constraints
if (in_array(UPDATE_DONE, $res)) {
Database::exec("ALTER TABLE `configtgz_x_module`
- ADD CONSTRAINT `configtgz_x_module_ibfk_1` FOREIGN KEY (`configid`) REFERENCES `configtgz` (`configid`) ON DELETE CASCADE,
+ ADD CONSTRAINT `configtgz_x_module_ibfk_1` FOREIGN KEY (`configid`) REFERENCES `configtgz` (`configid`) ON DELETE CASCADE");
+ Database::exec("ALTER TABLE `configtgz_x_module`
ADD CONSTRAINT `configtgz_x_module_ibfk_2` FOREIGN KEY (`moduleid`) REFERENCES `configtgz_module` (`moduleid`)");
}
diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php
index efe34136..121e4cee 100644
--- a/modules-available/sysconfig/page.inc.php
+++ b/modules-available/sysconfig/page.inc.php
@@ -106,8 +106,6 @@ class Page_SysConfig extends Page
*/
protected function doRender()
{
- Render::setTitle(Dictionary::translate('lang_location'));
-
$action = Request::any('action', 'list');
switch ($action) {
case 'addmodule':
diff --git a/modules-available/sysconfignew/style.css b/modules-available/sysconfignew/style.css
new file mode 100644
index 00000000..43f708d1
--- /dev/null
+++ b/modules-available/sysconfignew/style.css
@@ -0,0 +1,59 @@
+.mod-nav {
+ width: 250px;
+ float: left;
+ margin-right: 4px;
+ border-right: solid 1px #DDD;
+ padding: 4px;
+ height: 545px;
+ overflow: auto;
+}
+
+.item {
+ padding: 4px;
+ margin: 3px 0;
+ border-radius: 3px;
+}
+
+.item:HOVER {
+ background-color: #EEE;
+ cursor: pointer;
+}
+
+.item-link {
+ color: #5893C6;
+}
+
+.item-lock {
+ color: #939393;
+}
+
+.dir-icon {
+ color: #2E6DA4;
+}
+
+.folder {
+ padding-left: 16px;
+ display: none;
+ border-left: dashed 1px #CCC;
+}
+
+#editor-header{
+ display: block;
+ float: none;
+ width: 875px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+
+.mod-editor{
+ display: block;
+ float: none;
+ resize: none;
+ width: 875px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+
+textarea.form-control .editor-box{
+ height: 520px;
+}
diff --git a/modules-available/translation/lang/de/template-tags.json b/modules-available/translation/lang/de/template-tags.json
index 3f381751..b8497bd9 100644
--- a/modules-available/translation/lang/de/template-tags.json
+++ b/modules-available/translation/lang/de/template-tags.json
@@ -2,6 +2,7 @@
"lang_createTag": "Tag erstellen",
"lang_global": "Global",
"lang_globalTooltip": "Dieser Tag ist global verf\u00fcgbar und braucht normalerweise nicht explizit f\u00fcr dieses Modul \u00fcbersetzt zu werden",
+ "lang_menuCategories": "Men\u00fckategorien",
"lang_messages": "Benachrichtigungen",
"lang_missing": "Fehlend",
"lang_module": "Modul",
diff --git a/modules-available/translation/lang/en/template-tags.json b/modules-available/translation/lang/en/template-tags.json
index 5aee54c3..ec2a26a3 100644
--- a/modules-available/translation/lang/en/template-tags.json
+++ b/modules-available/translation/lang/en/template-tags.json
@@ -2,6 +2,7 @@
"lang_createTag": "Create Tag",
"lang_global": "Global",
"lang_globalTooltip": "This tag is global; usually there is no need to translate it explicitly for this module",
+ "lang_menuCategories": "Menu categories",
"lang_messages": "Messages",
"lang_missing": "Missing",
"lang_module": "Module",
diff --git a/modules-available/translation/page.inc.php b/modules-available/translation/page.inc.php
index 5b2d24e1..74cf27a8 100644
--- a/modules-available/translation/page.inc.php
+++ b/modules-available/translation/page.inc.php
@@ -42,7 +42,7 @@ class Page_Translation extends Page
public function __construct()
{
- $this->builtInSections = array('template', 'messages', 'module', 'custom');
+ $this->builtInSections = array('template', 'messages', 'module', 'menucategory', 'custom');
}
private function isValidSection($section)
@@ -167,6 +167,13 @@ class Page_Translation extends Page
return;
}
+ // Menu Category
+ if ($this->section === 'menucategory') {
+ $this->ensureValidDestLanguage();
+ $this->showMenuCategoryEdit();
+ return;
+ }
+
// Custom
if ($this->section === 'custom') {
$this->ensureValidDestLanguage();
@@ -174,7 +181,7 @@ class Page_Translation extends Page
return;
}
- $this->redirect();
+ $this->redirect(1);
}
private function showListOfModules()
@@ -212,6 +219,8 @@ class Page_Translation extends Page
$this->showModuleMessages();
// Other/hardcoded strings
$this->showModuleStrings();
+ // Menu categories
+ $this->showModuleMenuCategories();
// Module specific
$this->showModuleCustom();
Render::closeTag('div');
@@ -285,6 +294,23 @@ class Page_Translation extends Page
}
Render::addTemplate('string-list', $data);
}
+
+ private function showModuleMenuCategories()
+ {
+ $moduleTags = $this->loadUsedMenuCategories();
+ $data = array('module' => $this->module->getIdentifier());
+ $data['tagcount'] = count($moduleTags);
+ foreach (Dictionary::getLanguages(true) as $lang) {
+ list($missing, $unused) = $this->getModuleTranslationStatus($lang['cc'], 'menucategory', true, $moduleTags);
+ $data['langs'][] = array(
+ 'cc' => $lang['cc'],
+ 'name' => $lang['name'],
+ 'missing' => $missing,
+ 'unused' => $unused
+ );
+ }
+ Render::addTemplate('menu-category-list', $data);
+ }
private function showModuleCustom()
{
@@ -352,6 +378,17 @@ class Page_Translation extends Page
));
}
+ private function showMenuCategoryEdit()
+ {
+ Render::addTemplate('edit', array(
+ 'destlang' => $this->destLang,
+ 'language' => Dictionary::getLanguageName($this->destLang),
+ 'tags' => $this->loadMenuCategoryEditArray(),
+ 'module' => $this->module->getIdentifier(),
+ 'section' => $this->section
+ ));
+ }
+
private function showCustomEdit()
{
Render::addTemplate('edit', array(
@@ -453,6 +490,23 @@ class Page_Translation extends Page
}
return $tags;
}
+
+ private function loadUsedMenuCategories($module = false)
+ {
+ if ($module === false) {
+ $module = $this->module;
+ }
+ $skip = strlen($module->getIdentifier()) + 1;
+ $match = $module->getIdentifier() . '.';
+ $want = array();
+ foreach (Module::getAll() as $module) {
+ $cat = $module->getCategory();
+ if (is_string($cat) && substr($cat, 0, $skip) === $match) {
+ $want[substr($cat, $skip)] = true;
+ }
+ }
+ return $want;
+ }
private function loadUsedCustomTags($subsection)
{
@@ -657,6 +711,13 @@ class Page_Translation extends Page
$table = $this->buildTranslationTable('module', array_keys($tags), true);
return $table;
}
+
+ private function loadMenuCategoryEditArray()
+ {
+ $tags = $this->loadUsedMenuCategories();
+ $table = $this->buildTranslationTable('categories', array_keys($tags), true);
+ return $table;
+ }
/**
* Get array to pass to edit page with all the message ids.
@@ -865,6 +926,9 @@ class Page_Translation extends Page
if ($this->section === 'module') {
return $prefix . '/module.json';
}
+ if ($this->section === 'menucategory') {
+ return $prefix . '/categories.json';
+ }
// Custom submodule
if ($this->section === 'custom') {
if ($this->customHandler === false || !isset($this->customHandler['subsections'])) {
diff --git a/modules-available/translation/templates/menu-category-list.html b/modules-available/translation/templates/menu-category-list.html
new file mode 100644
index 00000000..4a0df819
--- /dev/null
+++ b/modules-available/translation/templates/menu-category-list.html
@@ -0,0 +1,23 @@
+<div class="col-lg-6">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_menuCategories}}
+ </div>
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-sm-6">
+ {{#langs}}
+ <a href="?do=Translation&amp;module={{module}}&amp;section=menucategory&amp;destlang={{cc}}">{{name}} &raquo;</a>
+ <ul>
+ <li>{{lang_missing}}: {{missing}}</li>
+ <li>{{lang_unused}}: {{unused}}</li>
+ </ul>
+ {{/langs}}
+ </div>
+ <div class="col-sm-6">
+ {{lang_tags}}: {{tagcount}}
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/modules-available/vmstore/page.inc.php b/modules-available/vmstore/page.inc.php
index 23b7375c..6ef04669 100644
--- a/modules-available/vmstore/page.inc.php
+++ b/modules-available/vmstore/page.inc.php
@@ -57,7 +57,9 @@ class Page_VmStore extends Page
Util::redirect('?do=VmStore');
}
$this->mountTask = Trigger::mount($vmstore);
- TaskmanagerCallback::addCallback($this->mountTask, 'manualMount', $vmstore);
+ if ($this->mountTask !== false) {
+ TaskmanagerCallback::addCallback($this->mountTask, 'manualMount', $vmstore);
+ }
}
} \ No newline at end of file
diff --git a/style/default.css b/style/default.css
index d49bcb18..9b93bfda 100644
--- a/style/default.css
+++ b/style/default.css
@@ -310,7 +310,7 @@ nav.sidebar li {
}
.slx-topbar div {
- margin-left: 225px;
+ margin-left: 270px;
}
.sidebar-bg {
@@ -324,6 +324,10 @@ nav.sidebar li {
/* .....NavBar: Fully showing nav bar..... */
@media (min-width: 1200px) {
+
+ nav.navbar.sidebar {
+ z-index: 200;
+ }
.navbar-right {
float: left !important;
@@ -465,76 +469,12 @@ section{
padding-left: 15px;
}
-/*
- * Sysconfig Module Editor
- */
-
-.mod-nav {
- width: 250px;
- float: left;
- margin-right: 4px;
- border-right: solid 1px #DDD;
- padding: 4px;
- height: 545px;
- overflow: auto;
-}
-
-.item {
- padding: 4px;
- margin: 3px 0;
- border-radius: 3px;
-}
-
-.item:HOVER {
- background-color: #EEE;
- cursor: pointer;
-}
-
-.item-link {
- color: #5893C6;
-}
-
-.item-lock {
- color: #939393;
-}
-
-.dir-icon {
- color: #2E6DA4;
-}
-
-.folder {
- padding-left: 16px;
- display: none;
- border-left: dashed 1px #CCC;
-}
-
-#editor-header{
- display: block;
- float: none;
- width: 875px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-
-.mod-editor{
- display: block;
- float: none;
- resize: none;
- width: 875px;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-
-.slx-cfg-toggle > input[type=checkbox] ~ label {
- font-weight: normal;
-}
-
-.slx-cfg-toggle > input[type=checkbox]:checked ~ label {
+li.slx-submenu a {
+ font-size: 80%;
font-weight: bold;
+ padding-left: 3em;
}
-/* what's this?
-textarea.form-control .editor-box{
- height: 520px;
+nav.navbar.sidebar {
+ color: #eee;
}
-*/