Line # Revision Author
1 8 ahitrov@rambler.ru <& "/contenido/components/header.msn" &>
2 <& "/contenido/components/naviline.msn", sect_id => $owner->id &>
3
4 <table width="100%" cellspacing="0" cellpadding="0" border="0">
5 <tr valign="top">
6 <td width="35%">
7
8 <& "/contenido/components/subsection.msn", section => $owner &>
9 <& "/contenido/components/class_filter.msn", class=> $class, section => $owner &>
10
11 % if (( $owner->id ) && ($owner->id > 0) )
12 % {
13 <& "/contenido/components/section_info.msn", section => $owner &>
14 % }
15
16 % my @LEFT = $m->comp('components/tasks.msn');
17 % my %LEFTh = map { $_->{attr} => $_ } (@LEFT);
18 % if (ref($request->{tab}->{lefts}))
19 % {
20 % for my $left (@{ $request->{tab}->{lefts} })
21 % {
22 % next if (! exists($LEFTh{$left}));
23 <& '/contenido/components/'.$LEFTh{$left}->{component}, %ARGS &>
24 % }
25 % }
26
27 <!-- Примечания -->
28 <fieldset>
29 <legend>Примечания</legend>
30 <table width="100%" cellspacing="5" cellpadding="0" class="tform">
31
32 <tr>
33 <th valign=top>1)</th>
34 <td width="100%">
35 Дата и время документа - поле, которое Вы можете редактировать.<br><br>
36 Кроме этого у каждого документа существует еще две временные отметки - дата создания (ctime) и дата модификации (mtime).
37 Это служебные поля и Вы не можете их изменять (они доступны только для чтения).
38 </td>
39 </tr>
40
41 </table>
42 </fieldset>
43
44 </td>
45 <td width="2%">&nbsp;</td>
46 <td width="65%">
47
48 % if($owner->id) {
49
50 <fieldset>
51 <legend>Документы\
52 % if ($class) {
53 класса <% $class %>\
54 % if ($use_section) {
55 c учетом текущей секции\
56 % }
57 % } else {
58 в разделе\
59 % }
60 % if ($total > 0) {
61 (всего: <% $total %>, показано с <% $first + 1 %> по <% ($first + $n > $total) ? $total : $first + $n %>)
62 % }
63 </legend>
64
65 % if ($total or defined($alpha) or defined($search) ) {
66 % if ($section_access == 2) {
67 <& "/contenido/components/new_objects_form.msn", proto => 'documents',
68 sect_id => $owner->id,
69 default => ($owner->default_document_class ? $owner->default_document_class : undef) &>
70 % }
71 <div style="font-size:75%; font-family:Arial;">
72 <table border="0" cellspacing="0" cellpadding="2" width="100%" style="margin:4px 0 0; border:1px solid gray;">
73 <tr bgcolor="#e0e0e0"><th colspan="4">Поиск по букве:&nbsp;&nbsp;[<a href="?id=<% $id %>" style="font-weight:normal;">сброс фильтра</a>]</th></tr>
74 <tr><td style="font-size:75%; font-family:Arial; padding:2px 4px;">
75 <& /inc/alpha.msn, alpha=>$alpha, params=>\%ARGS, &>
76 </td></tr></table>
77 % ## Форма поиска. Работает при включенном фильтре класса
78 % ## и описанной для класса функции search_fields
79 % ########################################################
80 % if ( $filter{class} ) {
81 % my $document = $filter{class}->new ($keeper);
82 % my @fields = $document->search_fields;
83 % if ( @fields ) {
84 % my @props = $document->required_properties;
85 <form action="sections.html">
86 <table border="0" cellspacing="0" cellpadding="2" width="100%" style="margin:4px 0; border:1px solid gray;">
87 <tr bgcolor="#e0e0e0"><th colspan="4">Поиск по полю:&nbsp;&nbsp;[<a href="?id=<% $id %>" style="font-weight:normal;">сброс фильтра</a>]</th></tr><tr>
88 <td width="1%" nowrap style="padding:2px 0 2px 4px;"><select name="search_by">
89 % foreach my $field ( @fields ) {
90 % my ($prop) = grep { $_->{'attr'} eq $field } @props;
91 % my $selected = $field eq $search_by ? ' selected' : '';
92 <option value="<% $field %>"<% $selected %>><% ref $prop ? $prop->{'shortname'} || $prop->{'rusname'} : $field %>
93 % }
94 </td><td width="0">:</td>
95 <td width="98%"><input type="text" name="search" value="<% $search %>" style="width:100%"></td>
96 <td width="1%" style="padding:2px 4px 2px 0;"><input type="submit" value=" &raquo; " style="border:1px solid gray;"></td>
97 </tr></table>
98 % if ( $id ) {
99 <input type="hidden" name="id" value="<% $id %>">
100 % }
101 % if ( $class ) {
102 <input type="hidden" name="class" value="<% $class %>">
103 % }
104 % if ( $use_section ) {
105 <input type="hidden" name="use_section" value="<% $use_section %>">
106 % }
107 </form>
108 % }
109 % }
110
111 <div style="height:5px"><spacer type="block" height="5"></div>
112 <& /inc/pages_.msn, p=>$p, n=>$n, total=>$total, href=>'sections.html', params=>\%ARGS, &>
113 </div>
114
115 <& /contenido/components/section_browse.msn, documents => \@documents, columns => \@columns, section => $owner, filter => \%filter_params, %ARGS &>
116
117 <div style="font-size:75%; font-family:Arial;">
118 <& /inc/pages_.msn, p=>$p, n=>$n, total=>$total, href=>'sections.html', params=>\%ARGS, &>
119 <div style="height:5px"><spacer type="block" height="5"></div>
120 </div>
121
122 % } else {
123 <h4 align="center"><i>---- Нет документов -----</i></h4>
124 % }
125 %
126 % if ($section_access == 2) {
127 <& "/contenido/components/new_objects_form.msn", proto => 'documents',
128 sect_id => $owner->id,
129 default => ($owner->default_document_class ? $owner->default_document_class : undef) &>
130 % }
131
132 </fieldset>
133 </td>
134 </tr>
135 </table>
136
137 % }
138
139 </body>
140 </html>
141 <%args>
142
143 $id => undef
144 $p => 1
145 $class => undef
146 $use_section => undef
147 $alpha => undef
148 $alpha_search => undef
149 $search_by => undef
150 $search => undef
151 $update => undef
152 $delete => undef
153
154 </%args>
155 <%init>
156
157 $id = 0 if $id =~ /\D/;
158 my $owner;
159
160 # Операции...
161 if ($id && ($id > 0))
162 {
163 $owner = $keeper->get_section_by_id($id);
164 }
165 if (! ref($owner))
166 {
167 return undef;
168 }
169
170 my %filter_params;
171 $filter_params{use_section} = $use_section if $use_section;
172 $filter_params{class} = $class if $class;
173 $filter_params{alpha} = $alpha if $alpha;
174 $filter_params{alpha_search} = $alpha_search if $alpha_search;
175 $filter_params{search_by} = $search_by if $search_by;
176 $filter_params{search} = $search if $search;
177 $filter_params{p} = $p if $p > 1;
178 $filter_params{s} = $id if $id;
179
180 16 ahitrov@rambler.ru # Фильтры работают в любом случае...
181 8 ahitrov@rambler.ru my $filter = $m->comp('/contenido/components/context.msn', name => 'filter');
182 my $profile = $m->comp('/contenido/components/context.msn', name => 'profile');
183
184 unless (defined $request->{section_accesses}->{$id})
185 {
186 $request->{section_accesses}->{$id} = $user->get_section_access($id);
187 }
188 my $section_access = $request->{section_accesses}->{$id};
189
190 my (@documents, $total);
191
192 my $s = $owner->id;
193 my $sorted = $owner->_sorted();
194 $s .= ",$filter" if ($filter > 0);
195
196 if ($update) {
197 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
198 my %updated;
199 while ( my ($field, $value) = each %ARGS ) {
200 if ( $field =~ /^update_(\d+)_(\w+)$/ ) {
201 my $oid = $1;
202 my $attr = $2;
203 $updated{$oid}{$attr} = $value;
204 }
205 }
206 my %classes = map { $_->{class} => 1 } values %updated;
207 foreach my $update_class ( keys %classes ) {
208 my @ids;
209 while ( my ($oid, $attr) = each %updated) {
210 push @ids, $oid if $attr->{class} eq $update_class;
211 }
212 my @objects = $keeper->get_documents (
213 id => \@ids,
214 class => $update_class
215 ) if @ids;
216 foreach my $object ( @objects ) {
217 my $document_access = $user->section_accesses($user, $object->section);
218 next unless $document_access == 2;
219 my $fields = $updated{$object->id};
220 my @props = grep { exists $_->{inline} && $_->{inline} } $object->structure;
221 if ( ref $fields eq 'HASH' ) {
222 foreach my $prop ( @props ) {
223 my $attr = $prop->{attr};
224 my $value = ref $fields && exists $fields->{$attr} ? $fields->{$attr} : undef;
225 if ( $prop->{db_type} eq 'float' ) {
226 for ( $value ) {
227 s/\,/\./;
228 s/^\s+//;
229 s/\s+$//;
230 }
231 }
232 if ( $prop->{type} eq 'checkbox' ) {
233 $value = $value ? 1 : undef;
234 }
235
236 $object->$attr($value);
237 }
238 $object->store;
239 }
240 }
241 }
242 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
243 }
244 if ( $delete ) {
245 my $return_params = join ('&', map { $_.'='.$filter_params{$_} } grep { $_ ne 's' } keys %filter_params );
246 my %deleted;
247 while ( my ($field, $value) = each %ARGS ) {
248 if ( $field =~ /^delete_(\d+)_(\w+)$/ ) {
249 my $oid = $1;
250 my $attr = $2;
251 $deleted{$oid}{$attr} = $value;
252 }
253 }
254 my %classes = map { $_->{class} => 1 } values %deleted;
255 foreach my $delete_class ( keys %classes ) {
256 my @ids;
257 while ( my ($oid, $attr) = each %deleted) {
258 push @ids, $oid if exists $attr->{id} && $attr->{id} && ($attr->{class} eq $delete_class);
259 }
260 my @objects = $keeper->get_documents (
261 id => \@ids,
262 class => $delete_class
263 ) if @ids;
264 foreach my $object ( @objects ) {
265 my $document_access = $user->section_accesses($user, $object->section);
266 next unless $document_access == 2;
267 $object->delete;
268 }
269 }
270 $m->redirect("sections.html?id=".$id.($return_params ? '&'.$return_params : ''));
271 }
272
273 my %filter=();
274 my %order = (not $class and $owner->order_by) ? (order_by => $owner->order_by) : (order => ['date','direct']);
275 if (defined $alpha and $alpha ne '') {
276 $filter{ilike}=1;
277 $filter{ $alpha_search || 'name' }="$alpha%";
278 $order{order}=['name','reverse'];
279 delete $order{order_by};
280 }
281 if ( $class ) {
282 $filter{class} = $class;
283 } elsif ( $owner->default_document_class ) {
284 $filter{class} = $owner->default_document_class;
285 } elsif ( $owner->default_table_class ) {
286 $filter{table} = $owner->default_table_class;
287 }
288 $filter{s}=$s unless ($class && !$use_section);
289 if ( $search_by && defined $search ) {
290 my $doc_class = $class || $owner->default_document_class;
291 if ( $doc_class ) {
292 my @props = $doc_class->new( $keeper )->structure();
293 my ($prop) = grep { $_->{attr} eq $search_by } @props if @props;
294 16 ahitrov@rambler.ru if ( ref $prop && ($prop->{type} eq 'integer' || $prop->{type} eq 'checkbox') ) {
295 8 ahitrov@rambler.ru $filter{$search_by} = int($search);
296 } else {
297 $filter{$search_by}='%'.$search.'%';
298 $filter{ilike} = 1;
299 }
300 } else {
301 $filter{$search_by}='%'.$search.'%';
302 $filter{ilike} = 1;
303 }
304 }
305
306 # Дополнительные фильтры раздела
307 if ($owner->filters) {
308 no strict 'vars';
309 my $filters = eval($owner->filters);
310 if ($@) {
311 warn "Bad filter: " . $owner->filters . " in section " . $owner->id;
312 } elsif (ref $filters eq 'HASH') {
313 map { $filter{$_} = $filters->{$_} } keys %$filters;
314 }
315 }
316
317 $total = $keeper->get_documents(%filter, count=>1);
318
319 my $n = 40;
320 my $first = $n * ($p - 1);
321 ($first,$p)=(0,0) if ($first>$total);
322
323 if ($class && !$use_section) {
324 @documents = $keeper->get_documents(%filter, %order, limit=>$n, offset=>$first);
325 } elsif ($sorted) {
326 @documents = $keeper->get_sorted_documents(%filter, limit=>$n, offset=>$first);
327 } else {
328 @documents = $keeper->get_documents(%filter, %order, limit=>$n, offset=>$first);
329 }
330
331 # набор колонок таблицы документов...
332 my @columns = $sorted ? ({attr => '_sort_', name => 'N'}) : ();
333
334 # пытаемся найти колонки, которые документ сам пожелал показать (required_properties -> column)...
335 if ($filter{class} or @documents and $documents[0]) {
336 push @columns,
337 sort {$a->{column} <=> $b->{column}}
338 grep {$_->{column}} ($filter{class} ? $filter{class}->new($keeper)->structure : $documents[0]->structure);
339 }
340
341 # стандартная жопка таблицы...
342 @columns = (@columns,
343 {attr => '_act_', rusname => 'Действия'},
344 );
345 </%init>

Небольшая справка по веткам

cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.

koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.

utf8 – актуальная ветка, заточенная под UTF-8.

Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.