Example:
- include( 'elements/edit.html',
+ <& elements/edit.html,
'name_singular' => #singular name for the record
# (preferred, will be pluralized automatically)
'name' => #name for the record
# (deprecated, will be pluralized simplistically)
- 'table' =>
+ 'table' => #database table
#? 'primary_key' => #required when the dbdef doesn't know...???
'labels' => {
'disabled' => 0,
'onchange' => 'javascript_function',
- 'include_opt_callback' => sub { #my $ = @_;
+ 'include_opt_callback' => sub { my $object = @_;
( 'option' => 'value', );
},
#agent virtualization
'agent_virt' => 1,
+ 'agent_null' => 1, #if true, always allow no-agentnum globals
'agent_null_right' => 'Access Right Name',
'agent_clone_extra_sql' => '', #if provided, this overrides the extra_sql
#implementing agent virt, for clone
# overrides default popurl(1)."process/$table.html"
'post_url' => popurl(1).'process/something',
+ # optional link to delete this object; primary key will be appended
+ 'delete_url' => $p.'misc/delete-something.html?',
+
#we're in a popup (no title/menu/searchboxes)
'popup' => 1,
+ #if you need to access the submit button
+ 'submit_id' => 'mysubmitbuttonid',
+
+ #we're embedded (rows only: no header at all, no html_init, no error
+ # display, no <FORM>, no hidden fields for table name or primary key, no
+ # display of primary key, no submit button, no html_foot, no footer)
+ 'embed' => $object, #need to pass the object
+ 'tablenum' => 4, #need to specify a table number when using multiple
+ #embedded edits on a page (and m2 stuff)
+
+ #don't show the primary key label and value
+ 'no_pkey_display' => 1,
+
###
# HTML callbacks
###
'html_init' => '', #after the header/menubar
+ 'form_init' => '', #after html_init, error and the opening <FORM>, but
+ #before any other form contents
+
+ 'html_table_class' => '', #HTML <TABLE CLASS=
+
#string or coderef of additional HTML to add before </TABLE>
'html_table_bottom' => '',
"html_string";
},
+ #javascript function name, will be called with form name as arg
+ 'onsubmit' => 'check_form_data',
+
#at the very bottom (well, as low as you can go from here)
'html_foot' => '',
#run before display to manipulate element of the 'fields' arrayref
'field_callback' => sub { my( $cgi, $object, $field_hashref ) = @_; },
- );
+ &>
</%doc>
-
+%
+% unless ( $opt{embed} ) {
+%
+% my $title = $opt{action}. ' '. ( $opt{name} || $opt{'name_singular'} );
+%
+% my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html";
+% $viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'};
+%
+% my @menubar;
+% if ( $opt{'menubar'} ) {
+% @menubar = @{ $opt{'menubar'} };
+% } else {
+% my $items = $opt{'name'} ? $opt{'name'}.'s' : PL($opt{'name_singular'});
+% @menubar = (
+% "View all $items" => $viewall_url,
+% );
+% }
+%
<% include('/elements/header'. ( $opt{popup} ? '-popup' : '' ). '.html',
- $title,
- include( '/elements/menubar.html', @menubar ),
- $opt{'body_etc'},
- )
+ $title,
+ include( '/elements/menubar.html', @menubar ),
+ $opt{'body_etc'},
+ )
%>
-<% defined($opt{'html_init'})
- ? ( ref($opt{'html_init'})
- ? &{$opt{'html_init'}}()
- : $opt{'html_init'}
- )
- : ''
-%>
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
-<% include('/elements/error.html') %>
+ <% include('/elements/error.html') %>
% my $url = $opt{'post_url'} || popurl(1)."process/$table.html";
-<FORM ACTION="<% $url %>" METHOD=POST NAME="edit_topform">
+% $js_form_validate = { 'edit_topform' => { 'name' => 'edit_topform' } };
+ <FORM NAME = "edit_topform"
+ METHOD = POST
+ ACTION = "<% $url %>"
+ <% $opt{onsubmit} ? 'onSubmit="return '.$opt{onsubmit}.'(this)"' : '' %>
+ >
+
+ <INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>">
+ <INPUT TYPE="hidden" ID="<% $pkey %>" NAME="<% $pkey %>" VALUE="<% $clone ? '' : $object->$pkey() %>">
+
+ <% defined($opt{'form_init'})
+ ? ( ref($opt{'form_init'})
+ ? &{$opt{'form_init'}}()
+ : $opt{'form_init'}
+ )
+ : ''
+ %>
+
+% unless ( $opt{'no_pkey_display'} ) {
+
+ <FONT CLASS="fsinnerbox-title">
+ <% ( $opt{labels} && exists $opt{labels}->{$pkey} )
+ ? $opt{labels}->{$pkey}
+ : $pkey
+ %>
+ </FONT>
+ #<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
-<INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>">
-<INPUT TYPE="hidden" NAME="<% $pkey %>" VALUE="<% $clone ? '' : $object->$pkey() %>">
+% }
-<FONT SIZE="+1"><B>
-<% ( $opt{labels} && exists $opt{labels}->{$pkey} )
- ? $opt{labels}->{$pkey}
- : $pkey
-%>
-</B></FONT>
-#<% ( !$clone && $object->$pkey() ) || "(NEW)" %>
+% }
-% my $tablenum = 0;
-<TABLE ID="TableNumber<% $tablenum++ %>" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+% my $tablenum = $opt{'tablenum'} || 0;
+<TABLE ID="TableNumber<% $tablenum++ %>"
+ CLASS="<% $opt{html_table_class} || 'fsinnerbox' %>"
+>
% my $g_row = 0;
% my @g_row_stack = ();
% #text and derivitives
% 'size' => $f->{'size'},
% 'maxlength' => $f->{'maxlength'},
+% 'prefix' => $f->{'prefix'},
+% 'postfix' => $f->{'postfix'},
+%
+% #textarea
+% 'rows' => $f->{'rows'},
+% 'cols' => $f->{'cols'},
%
% #checkbox, title, fixed, hidden
% #& deprecated weird value hashref used only by reason.html
% 'value' => $f->{'value'},
%
+% #fixed
+% 'noescape' => $f->{'noescape'},
+%
% #select(-*)
% 'options' => $f->{'options'},
% 'labels' => $f->{'labels'},
% 'multiple' => $f->{'multiple'},
+% 'label_showkey' => $f->{'label_showkey'},
% 'disable_empty' => $f->{'disable_empty'},
% #select-reason
% 'reason_class' => $f->{'reason_class'},
+% #select-agent
+% 'viewall_right' => $f->{'viewall_right'},
%
% #selectlayers
% 'layer_fields' => $f->{'layer_fields'},
% 'layer_values' => $layer_values,
% 'html_between' => $f->{'html_between'},
%
-% #umm. for select-agent_types at least
+% #umm. for select-agent_type at least
% 'disabled' => $f->{'disabled'},
-% );
+% 'fixed' => $f->{'fixed'},
+% 'label_callback'=> $f->{'label_callback'},
+% 'element_etc' => $f->{'element_etc'},
%
-% #selectlayers, others?
-% $include_common{$_} = $f->{$_}
-% foreach grep exists($f->{$_}),
-% qw( js_only html_only select_only layers_only cell_style);
+% #for select-ticketing_queueid at least
+% 'post_options' => $f->{'post_options'},
%
-% #select-*
-% $include_common{$_} = $f->{$_}
-% foreach grep exists($f->{$_}), qw( empty_label );
+% #any?
+% 'colspan' => $f->{'colspan'},
+% 'required' => $f->{'required'},
%
-% #select-table, checkboxes-table
-% $include_common{$_} = $f->{$_}
-% foreach grep exists($f->{$_}), qw( table name_col );
+% #contact
+% 'custnum' => $f->{'custnum'},
+% 'prospectnum' => $f->{'prospectnum'},
%
-% #checkboxes-table
-% $include_common{$_} = $f->{$_}
-% foreach grep exists($f->{$_}), qw( target_table link_table );
+% );
%
-% #*-table
-% $include_common{$_} = $f->{$_}
-% foreach grep exists($f->{$_}), qw( hashref agent_virt agent_null_right );
+% $include_common{$_} = $f->{$_} foreach grep exists($f->{$_}),
+% qw( js_only html_only select_only layers_only cell_style ),#selectlayers,?
+% qw( empty_label ), # select-*
+% qw( value_col compare_sub order_by addl_from ), # select-table
+% qw( table name_col ), #(select,checkboxes)-table
+% qw( target_table link_table ), #checkboxes-table
+% qw( hashref agent_virt agent_null agent_null_right ),#*-table
+% qw( formatted_value ), #fixed
+% qw( country ), #select-country
+% qw( width height config ), #htmlarea
+% qw( is_optional alt_format ), #select-cust_location
+% qw( classnum ), # select-inventory_item
+% qw( aligned ), # columnstart
+% qw( debug ), # select-table
+% ;
+%
+% #select-table
+% $include_common{$_} = ref( $f->{$_} ) eq 'CODE'
+% ? &{ $f->{$_} }( $cgi, $object ) #, $f )
+% : $f->{$_}
+% foreach grep exists($f->{$_}), qw( extra_sql );
%
% if ( $type eq 'tablebreak-tr-title' ) {
% $include_common{'table_id'} = 'TableNumber'. $tablenum++;
+% }
+% if ( $type eq 'tablebreak-tr-title' || $type eq 'title' ) {
% $include_common{'colspan'} = $f->{colspan} if $f->{colspan};
% }
%
% if ( $f->{include_opt_callback} ) {
-% %include_common = ( %include_common, &{ $f->{include_opt_callback} } );
+% %include_common = ( %include_common,
+% &{ $f->{include_opt_callback} }( $object )
+% );
% }
%
% my $layer_prefix_on = '';
%
+% my $submitid = $opt{submit_id} ? $opt{submit_id} : '';
+%
% my $include_sub = sub {
% my %opt = @_;
%
% $include_common{'layer_prefix'} = "$field$fieldnum."
% if $layer_prefix_on;
%
+% ## set conditionname field values for validation.
+% if ($field eq 'conditionname') {
+% my $validate_field = $field . $fieldnum . '.after_event.run_delay';
+% $js_form_validate->{edit_topform}->{validate_fields}{$validate_field} = 'digits: true';
+% $js_form_validate->{edit_topform}->{error_message}{$validate_field} = 'Please only enter numbers here.';
+% }
+%
% my @include =
% ( "/elements/$include.html",
% 'field' => "$field$fieldnum",
% 'id' => "$field$fieldnum", #separate?
% 'label_id' => $field."_label$fieldnum", #don't want field0_label0...
+% 'submit_id' => $submitid,
% %include_common,
% %opt,
% );
+%
+% if ( $include eq 'tr-input-date-field' ) {
+% # it's either hacking it here, or changing a lot more stuff
+% @include = (
+% "/elements/$include.html", {
+% 'name' => $field,
+% 'value' => $opt{curr_value},
+% 'label' => $label,
+% 'noinit' => $f->{noinit},
+% 'required' => $f->{'required'},
+% }
+% );
+% }
+%
% @include;
% };
%
% $g_row = 1 if $type eq 'tablebreak-tr-title';
% $g_row++;
% $g_row++ if $type eq 'title';
+% $g_row += scalar( @{ $f->{options} } )-1 if $type eq 'radio';
% } else {
% if ( $type eq 'columnstart' ) {
% push @g_row_stack, $g_row;
% }
% foreach my $name_obj ( @existing ) {
%
+% my $m2_label = $f->{'m2_label'};
+% $m2_label = &{ $f->{'m2_label_callback'} }($name_obj) if $f->{'m2_label_callback'};
+%
% my $ex_label = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this '.
% lc($f->{'m2_label'}).
% qq(" onClick="remove_$field($fieldnum);").
% ' STYLE="color:#ff0000;font-weight:bold;'.
% 'padding-left:2px;padding-right:2px"'.
-% '> '. ($f->{'m2_label'} || $field ). ' ';
+% '> '. ($m2_label || $field ). ' ';
%
% if ( $f->{'layer_values_callback'} ) {
% my %switches = ( 'mode' => $mode );
% }
% warn "layer values: ". Dumper($layer_values)
% if $opt{'debug'};
-%
+%
% my @existing = &{ $include_sub }(
% 'label' => $ex_label,
% 'fieldnum' => $fieldnum,
% if ( $f->{curr_value_callback} ) {
% $curr_value = &{ $f->{curr_value_callback} }( $cgi, $object, $field ),
% } else {
-% $curr_value = $object->$field();
+% $curr_value = $object->$field() if $field;
% }
% $curr_value = &{ $opt{'value_callback'} }( $f->{'field'}, $curr_value )
% if $opt{'value_callback'} && $mode ne 'error';
// only spawn if we're the last element... return if not
- var field_regex = /(\d+)(_[a-z]+)?$/;
+ var field_regex = /(\d+)(_[a-z_0-9]+)?$/;
var match = field_regex.exec(what.name);
if ( !match ) {
- alert(what.name + " didn't match?!");
+ alert(what.name + " didn't match for " + what);
return;
}
if ( match[1] != <%$field%>_fieldnum ) {
return;
}
+% if ( exists( $f->{'js_spawn_test'} ) ) {
+ // XXX check a passed-in hook here and optionall return
+ if ( <% $f->{'js_spawn_test'} %> ) {
+ // then go ahead and spawn
+ } else {
+ return;
+ }
+% }
+
// change the label on the last entry & add a remove button
var prev_label = document.getElementById('<% $field %>_label' + <%$field%>_fieldnum );
prev_label.innerHTML = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this <% lc($f->{'m2_label'}) %>" onClick="remove_<% $field %>(' + <%$field%>_fieldnum + ');" STYLE="color:#ff0000;font-weight:bold;padding-left:2px;padding-right:2px" > <% $f->{'m2_label'} || $field %>';
var newrow = <% include(@layer_opt, html_only=>1) |js_string %>;
-% if ( $type eq 'selectlayers' ) { #until the rest have html/js_only
- var newfunc = <% include(@layer_opt, js_only =>1) |js_string %>;
+% #until the rest have html/js_only
+% if ( ($type eq 'selectlayers') || ($type eq 'selectlayersx') || ($type =~ /^select-cgp_rule_/) || ($type eq 'contact') ) {
+ var newfunc = <% include(@layer_opt, js_only=>1) |js_string %>;
% } else {
var newfunc = '';
% }
var row = table.insertRow(<%$field%>_rownum++);
- var label_cell = document.createElement('TD');
+ var label_cell = document.createElement('TH');
label_cell.id = '<% $field %>_label' + <%$field%>_fieldnum;
widget_cell.style.borderTop = "1px solid black";
widget_cell.style.paddingTop = "3px";
- widget_cell.colSpan = "<% $f->{'colspan'} || 1 %>"
+ widget_cell.colSpan = "<% $f->{'colspan'} || 1 %>";
widget_cell.innerHTML = newrow;
: $opt{'html_bottom'}
%>
-<BR>
+% ## set extra field values for validation. ie price plan fields
+% my $extra_fields_to_validate = $opt{'extra_fields_validate'};
+% my %validate_error_messages = (
+% 'digits: true' => 'Please only enter numbers here.',
+% 'email: true' => 'Please enter a valid email here.',
+% );
+% foreach my $extra_fields (keys %$extra_fields_to_validate) {
+% my $validate_type = $extra_fields_to_validate->{$extra_fields};
+% $js_form_validate->{edit_topform}->{validate_fields}{$extra_fields} = $validate_type;
+% $js_form_validate->{edit_topform}->{error_message}{$extra_fields} = $validate_error_messages{$validate_type};
+% }
-<INPUT TYPE="submit" ID="submit" VALUE="<% ( !$clone && $object->$pkey() ) ? "Apply changes" : "Add ". ( $opt{'name'} || $opt{'name_singular'} ) %>">
+% unless ($opt{'embed'}) {
+
+ <BR>
+
+% unless ($opt{'no_submit'}) {
+ <INPUT TYPE = "submit"
+ ID = "submit"
+ VALUE = "<% ( !$clone && $object->$pkey() )
+ ? "Apply changes"
+ : "Add ". ($opt{'name'} || $opt{'name_singular'})
+ %>"
+ >
+% if ( $opt{'delete_url'} and $object->get($pkey) ) {
+% my $delete_msg = 'Delete this '.
+% ($opt{'name_singular'} || $opt{'name'});
+% my $delete_url = $opt{'delete_url'};
+% $delete_url .= '?' unless $delete_url =~ /\?/;
+% $delete_url .= $object->get($pkey);
+ <SCRIPT TYPE="text/javascript">
+ function confirm_delete() {
+ if(confirm(<% $delete_msg . '?' |js_string %>)) {
+ window.location.href = <% $delete_url |js_string %>;
+ }
+ }
+ </SCRIPT>
+ <INPUT TYPE = "button"
+ VALUE = "<% $delete_msg |h %>"
+ onclick = "confirm_delete()">
+% }
+% }
-</FORM>
+ </FORM>
-<% ref( $opt{'html_foot'} )
- ? &{ $opt{'html_foot'} }( $object )
- : $opt{'html_foot'}
-%>
+ <% ref( $opt{'html_foot'} )
+ ? &{ $opt{'html_foot'} }( $object )
+ : $opt{'html_foot'}
+ %>
+
+% my %footerdata = (
+% 'formvalidation' => $js_form_validate,
+% );
+
+ <% include("/elements/footer.html", %footerdata) %>
-<% include("/elements/footer.html") %>
+% }
<%init>
my(%opt) = @_;
+my $conf = new FS::Conf;
my $curuser = $FS::CurrentUser::CurrentUser;
#false laziness w/process.html
my $fields = $opt{'fields'}
#|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ];
|| [ grep { $_ ne $pkey } fields($table) ];
-#my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields;
+my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields;
-if ( $cgi->param('redirect') ) {
- my $session = $cgi->param('redirect');
- my $pref = $curuser->option("redirect$session");
- die "unknown redirect session $session\n" unless length($pref);
- $cgi = new CGI($pref);
-}
+push @actualfields, $pkey;
+push @actualfields, 'ip_addr' if $table eq 'svc_broadband';
+push @actualfields, 'usergroup' if ($table eq 'svc_broadband' && $conf->exists('svc_broadband-radius'));
+
+my $js_form_validate = {};
-&{$opt{'begin_callback'}}( $cgi, $fields, \%opt )
- if $opt{'begin_callback'};
-
-my %qsearch = (
- 'table' => $table,
- 'extra_sql' => ( $opt{'agent_virt'}
- ? ' AND '. $curuser->agentnums_sql(
- 'null_right' => $opt{'agent_null_right'}
- )
- : ''
- ),
-);
-
-my $mode;
-my $object;
+my( $mode, $object);
my $clone = '';
-if ( $cgi->param('error') ) {
+if ( $opt{'embed'} ) {
- $mode = 'error';
+ $object = $opt{'embed'};
+ $mode = $cgi->param('error')
+ ? 'error'
+ : $object->$pkey()
+ ? 'edit'
+ : 'new';
- $object = $class->new( {
- map { $_ => scalar($cgi->param($_)) } fields($table)
- });
+} else {
- &{$opt{'error_callback'}}( $cgi, $object, $fields, \%opt )
- if $opt{'error_callback'};
+ #$m->comp('/elements/handle_uri_query');
+ if ( $cgi->param('redirect') ) {
+ my $session = $cgi->param('redirect');
+ my $pref = $curuser->option("redirect$session");
+ die "unknown redirect session $session\n" unless length($pref);
+ $cgi = new CGI($pref);
+ }
-} elsif ( $cgi->param('clone') =~ /^(\d+)$/ ) {
+ &{$opt{'begin_callback'}}( $cgi, $fields, \%opt )
+ if $opt{'begin_callback'};
+
+ my %qsearch = (
+ 'table' => $table,
+ 'extra_sql' => ( $opt{'agent_virt'}
+ ? ' AND '. $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ )
+ : ''
+ ),
+ );
- $mode = 'clone';
+ if ( $cgi->param('error') ) {
- $clone = $1;
+ $mode = 'error';
- $qsearch{'extra_sql'} = ' AND '. $opt{'agent_clone_extra_sql'}
- if $opt{'agent_clone_extra_sql'};
+ $object = $class->new( {
+ map { $_ => scalar($cgi->param($_)) } @actualfields
+ });
- $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } })
- or die "$pkey $clone not found in $table";
+ &{$opt{'error_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'error_callback'};
- &{$opt{'clone_callback'}}( $cgi, $object, $fields, \%opt )
- if $opt{'clone_callback'};
+ } elsif ( $cgi->param('clone') =~ /^(\d+)$/ ) {
- #$object->$pkey('');
+ $mode = 'clone';
- $opt{action} ||= 'Add';
+ $clone = $1;
-} elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing
+ $qsearch{'extra_sql'} = ' AND '. $opt{'agent_clone_extra_sql'}
+ if $opt{'agent_clone_extra_sql'};
- $mode = 'edit';
+ $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $clone } })
+ or die "$pkey $clone not found in $table";
- my $value;
- if ( $cgi->param($pkey) ) {
- $value = $cgi->param($pkey)
- } else {
- my( $query ) = $cgi->keywords;
- $value = $query;
- }
- $value =~ /^(\d+)$/ or die "unparsable $pkey";
- $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $1 } })
- or die "$pkey $1 not found in $table";
-
- warn "$table $pkey => $1"
- if $opt{'debug'};
+ &{$opt{'clone_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'clone_callback'};
- &{$opt{'edit_callback'}}( $cgi, $object, $fields, \%opt )
- if $opt{'edit_callback'};
+ #$object->$pkey('');
-} else { #adding
+ $opt{action} ||= 'Add';
- $mode = 'new';
+ } elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing
- my $hashref = $opt{'new_hashref_callback'}
- ? &{$opt{'new_hashref_callback'}}
- : {};
+ $mode = 'edit';
- $object = $opt{'new_object_callback'}
- ? &{$opt{'new_object_callback'}}( $cgi, $hashref, $fields, \%opt )
- : $class->new( $hashref );
+ my $value;
+ if ( $cgi->param($pkey) ) {
+ $value = $cgi->param($pkey)
+ } else {
+ my( $query ) = $cgi->keywords;
+ $value = $query;
+ }
+ $value =~ /^(\d+)$/ or die "unparsable $pkey";
+ $object = qsearchs({ %qsearch, 'hashref' => { $pkey => $1 } })
+ or die "$pkey $1 not found in $table";
- &{$opt{'new_callback'}}( $cgi, $object, $fields, \%opt )
- if $opt{'new_callback'};
+ warn "$table $pkey => $1"
+ if $opt{'debug'};
-}
+ &{$opt{'edit_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'edit_callback'};
-&{$opt{'end_callback'}}( $cgi, $object, $fields, \%opt )
- if $opt{'end_callback'};
+ } else { #adding
-$opt{action} ||= $object->$pkey() ? 'Edit' : 'Add';
+ $mode = 'new';
-my $title = $opt{action}. ' '. ( $opt{name} || $opt{'name_singular'} );
+ my $hashref = $opt{'new_hashref_callback'}
+ ? &{$opt{'new_hashref_callback'}}
+ : {};
-my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html";
-$viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'};
+ $object = $opt{'new_object_callback'}
+ ? &{$opt{'new_object_callback'}}( $cgi, $hashref, $fields, \%opt )
+ : $class->new( $hashref );
+
+ &{$opt{'new_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'new_callback'};
+
+ }
+
+ &{$opt{'end_callback'}}( $cgi, $object, $fields, \%opt )
+ if $opt{'end_callback'};
+
+ $opt{action} ||= $object->$pkey() ? 'Edit' : 'Add';
-my @menubar = ();
-if ( $opt{'menubar'} ) {
- @menubar = @{ $opt{'menubar'} };
-} else {
- my $items = $opt{'name'} ? $opt{'name'}.'s' : PL($opt{'name_singular'});
- @menubar = (
- "View all $items" => $viewall_url,
- );
}
</%init>