Line # Revision Author
1 842 ahitrov <!DOCTYPE html>
2 8 ahitrov@rambler.ru <& "/contenido/components/header.msn" &>
3 <& "/contenido/components/naviline.msn", sect_id => $owner->id &>
4
5 17 ahitrov@rambler.ru <script type="text/javascript">
6 <!--
7 function set_create_button( oSelect, sBtnID ) {
8 if ( oSelect.value == '' ) {
9 $('#'+sBtnID).attr('disabled','disabled');
10 } else {
11 $('#'+sBtnID).removeAttr('disabled');
12 }
13 }
14 //-->
15 </script>
16
17 8 ahitrov@rambler.ru <table width="100%" cellspacing="0" cellpadding="0" border="0">
18 <tr valign="top">
19 607 ahitrov <td id="column-side">
20 8 ahitrov@rambler.ru
21 <& "/contenido/components/subsection.msn", section => $owner &>
22 <& "/contenido/components/class_filter.msn", class=> $class, section => $owner &>
23
24 % if (( $owner->id ) && ($owner->id > 0) )
25 % {
26 <& "/contenido/components/section_info.msn", section => $owner &>
27 % }
28
29 % my @LEFT = $m->comp('components/tasks.msn');
30 % my %LEFTh = map { $_->{attr} => $_ } (@LEFT);
31 % if (ref($request->{tab}->{lefts}))
32 % {
33 % for my $left (@{ $request->{tab}->{lefts} })
34 % {
35 % next if (! exists($LEFTh{$left}));
36 <& '/contenido/components/'.$LEFTh{$left}->{component}, %ARGS &>
37 % }
38 % }
39
40 <!-- Примечания -->
41 <fieldset>
42 <legend>Примечания</legend>
43 <table width="100%" cellspacing="5" cellpadding="0" class="tform">
44
45 <tr>
46 <th valign=top>1)</th>
47 <td width="100%">
48 Дата и время документа - поле, которое Вы можете редактировать.<br><br>
49 Кроме этого у каждого документа существует еще две временные отметки - дата создания (ctime) и дата модификации (mtime).
50 Это служебные поля и Вы не можете их изменять (они доступны только для чтения).
51 </td>
52 </tr>
53
54 </table>
55 </fieldset>
56
57 </td>
58 607 ahitrov <td width="2%"><a href="javascript:void()" class="width-toggler"><img src="/contenido/i/icons/left-right.png" width="30"></a></td>
59 <td id="column-content">
60 8 ahitrov@rambler.ru % if($owner->id) {
61
62 <fieldset>
63 <legend>Документы\
64 % if ($class) {
65 класса <% $class %>\
66 % if ($use_section) {
67 c учетом текущей секции\
68 % }
69 % } else {
70 в разделе\
71 % }
72 118 ahitrov % if (!$owner->no_count && $total > 0) {
73 624 ahitrov (всего: <% $total %>, показано с <% $first + 1 %> по <% $sorted ? $total : ($first + $n > $total) ? $total : $first + $n %>)
74 118 ahitrov % } elsif ( $owner->no_count ) {
75 (<span style="color:yellow">без пересчета</span>, показано с <% $first + 1 %> по <% $first + scalar @documents %>)
76 8 ahitrov@rambler.ru % }
77 </legend>
78
79 118 ahitrov % if ($total || scalar @documents || defined($alpha) || defined($search) ) {
80 616 ahitrov <table border="0" cellspacing="0" cellpadding="2" width="100%">
81 <tr>
82 8 ahitrov@rambler.ru % if ($section_access == 2) {
83 616 ahitrov <td width="99%">
84 8 ahitrov@rambler.ru <& "/contenido/components/new_objects_form.msn", proto => 'documents',
85 616 ahitrov sect_id => $owner->id, section => $owner,
86 default => ($owner->default_document_class ? $owner->default_document_class : undef) &>
87 </td>
88 8 ahitrov@rambler.ru % }
89 616 ahitrov <td width="1%">
90 <& "/contenido/components/section_page_size.msn", section => $owner &>
91 </td>
92 </tr>
93 </table>
94 117 ahitrov <div style="font-size:12px; font-family:Arial;">
95 850 ahitrov <table border="0" cellspacing="0" cellpadding="2" width="100%" style="margin:5px 0; border:1px solid gray;">
96 8 ahitrov@rambler.ru <tr bgcolor="#e0e0e0"><th colspan="4">Поиск по букве:&nbsp;&nbsp;[<a href="?id=<% $id %>" style="font-weight:normal;">сброс фильтра</a>]</th></tr>
97 117 ahitrov <tr><td style="font-size:12px; font-family:Arial; padding:2px 4px;">
98 8 ahitrov@rambler.ru <& /inc/alpha.msn, alpha=>$alpha, params=>\%ARGS, &>
99 </td></tr></table>
100 % ## Форма поиска. Работает при включенном фильтре класса
101 % ## и описанной для класса функции search_fields
102 % ########################################################
103 450 ahitrov % if ( $filter{class} || $filter{table} ) {
104 459 ahitrov % my ($document) = $filter{class} ? ($filter{class}->new( $keeper )) : map { $_->new( $keeper ) } grep { $_->new( $keeper )->class_table eq $owner->default_table_class } @{ $user->get_available_classes };
105 8 ahitrov@rambler.ru % my @fields = $document->search_fields;
106 % if ( @fields ) {
107 % my @props = $document->required_properties;
108 <form action="sections.html">
109 850 ahitrov <table border="0" cellspacing="0" cellpadding="2" width="100%" style="margin:5px 0; border:1px solid gray;">
110 8 ahitrov@rambler.ru <tr bgcolor="#e0e0e0"><th colspan="4">Поиск по полю:&nbsp;&nbsp;[<a href="?id=<% $id %>" style="font-weight:normal;">сброс фильтра</a>]</th></tr><tr>
111 <td width="1%" nowrap style="padding:2px 0 2px 4px;"><select name="search_by">
112 % foreach my $field ( @fields ) {
113 % my ($prop) = grep { $_->{'attr'} eq $field } @props;
114 % my $selected = $field eq $search_by ? ' selected' : '';
115 <option value="<% $field %>"<% $selected %>><% ref $prop ? $prop->{'shortname'} || $prop->{'rusname'} : $field %>
116 % }
117 850 ahitrov </select></td><td width="0">:</td>
118 8 ahitrov@rambler.ru <td width="98%"><input type="text" name="search" value="<% $search %>" style="width:100%"></td>
119 <td width="1%" style="padding:2px 4px 2px 0;"><input type="submit" value=" &raquo; " style="border:1px solid gray;"></td>
120 </tr></table>
121 % if ( $id ) {
122 <input type="hidden" name="id" value="<% $id %>">
123 % }
124 % if ( $class ) {
125 <input type="hidden" name="class" value="<% $class %>">
126 % }
127 % if ( $use_section ) {
128 <input type="hidden" name="use_section" value="<% $use_section %>">
129 % }
130 </form>
131 % }
132 % }
133
134 850 ahitrov % if ( $m->comp_exists ("/contenido/components/sections_actions.msn") ) {
135 <& "/contenido/components/sections_actions.msn", section => $owner, documents => \@documents, columns => \@columns, filter => \%filter_params, %ARGS &>\
136 % }
137
138 8 ahitrov@rambler.ru <div style="height:5px"><spacer type="block" height="5"></div>
139 118 ahitrov % if ( $owner->no_count ) {
140 <& /inc/pages_nocount.msn, p=>$p, n=>$n, found=> scalar @documents, href=>'sections.html', params=>\%ARGS, size => 15 &>
141 624 ahitrov % } elsif ( $sorted ) {
142 118 ahitrov % } else {
143 8 ahitrov@rambler.ru <& /inc/pages_.msn, p=>$p, n=>$n, total=>$total, href=>'sections.html', params=>\%ARGS, &>
144 118 ahitrov % }
145 8 ahitrov@rambler.ru </div>
146
147 <& /contenido/components/section_browse.msn, documents => \@documents, columns => \@columns, section => $owner, filter => \%filter_params, %ARGS &>
148
149 117 ahitrov <div style="font-size:12px; font-family:Arial;">
150 118 ahitrov % if ( $owner->no_count ) {
151 <& /inc/pages_nocount.msn, p=>$p, n=>$n, found=> scalar @documents, href=>'sections.html', params=>\%ARGS, size => 15 &>
152 624 ahitrov % } elsif ( $sorted ) {
153 118 ahitrov % } else {
154 8 ahitrov@rambler.ru <& /inc/pages_.msn, p=>$p, n=>$n, total=>$total, href=>'sections.html', params=>\%ARGS, &>
155 118 ahitrov % }
156 8 ahitrov@rambler.ru <div style="height:5px"><spacer type="block" height="5"></div>
157 </div>
158
159 % } else {
160 <h4 align="center"><i>---- Нет документов -----</i></h4>
161 % }
162 %
163 % if ($section_access == 2) {
164 <& "/contenido/components/new_objects_form.msn", proto => 'documents',
165 sect_id => $owner->id,
166 default => ($owner->default_document_class ? $owner->default_document_class : undef) &>
167 % }
168
169 </fieldset>
170 </td>
171 </tr>
172 </table>
173
174 % }
175
176 </body>
177 </html>
178 607 ahitrov <%once>
179
180 my $cookie_name = 'content_fullwidth';
181
182 </%once>
183 8 ahitrov@rambler.ru <%args>
184
185 $id => undef
186 $p => 1
187 $class => undef
188 $use_section => undef
189 $alpha => undef
190 $alpha_search => undef
191 $search_by => undef
192 $search => undef
193 $update => undef
194 $delete => undef
195
196 </%args>
197 <%init>
198
199 $id = 0 if $id =~ /\D/;
200 607 ahitrov my $content_fullwidth = $m->comp('/contenido/components/cookies.msn', name => $cookie_name);
201
202 8 ahitrov@rambler.ru my $owner;
203
204 # Операции...
205 if ($id && ($id > 0))
206 {
207 $owner = $keeper->get_section_by_id($id);
208 }
209 if (! ref($owner))
210 {
211 return undef;
212 }
213
214 my %filter_params;
215 $filter_params{use_section} = $use_section if $use_section;
216 $filter_params{class} = $class if $class;
217 $filter_params{alpha} = $alpha if $alpha;
218 $filter_params{alpha_search} = $alpha_search if $alpha_search;
219 $filter_params{search_by} = $search_by if $search_by;
220 $filter_params{search} = $search if $search;
221 $filter_params{p} = $p if $p > 1;
222 $filter_params{s} = $id if $id;
223
224 16 ahitrov@rambler.ru # Фильтры работают в любом случае...
225 8 ahitrov@rambler.ru my $filter = $m->comp('/contenido/components/context.msn', name => 'filter');
226 my $profile = $m->comp('/contenido/components/context.msn', name => 'profile');
227
228 if ($update) {
229 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
230 my %updated;
231 while ( my ($field, $value) = each %ARGS ) {
232 if ( $field =~ /^update_(\d+)_(\w+)$/ ) {
233 my $oid = $1;
234 my $attr = $2;
235 $updated{$oid}{$attr} = $value;
236 }
237 }
238 my %classes = map { $_->{class} => 1 } values %updated;
239 foreach my $update_class ( keys %classes ) {
240 my @ids;
241 while ( my ($oid, $attr) = each %updated) {
242 push @ids, $oid if $attr->{class} eq $update_class;
243 }
244 my @objects = $keeper->get_documents (
245 id => \@ids,
246 class => $update_class
247 ) if @ids;
248 foreach my $object ( @objects ) {
249 my $document_access = $user->section_accesses($user, $object->section);
250 next unless $document_access == 2;
251 my $fields = $updated{$object->id};
252 my @props = grep { exists $_->{inline} && $_->{inline} } $object->structure;
253 if ( ref $fields eq 'HASH' ) {
254 foreach my $prop ( @props ) {
255 my $attr = $prop->{attr};
256 my $value = ref $fields && exists $fields->{$attr} ? $fields->{$attr} : undef;
257 395 ahitrov if ( $prop->{type} eq 'checkbox' ) {
258 $value = $value ? 1 : undef;
259 }
260 386 ahitrov if ( exists $prop->{db_type} ) {
261 if ( $prop->{db_type} eq 'float' ) {
262 for ( $value ) {
263 s/\,/\./;
264 s/^\s+//;
265 s/\s+$//;
266 }
267 if ( $value eq '' ) {
268 $value = undef;
269 }
270 } elsif ( $prop->{db_type} eq 'integer' || $prop->{db_type} eq 'smallint' ) {
271 $value =~ s/\D//sg if $value;
272 if ( $value eq '' ) {
273 $value = undef;
274 }
275 8 ahitrov@rambler.ru }
276 }
277
278 $object->$attr($value);
279 }
280 $object->store;
281 }
282 }
283 }
284 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
285 }
286 if ( $delete ) {
287 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
288 my %deleted;
289 while ( my ($field, $value) = each %ARGS ) {
290 if ( $field =~ /^delete_(\d+)_(\w+)$/ ) {
291 my $oid = $1;
292 my $attr = $2;
293 $deleted{$oid}{$attr} = $value;
294 }
295 }
296 my %classes = map { $_->{class} => 1 } values %deleted;
297 foreach my $delete_class ( keys %classes ) {
298 my @ids;
299 while ( my ($oid, $attr) = each %deleted) {
300 push @ids, $oid if exists $attr->{id} && $attr->{id} && ($attr->{class} eq $delete_class);
301 }
302 my @objects = $keeper->get_documents (
303 id => \@ids,
304 class => $delete_class
305 ) if @ids;
306 foreach my $object ( @objects ) {
307 my $document_access = $user->section_accesses($user, $object->section);
308 next unless $document_access == 2;
309 $object->delete;
310 }
311 }
312 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
313 }
314 386 ahitrov if ( $ARGS{move} || $ARGS{link} ) {
315 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
316 if ( exists $ARGS{tree} && $ARGS{tree} && $ARGS{tree} != $owner->id ) {
317 my %updated;
318 while ( my ($field, $value) = each %ARGS ) {
319 388 ahitrov if ( $field =~ /^delete_(\d+)_(\w+)$/ ) {
320 386 ahitrov my $oid = $1;
321 my $attr = $2;
322 $updated{$oid}{$attr} = $value;
323 }
324 }
325 522 ahitrov warn Dumper \%updated if $DEBUG;
326 386 ahitrov my %classes = map { $_->{class} => 1 } values %updated;
327 my $parent_new = $keeper->get_section_by_id( $ARGS{tree} );
328 my $document_access = $user->section_accesses($user, $parent_new->id);
329 if ( $document_access == 2 ) {
330 foreach my $update_class ( keys %classes ) {
331 my @ids;
332 while ( my ($oid, $attr) = each %updated) {
333 388 ahitrov push @ids, $oid if exists $attr->{id} && $attr->{id} && ($attr->{class} eq $update_class);
334 386 ahitrov }
335 my @objects = $keeper->get_documents (
336 id => \@ids,
337 class => $update_class
338 ) if @ids;
339 my ($prop) = grep { $_->{attr} eq 'sections' } $update_class->new( $keeper )->structure;
340 if ( ref $prop && exists $prop->{db_type} && exists $prop->{db_field} ) {
341 foreach my $object ( @objects ) {
342 if ( $prop->{db_type} eq 'integer[]' ) {
343 my @sections = grep { $_ != $parent_new->id } $object->sections;
344 if ( @sections && $sections[0] == $owner->id ) {
345 419 ahitrov if ( $ARGS{move} ) {
346 shift @sections;
347 unshift @sections, $parent_new->id;
348 } else {
349 push @sections, $parent_new->id;
350 }
351 } else {
352 if ( $ARGS{move} ) {
353 @sections = grep { $_ != $owner->id } @sections;
354 }
355 521 ahitrov push @sections, $parent_new->id;
356 386 ahitrov }
357 $object->sections( @sections );
358 } else {
359 $object->sections( $parent_new->id );
360 }
361 $object->store;
362 }
363 }
364 }
365 }
366 }
367 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
368 522 ahitrov } elsif ( $ARGS{unlink} ) {
369 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
370 my $document_access = $user->section_accesses($user, $owner->id);
371 my %updated;
372 while ( my ($field, $value) = each %ARGS ) {
373 if ( $field =~ /^delete_(\d+)_(\w+)$/ ) {
374 my $oid = $1;
375 my $attr = $2;
376 $updated{$oid}{$attr} = $value;
377 }
378 }
379 warn Dumper \%updated if $DEBUG;
380 my %classes = map { $_->{class} => 1 } values %updated;
381 if ( $document_access == 2 ) {
382 foreach my $update_class ( keys %classes ) {
383 my @ids;
384 while ( my ($oid, $attr) = each %updated) {
385 push @ids, $oid if exists $attr->{id} && $attr->{id} && ($attr->{class} eq $update_class);
386 }
387 my @objects = $keeper->get_documents (
388 id => \@ids,
389 class => $update_class
390 ) if @ids;
391 my ($prop) = grep { $_->{attr} eq 'sections' } $update_class->new( $keeper )->structure;
392 if ( ref $prop && exists $prop->{db_type} && exists $prop->{db_field} ) {
393 foreach my $object ( @objects ) {
394 if ( $prop->{db_type} eq 'integer[]' ) {
395 my @sections = grep { $_ != $owner->id } $object->sections;
396 $object->sections( @sections );
397 } else {
398 $object->sections( undef );
399 }
400 $object->store;
401 }
402 }
403 }
404 }
405 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
406 386 ahitrov }
407 8 ahitrov@rambler.ru
408 621 ahitrov unless (defined $request->{section_accesses}->{$id}) {
409 $request->{section_accesses}->{$id} = $user->get_section_access($id);
410 }
411 my $section_access = $request->{section_accesses}->{$id};
412
413 my (@documents, $total);
414
415 my $s = $owner->id;
416 my $sorted = $owner->_sorted();
417 $s .= ",$filter" if ($filter > 0);
418
419 8 ahitrov@rambler.ru my %filter=();
420 131 ahitrov my $nothing_found = 0;
421 8 ahitrov@rambler.ru my %order = (not $class and $owner->order_by) ? (order_by => $owner->order_by) : (order => ['date','direct']);
422 if (defined $alpha and $alpha ne '') {
423 $filter{ilike}=1;
424 $filter{ $alpha_search || 'name' }="$alpha%";
425 $order{order}=['name','reverse'];
426 delete $order{order_by};
427 }
428 if ( $class ) {
429 $filter{class} = $class;
430 } elsif ( $owner->default_document_class ) {
431 $filter{class} = $owner->default_document_class;
432 } elsif ( $owner->default_table_class ) {
433 $filter{table} = $owner->default_table_class;
434 }
435 $filter{s}=$s unless ($class && !$use_section);
436 if ( $search_by && defined $search ) {
437 my $doc_class = $class || $owner->default_document_class;
438 if ( $doc_class ) {
439 my @props = $doc_class->new( $keeper )->structure();
440 my ($prop) = grep { $_->{attr} eq $search_by } @props if @props;
441 131 ahitrov if ( ref $prop && ($prop->{type} eq 'integer' || $prop->{type} eq 'checkbox' ||
442 546 ahitrov (($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup' || $prop->{type} eq 'status') && $search =~ /^\d+$/) ||
443 137 ahitrov (exists $prop->{db_type} && $prop->{db_type} =~ /integer\[\]/) )) {
444 8 ahitrov@rambler.ru $filter{$search_by} = int($search);
445 546 ahitrov } elsif ( ref $prop && $prop->{type} eq 'status' && $search =~ /\D/ ) {
446 my $str;
447 foreach my $pair ( @{$prop->{cases}} ) {
448 if ( lc(Encode::decode('utf-8', $pair->[1])) eq lc(Encode::decode('utf-8', $search)) || lc(Encode::decode('utf-8', $pair->[0])) eq lc(Encode::decode('utf-8', $search)) ) {
449 $str = $pair->[0];
450 last;
451 }
452 }
453 if ( $str ) {
454 $filter{$search_by} = $str;
455 }
456 131 ahitrov } elsif ( ref $prop && ($prop->{type} eq 'pickup' || $prop->{type} eq 'lookup') && $search =~ /\D/ ) {
457 my $lookup_opts = $prop->{lookup_opts};
458 386 ahitrov if ( ref $lookup_opts && (exists $lookup_opts->{class} || exists $lookup_opts->{table}) ) {
459 131 ahitrov my $search_field = exists $lookup_opts->{search_by} ? $lookup_opts->{search_by} : 'name';
460 my @ids = $keeper->get_documents (
461 ids => 1,
462 386 ahitrov exists $lookup_opts->{class} ? (class => $lookup_opts->{class}) : (table => $lookup_opts->{table}),
463 131 ahitrov ilike => 1,
464 $search_field => '%'.$search.'%',
465 );
466 if ( @ids ) {
467 $filter{$search_by} = \@ids;
468 } else {
469 $nothing_found = 1;
470 }
471 }
472 8 ahitrov@rambler.ru } else {
473 $filter{$search_by}='%'.$search.'%';
474 $filter{ilike} = 1;
475 }
476 } else {
477 $filter{$search_by}='%'.$search.'%';
478 $filter{ilike} = 1;
479 }
480 }
481
482 131 ahitrov # Дополнительные фильтры раздела
483 if ($owner->filters) {
484 no strict 'vars';
485 my $filters = eval($owner->filters);
486 if ($@) {
487 warn "Bad filter: " . $owner->filters . " in section " . $owner->id;
488 } elsif (ref $filters eq 'HASH') {
489 while ( my ($key, $val) = each %$filters ) {
490 $filter{$key} = $val;
491 }
492 }
493 }
494 8 ahitrov@rambler.ru
495 118 ahitrov $total = $keeper->get_documents(%filter, count=>1) unless $owner->no_count;
496 8 ahitrov@rambler.ru
497 616 ahitrov my $n = ref $owner && $owner->_page_size ? $owner->_page_size : 40;
498 8 ahitrov@rambler.ru my $first = $n * ($p - 1);
499 118 ahitrov ($first,$p)=(0,0) if (!$owner->no_count && $first>$total);
500 8 ahitrov@rambler.ru
501 131 ahitrov unless ( $nothing_found ) {
502 if ($class && !$use_section) {
503 @documents = $keeper->get_documents(%filter, %order, limit=>$n, offset=>$first);
504 } elsif ($sorted) {
505 607 ahitrov @documents = $keeper->get_sorted_documents(%filter);
506 131 ahitrov } else {
507 @documents = $keeper->get_documents(%filter, %order, limit=>$n, offset=>$first);
508 }
509 8 ahitrov@rambler.ru }
510 # набор колонок таблицы документов...
511 131 ahitrov my @columns = $sorted ? ({attr => '_sort_', name => 'N'}) : ();
512 8 ahitrov@rambler.ru
513 131 ahitrov # пытаемся найти колонки, которые документ сам пожелал показать (required_properties -> column)...
514 if ($filter{class} or @documents and $documents[0]) {
515 push @columns,
516 sort {$a->{column} <=> $b->{column}}
517 grep {$_->{column}} ($filter{class} ? $filter{class}->new($keeper)->structure : $documents[0]->structure);
518 }
519 8 ahitrov@rambler.ru
520 131 ahitrov # стандартная жопка таблицы...
521 @columns = (@columns,
522 {attr => '_act_', rusname => 'Действия'},
523 );
524
525 8 ahitrov@rambler.ru </%init>