Merge pull request #2211 from unraid/feat/responsive-improvements

feat: responsive improvements rd. 2
This commit is contained in:
tom mortensen
2025-05-28 09:48:02 -07:00
committed by GitHub
21 changed files with 224 additions and 17114 deletions

View File

@@ -12,7 +12,7 @@ Code='e956'
###################################################
$currentUnraidPage = str_replace('Browse','Main',basename(explode('?',$_SERVER['REQUEST_URI'])[0]));
$guiSearchBoxSpan = "<span id='guiSearchBoxSpan'><input type='text' id='guiSearchBox' autocomplete='new-password'></input></span><span class='guiSearchBoxResults'></span>";
$guiSearchBoxSpan = "<span id='guiSearchBoxSpan'><input type='text' id='guiSearchBox' autocomplete='new-password'></input></span>";
?>
<script>
var languageVisible;

View File

@@ -4,7 +4,9 @@
}
#guiSearchBoxSpan {
display: inline-block;
position: relative;
display: inline-flex;
align-items: center;
padding: 0;
text-align: left;
height: auto;
@@ -18,25 +20,29 @@
border-radius: 20px;
color: var(--gui-search-search-box-text-color);
background-color: var(--gui-search-search-box-background-color);
padding-left: 4rem;
}
.Theme--black,
.Theme--white {
#guiSearchBoxSpan {
position: relative;
margin: 4px 2px 2px 2px;
width: 100%;
.awesomplete,
#guiSearchBox {
width: 100%;
}
}
#guiSearchBoxSpan:after {
font-family: unraid;
content: "\e956";
position: absolute;
top: 0.8rem;
top: 50%;
left: 1.5rem;
transform: translateY(-50%);
font-size: 1.3rem;
}
#guiSearchBox {
padding-left: 4rem;
}
}
.Theme--sidebar {

View File

@@ -1,10 +0,0 @@
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
Theme: GitHub Dark
Description: Dark theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-dark
Current colors taken from GitHub's CSS
*/.hljs{background:#0d1117;color:#c9d1d9}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{background-color:#033a16;color:#aff5b4}.hljs-deletion{background-color:#67060c;color:#ffdcd7}

View File

@@ -1,12 +0,0 @@
{
".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs": {
"file": "_nuxt/unraid-components.client-Chq1f4tv.js",
"name": "unraid-components.client",
"src": ".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs",
"isEntry": true,
"css": [
"_nuxt/unraid-components-BvEqdEb_.css"
]
},
"ts": 1746122627
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +0,0 @@
{
"src/register.ts": {
"file": "register.D9MKs8Co.js",
"name": "register",
"src": "src/register.ts",
"isEntry": true
},
"style.css": {
"file": "ui.CaW9jS_X.css",
"src": "style.css"
}
}

View File

@@ -13,10 +13,6 @@ Type="xmenu"
*/
?>
<?
function clone_list($disk) {
global $pools;
return strpos($disk['status'],'_NP')===false && ($disk['type']=='Data' || in_array($disk['name'],$pools));
}
if (count($pages)==2) $tabbed = false;
$refs = []; $n = 0;

View File

@@ -528,7 +528,7 @@ function portToggle(port, cmd) {
}
$(function() {
const ctrl = "<span id='wait_eth0' class='status red-text hide' style='font-size:1.2rem;font-style:italic'><i class='fa fa-spinner fa-spin'></i> _(Please wait)_... _(configuring interface)_</span>";
const ctrl = "<span id='wait_eth0' class='red-text hidden' style='font-size:1.2rem;font-style:italic'><i class='fa fa-spinner fa-spin'></i> _(Please wait)_... _(configuring interface)_</span>";
const form = document.eth0_settings;
const dns = document.dns_settings;
<?if (!$service):?>

View File

@@ -1,19 +1,6 @@
Menu="Tasks:2"
Type="xmenu"
Tabs="false"
Code="f08a"
Cond="@filesize('/boot/config/favorites.cfg')"
---
<script>
function delPage(page) {
$.post('/webGui/include/MyFavorites.php',{action:'del',page:page},function(){refresh();});
}
$(function(){
$('div.Panel').each(function(){
var page = $(this).find('a').prop('href').split('/').pop();
$(this).find('span').append('<i class="fa fa-trash-o favo" title="_(Remove from favorites)_" onclick="delPage(&quot;'+page+'&quot;);return false"></i>');
$(this).hover(function(){$(this).find('i.favo').show();},function(){$(this).find('i.favo').hide();});
});
$.post('/webGui/include/MyFavorites.php',{action:'clear'},function(){if ($('div.Panel').length==0) $('#nofavs').show();});
});
</script>

View File

@@ -12,12 +12,6 @@ Type="xmenu"
* all copies or substantial portions of the Software.
*/
?>
<?
function clone_list($disk) {
global $pools;
return strpos($disk['status'],'_NP')===false && ($disk['type']=='Data' || in_array($disk['name'],$pools));
}
?>
<script>
function toggleButton(button,id) {
var disabled = true;

View File

@@ -3,4 +3,55 @@ Type="menu"
Title="My Favorites"
Tag="heart"
---
<div id="nofavs" style="display:none;width:100%"><center>_(No favorites available)_</center></div>
<script>
function delPage(page) {
if (!page || typeof page !== 'string') {
console.error('Invalid page parameter');
return;
}
$.post('/webGui/include/MyFavorites.php', {
action: 'del',
page: page,
})
.done(function() {
refresh();
})
.fail(function(xhr, status, error) {
console.error('Failed to remove favorite:', error);
});
}
$(function(){
const $panels = $('.Panel');
if ($panels.length === 0) {
$('#nofavs').show();
return;
}
$panels.each(function(){
const href = $(this).find('a').prop('href');
const urlParts = href.split('/');
const page = urlParts[urlParts.length - 1];
if (!page || page.includes('..') || page.includes('/')) {
console.warn('Invalid page extracted from href:', href);
return;
}
const trashIcon = $('<i class="fa fa-trash-o favo" title="_(Remove from favorites)_"></i>');
trashIcon.on('click', function(e) {
e.preventDefault();
delPage(page);
return false;
});
$(this).find('span').append(trashIcon);
$(this).hover(function() {
$(this).find('i.favo').toggle();
});
});
});
</script>
<h3 id="nofavs" class="text-center" style="display: none">
_(No favorites available)_
</h3>

View File

@@ -2,7 +2,7 @@ Menu="Notifications:3"
Title="Notification Agents"
Tag="rss-square"
---
<?PHP
<?php
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
*
@@ -88,81 +88,144 @@ function initDropdown() {
<input type="hidden" name="#command" value="/webGui/scripts/agent">
<input type="hidden" name="#arg[1]" value="">
<input type="hidden" name="#arg[2]" value="">
</form>
<?
<?php
$fields = ['Event','Subject','Timestamp','Description','Importance','Content','Link'];
$xml_files = glob("/usr/local/emhttp/plugins/dynamix/agents/*.xml");
$i = 1;
foreach ($xml_files as $xml_file) {
$xml = @simplexml_load_file($xml_file);
if ( ! $xml ) continue;
if ( isset($xml->Language) ) {
$guiLanguage = ($locale == "" ) ? "en_US" : $locale;
$acceptedLanguages = explode(" ",$xml->Language);
if ( ! in_array($guiLanguage,$acceptedLanguages) )
$xml = @simplexml_load_file($xml_file);
if (! $xml) {
continue;
}
$name = str_replace(' ','_',$xml->Name);
if (isset($xml->Language)) {
$guiLanguage = ($locale == "") ? "en_US" : $locale;
$acceptedLanguages = explode(" ", $xml->Language);
if (! in_array($guiLanguage, $acceptedLanguages)) {
continue;
}
}
$name = str_replace(' ', '_', $xml->Name);
$titleId = 'agent-' . strtolower($name);
$enabledAgent = agent_fullname("$name.sh", "enabled");
$disabledAgent = agent_fullname("$name.sh", "disabled");
if (is_file($disabledAgent)) {
$file = $disabledAgent;
if (is_file($enabledAgent)) unlink($enabledAgent);
$file = $disabledAgent;
if (is_file($enabledAgent)) {
unlink($enabledAgent);
}
} else {
$file = $enabledAgent;
$file = $enabledAgent;
}
$values = [];
$script = "";
if (is_file($file)) {
preg_match("/[#]{6,100}([^#]*?)[#]{6,100}/si", file_get_contents($file), $match);
if (isset($match[1])) {
foreach (explode(PHP_EOL, $match[1]) as $line) {
if (strpos($line, "=")) {
[$k, $v] = my_explode("=",str_replace("\"", "", $line),2);
$values[$k] = $v;
}
preg_match("/[#]{6,100}([^#]*?)[#]{6,100}/si", file_get_contents($file), $match);
if (isset($match[1])) {
foreach (explode(PHP_EOL, $match[1]) as $line) {
if (strpos($line, "=")) {
[$k, $v] = my_explode("=", str_replace("\"", "", $line), 2);
$values[$k] = $v;
}
}
}
}
}
foreach (explode(PHP_EOL,(String) $xml->Script) as $line) if (trim($line)) $script .= trim($line)."{1}";
echo '<div class="title"><span class="left"><img src="/plugins/dynamix/icons/'.strtolower(str_replace('_','',$name)).'.png" class="icon" style="height:16px;width:16px;">'.str_replace('_',' ',$name).'</span><span class="status vhshift">'.(is_file($enabledAgent) ? '<span class="green">'._("Enabled").'</span>' : '<span class="red">'._("Disabled").'</span>').'</span></div>';
echo '<form method="POST" name="'.$name.'" action="/update.php" target="progressFrame">';
echo '<input type="hidden" name="#include" value="/webGui/include/update.file.php">';
echo '<input type="hidden" name="#file" value="'.$file.'">';
echo '<input type="hidden" name="#command" value="/webGui/scripts/agent">';
echo '<input type="hidden" name="#arg[1]" value="">';
echo '<input type="hidden" name="#arg[2]" value="">';
echo '<input type="hidden" name="text" value="">';
echo '<dl><dt>'._("Agent function").':</dt><dd><select name="Enabled">';
echo mk_option(is_file($disabledAgent), 'no', _('Disabled'));
echo mk_option(is_file($enabledAgent), 'yes', _('Enabled'));
echo '</select></dd></dl>';
echo '<script>scripts["'.$name.'"]='.json_encode($script).';enabledAgents["'.$name.'"]="'.$enabledAgent.'";disabledAgents["'.$name.'"]="'.$disabledAgent.'";</script>';
foreach ($xml->Variables->children() as $v) {
$vName = preg_replace('#\[([^\]]*)\]#', '<$1>', (string) $v);
$vDesc = ucfirst(strtolower(preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Desc)));
$vDefault = preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Default);
$vHelp = preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Help);
echo "<dl><dt>$vDesc:</dt><dd>";
if (preg_match('/title|message/', $vDesc)) {
echo '<select id="slot_'.$i++.'" name="'.$vName.'" multiple style="display:none">';
$value = str_replace('\n',',',isset($values[$vName]) ? $values[$vName] : $vDefault);
foreach ($fields as $field) echo mk_option_check($value,'$'.strtoupper($field),_($field));
echo '</select>';
} else {
echo '<input type="text" name="'.$vName.'" class="variable" required value="'.( isset($values[$vName]) ? $values[$vName] : $vDefault ).'">';
}
echo '</dd></dl>';
if ($vHelp) echo '<blockquote class="inline_help">'.$vHelp.'</blockquote>';
foreach (explode(PHP_EOL, (string) $xml->Script) as $line) {
if (trim($line)) {
$script .= trim($line)."{1}";
}
}
echo '<dl><dt>&nbsp;</dt><dd><input type="submit" value='._("Apply").' onclick="prepareService(this, \''.$name.'\')" disabled>';
echo '<input type="button" value='._("Done").' onclick="done()">';
if (is_file($file)) {
echo '<input type="button" value='._("Delete").' onclick="execCmd(\'delete\',\''.$name.'\')">';
echo '<input type="button" value='._("Test").' onclick="testService(\''.$name.'\')"'.($file==$enabledAgent ? '>' : ' disabled>');
}
echo '</dd></dl></form><div style="min-height:50px;"></div>';
$displayName = str_replace('_', ' ', $name);
$iconPath = "/plugins/dynamix/icons/" . strtolower(str_replace('_', '', $name)) . ".png";
$isEnabled = is_file($enabledAgent);
$statusClass = $isEnabled ? 'green' : 'red';
$statusText = $isEnabled ? _("Enabled") : _("Disabled");
?>
<div id="<?= $titleId ?>" class="title">
<span class="left">
<img src="<?= $iconPath ?>" class="icon" style="height:16px;width:16px;">
<?= $displayName ?>
</span>
<span class="right status">
<span class="<?= $statusClass ?>"><?= $statusText ?></span>
</span>
</div>
<form method="POST" name="<?= $name ?>" action="/update.php" target="progressFrame">
<input type="hidden" name="#include" value="/webGui/include/update.file.php">
<input type="hidden" name="#file" value="<?= $file ?>">
<input type="hidden" name="#command" value="/webGui/scripts/agent">
<input type="hidden" name="#arg[1]" value="">
<input type="hidden" name="#arg[2]" value="">
<input type="hidden" name="text" value="">
<dl>
<dt><?= _("Agent function") ?>:</dt>
<dd>
<select name="Enabled">
<?= mk_option(is_file($disabledAgent), 'no', _('Disabled')) ?>
<?= mk_option(is_file($enabledAgent), 'yes', _('Enabled')) ?>
</select>
</dd>
</dl>
<script>
scripts["<?= $name ?>"] = <?= json_encode($script) ?>;
enabledAgents["<?= $name ?>"] = "<?= $enabledAgent ?>";
disabledAgents["<?= $name ?>"] = "<?= $disabledAgent ?>";
</script>
<?php foreach ($xml->Variables->children() as $v):
$vName = preg_replace('#\[([^\]]*)\]#', '<$1>', (string) $v);
$vDesc = ucfirst(strtolower(preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Desc)));
$vDefault = preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Default);
$vHelp = preg_replace('#\[([^\]]*)\]#', '<$1>', $v->attributes()->Help);
$currentValue = isset($values[$vName]) ? $values[$vName] : $vDefault;
$isTitleOrMessage = preg_match('/title|message/', $vDesc);
?>
<dl>
<dt><?= $vDesc ?>:</dt>
<dd>
<?php if ($isTitleOrMessage):
$value = str_replace('\n', ',', $currentValue);
?>
<select id="slot_<?= $i++ ?>" name="<?= $vName ?>" multiple style="display:none">
<?php foreach ($fields as $field): ?>
<?= mk_option_check($value, '$'.strtoupper($field), _($field)) ?>
<?php endforeach; ?>
</select>
<?php else: ?>
<input type="text" name="<?= $vName ?>" class="variable" required value="<?= $currentValue ?>">
<?php endif; ?>
</dd>
</dl>
<?php if ($vHelp): ?>
<blockquote class="inline_help"><?= $vHelp ?></blockquote>
<?php endif; ?>
<?php endforeach; ?>
<dl>
<dt>&nbsp;</dt>
<dd>
<div class="buttons-spaced">
<input type="submit" value="<?= _("Apply") ?>" onclick="prepareService(this, '<?= $name ?>')" disabled>
<input type="button" value="<?= _("Done") ?>" onclick="done()">
<?php if (is_file($file)): ?>
<input type="button" value="<?= _("Delete") ?>" onclick="execCmd('delete','<?= $name ?>')">
<input type="button" value="<?= _("Test") ?>" onclick="testService('<?= $name ?>')"<?= $file == $enabledAgent ? '>' : ' disabled>' ?>
<?php endif; ?>
</div>
</dd>
</dl>
</form>
<?php
}
?>

View File

@@ -13,10 +13,6 @@ Type="xmenu"
*/
?>
<?
function clone_list($disk) {
global $pools;
return strpos($disk['status'],'_NP')===false && ($disk['type']=='Data' || in_array($disk['name'],$pools));
}
if ($name) {
$refs = []; $n = $i = 0;
// Natural sorting of share names

View File

@@ -107,7 +107,9 @@ function generatePanels($page, $path, $defaultIcon, $docroot, $useTabCookie = fa
foreach ($pgs as $pg) {
$output .= generatePanel($pg, $path, $defaultIcon, $docroot, $useTabCookie);
}
return '<div class="Panels">'.$output.'</div>';
return !empty($output)
? '<div class="Panels">'.$output.'</div>'
: '';
}
/**

View File

@@ -566,6 +566,9 @@ function comparePCIData() {
return $changes;
}
function clone_list($disk) {
global $pools;
return strpos($disk['status'],'_NP')===false && ($disk['type']=='Data' || in_array($disk['name'],$pools));
}
?>

View File

@@ -25,7 +25,7 @@ input.mask {
width: 30px;
}
input.port {
width: 50px;
width: 64px;
}
input.ok {
color: #f2f2f2;

View File

@@ -197,10 +197,11 @@ a.button,
}
/* necessary evil until we re-write button styles */
.buttons-no-margin {
.buttons-no-margin,
.buttons-spaced {
display: flex;
flex-wrap: wrap;
gap: 1rem;
gap: 1.2rem;
input[type="button"],
input[type="reset"],
@@ -656,13 +657,17 @@ div.title.shift {
margin-top: auto;
}
@media (min-width: 768px) {
#footer {
grid-template-columns: minmax(0, auto) minmax(0, auto);
justify-content: space-between;
}
}
@media (min-width: 768px) and (min-height: 768px) {
#footer {
position: fixed;
bottom: 0;
left: 0;
z-index: 10000;
grid-template-columns: minmax(0, auto) minmax(0, auto);
justify-content: space-between;
}
}
#countdown {
@@ -1362,6 +1367,7 @@ a.list {
.tab-content {
display: none;
padding-top: 2rem;
form:first-of-type {
padding-top: 1rem;
@@ -1758,6 +1764,22 @@ span#wlan0 {
font-family: bitstream, monospace;
}
.text-center {
text-align: center;
}
.text-left {
text-align: left;
}
.text-right {
text-align: right;
}
.text-justify {
text-align: justify;
}
.hidden {
display: none;
}

View File

@@ -1262,9 +1262,6 @@ div.icon-zip {
#guiSearchBox:placeholder-shown {
caret-color: transparent;
}
.guiSearchBoxResults {
width: 450px;
}
.awesomplete [hidden] {
display: none;
}
@@ -1403,11 +1400,6 @@ div.icon-zip {
div.box {
line-height: 2.4rem;
}
.guiSearchBoxResults {
position: fixed !important;
top: 90px !important;
left: 250px !important;
}
select[name="port_select"] {
border: none;
min-width: 54px;