]> git.proxmox.com Git - pve-manager-legacy.git/commitdiff
include bootstrap html framework
authorDietmar Maurer <dietmar@proxmox.com>
Fri, 2 May 2014 05:44:53 +0000 (07:44 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Fri, 2 May 2014 09:35:16 +0000 (11:35 +0200)
PVE/API2/Formatter/Bootstrap.pm [new file with mode: 0644]
bin/pveproxy
defines.mk
www/bootstrap/Makefile [new file with mode: 0644]
www/bootstrap/bootstrap-3.1.1-dist.zip [new file with mode: 0644]

diff --git a/PVE/API2/Formatter/Bootstrap.pm b/PVE/API2/Formatter/Bootstrap.pm
new file mode 100644 (file)
index 0000000..75baf98
--- /dev/null
@@ -0,0 +1,232 @@
+package PVE::API2::Formatter::Bootstrap;
+
+use strict;
+use warnings;
+use URI::Escape;
+use HTML::Entities;
+use JSON;
+
+use PVE::AccessControl; # to generate CSRF token
+
+# Helpers to generate simple html pages using Bootstrap markup.
+
+my $jssrc = <<_EOJS;
+PVE = {
+    delete_auth_cookie: function() {
+       document.cookie = "PVEAuthCookie=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; secure;";
+    },
+    open_vm_console: function(node, vmid) {
+       console.log("open vm " + vmid + " on node " + node);
+
+       var downloadWithName = function(uri, name) {
+           var link =  jQuery('#pve_console_anchor');
+           link.attr("href", uri);
+
+           // Note: we need to tell android the correct file name extension
+           // but we do not set 'download' tag for other environments, because
+           // It can have strange side effects (additional user prompt on firefox)
+           var andriod = navigator.userAgent.match(/Android/i) ? true : false;
+           if (andriod) {
+               link.attr("download", name);
+           }
+
+           if (document.createEvent) {
+               var evt = document.createEvent("MouseEvents");
+                evt.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
+               link.get(0).dispatchEvent(evt);
+           } else {
+               link.get(0).fireEvent('onclick');
+           }
+       };
+
+       jQuery.ajax("/api2/json/console", {
+           data: { vmid: vmid, node: node },
+           headers: { CSRFPreventionToken: PVE.CSRFPreventionToken },
+           dataType: 'json',
+           type: 'POST',
+           error: function(jqXHR, textStatus, errorThrown) {
+               // fixme: howto view JS errors ?
+               console.log("ERROR " +  textStatus + ": " + errorThrown);
+           },
+           success:   function(data) {
+               var raw = "[virt-viewer]\\n";
+               jQuery.each(data.data, function(k, v) {
+                   raw += k + "=" + v + "\\n";
+               });
+               var url = 'data:application/x-virt-viewer;charset=UTF-8,' +
+                   encodeURIComponent(raw);
+
+               downloadWithName(url, "pve-spice.vv");
+           }
+       });
+    }
+};
+_EOJS
+
+sub new {
+    my ($class, $res, $url) = @_;
+
+    my $self = bless {
+       url => $url,
+       js => '',
+    };
+
+    if (my $username = $res->{auth}->{userid}) {
+       $self->{csrftoken} = PVE::AccessControl::assemble_csrf_prevention_token($username);
+    }
+
+    return $self;
+}
+  
+sub body {
+    my ($self, $html) = @_;
+
+    my $jssetup = '';
+
+    if ($self->{csrftoken}) {
+       $jssetup .= "PVE.CSRFPreventionToken = '$self->{csrftoken}';\n";
+    }
+
+    return <<_EOD;
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <title>Proxmox VE Portal at '$hostname'</title>
+
+    <!-- Bootstrap -->
+    <link href="/css/bootstrap.min.css" rel="stylesheet">
+
+    <script type="text/javascript">
+    $jssrc
+    $jssetup
+    </script>
+
+    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
+    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
+    <!--[if lt IE 9]>
+      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
+      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
+    <![endif]-->
+
+    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
+    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
+    <!-- Include all compiled plugins (below), or include individual files as needed -->
+    <script src="/js/bootstrap.min.js"></script>
+
+  </head>
+  <body>
+    <a class="hidden" id="pve_console_anchor"></a>
+    $html
+    <script type="text/javascript">
+      $self->{js}
+    </script>
+  </body>
+</html>
+_EOD
+}
+
+my $comp_id_counter = 0;
+
+sub el {
+    my ($self, %param) = @_;
+    
+    $param{tag} = 'div' if !$param{tag};
+
+    my $id;
+
+    my $html = "<$param{tag}";
+
+    if (wantarray) {
+       $comp_id_counter++;
+       $id = "pveid$comp_id_counter";
+       $html .= " id=$id";
+    }
+
+    my $skip = {
+       tag => 1,
+       cn => 1,
+       html => 1,
+       text => 1,
+    };
+
+    my $boolattr = {
+       required => 1,
+       autofocus => 1,
+    };
+
+    my $noescape = {
+       placeholder => 1,
+    };
+
+    foreach my $attr (keys %param)  {
+       next if $skip->{$attr};
+       my $v = $noescape->{$attr} ? $param{$attr} : uri_escape_utf8($param{$attr},"[^\/\ A-Za-z0-9\-\._~]");
+       next if !defined($v);
+       if ($boolattr->{$attr}) {
+           $html .= " $attr" if $v;
+       } else {
+           $html .= " $attr=\"$v\"";
+       }
+    }
+
+    $html .= ">";
+
+
+    if (my $cn = $param{cn}) {  
+       if(ref($cn) eq 'ARRAY'){ 
+           foreach my $rec (@$cn) {
+               $html .= $self->el(%$rec);
+           }
+       } else {
+           $html .= $self->el(%$cn);
+       }
+    } elsif ($param{html}) {
+       $html .= $param{html};
+    } elsif ($param{text}) {
+       $html .= encode_entities($param{text});
+    }
+
+    $html .= "</$param{tag}>";
+
+    return wantarray ? ($html, $id) : $html;
+}
+
+sub alert {
+    my ($self, %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;
index 970de993f011290b59b0894bf0064ea052b7e9e7..1522531586adc299866b3e1e5f2b830a104a8b13 100755 (executable)
@@ -79,6 +79,7 @@ eval {
     add_dirs($dirs, '/pve2/ext4/', '/usr/share/pve-manager/ext4/');
     add_dirs($dirs, '/pve2/images/' => '/usr/share/pve-manager/images/');
     add_dirs($dirs, '/pve2/css/' => '/usr/share/pve-manager/css/');
+    add_dirs($dirs, '/pve2/js/' => '/usr/share/pve-manager/js/');
     add_dirs($dirs, '/vncterm/' => '/usr/share/vncterm/');
 
     $daemon = PVE::APIDaemon->new(
index d832684f7963a145452f2ae3dd842fc384fff463..410c7dfaf39696cd15c1df0ed045fa2f753bae8f 100644 (file)
@@ -17,3 +17,4 @@ WWWROOTDIR=${WWWBASEDIR}/root
 WWWIMAGEDIR=${WWWBASEDIR}/images
 WWWEXT4DIR=${WWWBASEDIR}/ext4
 WWWCSSDIR=${WWWBASEDIR}/css
+WWWJSDIR=${WWWBASEDIR}/js
diff --git a/www/bootstrap/Makefile b/www/bootstrap/Makefile
new file mode 100644 (file)
index 0000000..be493fd
--- /dev/null
@@ -0,0 +1,30 @@
+include ../../defines.mk
+
+BTDIR=bootstrap-3.1.1-dist
+BTSRC=${BTDIR}.zip
+
+BTDATA =                                       \
+       ${BTDIR}/css/bootstrap.min.css          \
+       ${BTDIR}/js/bootstrap.min.js
+
+${BTDATA}: ${BTSRC}
+       rm -rf ${BTDIR}
+       unzip -x ${BTSRC}
+       touch $@
+
+all: ${BTDATA}
+
+.PHONY: install 
+install: ${BTDATA}
+       install -d ${WWWCSSDIR}
+       install -m 0644 -o www-data -g www-data ${BTDIR}/css/bootstrap.min.css ${WWWCSSDIR}
+       install -d ${WWWJSDIR}
+       install -m 0644 -o www-data -g www-data ${BTDIR}/js/bootstrap.min.js ${WWWJSDIR}
+
+.PHONY: distclean
+distclean: clean
+
+.PHONY: clean
+clean:
+       rm -rf *~ ${BTDIR}
+
diff --git a/www/bootstrap/bootstrap-3.1.1-dist.zip b/www/bootstrap/bootstrap-3.1.1-dist.zip
new file mode 100644 (file)
index 0000000..ad4b2fd
Binary files /dev/null and b/www/bootstrap/bootstrap-3.1.1-dist.zip differ