Revision 630
- Date:
- 2016/12/09 15:54:41
- Files:
-
- /utf8/plugins/tag/comps/contenido/tag/ajax/tag_edit_form.html (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/ajax/tag_store.html (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/components/block_tag_list.msn (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/components/form_tag_edit.msn (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/components/inputs
- /utf8/plugins/tag/comps/contenido/tag/components/inputs/tag_tree.msn (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/components/outputs
- /utf8/plugins/tag/comps/contenido/tag/components/outputs/tag_tree.msn (Diff) (Checkout)
- /utf8/plugins/tag/comps/contenido/tag/i/css/styles.css (Diff) (Checkout)
- /utf8/plugins/tag/lib/tag/Cloud.pm (Diff) (Checkout)
- /utf8/plugins/tag/lib/tag/Keeper.pm (Diff) (Checkout)
- /utf8/plugins/tag/lib/tag/Tag.pm (Diff) (Checkout)
- /utf8/plugins/tag/sql/TOAST/tags-update.630.sql (Diff) (Checkout)
- /utf8/plugins/tag/sql/TOAST/tags.sql (Diff) (Checkout)
Legend:
- Added
- Removed
- Modified
-
utf8/plugins/tag/comps/contenido/tag/ajax/tag_edit_form.html
1 1 % if ( ref $tag ) { 2 % if ( $tag->id ) { 2 3 <fieldset> 3 4 <legend><% $tag->id ? 'Редактировать' : 'Создать' %> тег</legend> 4 5 <& /contenido/tag/components/form_tag_edit.msn, object => $tag &> 5 6 </fieldset> 7 % } else { 8 <fieldset> 9 <legend><% $tag->id ? 'Редактировать' : 'Создать' %> тег</legend> 10 <& /contenido/tag/components/form_tag_edit.msn, object => $tag &> 11 </fieldset> 12 % } 6 13 % } else { 7 14 <div class="error-prompt">Не найден тег с ID=<% $id |h %></div> 8 15 % } -
utf8/plugins/tag/comps/contenido/tag/ajax/tag_store.html
1 <% $json %> 2 <%once> 3 4 use JSON::XS; 5 6 </%once> 7 <%args> 8 9 $id => undef 10 11 </%args> 12 <%init> 13 14 my %result; 15 16 warn Dumper \%ARGS; 17 if ( !$id || $id && $id =~ /^\d+$/ && $id > 0 ) { 18 my $tag; 19 if ( $id ) { 20 $tag = $keeper->get_document_by_id( $id, class => 'tag::Tag' ); 21 } else { 22 $tag = tag::Tag->new( $keeper ); 23 } 24 if ( ref $tag ) { 25 my $dup = $keeper->get_documents( 26 $tag->id ? ( excludes => $tag->id ) : (), 27 name => $ARGS{name}, 28 ilike => 1, 29 class => 'tag::Tag', 30 count => 1, 31 ); 32 if ( $dup ) { 33 $result{error} = Encode::decode('utf-8', 'Найден дубликат тега с таким названием'); 34 } else { 35 $tag->name( $ARGS{name} ); 36 $tag->alias( $ARGS{alias} ); 37 $tag->status( $ARGS{status} ); 38 $m->comp('/contenido/tag/components/outputs/tag_tree.msn', SETS => \%ARGS, object => $tag); 39 if ( $tag->store ) { 40 $result{success} = 1; 41 $result{id} = $tag->id; 42 } else { 43 $result{error} = Encode::decode('utf-8', 'Системная ошибка сохранения. Смотри логи'); 44 } 45 } 46 } else { 47 $result{error} = Encode::decode('utf-8', 'Тег с данным идентификатором не найден'); 48 } 49 } else { 50 $result{error} = Encode::decode('utf-8', 'Неверно указан идентификатор'); 51 } 52 53 my $json = encode_json \%result; 54 # $r->content_type('application/json'); 55 56 </%init> -
utf8/plugins/tag/comps/contenido/tag/components/block_tag_list.msn
1 1 % if ( @$tags ) { 2 <script type="text/javascript"> 3 <!-- 4 $(document).ready(function(){ 5 $('.js-edit-tag').on('click', function( ev ){ 6 ev.preventDefault(); 7 OpenContentForm( $(this).data('id') ); 8 }); 9 10 }); 11 //--> 12 </script> 2 13 <table width="100%" border="0" cellpadding="4" cellspacing="0" class="tlistdocs"> 3 14 <tr bgcolor="#efefef"> 4 15 <th>id</th> … … 9 20 </tr> 10 21 % foreach my $tag ( @$tags ) { 11 22 <tr valign="top"> 12 <td><% $tag->id %></td> 13 <td><% $tag->name %></td> 23 <td><a href="?id=<% $tag->id %>" class="status-<% $tag->status %> js-edit-tag" data-id="<% $tag->id %>"><% $tag->id %></a></td> 24 <td><a href="?id=<% $tag->id %>" class="status-<% $tag->status %> js-edit-tag" data-id="<% $tag->id %>"><% $tag->name %></a></td> 14 25 <td><% $tag->alias %></td> 15 26 <td></td> 16 27 <td></td> -
utf8/plugins/tag/comps/contenido/tag/components/form_tag_edit.msn
1 <script type="text/javascript"> 2 <!-- 3 $(document).ready(function(){ 4 $('#tag-edit-submit').on('click', function(ev){ 5 ev.preventDefault(); 6 var oForm = document.forms['tag-edit-form']; 7 if ( oForm.elements['name'].value == '' ) { 8 $('#tag-edit-error-prompt').text('Не указано название тега').show(); 9 oForm.elements['name'].focus(); 10 return false; 11 } 12 var nId = oForm.elements['id'].value; 13 var sName = oForm.elements['name'].value; 14 var sAlias = oForm.elements['alias'].value; 15 var nStatus = oForm.elements['status'].value; 16 var nPid = oForm.elements['pid'].value; 17 $('#tag-edit-error-prompt').hide(); 18 $.ajax({ 19 'url' : '/contenido/tag/ajax/tag_store.html', 20 'data' : { 'id' : nId, 'name' : sName, 'alias' : sAlias, 'status' : nStatus, 'pid' : nPid }, 21 'type' : 'POST', 22 'dataType' : "json", 23 'success' : function( data ) { 24 if ( data.error ) { 25 $('#tag-edit-error-prompt').text(data.error).show(); 26 } 27 if ( data.success ) { 28 nTagsFormEditing = 0; 29 OpenContentForm( data.id ); 30 } 31 }, 32 'error' : function(XMLHttpRequest, textStatus) { 33 alert(textStatus); 34 } 35 }); 36 }); 37 }); 38 //--> 39 </script> 1 40 <form enctype="multipart/form-data" method="POST" name="tag-edit-form"> 2 41 <input type="hidden" name="id" value="<% $object->id %>"> 42 % if ( $object->id ) { 43 <div class="form-field"> 44 <div class="prompt">ID: <span class="value"><% $object->id %></span></div> 45 </div> 46 % } 47 % foreach my $name ( qw( name alias status ) ) { 48 % my $prop = $props{$name}; 49 % my $type = $prop->{type}; 50 % if ( $m->comp_exists( "/contenido/components/inputs/$type.msn" ) ) { 51 <div class="form-field"> 52 <div class="prompt"><% $prop->{rusname} %><span class="desc">| Attr=<% $prop->{attr} %>; Type=<% $prop->{type} %></span></div> 53 <& "/contenido/components/inputs/$type.msn", object => $object, prop => $prop, name => $name, check => $object->$name &> 54 </div> 55 % } 56 % } 57 % if ( $state->{tag}->tag_structure eq 'tree' ) { 58 % my $name = 'pid'; 59 % my $prop = $props{$name}; 60 <div class="form-field"> 61 <div class="prompt"><% $prop->{rusname} %><span class="desc">| Attr=<% $prop->{attr} %></span></div> 62 <& /contenido/tag/components/inputs/tag_tree.msn, object => $object, name => 'pid', prop => $prop &> 63 % } 64 </div> 65 <div id="tag-edit-error-prompt" class="error-prompt" style="display:none;"></div> 66 <div class="form-submit"> 67 <input id="tag-edit-submit" type="button" class="input_btn" value="Сохранить"> 68 </div> 3 69 </form> 4 70 <%args> 5 71 … … 10 76 11 77 return unless ref $object; 12 78 my @props = $object->structure; 79 my %props = map { $_->{attr} => $_ } @props; 13 80 14 81 </%init> -
utf8/plugins/tag/comps/contenido/tag/components/inputs/tag_tree.msn
1 <select name="<% $name %>" style="width:37%" autocomplete="off"> 2 <option value="-1" style="color:red">Тег вне иерархии</option> 3 <option value="0" style="color:blue"<% $check == 0 && $object->level > 0 ? ' selected' : '' %>>Верхний уровень</option> 4 % if ( exists $tree->{root} && scalar @{$tree->{root}} ) { 5 % foreach my $tag ( @{$tree->{root}} ) { 6 % my $selected = $object->pid && $tag->id == $object->pid ? ' selected' : ''; 7 <option value="<% $tag->id %>" style="padding-left:20px;<% $selected ? 'font-weight:bold;' : '' %>"<% $selected %>><% $tag->name.($tag->alias ? ' ('.$tag->alias.')' : '') %></option> 8 % } 9 % } 10 </select> 11 <%args> 12 13 $object => undef 14 $name => 'pid' 15 $prop => undef 16 17 </%args> 18 <%init> 19 20 return unless ref $object; 21 ($prop) = grep { $_->{attr} eq $name } $object->structure unless ref $prop; 22 my $tree = $keeper->{tag}->get_tree( level => 3 ); 23 my $check = $object->$name; 24 25 </%init> -
utf8/plugins/tag/comps/contenido/tag/components/outputs/tag_tree.msn
1 <%args> 2 3 $SETS => {} 4 $object => undef 5 6 </%args> 7 <%init> 8 9 return unless ref $object; 10 return unless exists $SETS->{pid} && defined $SETS->{pid}; 11 12 my $pid = $SETS->{pid}; 13 if ( $pid == 0 ) { 14 $object->pid( 0 ); 15 $object->level( 1 ); 16 } elsif ( $pid < 0 ) { 17 $object->pid( 0 ); 18 $object->level( 0 ); 19 } elsif ( $pid > 0 ) { 20 my $tag = $keeper->get_document_by_id( $pid, class => 'tag::Tag' ); 21 if ( ref $tag ) { 22 $object->pid( $pid ); 23 $object->level( $tag->level + 1 ); 24 } else { 25 $object->pid( 0 ); 26 $object->level( 0 ); 27 } 28 } 29 30 </%init> -
utf8/plugins/tag/comps/contenido/tag/i/css/styles.css
2 2 .tag-plugin .block-add-link a { text-decoration:none; } 3 3 .tag-plugin .block-add-link a:hover { text-decoration:underline; } 4 4 5 .tag-plugin a.status-0 { color:gray; } 6 .tag-plugin a.status-1 { color:#0000ee; } 7 .tag-plugin a.status-3 { color:red; } 8 .tag-plugin .error-prompt { border:1px solid red; padding:10px; color:red; font-size:90%; } 5 9 6 .tag-plugin .error-prompt { border:1px solid red; padding:10px; color:red; } -
utf8/plugins/tag/lib/tag/Cloud.pm
72 72 } 73 73 } 74 74 } else { 75 warn "Tag Cloud update error: cloud_element_id=".$self->id.", no source or destination available\n"; 75 warn "Tag Cloud update error: cloud_element_id=".$self->id.", no source (".$self->source_class.", ".$self->source_id.") or destination (".$self->dest_class.", ".$self->dest_id.") available\n"; 76 76 } 77 return 1; 77 78 } 78 79 79 80 sub post_delete … … 81 82 my $self = shift; 82 83 my $object = $keeper->get_document_by_id($self->dest_id, class => $self->dest_class ) if $self->dest_id && $self->dest_class; 83 84 my $tag = $self->keeper->get_document_by_id($self->source_id, class => $self->source_class ) if $self->source_id && $self->source_class; 84 if ( ref $object && ref $tag ) { 85 my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure; 86 my $class = $object->class; 87 my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0; 88 if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) { 89 my $name = $prop->{attr}; 90 my $struct; 91 if ( ref $object->$name ) { 92 $struct = $object->$name; 93 } elsif ( $object->$name ) { 94 $struct = JSON::XS->new->utf8->decode( $object->$name ); 95 } 96 if ( ref $struct eq 'ARRAY' && @$struct && (grep { $_->{id} == $tag->id } @$struct) ) { 97 @$struct = grep { $_->{id} != $tag->id } @$struct; 98 unless ( $is_extra ) { 99 $struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct )); 85 if ( ref $object || ref $tag ) { 86 if ( ref $object ) { 87 my ($prop) = grep { $_->{type} eq 'tagset' } $object->structure; 88 my $class = $object->class; 89 my $is_extra = grep { ref $_ && $_->{attr} eq $name } $class->extra_properties ? 1 : 0; 90 if ( ref $prop && !(exists $prop->{virtual} && $prop->{virtual}) ) { 91 my $name = $prop->{attr}; 92 my $struct; 93 if ( ref $object->$name ) { 94 $struct = $object->$name; 95 } elsif ( $object->$name ) { 96 $struct = JSON::XS->new->utf8->decode( $object->$name ); 100 97 } 101 $object->$name( $struct ); 102 $object->store; 98 if ( ref $struct eq 'ARRAY' && @$struct && (grep { $_->{id} == $tag->id } @$struct) ) { 99 @$struct = grep { $_->{id} != $tag->id } @$struct; 100 unless ( $is_extra ) { 101 $struct = Encode::encode('utf-8', JSON::XS->new->encode( $struct )); 102 } 103 $object->$name( $struct ); 104 $object->store; 105 } 103 106 } 104 107 } 105 } else { 106 warn "Tag Cloud delete error: cloud_element_id=".$self->id.", no source or destination available\n"; 107 108 } 109 if ( !ref $object || !ref $tag ) { 110 my $err = ''; 111 $err .= ", no tag (".$self->source_class.", ".$self->source_id.")" unless ref $tag; 112 $err .= ", no object (".$self->dest_class.", ".$self->dest_id.")" unless ref $object; 113 warn "Tag Cloud delete warning: cloud_element_id=".$self->id.$err." available\n"; 114 } 115 return 1; 108 116 } 109 117 110 118 1; -
utf8/plugins/tag/lib/tag/Keeper.pm
20 20 21 21 my $tree; 22 22 my $cache_key = 'plugin_tag_tree_level_'.join('_', @$level); 23 if ( $cache && $keeper->MEMD ) { 24 $tree = $keeper->MEMD->get( $key ); 23 if ( $cache > 0 && $keeper->MEMD ) { 24 $tree = $keeper->MEMD->get( $cache_key ); 25 25 } 26 26 unless ( defined $tree ) { 27 27 $tree = { hash => {}, root => [] }; … … 32 32 order_by => 'level, pid, id', 33 33 return_mode => 'array_ref', 34 34 ); 35 foreach my $tag ( @$tree ) { 35 foreach my $tag ( @$tags ) { 36 36 $tag->{keeper} = undef; 37 $hash->{$tag->id} = $tag; 37 $tree->{hash}{$tag->id} = $tag; 38 38 if ( $tag->pid ) { 39 39 push @{$tree->{$tag->pid}}, $tag; 40 40 if ( exists $tree->{hash}{$tag->pid} ) { … … 44 44 push @{$tree->{root}}, $tag; 45 45 } 46 46 if ( $cache && $keeper->MEMD ) { 47 $keeper->MEMD->set( $key, $tree, 3600 ); 47 $keeper->MEMD->set( $cache_key, $tree, 3600 ); 48 48 } 49 49 } 50 50 } -
utf8/plugins/tag/lib/tag/Tag.pm
7 7 { 8 8 return ( 9 9 { 'attr' => 'name', 'rusname' => 'Название тега', shortname => 'Тег' }, 10 { 'attr' => 'status', 11 cases => [ 12 [0, 'Скрытый'], 13 [1, 'Активный'], 14 [-1, 'Удален'], 15 16 ], 17 }, 10 18 { 'attr' => 'alt_name', type => 'string', 'rusname' => 'Альтернативная форма названия', shortname => 'Словоформа' }, 11 19 ) 12 20 } -
utf8/plugins/tag/sql/TOAST/tags-update.630.sql
1 alter table tags alter column level set default 0; 2 update tags set level = 0 where level is null; 3 4 drop index tags_pid; 5 create index tags_pid on tags (pid) WHERE level > 0; -
utf8/plugins/tag/sql/TOAST/tags.sql
7 7 status smallint not null default 0, 8 8 sections integer, 9 9 pid integer default 0, 10 level integer default 1, 10 level integer default 0, 11 11 name text, 12 12 alias text, 13 13 data text 14 14 ); 15 15 create index tags_name on tags (name); 16 16 create index tags_alias on tags (alias) WHERE alias IS NOT NULL AND alias != ''; 17 create index tags_pid on tags (pid); 17 create index tags_pid on tags (pid) WHERE level > 0;