From f01e2ce0aa6c1925e6266d78797025ec68bfac07 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 26 Jan 2007 08:04:37 +0000 Subject: [PATCH] top bar option! --- FS/FS/Record.pm | 18 +- FS/FS/access_user.pm | 14 +- FS/FS/m2m_Common.pm | 92 +++-- FS/FS/option_Common.pm | 105 +++-- httemplate/elements/header.html | 68 +++- httemplate/elements/menu.html | 15 +- httemplate/elements/xmenu.css | 11 +- httemplate/elements/xmenu.top.css | 211 ++++++++++ httemplate/elements/xmenu.top.js | 671 ++++++++++++++++++++++++++++++++ httemplate/images/arrow.down.png | Bin 170 -> 155 bytes httemplate/images/menu-left-example.png | Bin 0 -> 24709 bytes httemplate/images/menu-top-example.png | Bin 0 -> 22816 bytes httemplate/pref/pref-process.html | 41 +- httemplate/pref/pref.html | 28 +- 14 files changed, 1173 insertions(+), 101 deletions(-) create mode 100644 httemplate/elements/xmenu.top.css create mode 100644 httemplate/elements/xmenu.top.js create mode 100644 httemplate/images/menu-left-example.png create mode 100644 httemplate/images/menu-top-example.png diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index 34b556eea..6b7e8d5fa 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -26,7 +26,7 @@ use Tie::IxHash; #export dbdef for now... everything else expects to find it here @EXPORT_OK = qw(dbh fields hfields qsearch qsearchs dbdef jsearch); -$DEBUG = 0; +$DEBUG = 3; $me = '[FS::Record]'; $nowarn_identical = 0; @@ -563,6 +563,17 @@ sub dbdef_table { dbdef->table($table); } +=item primary_key + +Returns the primary key for the table. + +=cut + +sub primary_key { + my $self = shift; + my $pkey = $self->dbdef_table->primary_key; +} + =item get, getfield COLUMN Returns the value of the column/field/key COLUMN. @@ -688,6 +699,8 @@ sub insert { my $self = shift; my $saved = {}; + warn "$self -> insert" if $DEBUG; + my $error = $self->check; return $error if $error; @@ -784,8 +797,7 @@ sub insert { dbh->rollback if $FS::UID::AutoCommit; return dbh->errstr; }; - #$i_sth->execute($oid) or do { - $i_sth->execute() or do { + $i_sth->execute() or do { #$i_sth->execute($oid) dbh->rollback if $FS::UID::AutoCommit; return $i_sth->errstr; }; diff --git a/FS/FS/access_user.pm b/FS/FS/access_user.pm index f45f17d60..9be9166f0 100644 --- a/FS/FS/access_user.pm +++ b/FS/FS/access_user.pm @@ -6,10 +6,12 @@ use FS::UID; use FS::Conf; use FS::Record qw( qsearch qsearchs dbh ); use FS::m2m_Common; +use FS::option_Common; use FS::access_usergroup; use FS::agent; -@ISA = qw( FS::m2m_Common FS::Record ); +@ISA = qw( FS::m2m_Common FS::option_Common FS::Record ); +#@ISA = qw( FS::m2m_Common FS::option_Common ); #kludge htpasswd for now (i hope this bootstraps okay) FS::UID->install_callback( sub { @@ -74,6 +76,10 @@ points to. You can ask the object for a copy with the I method. sub table { 'access_user'; } +sub _option_table { 'access_user_pref'; } +sub _option_namecol { 'prefname'; } +sub _option_valuecol { 'prefvalue'; } + =item insert Adds this record to the database. If there is an error, returns the error, @@ -177,7 +183,11 @@ returns the error, otherwise returns false. =cut sub replace { - my($new, $old) = ( shift, shift ); + my $new = shift; + + my $old = ( ref($_[0]) eq ref($new) ) + ? shift + : $new->replace_old; local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; diff --git a/FS/FS/m2m_Common.pm b/FS/FS/m2m_Common.pm index fd8700a2d..5dc2a8ec8 100644 --- a/FS/FS/m2m_Common.pm +++ b/FS/FS/m2m_Common.pm @@ -3,25 +3,26 @@ package FS::m2m_Common; use strict; use vars qw( @ISA $DEBUG ); use FS::Schema qw( dbdef ); -use FS::Record qw( qsearch qsearchs ); #dbh ); +use FS::Record qw( qsearch qsearchs dbh ); -@ISA = qw( FS::Record ); +#hmm. well. we seem to be used as a mixin. +#@ISA = qw( FS::Record ); $DEBUG = 0; =head1 NAME -FS::m2m_Common - Base class for classes in a many-to-many relationship +FS::m2m_Common - Mixin class for classes in a many-to-many relationship =head1 SYNOPSIS use FS::m2m_Common; -@ISA = qw( FS::m2m_Common ); +@ISA = qw( FS::m2m_Common FS::Record ); =head1 DESCRIPTION -FS::m2m_Common is intended as a base class for classes which have a +FS::m2m_Common is intended as a mixin class for classes which have a many-to-many relationship with another table (via a linking table). Note: It is currently assumed that the link table contains two fields @@ -31,7 +32,17 @@ named the same as the primary keys of ths base and target tables. =over 4 -=item process_m2m +=item process_m2m OPTION => VALUE, ... + +Available options: + +link_table (required) - + +target_table (required) - + +params (required) - hashref; keys are primary key values in target_table (values are boolean). For convenience, keys may optionally be prefixed with the name +of the primary key, as in agentnum54 instead of 54, or passed as an arrayref +of values. =cut @@ -39,41 +50,64 @@ sub process_m2m { my( $self, %opt ) = @_; my $self_pkey = $self->dbdef_table->primary_key; + my %hash = ( $self_pkey => $self->$self_pkey() ); my $link_table = $self->_load_table($opt{'link_table'}); my $target_table = $self->_load_table($opt{'target_table'}); my $target_pkey = dbdef->table($target_table)->primary_key; - foreach my $target_obj ( qsearch($target_table, {} ) ) { + if ( ref($opt{'params'}) eq 'ARRAY' ) { + $opt{'params'} = { map { $_=>1 } @{$opt{'params'}} }; + } - my $targetnum = $target_obj->$target_pkey(); + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + foreach my $del_obj ( + grep { + my $targetnum = $_->$target_pkey(); + ( ! $opt{'params'}->{$targetnum} + && ! $opt{'params'}->{"$target_pkey$targetnum"} + ); + } + qsearch( $link_table, \%hash ) + ) { + my $error = $del_obj->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } - my $link_obj = qsearchs( $link_table, { - $self_pkey => $self->$self_pkey(), - $target_pkey => $targetnum, + foreach my $add_targetnum ( + grep { ! qsearchs( $link_table, { %hash, $target_pkey => $_ } ) } + map { /^($target_pkey)?(\d+)$/; $2; } + grep { /^($target_pkey)?(\d+)$/ } + grep { $opt{'params'}->{$_} } + keys %{ $opt{'params'} } + ) { + + my $add_obj = "FS::$link_table"->new( { + %hash, + $target_pkey => $add_targetnum, }); - - if ( $link_obj && ! $opt{'params'}->{"$target_pkey$targetnum"} ) { - - my $d_link_obj = $link_obj; #need to save $link_obj for below. - my $error = $d_link_obj->delete; - die $error if $error; - - } elsif ( $opt{'params'}->{"$target_pkey$targetnum"} && ! $link_obj ) { - - #ok to clobber it now (but bad form nonetheless?) - #$link_obj = new "FS::$link_table" ( { - $link_obj = "FS::$link_table"->new( { - $self_pkey => $self->$self_pkey(), - $target_pkey => $targetnum, - }); - my $error = $link_obj->insert; - die $error if $error; + my $error = $add_obj->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; } - } + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } diff --git a/FS/FS/option_Common.pm b/FS/FS/option_Common.pm index ad3c26958..0efacbd8a 100644 --- a/FS/FS/option_Common.pm +++ b/FS/FS/option_Common.pm @@ -6,7 +6,7 @@ use FS::Record qw( qsearch qsearchs dbh ); @ISA = qw( FS::Record ); -$DEBUG = 0; +$DEBUG = 3; =head1 NAME @@ -18,6 +18,11 @@ use FS::option_Common; @ISA = qw( FS::option_Common ); +#optional for non-standard names +sub _option_table { 'table_name'; } #defaults to ${table}_option +sub _option_namecol { 'column_name'; } #defaults to optionname +sub _option_valuecol { 'column_name'; } #defaults to optionvalue + =head1 DESCRIPTION FS::option_Common is intended as a base class for classes which have a @@ -66,14 +71,17 @@ sub insert { return $error; } - my $pkey = $self->pkey; + my $pkey = $self->primary_key; my $option_table = $self->option_table; + my $namecol = $self->_option_namecol; + my $valuecol = $self->_option_valuecol; + foreach my $optionname ( keys %{$options} ) { my $href = { - $pkey => $self->get($pkey), - 'optionname' => $optionname, - 'optionvalue' => $options->{$optionname}, + $pkey => $self->get($pkey), + $namecol => $optionname, + $valuecol => $options->{$optionname}, }; #my $option_record = eval "new FS::$option_table \$href"; @@ -123,7 +131,7 @@ sub delete { return $error; } - my $pkey = $self->pkey; + my $pkey = $self->primary_key; #my $option_table = $self->option_table; foreach my $obj ( $self->option_objects ) { @@ -140,7 +148,7 @@ sub delete { } -=item replace OLD_RECORD [ HASHREF | OPTION => VALUE ... ] +=item replace [ OLD_RECORD ] [ HASHREF | OPTION => VALUE ... ] Replaces the OLD_RECORD with this one in the database. If there is an error, returns the error, otherwise returns false. @@ -152,12 +160,16 @@ created or modified (see L). sub replace { my $self = shift; - my $old = shift; + + my $old = ( ref($_[0]) eq ref($self) ) + ? shift + : $self->replace_old; + my $options = ( ref($_[0]) eq 'HASH' ) ? shift : { @_ }; - warn "FS::option_Common::insert called on $self with options ". + warn "FS::option_Common::replace called on $self with options ". join(', ', map "$_ => ". $options->{$_}, keys %$options) if $DEBUG; @@ -178,30 +190,44 @@ sub replace { return $error; } - my $pkey = $self->pkey; + my $pkey = $self->primary_key; my $option_table = $self->option_table; + my $namecol = $self->_option_namecol; + my $valuecol = $self->_option_valuecol; + foreach my $optionname ( keys %{$options} ) { - my $old = qsearchs( $option_table, { - $pkey => $self->get($pkey), - 'optionname' => $optionname, + + warn "FS::option_Common::replace: inserting or replacing option: $optionname" + if $DEBUG > 1; + + my $oldopt = qsearchs( $option_table, { + $pkey => $self->get($pkey), + $namecol => $optionname, } ); my $href = { - $pkey => $self->get($pkey), - 'optionname' => $optionname, - 'optionvalue' => $options->{$optionname}, + $pkey => $self->get($pkey), + $namecol => $optionname, + $valuecol => $options->{$optionname}, }; - #my $new = eval "new FS::$option_table \$href"; + #my $newopt = eval "new FS::$option_table \$href"; #if ( $@ ) { # $dbh->rollback if $oldAutoCommit; # return $@; #} - my $new = "FS::$option_table"->new($href); + my $newopt = "FS::$option_table"->new($href); + + my $opt_pkey = $newopt->primary_key; - $new->optionnum($old->optionnum) if $old; - my $error = $old ? $new->replace($old) : $new->insert; + $newopt->$opt_pkey($oldopt->$opt_pkey) if $oldopt; + warn $oldopt; + warn "FS::option_Common::replace: ". + ( $oldopt ? "$newopt -> replace($oldopt)" : "$newopt -> insert" ) + if $DEBUG > 2; + my $error = $oldopt ? $newopt->replace($oldopt) : $newopt->insert; + warn $error; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -210,7 +236,7 @@ sub replace { #remove extraneous old options foreach my $opt ( - grep { !exists $options->{$_->optionname} } $old->option_objects + grep { !exists $options->{$_->$namecol()} } $old->option_objects ) { my $error = $opt->delete; if ( $error ) { @@ -233,7 +259,7 @@ Returns all options as FS::I_option objects. sub option_objects { my $self = shift; - my $pkey = $self->pkey; + my $pkey = $self->primary_key; my $option_table = $self->option_table; qsearch($option_table, { $pkey => $self->get($pkey) } ); } @@ -246,7 +272,9 @@ Returns a list of option names and values suitable for assigning to a hash. sub options { my $self = shift; - map { $_->optionname => $_->optionvalue } $self->option_objects; + my $namecol = $self->_option_namecol; + my $valuecol = $self->_option_valuecol; + map { $_->$namecol() => $_->$valuecol() } $self->option_objects; } =item option OPTIONNAME @@ -257,30 +285,35 @@ Returns the option value for the given name, or the empty string. sub option { my $self = shift; - my $pkey = $self->pkey; + my $pkey = $self->primary_key; my $option_table = $self->option_table; - my $obj = - qsearchs($option_table, { - $pkey => $self->get($pkey), - optionname => shift, - } ); - $obj ? $obj->optionvalue : ''; + my $namecol = $self->_option_namecol; + my $valuecol = $self->_option_valuecol; + my $hashref = { + $pkey => $self->get($pkey), + $namecol => shift, + }; + warn "$self -> option: searching for ". + join(' / ', map { "$_ => ". $hashref->{$_} } keys %$hashref ) + if $DEBUG; + my $obj = qsearchs($option_table, $hashref); + $obj ? $obj->$valuecol() : ''; } -sub pkey { - my $self = shift; - my $pkey = $self->dbdef_table->primary_key; -} - sub option_table { my $self = shift; - my $option_table = $self->table . '_option'; + my $option_table = $self->_option_table; eval "use FS::$option_table"; die $@ if $@; $option_table; } +#defaults +sub _option_table { shift->table .'_option'; } +sub _option_namecol { 'optionname'; } +sub _option_valuecol { 'optionvalue'; } + =back =head1 BUGS diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 0e69b19ca..1f5674885 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -1,11 +1,3 @@ -% -% my($title, $menubar) = ( shift, shift ); -% my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc. -% my $head = @_ ? shift : ''; #$head is for things that go in the section -% my $conf = new FS::Conf; -% -% - @@ -16,7 +8,10 @@ - <% include('menu.html', 'freeside_baseurl' => $fsurl ) %> + <% include('menu.html', 'freeside_baseurl' => $fsurl, + 'position' => $menu_position, + ) + %> + + + + + + + + + + + + + + +% } + @@ -172,13 +191,26 @@ input.fsblackbuttonselected { + + + +% if ( $menu_position eq 'left' ) { + - + +% } + + + + + +% if ( $menu_position eq 'left' ) { +
- - + +% if ( $opt{'position'} eq 'top' ) { + + + + +% } else { # elsif ( $opt{'position'} eq 'left' ) { + + + + +% } +