From ab546fefa2b7e8339d35585aa55da30ce6bece1d Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 16:06:07 +0200 Subject: [dictionary] Handle case where we have no Page --- inc/dictionary.inc.php | 3 ++- modules-available/baseconfig_partitions_cdn/install.inc.php | 7 +++++++ modules-available/citymanagement/install.inc.php | 7 +++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 modules-available/baseconfig_partitions_cdn/install.inc.php create mode 100644 modules-available/citymanagement/install.inc.php 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/modules-available/baseconfig_partitions_cdn/install.inc.php b/modules-available/baseconfig_partitions_cdn/install.inc.php new file mode 100644 index 00000000..3ae2ed7b --- /dev/null +++ b/modules-available/baseconfig_partitions_cdn/install.inc.php @@ -0,0 +1,7 @@ + 'danger', 'message' => 'Failed to retrieve the list: ' . print_r($data, true) - ),'main'); + ), 'main'); return; } $action = Request::any('action'); 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/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 -- cgit v1.2.3-55-g7522 From 40e6961473286ad149cc9c8068bc6b7f5912f578 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 17:20:44 +0200 Subject: [sysconfig/ssh] Default to port 22 --- modules-available/sysconfig/addmodule_sshconfig.inc.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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'); } -- cgit v1.2.3-55-g7522 From 1b5355fb961f62508d3a3c356182421149ec49a1 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 17:50:38 +0200 Subject: [module] PageTitle: Fallback to module name --- inc/module.inc.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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() -- cgit v1.2.3-55-g7522 From 7982cce9f5da57f3d41afe8072965fad312effb9 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 17:51:05 +0200 Subject: [property] Increate ML list download timeout --- inc/property.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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']; -- cgit v1.2.3-55-g7522 From aa22a5a5b655df0cd5b79d849c76551982a9854f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 17:58:48 +0200 Subject: Fix some translations and page titles --- modules-available/adduser/page.inc.php | 2 -- modules-available/backup/page.inc.php | 1 - modules-available/eventlog/page.inc.php | 1 - modules-available/locations/page.inc.php | 8 +++----- modules-available/session/page.inc.php | 1 - modules-available/statistics/page.inc.php | 1 - modules-available/sysconfig/addmodule_adauth.inc.php | 2 +- modules-available/sysconfig/addmodule_ldapauth.inc.php | 2 +- modules-available/sysconfig/page.inc.php | 2 -- 9 files changed, 5 insertions(+), 15 deletions(-) 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..6cd3168f 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 { 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/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/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/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/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': -- cgit v1.2.3-55-g7522 From eb448fcc611b87108b00b3d402188519a54b5764 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Thu, 9 Jun 2016 18:06:06 +0200 Subject: Remove remaining references to schema version --- inc/taskmanagercallback.inc.php | 19 ++++++++++--------- modules-available/backup/page.inc.php | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) 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/modules-available/backup/page.inc.php b/modules-available/backup/page.inc.php index 6cd3168f..34777db8 100644 --- a/modules-available/backup/page.inc.php +++ b/modules-available/backup/page.inc.php @@ -50,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); @@ -95,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', -- cgit v1.2.3-55-g7522 From ca016030a647f05b9dbf7edd590975efe09c45a4 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 10 Jun 2016 11:56:10 +0200 Subject: [install-all] cmdline script to install/update database --- install-all | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100755 install-all 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." + -- cgit v1.2.3-55-g7522 From 91bfa07f909101a42476accff50981d649e725d2 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 11:21:29 +0200 Subject: [dashboard] Add submenu feature --- inc/dashboard.inc.php | 17 ++++++++++++++--- modules-available/main/templates/main-menu.html | 3 +++ style/default.css | 6 ++++++ 3 files changed, 23 insertions(+), 3 deletions(-) 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/modules-available/main/templates/main-menu.html b/modules-available/main/templates/main-menu.html index af8f833f..6538e2a3 100644 --- a/modules-available/main/templates/main-menu.html +++ b/modules-available/main/templates/main-menu.html @@ -33,6 +33,9 @@ diff --git a/style/default.css b/style/default.css index 3701c43f..c77149da 100644 --- a/style/default.css +++ b/style/default.css @@ -469,6 +469,12 @@ section{ padding-left: 15px; } +li.slx-submenu { + font-size: 80%; + font-weight: bold; + padding-left: 1em; +} + /* * Sysconfig Module Editor */ -- cgit v1.2.3-55-g7522 From c8cd280d522a2522c541467b1b84c4a8666b5b38 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 11:22:53 +0200 Subject: [baseconfig] Reimplement toggle/enabled switch from UFPR, sort properly, make download button honor current module/location --- modules-available/baseconfig/api.inc.php | 22 ++++-- modules-available/baseconfig/page.inc.php | 85 ++++++++++++++------- modules-available/baseconfig/templates/_page.html | 87 +++++++++++----------- .../locations/baseconfig/getconfig.inc.php | 9 ++- 4 files changed, 126 insertions(+), 77 deletions(-) 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 /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/page.inc.php b/modules-available/baseconfig/page.inc.php index d14c64ac..6f3ed806 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,35 +152,43 @@ 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, diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html index d5548ae9..5c89213f 100644 --- a/modules-available/baseconfig/templates/_page.html +++ b/modules-available/baseconfig/templates/_page.html @@ -10,58 +10,59 @@ {{/override}} -
- - - {{#categories}} -
- -
-
-
- {{#settings}} -
-
-
-
{{setting}}
- {{^override}} -
- {{defaultvalue}} -
- {{/override}} - {{#override}} - - {{/override}} -
-
- {{{item}}} -
-
- -
+ + + {{#categories}} +
+ +
+
+ {{#settings}} +
+
+
+
{{setting}}
+ {{^override}} +
+ {{defaultvalue}}
+ + {{/override}} + {{#override}} + + {{/override}}
- +
+ + {{/settings}}
- {{/categories}}
+ {{/categories}} + {{^override}} Download + {{/override}} + {{#override}} + Download + {{/override}} 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 @@ 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 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 @@ +
+
+
+ {{lang_menuCategories}} +
+
+
+
+ {{#langs}} + {{name}} » +
    +
  • {{lang_missing}}: {{missing}}
  • +
  • {{lang_unused}}: {{unused}}
  • +
+ {{/langs}} +
+
+ {{lang_tags}}: {{tagcount}} +
+
+
+
+
\ No newline at end of file -- cgit v1.2.3-55-g7522 From f5f8d91f25378464c59fbec49ebf43f00c668966 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 16:12:17 +0200 Subject: Fix main menu text color, make sub-section text bold --- style/default.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/style/default.css b/style/default.css index c77149da..bf1834d6 100644 --- a/style/default.css +++ b/style/default.css @@ -469,10 +469,14 @@ section{ padding-left: 15px; } -li.slx-submenu { +li.slx-submenu a { font-size: 80%; font-weight: bold; - padding-left: 1em; + padding-left: 3em; +} + +nav.navbar.sidebar { + color: #eee; } /* -- cgit v1.2.3-55-g7522 From 1692a395d90e5ff4c9b826ab2b126b9572f05cd9 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 16:13:27 +0200 Subject: [citymanagement] Create new menu categories in cities module (mostly as an example) --- modules-available/citymanagement/config.json | 2 +- modules-available/citymanagement/lang/de/categories.json | 3 +++ modules-available/citymanagement/lang/en/categories.json | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 modules-available/citymanagement/lang/de/categories.json create mode 100644 modules-available/citymanagement/lang/en/categories.json 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/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 -- cgit v1.2.3-55-g7522 From 1873fa94f309b4acc2c16eea2b26387d540ae55f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 17:13:54 +0200 Subject: Add documentation --- doc/baseconfig_-_config-variables | 42 +++++++++++++++++++++++++++++++++++++++ doc/dashboard | 20 +++++++++++++++++++ doc/enabling_modules | 16 +++++++++++++++ doc/installation | 28 ++++++++++++++++++++++++++ doc/javascript_css | 19 ++++++++++++++++++ doc/main_page_warnings | 17 ++++++++++++++++ doc/module-dependencies | 31 +++++++++++++++++++++++++++++ 7 files changed, 173 insertions(+) create mode 100644 doc/baseconfig_-_config-variables create mode 100644 doc/dashboard create mode 100644 doc/enabling_modules create mode 100644 doc/installation create mode 100644 doc/javascript_css create mode 100644 doc/main_page_warnings create mode 100644 doc/module-dependencies 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//baseconfig/categories.json: Defines categories for +configuration variables. Syntax is : + +./modules//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//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//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('') +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//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. + -- cgit v1.2.3-55-g7522 From 326fef724effa79b4a1900f7a155163f9cf50b7e Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 17:50:56 +0200 Subject: [bootstrap_switch] New module for bootstrap-switch plugin --- modules-available/bootstrap_switch/README | 19 ++++++++++++++++ modules-available/bootstrap_switch/clientscript.js | 25 ++++++++++++++++++++++ modules-available/bootstrap_switch/config.json | 1 + modules-available/bootstrap_switch/style.css | 22 +++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 modules-available/bootstrap_switch/README create mode 100644 modules-available/bootstrap_switch/clientscript.js create mode 100644 modules-available/bootstrap_switch/config.json create mode 100644 modules-available/bootstrap_switch/style.css 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: + +// SLX-Admin: Enable for class bs-switch +$.fn.bootstrapSwitch.defaults.size = 'mini'; +$("input.bs-switch").bootstrapSwitch(); + + +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("
",{"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("
",{"class":this.options.baseClass+"-container"}),this.$on=e("",{html:this.options.onText,"class":this.options.baseClass+"-handle-on "+this.options.baseClass+"-"+this.options.onColor}),this.$off=e("",{html:this.options.offText,"class":this.options.baseClass+"-handle-off "+this.options.baseClass+"-"+this.options.offColor}),this.$label=e("",{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:" ",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 -- cgit v1.2.3-55-g7522 From 3b5497dcabe52ff99e787979e39acb734012e041 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 14 Jun 2016 17:51:17 +0200 Subject: [baseconfig] Use bootstap-switch for checkboxes --- modules-available/baseconfig/page.inc.php | 1 + modules-available/baseconfig/templates/_page.html | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php index 6f3ed806..056dbab1 100644 --- a/modules-available/baseconfig/page.inc.php +++ b/modules-available/baseconfig/page.inc.php @@ -193,6 +193,7 @@ class Page_BaseConfig extends Page '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 5c89213f..4d4c05aa 100644 --- a/modules-available/baseconfig/templates/_page.html +++ b/modules-available/baseconfig/templates/_page.html @@ -29,10 +29,10 @@
{{defaultvalue}}
- + {{/override}} {{#override}} - + {{/override}}
-- cgit v1.2.3-55-g7522 From 2180db9debec5ad86dd2d089be7ece80bee064a0 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 15 Jun 2016 15:09:21 +0200 Subject: [sysconfignew] Move css from global file to module specific one --- modules-available/sysconfignew/style.css | 59 +++++++++++++++++++++++++ style/default.css | 74 -------------------------------- 2 files changed, 59 insertions(+), 74 deletions(-) create mode 100644 modules-available/sysconfignew/style.css 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/style/default.css b/style/default.css index bf1834d6..ab9eca08 100644 --- a/style/default.css +++ b/style/default.css @@ -478,77 +478,3 @@ li.slx-submenu a { nav.navbar.sidebar { color: #eee; } - -/* - * 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 { - font-weight: bold; -} - -/* what's this? -textarea.form-control .editor-box{ - height: 520px; -} -*/ -- cgit v1.2.3-55-g7522