7 # #? 'primary_key' => #required when the dbdef doesn't know...???
12 # listref - each item is a literal column name (or method) or hashref
14 # if not specified all columns (except for the primary key) will be editable
17 # { 'field' => 'another_columname',
18 # 'type' => 'text', #text, fixed, hidden
22 # 'menubar' => '', #menubar arrayref
24 # #run when re-displaying with an error
25 # 'error_callback' => sub { my( $cgi, $object ) = @_; },
28 # 'edit_callback' => sub { my( $cgi, $object ) = @_; },
30 # # returns a hashref for the new object
31 # 'new_hashref_callback'
34 # 'new_callback' => sub { my( $cgi, $object ) = @_; },
37 # 'field_callback' => sub { },
39 # #string or coderef of additional HTML to add before </TABLE>
40 # 'html_table_bottom' => '',
42 # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search'
44 # 'html_bottom' => '', #string
45 # 'html_bottom' => sub {
53 #false laziness w/process.html
54 my $table = $opt{'table'};
55 my $class = "FS::$table";
56 my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} ||
57 my $fields = $opt{'fields'}
58 #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ];
59 || [ grep { $_ ne $pkey } fields($table) ];
60 #my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields;
63 if ( $cgi->param('error') ) {
65 $object = $class->new( {
66 map { $_ => scalar($cgi->param($_)) } fields($table)
69 &{$opt{'error_callback'}}($cgi, $object)
70 if $opt{'error_callback'};
72 } elsif ( $cgi->keywords ) { #editing
74 my( $query ) = $cgi->keywords;
76 $object = qsearchs( $table, { $pkey => $1 } );
77 warn "$table $pkey => $1"
80 &{$opt{'edit_callback'}}($cgi, $object)
81 if $opt{'edit_callback'};
85 my $hashref = $opt{'new_hashref_callback'}
86 ? &{$opt{'new_hashref_callback'}}
89 $object = $class->new( $hashref );
91 &{$opt{'new_callback'}}($cgi, $object)
92 if $opt{'new_callback'};
96 my $action = $object->$pkey() ? 'Edit' : 'Add';
98 my $title = "$action $opt{'name'}";
101 if ( $opt{'menubar'} ) {
102 @menubar = @{ $opt{'menubar'} };
105 'Main menu' => $p, #eventually get rid of this when the ACL/UI update is done
106 #eventually use Lingua::bs to pluralize
107 "View all $opt{'name'}s" => $p. ( $opt{'viewall_dir'} || 'search' ).
112 %><%= include("/elements/header.html", $title,
113 include( '/elements/menubar.html', @menubar )
117 <% if ( $cgi->param('error') ) { %>
118 <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT>
122 <FORM ACTION="<%= popurl(1) %>process/<%= $table %>.html" METHOD=POST>
123 <INPUT TYPE="hidden" NAME="<%= $pkey %>" VALUE="<%= $object->$pkey() %>">
124 <%= ( $opt{labels} && exists $opt{labels}->{$pkey} )
125 ? $opt{labels}->{$pkey}
128 #<%= $object->$pkey() || "(NEW)" %>
130 <%= ntable("#cccccc",2) %>
132 <% foreach my $f ( map { ref($_) ? $_ : {'field'=>$_} }
136 &{ $opt{'field_callback'} }( $f )
137 if $opt{'field_callback'};
139 my $field = $f->{'field'};
140 my $type = $f->{'type'} ||= 'text';
147 <%= ( $opt{labels} && exists $opt{labels}->{$field} )
148 ? $opt{labels}->{$field}
154 #eventually more options for <SELECT>, etc. fields
155 if ( $type eq 'fixed' ) {
158 <TD BGCOLOR="#dddddd"><%= $f->{'value'} %></TD>
159 <INPUT TYPE="hidden" NAME="<%= $field %>" VALUE="<%= $f->{'value'} %>">
164 <INPUT TYPE="<%= $type %>" NAME="<%= $field %>" VALUE="<%= $object->$field() %>">
173 <%= ref( $opt{'html_table_bottom'} )
174 ? &{ $opt{'html_table_bottom'} }( $object )
175 : $opt{'html_table_bottom'}
180 <%= ref( $opt{'html_bottom'} )
181 ? &{ $opt{'html_bottom'} }( $object )
182 : $opt{'html_bottom'}
187 <INPUT TYPE="submit" VALUE="<%= $object->$pkey() ? "Apply changes" : "Add $opt{'name'}" %>">
191 <%= include("/elements/footer.html") %>