mirror of
https://git.proxmox.com/git/pve-http-server
synced 2026-03-24 11:38:00 +00:00
formatter: html: update to bootstrap 5
this makes a few changes necessary, but not too much: * include the different directory for bootstrap5 * use different navbar markup * different classes for navbar container + items * add classes to pre tag since it's not styled anymore in newer bootstrap versions * add 'form-label' to labels * use containers with 'mb-3' for form + buttons * use 'd-grid' container for button instead of 'btn-block' * add 'breadcrumb-item' where necessary Since bootstrap 5 does not depend on jQuery anymore, use that chance to remove it here as dependency too. For that remove the 'button' and 'add_js' subs that were never actually used. Also remove the general /js/ alias and the now unnecessary fonts for bootstrap. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> Link: https://lore.proxmox.com/20250605090251.886802-1-d.csapak@proxmox.com
This commit is contained in:
parent
f10efa82d0
commit
157d9875f6
3
debian/control
vendored
3
debian/control
vendored
@ -15,8 +15,7 @@ Depends: libanyevent-http-perl,
|
|||||||
libhttp-date-perl,
|
libhttp-date-perl,
|
||||||
libhttp-message-perl,
|
libhttp-message-perl,
|
||||||
libio-socket-ssl-perl,
|
libio-socket-ssl-perl,
|
||||||
libjs-bootstrap,
|
libjs-bootstrap5,
|
||||||
libjs-jquery,
|
|
||||||
libjson-perl,
|
libjson-perl,
|
||||||
libnet-ip-perl,
|
libnet-ip-perl,
|
||||||
libpve-common-perl (>= 8.0.2),
|
libpve-common-perl (>= 8.0.2),
|
||||||
|
|||||||
@ -2025,12 +2025,8 @@ sub new {
|
|||||||
$self->{formatter_config}->{csrfgen_func} =
|
$self->{formatter_config}->{csrfgen_func} =
|
||||||
$self->can('generate_csrf_prevention_token');
|
$self->can('generate_csrf_prevention_token');
|
||||||
|
|
||||||
# add default dirs which includes jquery and bootstrap
|
# libjs-bootstrap5 uses a different dir with symlinks
|
||||||
my $jsbase = '/usr/share/javascript';
|
add_dirs($self->{dirs}, '/bootstrap5/' => "/usr/share/bootstrap-html/");
|
||||||
add_dirs($self->{dirs}, '/js/' => "$jsbase/");
|
|
||||||
# libjs-bootstrap uses symlinks for this, which we do not want to allow..
|
|
||||||
my $glyphicons = '/usr/share/fonts/truetype/glyphicons/';
|
|
||||||
add_dirs($self->{dirs}, '/js/bootstrap/fonts/' => "$glyphicons");
|
|
||||||
|
|
||||||
# init inotify
|
# init inotify
|
||||||
PVE::INotify::inotify_init();
|
PVE::INotify::inotify_init();
|
||||||
|
|||||||
@ -53,7 +53,7 @@ sub body {
|
|||||||
<title>$self->{title}</title>
|
<title>$self->{title}</title>
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- Bootstrap -->
|
||||||
<link href="/js/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
<link href="/bootstrap5/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$jssetup
|
$jssetup
|
||||||
@ -65,10 +65,8 @@ body {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
<!-- Include bootstrap bundle (everything necessary to run) -->
|
||||||
<script src="/js/jquery/jquery.min.js"></script>
|
<script src="/bootstrap5/js/bootstrap.bundle.min.js"></script>
|
||||||
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
|
||||||
<script src="/js/bootstrap/js/bootstrap.min.js"></script>
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -155,33 +153,4 @@ sub alert {
|
|||||||
return $self->el(class => "alert alert-danger", %param);
|
return $self->el(class => "alert alert-danger", %param);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub add_js {
|
|
||||||
my ($self, $js) = @_;
|
|
||||||
|
|
||||||
$self->{js} .= $js . "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
my $format_event_callback = sub {
|
|
||||||
my ($info) = @_;
|
|
||||||
|
|
||||||
my $pstr = encode_json($info->{param});
|
|
||||||
return "function(e){$info->{fn}.apply(e, $pstr);}";
|
|
||||||
};
|
|
||||||
|
|
||||||
sub button {
|
|
||||||
my ($self, %param) = @_;
|
|
||||||
|
|
||||||
$param{tag} = 'button';
|
|
||||||
$param{class} = "btn btn-default btn-xs";
|
|
||||||
|
|
||||||
if (my $click = delete $param{click}) {
|
|
||||||
my ($html, $id) = $self->el(%param);
|
|
||||||
my $cb = &$format_event_callback($click);
|
|
||||||
$self->add_js("jQuery('#$id').on('click', $cb);");
|
|
||||||
return $html;
|
|
||||||
} else {
|
|
||||||
return $self->el(%param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@ -27,75 +27,86 @@ my $get_portal_login_url = sub {
|
|||||||
sub render_page {
|
sub render_page {
|
||||||
my ($doc, $html, $config) = @_;
|
my ($doc, $html, $config) = @_;
|
||||||
|
|
||||||
my $items = [];
|
|
||||||
|
|
||||||
push @$items, {
|
|
||||||
tag => 'li',
|
|
||||||
cn => {
|
|
||||||
tag => 'a',
|
|
||||||
href => $get_portal_login_url->($config),
|
|
||||||
onclick => "PVE.delete_auth_cookie();",
|
|
||||||
text => "Logout",
|
|
||||||
}};
|
|
||||||
|
|
||||||
my $base_url = $get_portal_base_url->($config);
|
my $base_url = $get_portal_base_url->($config);
|
||||||
|
|
||||||
my $nav = $doc->el(
|
my $nav = $doc->el(
|
||||||
class => "navbar navbar-inverse navbar-fixed-top",
|
class => "navbar navbar-dark navbar-expand-lg bg-dark fixed-top",
|
||||||
role => "navigation", cn => {
|
'data-bs-theme' => 'dark',
|
||||||
class => "container", cn => [
|
role => "navigation",
|
||||||
|
cn => {
|
||||||
|
class => "container",
|
||||||
|
cn => [
|
||||||
{
|
{
|
||||||
class => "navbar-header", cn => [
|
tag => 'a',
|
||||||
|
class => "navbar-brand",
|
||||||
|
href => $base_url,
|
||||||
|
text => $config->{title},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tag => 'button',
|
||||||
|
type => 'button',
|
||||||
|
class => "navbar-toggler",
|
||||||
|
'data-bs-toggle' => "collapse",
|
||||||
|
'data-bs-target' => ".navbarNav",
|
||||||
|
cn => [
|
||||||
{
|
{
|
||||||
tag => 'button',
|
tag => 'span',
|
||||||
type => 'button',
|
class => 'navbar-toggler-icon',
|
||||||
class => "navbar-toggle",
|
|
||||||
'data-toggle' => "collapse",
|
|
||||||
'data-target' => ".navbar-collapse",
|
|
||||||
cn => [
|
|
||||||
{ tag => 'span', class => 'sr-only', text => "Toggle navigation" },
|
|
||||||
{ tag => 'span', class => 'icon-bar' },
|
|
||||||
{ tag => 'span', class => 'icon-bar' },
|
|
||||||
{ tag => 'span', class => 'icon-bar' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
tag => 'a',
|
|
||||||
class => "navbar-brand",
|
|
||||||
href => $base_url,
|
|
||||||
text => $config->{title},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
class => "collapse navbar-collapse",
|
class => "collapse navbar-collapse navbarNav",
|
||||||
cn => {
|
cn => {
|
||||||
tag => 'ul',
|
tag => 'ul',
|
||||||
class => "nav navbar-nav",
|
class => "navbar-nav",
|
||||||
cn => $items,
|
cn => [
|
||||||
|
{
|
||||||
|
tag => 'li',
|
||||||
|
class => 'nav-item',
|
||||||
|
cn => {
|
||||||
|
tag => 'a',
|
||||||
|
class => 'nav-link',
|
||||||
|
href => $get_portal_login_url->($config),
|
||||||
|
onclick => "PVE.delete_auth_cookie();",
|
||||||
|
text => "Logout",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
$items = [];
|
my $items = [];
|
||||||
my @pcomp = split('/', $doc->{url});
|
my @pcomp = split('/', $doc->{url});
|
||||||
shift @pcomp; # empty
|
shift @pcomp; # empty
|
||||||
shift @pcomp; # api2
|
shift @pcomp; # api2
|
||||||
shift @pcomp; # $format
|
shift @pcomp; # $format
|
||||||
|
|
||||||
my $href = $base_url;
|
my $href = $base_url;
|
||||||
push @$items, { tag => 'li', cn => {
|
push @$items, {
|
||||||
tag => 'a',
|
tag => 'li',
|
||||||
href => $href,
|
class => 'breadcrumb-item',
|
||||||
text => 'Home'}};
|
cn => {
|
||||||
|
|
||||||
foreach my $comp (@pcomp) {
|
|
||||||
$href .= "/".encode_entities($comp);
|
|
||||||
push @$items, { tag => 'li', cn => {
|
|
||||||
tag => 'a',
|
tag => 'a',
|
||||||
href => $href,
|
href => $href,
|
||||||
text => $comp}};
|
text => 'Home',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach my $comp (@pcomp) {
|
||||||
|
$href .= "/" . encode_entities($comp);
|
||||||
|
push @$items, {
|
||||||
|
tag => 'li',
|
||||||
|
class => 'breadcrumb-item',
|
||||||
|
cn => {
|
||||||
|
tag => 'a',
|
||||||
|
href => $href,
|
||||||
|
text => $comp,
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
my $breadcrumbs = $doc->el(tag => 'ol', class => 'breadcrumb container', cn => $items);
|
my $breadcrumbs = $doc->el(tag => 'ol', class => 'breadcrumb container', cn => $items);
|
||||||
@ -114,6 +125,7 @@ my $login_form = sub {
|
|||||||
my $items = [
|
my $items = [
|
||||||
{
|
{
|
||||||
tag => 'label',
|
tag => 'label',
|
||||||
|
class => 'form-label',
|
||||||
text => "Please sign in",
|
text => "Please sign in",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -150,14 +162,24 @@ my $login_form = sub {
|
|||||||
action => $get_portal_login_url->($config),
|
action => $get_portal_login_url->($config),
|
||||||
cn => [
|
cn => [
|
||||||
{
|
{
|
||||||
class => 'form-group',
|
class => "mb-3",
|
||||||
cn => $items,
|
cn => [
|
||||||
|
{
|
||||||
|
class => 'form-group',
|
||||||
|
cn => $items,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tag => 'button',
|
class => "d-grid",
|
||||||
type => 'submit',
|
cn => [
|
||||||
class => 'btn btn-lg btn-primary btn-block',
|
{
|
||||||
text => "Sign in",
|
tag => 'button',
|
||||||
|
type => 'submit',
|
||||||
|
class => 'btn btn-lg btn-primary',
|
||||||
|
text => "Sign in",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -236,13 +258,13 @@ PVE::APIServer::Formatter::register_formatter($portal_format, sub {
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
my $json = to_json($data, {allow_nonref => 1, pretty => 1, canonical => 1});
|
my $json = to_json($data, {allow_nonref => 1, pretty => 1, canonical => 1});
|
||||||
$html .= $doc->el(tag => 'pre', text => $json);
|
$html .= $doc->el(tag => 'pre', class => 'bg-light border rounded p-2', text => $json);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
my $json = to_json($data, {allow_nonref => 1, pretty => 1, canonical => 1});
|
my $json = to_json($data, {allow_nonref => 1, pretty => 1, canonical => 1});
|
||||||
$html .= $doc->el(tag => 'pre', text => $json);
|
$html .= $doc->el(tag => 'pre', class => 'bg-light border rounded p-2', text => $json);
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = $doc->el(class => 'container', html => $html);
|
$html = $doc->el(class => 'container', html => $html);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user