diff --git a/include/lucidAuth.functions.php b/include/lucidAuth.functions.php index cc56ef6..df2aab2 100644 --- a/include/lucidAuth.functions.php +++ b/include/lucidAuth.functions.php @@ -66,17 +66,17 @@ function storeToken (string $secureToken, string $qualifiedUsername, string $htt INSERT INTO SecureToken (UserId, Value) SELECT User.Id, :securetoken FROM User - WHERE User.Username = :qualifiedusername + WHERE LOWER(User.Username) = :qualifiedusername '); $pdoQuery->execute([ ':securetoken' => $secureToken, - ':qualifiedusername' => $qualifiedUsername + ':qualifiedusername' => strtolower($qualifiedUsername) ]); } catch (Exception $e) { return ['status' => 'Fail', 'reason' => $e]; } - + // Save authentication token in cookie clientside $cookieDomain = array_values(array_filter($settings->Session['CookieDomains'], function ($value) use ($httpHost) { // Check if $_SERVER['HTTP_HOST'] matches any of the configured domains (either explicitly or as a subdomain) @@ -114,18 +114,19 @@ function validateToken (string $secureToken) { // Retrieve all authentication tokens from database matching username $pdoQuery = $pdoDB->prepare(' - SELECT SecureToken.Value + SELECT User.Id, SecureToken.Value FROM SecureToken - LEFT JOIN User + LEFT JOIN User ON (User.Id=SecureToken.UserId) - WHERE User.Username = :username + WHERE LOWER(User.Username) = :username '); $pdoQuery->execute([ - ':username' => (string)$jwtPayload->sub + ':username' => (string) strtolower($jwtPayload->sub) ]); foreach($pdoQuery->fetchAll(PDO::FETCH_ASSOC) as $row) { try { $storedTokens[] = JWT::decode($row['Value'], base64_decode($settings->JWT['PrivateKey_base64']), $settings->JWT['Algorithm']); + $currentUserId = $row['Id']; } catch (Exception $e) { continue; } @@ -137,7 +138,8 @@ function validateToken (string $secureToken) { })) === 1) { return [ 'status' => 'Success', - 'name' => $jwtPayload->name + 'name' => $jwtPayload->name, + 'uid' => $currentUserId ]; } else { if ($settings->Debug['LogToFile']) { diff --git a/include/lucidAuth.template.php b/include/lucidAuth.template.php index af0bc27..e1b45b6 100644 --- a/include/lucidAuth.template.php +++ b/include/lucidAuth.template.php @@ -10,14 +10,10 @@ $pageLayout['full'] = <<<'FULL' lucidAuth - - - - - + @@ -36,6 +32,46 @@ $pageLayout['full'] = <<<'FULL' FULL; +$pageLayout['full_alt'] = <<<'FULL_ALT' + + + + + lucidAuth + + + + + + + + + + +
+
+
+
+
+ + %1$s +
+
+ %2$s +
+
+ + +
+
+
+ + +FULL_ALT; + $pageLayout['bare'] = <<<'BARE' @@ -43,7 +79,7 @@ $pageLayout['bare'] = <<<'BARE' lucidAuth - + @@ -54,16 +90,18 @@ BARE; $contentLayout['login'] = <<<'LOGIN' -
- Login Details +
-
+ Secure! LOGIN; -$contentLayout['manage'] = <<<'MANAGE' +$contentLayout['manage']['header'] = <<<'MANAGE_HEADER' - Ingelogd als %1$s --- [EN NL] [Log uit] -
- Beheer Gebruikers + Logged in as %1$s --- [EN NL] [Logout] + +MANAGE_HEADER; +$contentLayout['manage']['section'] = <<<'MANAGE_SECTION' -
-MANAGE; +MANAGE_SECTION; ?> \ No newline at end of file diff --git a/public/lucidAuth.manage.php b/public/lucidAuth.manage.php index d19d1a3..c6ea335 100644 --- a/public/lucidAuth.manage.php +++ b/public/lucidAuth.manage.php @@ -12,32 +12,33 @@ try { $allUsers = $pdoDB->query(' - SELECT User.Username, Role.Rolename, COUNT(DISTINCT SecureToken.Value) AS Sessions + SELECT User.Id, User.Username, Role.Rolename FROM User - LEFT JOIN Role - ON (User.RoleId=Role.Id) - LEFT JOIN SecureToken - ON (User.Id=SecureToken.UserId) + LEFT JOIN Role + ON (Role.Id = User.RoleId) ')->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $e) { // Should really do some actual errorhandling here throw new Exception($e); } - foreach($allUsers as $row) { - $tableRows[] = sprintf('%1$s%2$s%3$s', + $tableRows[] = sprintf('%3$s%4$s%5$s', + $validateTokenResult['uid'] === $row['Id'] ? ' class="currentuser"': null, + $row['Id'], explode('\\', $row['Username'])[1], $row['Rolename'], - $row['Sessions'] + '' . ($validateTokenResult['uid'] === $row['Id'] ? null : ' ') ); } - echo sprintf($pageLayout['full'], - sprintf($contentLayout['manage'], - $validateTokenResult['name'], + echo sprintf($pageLayout['full_alt'], + sprintf($contentLayout['manage']['header'], + $validateTokenResult['name'] + ), + sprintf($contentLayout['manage']['section'], implode($tableRows) - ) - ); + ) + ); } else { // No cookie containing valid authentication token found; // explicitly deleting any remaining cookie, then redirecting to loginpage diff --git a/public/lucidAuth.setXDomainCookie.php b/public/lucidAuth.setXDomainCookie.php index c3ab1f8..0d20746 100644 --- a/public/lucidAuth.setXDomainCookie.php +++ b/public/lucidAuth.setXDomainCookie.php @@ -3,8 +3,7 @@ include_once('../include/lucidAuth.functions.php'); - - // Start with checking $_REQUEST['ref'] + // Start with checking $_REQUEST['ref'] // What do we need? // token again? @@ -16,6 +15,24 @@ // let the client setup multiple iframes for all domains other than origin domains // this requires passing an array of domains to the client in asynchronous reply; which feels insecure + if (!empty($_REQUEST['ref'])) { + try { + $queryString = json_decode(base64_decode($_REQUEST['ref']), JSON_OBJECT_AS_ARRAY); + } + catch (Exception $e) { + // Silently fail, unless explicitly specified otherwise + if ($settings->Debug['Verbose']) throw new Exception($e); + exit; + } + + switch ($queryString['action']) { + case 'login': + break; + default: + break; + } + } + include_once('../include/lucidAuth.template.php'); echo sprintf($pageLayout['bare'], diff --git a/public/misc/script.editable.table.js b/public/misc/script.editable.table.js index 36be540..66984b6 100644 --- a/public/misc/script.editable.table.js +++ b/public/misc/script.editable.table.js @@ -13,7 +13,7 @@ $.fn.editableTableWidget = function (options) { editor = activeOptions.editor.css('position', 'absolute').hide().appendTo(element.parent()), active, showEditor = function (select) { - active = element.find('td:focus'); + active = element.find('td:focus:not(".immutable")'); if (active.length) { editor.val(active.text()) .removeClass('error') @@ -89,26 +89,26 @@ $.fn.editableTableWidget = function (options) { editor.removeClass('error'); } }); - element.on('click keypress dblclick', showEditor) - .css('cursor', 'pointer') - .keydown(function (e) { - var prevent = true, - possibleMove = movement($(e.target), e.which); - if (possibleMove.length > 0) { - possibleMove.focus(); - } else if (e.which === ENTER) { - showEditor(false); - } else if (e.which === 17 || e.which === 91 || e.which === 93) { - showEditor(true); - prevent = false; - } else { - prevent = false; - } - if (prevent) { - e.stopPropagation(); - e.preventDefault(); - } - }); + element.on('click keypress dblclick', showEditor) + .css('cursor', 'pointer') + .keydown(function (e) { + var prevent = true, + possibleMove = movement($(e.target), e.which); + if (possibleMove.length > 0) { + possibleMove.focus(); + } else if (e.which === ENTER) { + showEditor(false); + } else if (e.which === 17 || e.which === 91 || e.which === 93) { + showEditor(true); + prevent = false; + } else { + prevent = false; + } + if (prevent) { + e.stopPropagation(); + e.preventDefault(); + } + }); element.find('td').prop('tabindex', 1); @@ -126,6 +126,6 @@ $.fn.editableTableWidget.defaultOptions = { cloneProperties: ['padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right', 'text-align', 'font', 'font-size', 'font-family', 'font-weight', 'border', 'border-top', 'border-bottom', 'border-left', 'border-right'], - editor: $('') + editor: $('') }; diff --git a/public/misc/script.manage.js b/public/misc/script.manage.js index 2837909..2048dda 100644 --- a/public/misc/script.manage.js +++ b/public/misc/script.manage.js @@ -1,3 +1,95 @@ $(document).ready(function(){ - $('#tabletest').editableTableWidget(); + // Initialize the editable-table functionality + $('#usertable').editableTableWidget(); + + $('#usertable button.delete').click(function() { + $(this).closest('tr').addClass('removed'); + }); + + $('#btnnewuser').click(function() { + // Create a new user; generate pseudo-random username + var newUser = 'User' + String(Math.floor(Math.random() * Math.floor(9999))).padStart(4, '0'); + + // Add new user to the interface + // (new `` in ``) + $('#usertable tbody').append($('', {class: 'new'}) + .append($('` + // To prevent recreating multiple new editors; reference the already existing `` + $('#usertable').editableTableWidget({editor: $('#editor')}); + // Add eventhandlers to buttons of newly added `` + $('#usertable .new button.delete').unbind().click(function() { + $(this).closest('tr').remove(); + }); + }); + + $('#btnsave').click(function() { + var newEntries = []; + $('#usertable .new').each(function() { + newEntries.push({ + 'userName': $(this).find('td:nth-child(1)').text(), + 'roleName': $(this).find('td:nth-child(2)').text() + }); + }); + var removedEntries = []; + $('#usertable .removed').each(function() { + removedEntries.push({ + 'userId': $(this).find('td:nth-child(1)').data('userid'), + 'userName': $(this).find('td:nth-child(1)').text(), + 'roleName': $(this).find('td:nth-child(2)').text() + }); + }); + +console.log({'new': newEntries, 'removed': removedEntries}); + +/* $.get("psworker.php", { + do: "mutate", + mutations: { + new: newEntries, + removed: removedEntries + } + })*/ + }); + + $('#btncancel').click(function() { + window.location.reload(); + }); + + $('#linklogout').click(function() { + console.log('Logging out!'); + }); + + if (localStorage.getItem('theme') !== null) { + $('#theme').addClass(localStorage.getItem('theme')); + } + + $('.logo .sub').click(function(event) { + var classes = ["tablecloth", "weave", "madras", "tartan", "seigaiha"]; + + if (event.ctrlKey) { + var selectedTheme = classes[~~(Math.random()*classes.length)]; + + $('#theme').removeClass(classes.join(' ')).addClass(selectedTheme); + localStorage.setItem('theme', selectedTheme); + } + if (event.altKey) { + $('#theme').removeClass(classes.join(' ')); + localStorage.removeItem('theme'); + } + }); + }); \ No newline at end of file diff --git a/public/misc/script.translation.js b/public/misc/script.translation.js index 7566134..9b002cd 100644 --- a/public/misc/script.translation.js +++ b/public/misc/script.translation.js @@ -1,8 +1,9 @@ var locales = { en: { - button_add: "add", + button_new: "new", + button_save: "save", button_cancel: "cancel", - button_continue: "continue", + button_sessions: "sessions", button_delete: "delete", button_login: "login", heading_error: "ERROR!", @@ -10,12 +11,16 @@ var locales = { label_username: "Username:", link_logout: "Logout", span_credentialsavailable: "Login credentials available upon request!", - span_loggedinas: "Logged in as" + span_loggedinas: "Logged in as", + th_username: "Username", + th_role: "Role", + th_manage: "Manage" }, nl: { - button_add: "voeg toe", - button_cancel: "annuleer", - button_continue: "doorgaan", + button_new: "nieuw", + button_save: "opslaan", + button_cancel: "annuleren", + button_sessions: "sessies", button_delete: "verwijder", button_login: "log in", heading_error: "FOUT!", @@ -23,7 +28,10 @@ var locales = { label_username: "Gebruikersnaam:", link_logout: "Log uit", span_credentialsavailable: "Inloggegevens verkrijgbaar op aanvraag!", - span_loggedinas: "Ingelogd als" + span_loggedinas: "Ingelogd als", + th_username: "Gebruikersnaam", + th_role: "Rol", + th_manage: "Beheer" } // ... etc. }; @@ -31,19 +39,19 @@ $(document).ready(function(){ $('[id^=linklanguage-]').click(function() { var selectedlang = $(this).attr('id').split('-')[1]; // Replace text of each element with translated value - $('[data-translation]').each(function(index) { + $('[data-translation]').each(function() { $(this).text(locales[selectedlang][$(this).data('translation')]); }); // Enable/disable (toggle) anchors $('span#user a.current').removeClass('current'); $(this).addClass('current'); - + // Store current languagesetting in persistent localstorage localStorage.setItem('language', selectedlang); }); - + if (localStorage.getItem('language') !== null) { - $('[data-translation]').each(function(index) { + $('[data-translation]').each(function() { $(this).text(locales[localStorage.getItem('language')][$(this).data('translation')]); }); $('span#user a.current').removeClass('current'); diff --git a/public/misc/style.css b/public/misc/style.css index 1a60e11..5a76a3f 100644 --- a/public/misc/style.css +++ b/public/misc/style.css @@ -96,64 +96,60 @@ body { .main { clear: both; } - .main fieldset { - border: 0; - } - .main fieldset legend { - visibility: hidden; - } - .main fieldset label.pre { + .main section { + clear: both; + } + .main section label.pre { display: inline-block; width: 155px; text-align: right; vertical-align: top; margin-top: 3px; } - .main fieldset label#labelallaliases { - float: left; - } - .main fieldset output#aliasstats { - float: left; - clear: left; - width: 160px; - text-align: right; - font-size: 12px; - } - .main fieldset output#aliasstats:after { - margin-left: 7px; - content: ' '; - } - .main fieldset input { + .main section input { border: 1px solid #003399; padding: 2px; width: 100px; } - .main fieldset input[type=radio] { + .main section input[type=radio] { border: none; margin-top: 7px; width: 20px; } - .main fieldset button { + .main header button, + .main section button { margin-left: 160px; text-transform: uppercase; } - .main fieldset select { - border: 1px solid #003399; - padding: 2px; - width: 375px; - } - .main fieldset select .new { - font-weight: bold; - } - .main fieldset select .deleted { - text-decoration: line-through; - } - .main fieldset#signup label.pre { - width: 205px; - } - .main fieldset#signup span.indent, .main fieldset#signup input.button { - margin-left: 210px; - } + .main header .buttons, + .main section .buttons { + text-align: center; + } + .main header .buttons button, + .main section .buttons button { + margin-left: inherit; + } + .main section table { + width: 100%; + } + .main section table * { + font-size: 14px; + padding: 2px; + margin: 0; + } + .main section table .new { + font-weight: bold; + } + .main section table .removed td:nth-child(-n+2) { + text-decoration: line-through; + color: grey; + } + .main section table tbody tr:nth-child(odd) { + background-color: rgb(215, 215, 215); + } + .main section table .immutable { + cursor: default !important; + } .main li { list-style: none; padding: 5px; @@ -214,25 +210,3 @@ body { .main span#user nav { display: inline; } - .main span#user #pluginlogos { - display: none; - position: absolute; - top: 72px; - right: 10px; - height: 112px; - width: 250px; - border: 1px solid rgb(0, 51, 153); - box-shadow: black 0px 0px 20px; - box-sizing: border-box; - padding-top: 5px; - background: white; - font-size: inherit; - font-weight: bold; - } - .main span#user #pluginlogos img { - width: 75px; - height: 75px; - filter: saturate(500%) contrast(200%) grayscale(100%) opacity(50%); - transition: all 375ms; - cursor: pointer; - } diff --git a/public/misc/style.panes.css b/public/misc/style.panes.css new file mode 100644 index 0000000..ac9fa89 --- /dev/null +++ b/public/misc/style.panes.css @@ -0,0 +1,50 @@ +body{ + margin: 0; +} +.wrapper{ + min-height: 100vh; + background: #FFFFFF; + display: flex; + flex-direction: column; +} +.header { + height: 100px; + background: #FFFFFF; + color: #000000; +} +.content { + display: flex; + flex: 1; + background: #333333; + color: #000; + min-height: 0px; + max-height: 100vh; +} +.columns{ + display: flex; + flex:1; +} +.main{ + flex: 1; + order: 2; + background: #fff; + border: 3px solid #CCCCCC; + border-radius: 5px; + height: 400px; + margin-top: auto; + margin-bottom: auto; +} +.main section { + overflow-y: scroll; + height: calc(100% - 100px); +} +.sidebar-first{ + width: 25%; + background: transparent; + order: 1; +} +.sidebar-second{ + width: 25%; + order: 3; + background: transparent; +} \ No newline at end of file diff --git a/public/misc/style.theme.css b/public/misc/style.theme.css index 382eb0a..1d78ca5 100644 --- a/public/misc/style.theme.css +++ b/public/misc/style.theme.css @@ -1,39 +1,39 @@ -html.tablecloth { - height: 100%; - background: repeating-linear-gradient(-45deg, transparent, transparent 1em, rgba(136, 136, 136, 0.4) 0, rgba(136, 136, 136, 0.1) 2em, transparent 0, transparent 1em, rgba(136, 136, 136, 0.3) 0, rgba(136, 136, 136, 0.2) 4em, transparent 0, transparent 1em, rgba(68, 68, 68, 0.6) 0, rgba(68, 68, 68, 0.2) 2em), - repeating-linear-gradient(45deg, transparent, transparent 1em, rgba(136, 136, 136, 0.4) 0, rgba(136, 136, 136, 0.1) 2em, transparent 0, transparent 1em, rgba(136, 136, 136, 0.3) 0, rgba(136, 136, 136, 0.2) 4em, transparent 0, transparent 1em, rgba(68, 68, 68, 0.4) 0, rgba(68, 68, 68, 0.1) 2em), #666; - background-blend-mode: multiply; -} - -html.weave { - background: linear-gradient(45deg, #666 12%, transparent 0, transparent 88%, #666 0), - linear-gradient(135deg, transparent 37%, #888 0, #888 63%, transparent 0), - linear-gradient(45deg, transparent 37%, #666 0, #666 63%, transparent 0), - #444; - background-size: 40px 40px; -} - -html.madras { - height: 100%; - background-color: #e9d4b9; - background-image: repeating-linear-gradient(45deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 120px, rgba(11, 36, 45, 0.5) 120px, rgba(11, 36, 45, 0.5) 140px), - repeating-linear-gradient(135deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 140px, rgba(11, 36, 45, 0.5) 140px, rgba(11, 36, 45, 0.5) 160px); -} - -html.tartan { - height: 100%; - background-color: #a0302c; - background-image: repeating-linear-gradient(20deg, transparent, transparent 50px, rgba(0, 0, 0, 0.4) 50px, rgba(0, 0, 0, 0.4) 53px, transparent 53px, transparent 63px, rgba(0, 0, 0, 0.4) 63px, rgba(0, 0, 0, 0.4) 66px, transparent 66px, transparent 116px, rgba(0, 0, 0, 0.5) 116px, rgba(0, 0, 0, 0.5) 166px, rgba(255, 255, 255, 0.2) 166px, rgba(255, 255, 255, 0.2) 169px, rgba(0, 0, 0, 0.5) 169px, rgba(0, 0, 0, 0.5) 179px, rgba(255, 255, 255, 0.2) 179px, rgba(255, 255, 255, 0.2) 182px, rgba(0, 0, 0, 0.5) 182px, rgba(0, 0, 0, 0.5) 232px, transparent 232px), - repeating-linear-gradient(290deg, transparent, transparent 50px, rgba(0, 0, 0, 0.4) 50px, rgba(0, 0, 0, 0.4) 53px, transparent 53px, transparent 63px, rgba(0, 0, 0, 0.4) 63px, rgba(0, 0, 0, 0.4) 66px, transparent 66px, transparent 116px, rgba(0, 0, 0, 0.5) 116px, rgba(0, 0, 0, 0.5) 166px, rgba(255, 255, 255, 0.2) 166px, rgba(255, 255, 255, 0.2) 169px, rgba(0, 0, 0, 0.5) 169px, rgba(0, 0, 0, 0.5) 179px, rgba(255, 255, 255, 0.2) 179px, rgba(255, 255, 255, 0.2) 182px, rgba(0, 0, 0, 0.5) 182px, rgba(0, 0, 0, 0.5) 232px, transparent 232px), - repeating-linear-gradient(145deg, transparent, transparent 2px, rgba(0, 0, 0, 0.2) 2px, rgba(0, 0, 0, 0.2) 3px, transparent 3px, transparent 5px, rgba(0, 0, 0, 0.2) 5px); -} - -html.seigaiha { - background-color: grey; - background-image: radial-gradient(circle at 100% 150%, grey 24%, silver 25%, silver 28%, grey 29%, grey 36%, silver 36%, silver 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0)), - radial-gradient(circle at 0 150%, grey 24%, silver 25%, silver 28%, grey 29%, grey 36%, silver 36%, silver 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0)), - radial-gradient(circle at 50% 100%, silver 10%, grey 11%, grey 23%, silver 24%, silver 30%, grey 31%, grey 43%, silver 44%, silver 50%, grey 51%, grey 63%, silver 64%, silver 71%, rgba(0, 0, 0, 0) 71%, rgba(0, 0, 0, 0)), - radial-gradient(circle at 100% 50%, silver 5%, grey 6%, grey 15%, silver 16%, silver 20%, grey 21%, grey 30%, silver 31%, silver 35%, grey 36%, grey 45%, silver 46%, silver 49%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0)), - radial-gradient(circle at 0 50%, silver 5%, grey 6%, grey 15%, silver 16%, silver 20%, grey 21%, grey 30%, silver 31%, silver 35%, grey 36%, grey 45%, silver 46%, silver 49%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0)); - background-size: 100px 50px; +#theme.tablecloth { + height: 100%; + background: repeating-linear-gradient(-45deg, transparent, transparent 1em, rgba(136, 136, 136, 0.4) 0, rgba(136, 136, 136, 0.1) 2em, transparent 0, transparent 1em, rgba(136, 136, 136, 0.3) 0, rgba(136, 136, 136, 0.2) 4em, transparent 0, transparent 1em, rgba(68, 68, 68, 0.6) 0, rgba(68, 68, 68, 0.2) 2em), + repeating-linear-gradient(45deg, transparent, transparent 1em, rgba(136, 136, 136, 0.4) 0, rgba(136, 136, 136, 0.1) 2em, transparent 0, transparent 1em, rgba(136, 136, 136, 0.3) 0, rgba(136, 136, 136, 0.2) 4em, transparent 0, transparent 1em, rgba(68, 68, 68, 0.4) 0, rgba(68, 68, 68, 0.1) 2em), #666; + background-blend-mode: multiply; +} + +#theme.weave { + background: linear-gradient(45deg, #666 12%, transparent 0, transparent 88%, #666 0), + linear-gradient(135deg, transparent 37%, #888 0, #888 63%, transparent 0), + linear-gradient(45deg, transparent 37%, #666 0, #666 63%, transparent 0), + #444; + background-size: 40px 40px; +} + +#theme.madras { + height: 100%; + background-color: #e9d4b9; + background-image: repeating-linear-gradient(45deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 120px, rgba(11, 36, 45, 0.5) 120px, rgba(11, 36, 45, 0.5) 140px), + repeating-linear-gradient(135deg, transparent 5px, rgba(11, 36, 45, 0.5) 5px, rgba(11, 36, 45, 0.5) 10px, rgba(211, 119, 111, 0) 10px, rgba(211, 119, 111, 0) 35px, rgba(211, 119, 111, 0.5) 35px, rgba(211, 119, 111, 0.5) 40px, rgba(11, 36, 45, 0.5) 40px, rgba(11, 36, 45, 0.5) 50px, rgba(11, 36, 45, 0) 50px, rgba(11, 36, 45, 0) 60px, rgba(211, 119, 111, 0.5) 60px, rgba(211, 119, 111, 0.5) 70px, rgba(247, 179, 85, 0.5) 70px, rgba(247, 179, 85, 0.5) 80px, rgba(247, 179, 85, 0) 80px, rgba(247, 179, 85, 0) 90px, rgba(211, 119, 111, 0.5) 90px, rgba(211, 119, 111, 0.5) 110px, rgba(211, 119, 111, 0) 110px, rgba(211, 119, 111, 0) 140px, rgba(11, 36, 45, 0.5) 140px, rgba(11, 36, 45, 0.5) 160px); +} + +#theme.tartan { + height: 100%; + background-color: #a0302c; + background-image: repeating-linear-gradient(20deg, transparent, transparent 50px, rgba(0, 0, 0, 0.4) 50px, rgba(0, 0, 0, 0.4) 53px, transparent 53px, transparent 63px, rgba(0, 0, 0, 0.4) 63px, rgba(0, 0, 0, 0.4) 66px, transparent 66px, transparent 116px, rgba(0, 0, 0, 0.5) 116px, rgba(0, 0, 0, 0.5) 166px, rgba(255, 255, 255, 0.2) 166px, rgba(255, 255, 255, 0.2) 169px, rgba(0, 0, 0, 0.5) 169px, rgba(0, 0, 0, 0.5) 179px, rgba(255, 255, 255, 0.2) 179px, rgba(255, 255, 255, 0.2) 182px, rgba(0, 0, 0, 0.5) 182px, rgba(0, 0, 0, 0.5) 232px, transparent 232px), + repeating-linear-gradient(290deg, transparent, transparent 50px, rgba(0, 0, 0, 0.4) 50px, rgba(0, 0, 0, 0.4) 53px, transparent 53px, transparent 63px, rgba(0, 0, 0, 0.4) 63px, rgba(0, 0, 0, 0.4) 66px, transparent 66px, transparent 116px, rgba(0, 0, 0, 0.5) 116px, rgba(0, 0, 0, 0.5) 166px, rgba(255, 255, 255, 0.2) 166px, rgba(255, 255, 255, 0.2) 169px, rgba(0, 0, 0, 0.5) 169px, rgba(0, 0, 0, 0.5) 179px, rgba(255, 255, 255, 0.2) 179px, rgba(255, 255, 255, 0.2) 182px, rgba(0, 0, 0, 0.5) 182px, rgba(0, 0, 0, 0.5) 232px, transparent 232px), + repeating-linear-gradient(145deg, transparent, transparent 2px, rgba(0, 0, 0, 0.2) 2px, rgba(0, 0, 0, 0.2) 3px, transparent 3px, transparent 5px, rgba(0, 0, 0, 0.2) 5px); +} + +#theme.seigaiha { + background-color: grey; + background-image: radial-gradient(circle at 100% 150%, grey 24%, silver 25%, silver 28%, grey 29%, grey 36%, silver 36%, silver 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0)), + radial-gradient(circle at 0 150%, grey 24%, silver 25%, silver 28%, grey 29%, grey 36%, silver 36%, silver 40%, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0)), + radial-gradient(circle at 50% 100%, silver 10%, grey 11%, grey 23%, silver 24%, silver 30%, grey 31%, grey 43%, silver 44%, silver 50%, grey 51%, grey 63%, silver 64%, silver 71%, rgba(0, 0, 0, 0) 71%, rgba(0, 0, 0, 0)), + radial-gradient(circle at 100% 50%, silver 5%, grey 6%, grey 15%, silver 16%, silver 20%, grey 21%, grey 30%, silver 31%, silver 35%, grey 36%, grey 45%, silver 46%, silver 49%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0)), + radial-gradient(circle at 0 50%, silver 5%, grey 6%, grey 15%, silver 16%, silver 20%, grey 21%, grey 30%, silver 31%, silver 35%, grey 36%, grey 45%, silver 46%, silver 49%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0)); + background-size: 100px 50px; } \ No newline at end of file
', { + text: newUser + })) + .append($('', { + text: 'User' + })) + .append($('', { + class: 'immutable', + html: ' ' + + '' + })) + ); + // Call `editableTableWidget()` again to include the newly added `