Revision 609
Date:
2016/11/02 14:43:55
Author:
ahitrov
Revision Log:
Manual document sorting using ajax.
Inline editing type can differ from form editing type.
Files:
Legend:
Added
Removed
Modified
utf8/core/comps/contenido/ajax/document_move.html
1
<% $json %>
2
<%once>
3
4
use JSON::XS;
5
6
</%once>
7
<%args>
8
9
$id => undef
10
$aid => undef
11
$s => undef
12
$move => undef
13
14
</%args>
15
<%init>
16
17
my %result;
18
19
if ( $id && $id =~ /^\d+$/ && $s && $s =~ /^\d+$/ && $move && $move =~ /^(up|down|first|last|before|after)$/ && (!$aid || $aid && $aid =~ /^\d+$/) ) {
20
my $section = $keeper->get_section_by_id( $s );
21
if ( ref $section ) {
22
if ( $section->_sorted ) {
23
if ( $section->dmove( $id, $move, $aid ) ) {
24
my $position = $section->_get_document_pos( $id );
25
warn Dumper( $position );
26
if ( ref $position && exists $position->{index} ) {
27
if ( exists $position->{before} ) {
28
$result{before} = $position->{before};
29
$result{success} = 1;
30
}
31
if ( exists $position->{after} ) {
32
$result{after} = $position->{after};
33
$result{success} = 1;
34
}
35
if ( exists $position->{first} ) {
36
$result{first} = 1;
37
$result{success} = 1;
38
}
39
if ( exists $position->{last} ) {
40
$result{last} = 1;
41
$result{success} = 1;
42
}
43
unless ( exists $result{success} ) {
44
$result{error} = Encode::decode('utf-8', 'Ошибка индексации. Для разбора полетов обратитесь к разработчикам');
45
}
46
} else {
47
$result{error} = Encode::decode('utf-8', 'Ошибка индексации. Для разбора полетов обратитесь к разработчикам');
48
}
49
} else {
50
$result{error} = Encode::decode('utf-8', 'Ошибка перемещения. Для разбора полетов обратитесь к разработчикам');
51
}
52
} else {
53
$result{error} = Encode::decode('utf-8', 'В данной секции отключен режим ручной сортировки');
54
}
55
} else {
56
$result{error} = Encode::decode('utf-8', 'Секция не найдена');
57
}
58
} else {
59
$result{error} = Encode::decode('utf-8', 'Переданы неверные параметры');
60
}
61
62
my $json = encode_json \%result;
63
64
</%init>
utf8/core/comps/contenido/components/section_browse.msn
42
42
});
43
43
% }
44
44
45
46
45
function mydump(arr,level) {
47
46
var dumped_text = "";
48
47
if(!level) level = 0;
…
…
67
66
return dumped_text;
68
67
}
69
68
70
69
$(document).ready(function(){
70
$('.move-up').on('click', function( ev ){
71
ev.preventDefault();
72
var $nID = $(this).data('id');
73
$.ajax({
74
'url' : '/contenido/ajax/document_move.html',
75
'data' : { 's' : <% ref $section ? $section->id : 0 %>, 'id' : $nID, 'move' : 'up' },
76
'dataType' : 'json',
77
'success' : function( data ){
78
if ( data.error ) {
79
alert( data.error );
80
} else if ( data.before ) {
81
var $nBefore = data.before;
82
$('#row-' + $nID).insertBefore('#row-' + $nBefore);
83
}
84
}
85
});
86
});
87
$('.move-down').on('click', function( ev ){
88
ev.preventDefault();
89
var $nID = $(this).data('id');
90
$.ajax({
91
'url' : '/contenido/ajax/document_move.html',
92
'data' : { 's' : <% ref $section ? $section->id : 0 %>, 'id' : $nID, 'move' : 'up' },
93
'dataType' : 'json',
94
'success' : function( data ){
95
if ( data.error ) {
96
alert( data.error );
97
} else if ( data.after ) {
98
var $nAfter = data.after;
99
$('#row-' + $nID).insertAfter('#row-' + $nAfter);
100
}
101
}
102
});
103
});
104
});
71
105
//-->
72
106
</script>
73
107
<form name="section_browse" action="sections.html" method="POST">
…
…
151
185
my $params_unsection = ref $filter eq 'HASH' ? join ('&', map { $_.'='.$filter->{$_} } grep { $_ ne 's' } keys %$filter ) : '';
152
186
153
187
my %lookup_elements;
154
my @inline_pickups = grep { exists $_->{inline} && ($_->{type} eq 'pickup' || $_->{type} eq 'autocomplete') } @$columns;
188
my @inline_pickups = grep {
189
my $type = exists $_->{inline_type} ? $_->{inline_type} : $_->{type};
190
exists $_->{inline} && ($type eq 'pickup' || $type eq 'autocomplete')
191
} @$columns;
155
192
156
193
map {
157
194
$_->{document_access} = $user->section_accesses($user, $_->section);
utf8/core/comps/contenido/components/section_browse_row.msn
1
<tr valign="top">
1
<tr valign="top" id="row-<% $document->id %>">
2
2
<td nowrap>\
3
3
% if ($document_access == 2) {
4
4
<input type="checkbox" class="common-check" name="<% 'delete_'.$document->id.'_id' %>">
…
…
10
10
% for my $col (@$columns) {
11
11
% if ($col->{attr} eq '_sort_') {
12
12
%
13
<td width="20px"><% $document->{sorder} %> <a
13
<td width="20px"><% $document->{sorder} %> <a class="move-up" data-id="<% $document->id %>"
14
14
href="document_move.html?id=<% $document->{id} %>&move=up&s=<% $id %><% $params_unsection ? '&'.$params_unsection : '' %>"><img
15
src="/contenido/i/ico-up-9x10.gif" border=0 alt="Переместить документ на шаг вверх"></a> <a
15
src="/contenido/i/ico-up-9x10.gif" border=0 alt="Переместить документ на шаг вверх"></a> <a class="move-down" data-id="<% $document->id %>"
16
16
href="document_move.html?id=<% $document->{id} %>&move=down&s=<% $id %><% $params_unsection ? '&'.$params_unsection : '' %>"><img
17
17
src="/contenido/i/ico-down-9x10.gif" border=0 alt="Переместить документ на шаг вниз"></a>\
18
18
%
…
…
56
56
%
57
57
% } elsif ( exists $col->{inline} && $col->{inline} ) {
58
58
% my $attr = $col->{attr};
59
% if ( $col->{type} =~ /^(string|integer|float)$/ && $col->{inline} ) {
59
% my $type = exists $col->{inline_type} ? $col->{inline_type} : $col->{type};
60
% if ( $type =~ /^(string|integer|float)$/ && $col->{inline} ) {
60
61
% my $style = $col->{inline_style} ? $col->{inline_style} : ($col->{type} =~ /^(integer|float)$/ ? 'text-align:right; ' : '' );
61
62
% $style .= $col->{inline_width} ? ' width:'.$col->{inline_width}.'px; ' : ' width:65px; ';
62
63
<td><input type="text" name="<% 'update_'.$document->id.'_'.$attr %>" value="<% $document->$attr |h %>" style="<% $style %>">
63
% } elsif ($col->{type} eq 'checkbox') {
64
% } elsif ($type eq 'checkbox') {
64
65
% my $checked = $document->$attr ? ' checked' : '';
65
66
<td align="center"><input type="checkbox" class="<% $attr %>-check" name="<% 'update_'.$document->id.'_'.$attr %>"<% $checked %>>
66
% } elsif ($col->{type} eq 'text') {
67
% } elsif ($type eq 'text') {
67
68
% my $style = $col->{inline_style} ? $col->{inline_style} : '';
68
69
% $style .= $col->{inline_width} ? ' width:'.$col->{inline_width}.'px; ' : ' width:100px; ';
69
70
% $style .= $col->{inline_height} ? ' width:'.$col->{inline_height}.'px; ' : ' height:70px; ';
…
…
73
74
% s/>/>/sgi;
74
75
% }
75
76
<td><textarea name="<% 'update_'.$document->id.'_'.$attr %>" style="<% $style %>"><% $value %></textarea>
76
% } elsif ($col->{type} eq 'select') {
77
% } elsif ($type eq 'select') {
77
78
% my $options = {};
78
79
% if ($toopi && (ref($toopi) eq 'HASH') && (exists($toopi->{$document->class}))) {
79
80
% %{ $options } = %{ $toopi->{$document->class} };
…
…
87
88
% }
88
89
% }
89
90
</select>
90
% } elsif ($col->{type} eq 'status') {
91
% } elsif ($type eq 'status') {
91
92
% my $cases = $col->{cases};
92
93
% if ( ref $cases eq 'ARRAY' ) {
93
94
<td><select name="<% 'update_'.$document->id.'_'.$attr %>" style="<% $col->{inline_width} ? 'width:'.$col->{inline_width}.'px;' : '' %> <% $col->{inline_style} || '' %>" autocomplete="off">
…
…
97
98
% }
98
99
</select>
99
100
% }
100
% } elsif ($col->{type} eq 'pickup' || $col->{type} eq 'autocomplete') {
101
% } elsif ($type eq 'pickup' || $type eq 'autocomplete') {
101
102
% my %opts = %{ $col->{lookup_opts} };
102
103
% my $doc;
103
104
% if ( $document->$attr ) {
…
…
108
109
title="<% defined $document->$attr ? 'Значение: '.$document->$attr : '' %>"
109
110
rel="<% 'update_'.$document->id.'_'.$attr %>" style="<% $col->{inline_width} ? 'width:'.$col->{inline_width}.'px;' : '' %> <% $col->{inline_style} || '' %>"
110
111
old-value="<% (ref $doc ? $doc->name : '') |h %>" onfocus="" onblur="">
111
% } elsif ($col->{type} eq 'lookup') {
112
% } elsif ($type eq 'lookup') {
112
113
% my %opts = %{ $col->{lookup_opts} };
113
114
% delete $opts{search_by} if exists $opts{search_by};
114
115
% my $docs;
…
…
139
140
%
140
141
<td><% $document->class_name %> <font color="#999999">(<% $document->class %>)</font>\
141
142
%
142
% } elsif ($col->{type} eq 'datetime') {
143
% } elsif ($type eq 'datetime') {
143
144
%
144
145
<td nowrap><& "/contenido/components/show_dtime.msn", dtime=>$document->{$col->{attr}} &>\
145
146
%
…
…
176
177
%
177
178
% } else {
178
179
% my $attr = $col->{attr};
179
% if ($col->{type} eq 'date') {
180
% if ($type eq 'date') {
180
181
% my $date=$document->{$col->{attr}};
181
182
% $date=~/(\d{4}-\d{2}-\d{2})/;
182
183
<td nowrap align="right"><% $1 || ' ' %>\
183
% } elsif ($col->{type} eq 'datetime') {
184
% } elsif ($type eq 'datetime') {
184
185
<td nowrap align="right"><% $document->{$col->{attr}} || ' ' %>\
185
% } elsif ($col->{type} eq 'integer') {
186
% } elsif ($type eq 'integer') {
186
187
<td align="right"><% $document->{$col->{attr}} %> \
187
% } elsif ($col->{type} eq 'lookup' || $col->{type} eq 'pickup' || $col->{type} eq 'autocomplete') {
188
% } elsif ($type eq 'lookup' || $type eq 'pickup' || $type eq 'autocomplete') {
188
189
<td align="left">\
189
190
% my $id = $document->{$col->{attr}};
190
191
% if ($id) {
…
…
197
198
% } else {
198
199
<span class="hiddensect">NULL</span>\
199
200
% }
200
% } elsif ($col->{type} eq 'checkbox') {
201
% } elsif ($type eq 'checkbox') {
201
202
<td align="center"><% $document->$attr ? '<img src="/contenido/i/checked-16x16.png" width="16" height="16">' : ' ' %>\
202
% } elsif ($col->{type} eq 'status') {
203
% } elsif ($type eq 'status') {
203
204
% my $status_map = ref $col->{cases} eq 'ARRAY' ? $col->{cases} : $keeper->default_status();
204
205
% my ($doc_status) = grep { $_->[0] eq $document->{$col->{attr}} } @$status_map;
205
206
% $doc_status ||= [$document->{$col->{attr}}, 'Неизвестный'];
utf8/core/lib/Contenido/Section.pm
200
200
201
201
sub _get_document_order {
202
202
my ($self) = shift;
203
return unless $self->_sorted;
203
204
204
205
my @order = $self->_sorted_order ? split( /,/, $self->_sorted_order ) : ();
205
206
…
…
244
245
}
245
246
246
247
248
sub _get_document_pos {
249
my ($self) = shift;
250
my ($doc_id) = shift;
251
return unless $doc_id && $doc_id =~ /^\d+$/;
252
return unless $self->_sorted;
253
254
my @order = $self->_sorted_order ? split( /,/, $self->_sorted_order ) : ();
255
my %pos;
256
for ( my $i = 0; $i < scalar @order; $i++ ) {
257
if ( $order[$i] == $doc_id ) {
258
$pos{index} = $i;
259
if ( $i > 0 ) {
260
$pos{after} = $order[$i-1];
261
}
262
if ( $i < $#order ) {
263
$pos{before} = $order[$i+1];
264
}
265
if ( $i == $#order ) {
266
$pos{last} = 1;
267
} elsif ( $i == 0 ) {
268
$pos{first} = 1;
269
}
270
last;
271
}
272
}
273
return (exists $pos{index} ? \%pos : undef);
274
}
275
276
247
277
# ----------------------------------------------------------------------------
248
278
# Метод для перемещение секции вверх/вниз по рубрикатору (изменение
249
279
# sorder)...
Небольшая справка по веткам
cnddist – контейнер, в котором хранятся все дистрибутивы всех библиотек и программных пакетов, которые использовались при построении различных версий Contenido. Если какой-то библиотеки в данном хранилище нет, инсталлятор сделает попытку "подтянуть" ее с веба (например, с CPAN). Если библиотека слишком старая, есть очень большая вероятность, что ее там уже нет. Поэтому мы храним весь хлам от всех сборок. Если какой-то дистрибутив вдруг отсутствует в cnddist - напишите нам, мы положим его туда.
koi8 – отмирающая ветка, чей код, выдача и все внутренние библиотеки заточены на кодировку KOI8-R. Вносятся только те дополнения, которые касаются внешнего вида и функционала админки, баги ядра, обязательные обновления портов и мелочи, которые легко скопипастить. В дальнейшем планируется полная остановка поддержки по данной ветке.
utf8 – актуальная ветка, заточенная под UTF-8.
Внутри каждой ветки: core – исходники ядра; install – скрипт установки инсталляции; plugins – плагины; samples – "готовые к употреблению" проекты, которые можно поставить, запустить и посмотреть, как они работают.