=head1 LICENSE
 
    Bweb - A Bacula web interface
-   Bacula® - The Network Backup Solution
+   Bacula® - The Network Backup Solution
 
    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of John Walker.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
    Switzerland, email:ftf@fsfeurope.org.
     $bweb->move_email();
 
 } elsif ($action eq 'change_location') {
-    $bweb->change_location();
+    $bweb->location_change();
 
 } elsif ($action eq 'location') {
-    $bweb->display_location();
+    $bweb->location_display();
 
 } elsif ($action eq 'about') {
     $bweb->display($bweb, 'about.tpl');
 } elsif ($action eq 'disable_job') {
     $bweb->enable_disable_job(0);
 
+} elsif ($action eq 'groups') {
+    $bweb->display_groups();
+
+} elsif ($action eq 'groups_edit') {
+    $bweb->groups_edit();
+
+} elsif ($action eq 'groups_save') {
+    $bweb->groups_save();
+
+} elsif ($action eq 'groups_add') {
+    $bweb->groups_add();
+
+} elsif ($action eq 'groups_del') {
+    $bweb->groups_del();
+
 } elsif ($action eq 'job') {
 
     print "<div><table border='0'><tr><td valign='top'>\n";
     my $fields = $bweb->get_form(qw/status level db_clients db_filesets
                                    limit age offset qclients qfilesets
+#                                  db_client_groups qclient_groups
                                    jobtype qpools db_pools/);
     $bweb->display($fields, "display_form_job.tpl");
 
 
     <select name='level' class='formulaire'>
       <option id='level_Any' value='Any'>Tous</option>
       <option id='level_F' value='F'>Full</option>
-      <option id='level_D' value='D'>Différentielle</option>
-      <option id='level_I' value='I'>Incrémentale</option>
+      <option id='level_D' value='D'>Différentielle</option>
+      <option id='level_I' value='I'>Incrémentale</option>
     </select>     
   </td>
 </tr>
       <option id='status_T'   value='T'>Ok</option>
       <option id='status_W'   value='W'>Warning</option>
       <option id='status_f'   value='f'>Erreur</option>
-      <option id='status_A'   value='A'>Annulé</option>
+      <option id='status_A'   value='A'>Annulé</option>
     </select>     
   </td>
 </tr>
     <h2>Pool</h2>
     <select name='pool' class='formulaire'>
       <option id='pool_tout' value=''>Tous</option>
-<TMPL_LOOP NAME=db_pools>
+<TMPL_LOOP db_pools>
       <option id='pool_<TMPL_VAR name>'><TMPL_VAR name></option>
 </TMPL_LOOP>
     </select>
 </tr>
 <tr>
   <td valign='top'>
-    <h2>Période</h2>
+    <h2>Période</h2>
     <select name='age' class='formulaire'>
+      <option id='age_86400'   value='86400'>Hier</option>
       <option id='age_604800'   value='604800'>Cette semaine</option>
       <option id='age_2678400'  value='2678400'>30 derniers jours</option>
       <option id='age_15552000' value='15552000'>6 derniers mois</option>
  </tr>
  <tr>
   <td valign='bottom'> 
-    <h2>Nombre d'élément</h2>
-    <input type='text' name='limit' value='<TMPL_VAR NAME=limit>' 
+    <h2>Nombre d'éléments</h2>
+    <input type='text' name='limit' value='<TMPL_VAR limit>' 
        class='formulaire' size='4'>
   </td>
 </tr>
     </select>
   </td>
 </tr>
+<TMPL_IF db_clients>
 <tr>
   <td valign='top'> 
     <h2>Clients</h2>
     <select name='client' size='15' class='formulaire' multiple>
-<TMPL_LOOP NAME=db_clients>
+<TMPL_LOOP db_clients>
       <option id='client_<TMPL_VAR clientname>'><TMPL_VAR clientname></option>
 </TMPL_LOOP>
     </select>
   </td>
 </tr>
-<!--
+</TMPL_IF>
+<TMPL_IF db_client_groups>
 <tr>
-  <td valign='top'> 
-    <h2>File Set</h2>
-    <select name='fileset' size='15' class='formulaire' multiple>
-<TMPL_LOOP NAME=db_filesets>
-      <option id='client_<TMPL_VAR fileset>'><TMPL_VAR NAME=fileset></option>
+  <td valign='top'>
+    <h2>Groupes</h2>
+    <select name='client_group' size='10' class='formulaire' multiple>
+<TMPL_LOOP db_client_groups>
+       <option id= 'group_<TMPL_VAR name>'><TMPL_VAR name></option>
 </TMPL_LOOP>
     </select>
   </td>
 </tr>
--->
+</TMPL_IF>
 </table>
   <input type="image" name='action' value='job' src='/bweb/update.png'>
 
      document.getElementById('client_' + <TMPL_VAR name>).selected = true;
   </TMPL_LOOP>
 
+  <TMPL_LOOP qclient_groups>
+     document.getElementById('group_' + <TMPL_VAR name>).selected = true;
+  </TMPL_LOOP>
+
   <TMPL_IF status>
      document.getElementById('status_<TMPL_VAR status>').selected=true;
   </TMPL_IF>
 
--- /dev/null
+<br/>
+ <div class='titlediv'>
+  <h1 class='newstitle'>Groupes</h1>
+ </div>
+ <div class="bodydiv">
+   <form action='?' method='get'>
+    <table id='id<TMPL_VAR ID>'></table>
+    <input type="image" name='action' value='groups_add' title='Ajouter' src='/bweb/add.png'> 
+    <input type="image" name='action' value='groups_del' 
+     onclick="return confirm('Vous voulez vraiment supprimer ce groupe ?');" 
+     title='Supprimer' src='/bweb/remove.png'> 
+    <input type="image" name='action' value='groups_edit' title='Modifier' src='/bweb/edit.png'> 
+
+    <input type="image" name='action' value='groups' title='Voir les groupes'
+     src='/bweb/zoom.png'>
+   </form>
+ </div>
+
+<script type="text/javascript" language="JavaScript">
+
+var header = new Array("Nom","Selection");
+
+var data = new Array();
+var chkbox;
+
+<TMPL_LOOP groups>
+
+chkbox = document.createElement('INPUT');
+chkbox.type  = 'radio';
+chkbox.name  = 'client_group';
+chkbox.value = '<TMPL_VAR client_group>';
+
+data.push( new Array(
+"<TMPL_VAR client_group>",
+chkbox
+ )
+);
+</TMPL_LOOP>
+
+nrsTable.setup(
+{
+ table_name:     "id<TMPL_VAR ID>",
+ table_header: header,
+ table_data: data,
+ up_icon: up_icon,
+ down_icon: down_icon,
+ prev_icon: prev_icon,
+ next_icon: next_icon,
+ rew_icon:  rew_icon,
+ fwd_icon:  fwd_icon,
+// natural_compare: false,
+ even_cell_color: even_cell_color,
+ odd_cell_color: odd_cell_color, 
+ header_color: header_color,
+ page_nav: true,
+ padding: 3,
+// disable_sorting: new Array(5,6),
+ rows_per_page: rows_per_page
+}
+);
+</script>
+
+
 
 =head1 LICENSE
 
    Bweb - A Bacula web interface
-   Bacula® - The Network Backup Solution
+   Bacula® - The Network Backup Solution
 
    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Bacula® is a registered trademark of John Walker.
+   Bacula® is a registered trademark of John Walker.
    The licensor of Bacula is the Free Software Foundation Europe
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
    Switzerland, email:ftf@fsfeurope.org.
 
 =head2 EXAMPLE
 
-    $ref = { name => 'me', age => 26 };
+    $ref = { name => 'me', age => 26 };
     $self->display($ref, "people.tpl");
 
 =cut
            if ($value =~ /^([\w\d\.\-\s]+)$/) {
                $ret{$i} = $1;
            }
-       } elsif ($i =~ /^j(\w+)s$/) { # quote join args
+       } elsif ($i =~ /^j(\w+)s$/) { # quote join args "'arg1', 'arg2'"
            my @value = grep { ! /^\s*$/ } CGI::param($1) ;
            if (@value) {
                $ret{$i} = $self->dbh_join(@value) ;
     if ($what{db_clients}) {
        my $query = "
 SELECT Client.Name as clientname
-FROM Client
+  FROM Client
 ";
 
        my $clients = $self->dbh_selectall_hashref($query, 'clientname');
                              values %$clients] ;
     }
 
+    if ($what{db_client_groups}) {
+       my $query = "
+SELECT client_group_name AS name 
+  FROM client_group
+";
+
+       my $grps = $self->dbh_selectall_hashref($query, 'name');
+       $ret{db_client_groups} = [sort {$a->{name} cmp $b->{name} } 
+                                 values %$grps] ;
+    }
+
     if ($what{db_mediatypes}) {
        my $query = "
 SELECT MediaType as mediatype
-FROM MediaType
+  FROM MediaType
 ";
 
        my $medias = $self->dbh_selectall_hashref($query, 'mediatype');
 
     if ($what{db_locations}) {
        my $query = "
-SELECT Location as location, Cost as cost FROM Location
+SELECT Location as location, Cost as cost 
+  FROM Location
 ";
        my $loc = $self->dbh_selectall_hashref($query, 'location');
        $ret{db_locations} = [ sort { $a->{location} 
     if ($what{db_filesets}) {
        my $query = "
 SELECT FileSet.FileSet AS fileset 
-FROM FileSet
+  FROM FileSet
 ";
 
        my $filesets = $self->dbh_selectall_hashref($query, 'fileset');
     if ($what{db_jobnames}) {
        my $query = "
 SELECT DISTINCT Job.Name AS jobname 
-FROM Job
+  FROM Job
 ";
 
        my $jobnames = $self->dbh_selectall_hashref($query, 'jobname');
     if ($what{db_devices}) {
        my $query = "
 SELECT Device.Name AS name
-FROM Device
+  FROM Device
 ";
 
        my $devices = $self->dbh_selectall_hashref($query, 'name');
        }
     }
 
+    if ($elt{client_groups}) {
+       my @clients = grep { ! /^\s*$/ } CGI::param('client_group');
+       if (@clients) {
+           $ret{client_groups} = \@clients;
+           my $str = $self->dbh_join(@clients);
+           $limit .= "AND client_group_name IN ($str) ";
+       }
+    }
+
     if ($elt{filesets}) {
        my @filesets = grep { ! /^\s*$/ } CGI::param('fileset');
        if (@filesets) {
 
     my ($limit, $label) = $self->get_limit(%arg);
     my ($where, undef) = $self->get_param('clients',
+                                         'client_groups',
                                          'level',
                                          'filesets',
                                          'jobtype',
                                          'jobid',
                                          'status');
 
+    my $cgq = '';
+    if (CGI::param('client_group')) {
+       $cgq = "
+LEFT JOIN client_group_member ON (Job.ClientId = client_group_member.ClientId)
+LEFT JOIN client_group USING (client_group_id)
+";
+    }
+
     my $query="
 SELECT  Job.JobId       AS jobid,
         Client.Name     AS client,
  FROM Client, 
       Job LEFT JOIN Pool     ON (Job.PoolId    = Pool.PoolId)
           LEFT JOIN FileSet  ON (Job.FileSetId = FileSet.FileSetId)
+          $cgq
  WHERE Client.ClientId=Job.ClientId
    AND Job.JobStatus != 'R'
  $where
 
     $self->dbh_do($query);
 
-    $self->display_location();
+    $self->location_display();
 }
 
 sub location_del
 
     $self->dbh_do($query);
 
-    $self->display_location();
+    $self->location_display();
 }
 
 
 
     $self->dbh_do($query);
 
-    $self->display_location();
+    $self->location_display();
 }
 
-sub display_location
+sub location_display
 {
     my ($self) = @_ ;
 
                   "update_location.tpl");
 }
 
+###########################################################
+
+sub groups_edit
+{
+    my ($self) = @_;
+
+    my $grp = $self->get_form(qw/qclient_group db_clients/);
+    $self->debug($grp);
+
+    unless ($grp->{qclient_group}) {
+       return $self->error("Can't get group");
+    }
+
+    my $query = "
+SELECT Name AS name 
+  FROM Client JOIN client_group_member using (clientid)
+              JOIN client_group using (client_group_id)
+WHERE client_group_name = $grp->{qclient_group}
+";
+
+    my $row = $self->dbh_selectall_hashref($query, "name");
+    $self->debug($row);
+    $self->display({ ID => $cur_id++,
+                    client_group => $grp->{qclient_group},
+                    %$grp,
+                    client_group_member => [ values %$row]}, 
+                  "groups_edit.tpl");
+}
+
+sub groups_save
+{
+    my ($self) = @_;
+
+    my $arg = $self->get_form(qw/qclient_group jclients qnewgroup/);
+    unless ($arg->{qclient_group}) {
+       return $self->error("Can't get groups");
+    }
+    
+    $self->{dbh}->begin_work();
+
+    my $query = "
+DELETE FROM client_group_member 
+      WHERE client_group_id IN 
+           (SELECT client_group_id 
+              FROM client_group 
+             WHERE client_group_name = $arg->{qclient_group})
+";
+    $self->dbh_do($query);
+
+    $query = "
+    INSERT INTO client_group_member (clientid, client_group_id) 
+       (SELECT  Clientid, 
+                (SELECT client_group_id 
+                   FROM client_group 
+                  WHERE client_group_name = $arg->{qclient_group})
+          FROM Client WHERE Name IN ($arg->{jclients})
+       )
+";
+    $self->dbh_do($query);
+
+    if ($arg->{qclient_group} ne $arg->{qnewgroup}) {
+       $query = "
+UPDATE client_group 
+   SET client_group_name = $arg->{qnewgroup}
+ WHERE client_group_name = $arg->{qclient_group}
+";
+
+       $self->dbh_do($query);
+    }
+
+    $self->{dbh}->commit() or $self->error($self->{dbh}->errstr);
+
+    $self->display_groups();
+}
+
+sub groups_del
+{
+    my ($self) = @_;
+    my $arg = $self->get_form(qw/qclient_group/);
+
+    unless ($arg->{qclient_group}) {
+       return $self->error("Can't get groups");
+    }
+
+    $self->{dbh}->begin_work();
+
+    my $query = "
+DELETE FROM client_group_member 
+      WHERE client_group_id IN 
+           (SELECT client_group_id 
+              FROM client_group 
+             WHERE client_group_name = $arg->{qclient_group});
+
+DELETE FROM client_group
+      WHERE client_group_name = $arg->{qclient_group};
+";
+    $self->dbh_do($query);
+
+    $self->{dbh}->commit();
+    
+    $self->display_groups();
+}
+
+
+sub groups_add
+{
+    my ($self) = @_;
+    my $arg = $self->get_form(qw/qclient_group/) ;
+
+    unless ($arg->{qclient_group}) {
+       $self->display({}, "groups_add.tpl");
+       return 1;
+    }
+
+    my $query = "
+INSERT INTO client_group (client_group_name) 
+VALUES ($arg->{qclient_group})
+";
+
+    $self->dbh_do($query);
+
+    $self->display_groups();
+}
+
+sub display_groups
+{
+    my ($self) = @_;
+
+    my $query = "
+SELECT client_group_name AS client_group 
+FROM client_group ORDER BY client_group_name;
+";
+
+    my $groups = $self->dbh_selectall_hashref($query, 'client_group');
+
+    $self->debug($groups);
+
+    $self->display({ ID => $cur_id++,
+                    groups => [ values %$groups ] },
+                  "display_groups.tpl");
+}
+
+###########################################################
+
 sub get_media_max_size
 {
     my ($self, $type) = @_;
     $self->display_media();
 }
 
-sub change_location
+sub location_change
 {
     my ($self) = @_ ;
 
     $self->display({ email  => $self->{info}->{email_media},
                     url => $url,
                     newlocation => $newloc,
-                    # [ { volumename => 'vol1' }, { volumename => 'vol2'\81\81 },..]
+                    # [ { volumename => 'vol1' }, { volumename => 'vol2'Â\81Â\81 },..]
                     medias => [ values %$medias ],
                   },
                   "change_location.tpl");