[dw-free] sort alpha by keyword on allpics/editpics page
[commit: http://hg.dwscoalition.org/dw-free/rev/a8d460b97735]
http://bugs.dwscoalition.org/show_bug.cgi?id=1433
Allow to sort icons by either upload order (current behavior/default) or by
keyword.
On your /icons page, the keyword sort results in multiple instances of the
icon showing up. Icons with no keywords (but have a nominal keyword of
"pic#1234") are sorted to the bottom of the list.
When doing /editicons, the keyword sort sorts only by the first keyword on
the list.
Patch by
allen.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=1433
Allow to sort icons by either upload order (current behavior/default) or by
keyword.
On your /icons page, the keyword sort results in multiple instances of the
icon showing up. Icons with no keywords (but have a nominal keyword of
"pic#1234") are sorted to the bottom of the list.
When doing /editicons, the keyword sort sorts only by the first keyword on
the list.
Patch by
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Files modified:
- cgi-bin/LJ/User.pm
- cgi-bin/LJ/Userpic.pm
- htdocs/allpics.bml
- htdocs/allpics.bml.text
- htdocs/editicons.bml
- htdocs/editicons.bml.text
-------------------------------------------------------------------------------- diff -r 079aa6f23dae -r a8d460b97735 cgi-bin/LJ/User.pm --- a/cgi-bin/LJ/User.pm Wed Apr 28 23:47:49 2010 -0700 +++ b/cgi-bin/LJ/User.pm Thu Apr 29 00:14:59 2010 -0700 @@ -5590,6 +5590,13 @@ sub allpics_base { return $u->journal_base . "/icons";; } +# clears the internally cached mapping of userpics to keywords for this +# User +sub clear_userpic_kw_map { + my $self = $_[0]; + + $self->{picid_kw_map} = undef; +} sub get_userpic_count { my $u = shift or return undef; @@ -5598,6 +5605,25 @@ sub get_userpic_count { return $count; } +# gets a mapping from userpic ids to keywords for this User. +sub get_userpic_kw_map { + my $self = shift; + + if ( $self->{picid_kw_map} ) { + return $self->{picid_kw_map}; + } + + my $picinfo = LJ::get_userpic_info( $self->userid, {load_comments => 0} ); + my $keywords = {}; + foreach my $keyword ( keys %{$picinfo->{kw}} ) { + my $picid = $picinfo->{kw}->{$keyword}->{picid}; + $keywords->{$picid} = [] unless $keywords->{$picid}; + push @{$keywords->{$picid}}, $keyword if ( $keyword && $picid ); + } + + $self->{picid_kw_map} = $keywords; + return $keywords; +} # <LJFUNC> # name: LJ::User::mogfs_userpic_key diff -r 079aa6f23dae -r a8d460b97735 cgi-bin/LJ/Userpic.pm --- a/cgi-bin/LJ/Userpic.pm Wed Apr 28 23:47:49 2010 -0700 +++ b/cgi-bin/LJ/Userpic.pm Thu Apr 29 00:14:59 2010 -0700 @@ -429,18 +429,9 @@ sub keywords { croak "Invalid opts passed to LJ::Userpic::keywords" if keys %opts; - my $picinfo = LJ::get_userpic_info($self->{userid}, {load_comments => 0}); + my $u = $self->owner; - # $picinfo is a hashref of userpic data - # keywords are stored in the "kw" field in the format keyword => {hash of some picture info} - - # create a hash of picids => keywords - my $keywords = {}; - foreach my $keyword (keys %{$picinfo->{kw}}) { - my $picid = $picinfo->{kw}->{$keyword}->{picid}; - $keywords->{$picid} = [] unless $keywords->{$picid}; - push @{$keywords->{$picid}}, $keyword if ($keyword && $picid); - } + my $keywords = $u->get_userpic_kw_map(); # return keywords for this picid my @pickeywords = $keywords->{$self->id} ? @{$keywords->{$self->id}} : (); @@ -921,6 +912,9 @@ sub set_keywords { undef, @data ); } + # clear the userpic-keyword map. + $u->clear_userpic_kw_map; + # Let the user know about any we didn't save # don't throw until the end or nothing will be saved! if (@kw_errors) { @@ -1036,6 +1030,65 @@ sub set_fullurl { return 1; } +# Sorts the given list of Userpics. +sub sort { + my ( $class, $userpics ) = @_; + + return () unless ( $userpics && ref $userpics ); + + my %kwhash; + my %nokwhash; + + for my $pic ( @$userpics ) { + my $pickw = $pic->keywords( raw => 1 ); + if ( $pickw ) { + $kwhash{$pickw} = $pic; + } else { + $pickw = $pic->keywords; + $nokwhash{$pickw} = $pic; + } + } + my @sortedkw = sort keys %kwhash; + my @sortednokw = sort keys %nokwhash; + + my @sortedpics; + foreach my $kw ( @sortedkw ) { + push @sortedpics, $kwhash{$kw}; + } + foreach my $kw ( @sortednokw ) { + push @sortedpics, $nokwhash{$kw}; + } + + return @sortedpics; +} + +# Organizes the given userpics by keyword. Returns an array of hashes, +# with values of keyword and userpic. +sub separate_keywords { + my ( $class, $userpics ) = @_; + + return () unless ( $userpics && ref $userpics ); + + my @userpic_array; + my @nokw_array; + foreach my $userpic ( @$userpics ) { + my @keywords = $userpic->keywords( raw => 1 ); + foreach my $keyword ( @keywords ) { + if ( $keyword ) { + push @userpic_array, { keyword => $keyword, userpic => $userpic }; + } else { + $keyword = $userpic->keywords; + push @nokw_array, { keyword => $keyword, userpic => $userpic }; + } + } + } + + @userpic_array = sort { $a->{keyword} cmp $b->{keyword} } @userpic_array; + push @userpic_array, sort { $a->{keyword} cmp $b->{keyword} } @nokw_array; + + return @userpic_array; +} + #### # error classes: diff -r 079aa6f23dae -r a8d460b97735 htdocs/allpics.bml --- a/htdocs/allpics.bml Wed Apr 28 23:47:49 2010 -0700 +++ b/htdocs/allpics.bml Thu Apr 29 00:14:59 2010 -0700 @@ -15,7 +15,6 @@ _c?> <?_code { # This page displays all of the user's userpics along with all user-contributed text -# FIXME: A lot more of this functionality should be coming from the Userpic.pm class use strict; use vars qw(%GET $title $body $head); @@ -106,41 +105,36 @@ _c?> #### show pictures - my $info = LJ::get_userpic_info( $u, { load_comments => 1, load_urls => 1, load_descriptions => 1 } ); - - my %keywords = (); - while (my ($kw, $pic) = each %{$info->{'kw'}}) { - LJ::text_out( BML::ebml( \$kw ) ); - push @{$keywords{$pic->{'picid'}}}, $kw; + my $keyword_sort = $GET{'keywordSort'}; + if ( $keyword_sort ) { + $getextra = $getextra ? $getextra . "&keywordSort=1" : "?keywordSort=1"; } - my %comments = (); - while (my ($pic, $comment) = each %{$info->{'comment'}}) { - LJ::text_out( BML::ebml( \$comment ) ); - $comments{$pic} = $comment; - } - - my %descriptions = (); - while ( my ($pic, $description) = each %{$info->{description}}) { - LJ::text_out( BML::ebml( \$description ) ); - $descriptions{$pic} = $description; - } - my $piccount = 0; - - my @allpics; - my $defaultpicid = $u ? $u->{'defaultpicid'} : undef; # allow support to view inactive userpics for debugging my $view_inactive = $GET{inactive} && $remote && ( $remote->has_priv( "supportviewscreened" ) || $remote->has_priv( "supporthelp" ) ); $view_inactive ||= $can_manage; - push @allpics, $info->{'pic'}->{$u->{'defaultpicid'}} if $defaultpicid; - push @allpics, map { $info->{'pic'}->{$_} } sort { $a <=> $b } - grep { $_ != $defaultpicid && ($info->{'pic'}->{$_}->{'state'} eq 'N' || $view_inactive) && - $info->{'pic'}->{$_}->{'state'} ne 'X' } - keys %{$info->{'pic'}}; + my @allpics = LJ::Userpic->load_user_userpics($u); + if ( @allpics ) { + if ( $keyword_sort ) { + @allpics = LJ::Userpic->separate_keywords( \@allpics ); + } else { + my @newpics; + my $default_pic; + foreach my $pic ( @allpics ) { + my $keyword = $pic->keywords; + if ( $pic->is_default ) { + $default_pic = { keyword => $keyword, userpic => $pic }; + } elsif ( $pic->state eq 'N' || ( $view_inactive && $pic->state ne 'X' ) ) { + push @newpics, { keyword => $keyword, userpic => $pic }; + } + } + @allpics = ( $default_pic, @newpics ); + } + } # pagination code @@ -166,11 +160,14 @@ _c?> @pics = @allpics; } - foreach my $pic (@pics) { + foreach my $userpic_hash ( @allpics ) { - # load the userpic object for each pic - my $userpic = LJ::Userpic->new( $u, $pic->{picid} ); + # if we have no default pic + next unless $userpic_hash; + my $userpic = $userpic_hash->{userpic}; + my $keywords = $userpic_hash->{keyword}; + if ($piccount++ == 0) { $body .= "<?h1 $ML{'.current'} h1?><?p "; if ($can_manage) { @@ -184,76 +181,84 @@ _c?> } else { $body .= BML::ml('.pics2', {'user' => LJ::ljuser($u), 'aopts' => "href='$LJ::SITEROOT/manage/subscriptions/user?journal=$u->{user}'"}); } - + + # show sort options + $body .= "<p>"; + $body .= $keyword_sort ? '<a href = "' . $u->allpics_base . '">' . "$ML{'.sort.default'}</a>" : "$ML{'.sort.default'}"; + $body .=" | "; + $body .= $keyword_sort ? "$ML{'.sort.keyword'}" : '<a href = "' . $u->allpics_base . '?keywordSort=1">' . "$ML{'.sort.keyword'}</a>"; + $body .= "</p>\n"; + $body .= " p?><table class='allpics'>"; } - + ### Keywords - my $eh_keywords = join(", ", sort { lc($a) cmp lc($b) } @{$keywords{$pic->{'picid'}}||[]}); - $eh_keywords = LJ::ehtml($eh_keywords); - + my $eh_keywords = LJ::ehtml( $keywords ); + if ($piccount % 2 == 1) { $body .= "<tr>"; } - + $body .= "<td class='pic'>"; - - my ($apre, $apost); - if ($pic->{'url'}) { - $apre = "<a href='" . LJ::ehtml($pic->{'url'}) . "'>"; + + my ( $apre, $apost ); + if ( $userpic->url ) { + $apre = "<a href='" . LJ::ehtml( $userpic->url ) . "'>"; $apost = "</a>"; } - + # for each image, we know the picid, get the html imgtag $body .= "$apre" . $userpic->imgtag . $apost . "</td><td class='desc'>"; - - if ($u->{'defaultpicid'} == $pic->{'picid'}) { + + if ( $userpic->is_default ) { $body .= "$ML{'.default'}<br />"; } - - if ($view_inactive && $pic->{'state'} eq 'I') { + + if ($view_inactive && $userpic->state eq 'I') { $body .= "<em>[$ML{'userpic.inactive'}]</em> " . LJ::help_icon('userpic_inactive') . "<br />"; } - - if ($eh_keywords) { + + if ( $eh_keywords ) { $body .= "<strong>$ML{'.keywords'}</strong> $eh_keywords<br />"; } - + # Comments - my $eh_comments = $comments{$pic->{'picid'}}; - if ($eh_comments) { + my $eh_comments = $userpic->comment; + if ( $eh_comments ) { + LJ::text_out( BML::ebml( \$eh_comments ) ); LJ::CleanHTML::clean(\$eh_comments, { 'wordlength' => 40, 'addbreaks' => 0, 'tablecheck' => 1, 'mode' => 'deny', }); - + $body .= "<strong>$ML{'.comment'}</strong> $eh_comments<br />\n"; } - # Descriptions - my $eh_descriptions = $descriptions{$pic->{picid}}; - if ($eh_descriptions) { - LJ::CleanHTML::clean(\$eh_descriptions, { + # Description + my $eh_description = $userpic->description; + if ($eh_description) { + LJ::text_out( BML::ebml( \$eh_description ) ); + LJ::CleanHTML::clean(\$eh_description, { wordlength => 40, addbreaks => 0, tablecheck => 1, mode => 'deny', }); - $body .= "<strong>$ML{'.description'}</strong> $eh_descriptions\n"; + $body .= "<strong>$ML{'.description'}</strong> $eh_description\n"; } - + $body .= "</td>"; - + if ($piccount % 2 == 1) { $body .= "<td class='blank'></td>"; } else { $body .= "</tr>\n"; } } - + if ($piccount) { if ($piccount % 2 == 1) { # finish off this row. @@ -274,7 +279,7 @@ _c?> $body = "<?h1 $ML{'.nopics.title'} h1?><?p ". BML::ml('.nopics.text.other2', {'aopts' => "href='$LJ::SITEROOT/manage/subscriptions/user?journal=$u->{user}'", username => $u->ljuser_display }). " p?>"; } } - + return; } _code?><?page diff -r 079aa6f23dae -r a8d460b97735 htdocs/allpics.bml.text --- a/htdocs/allpics.bml.text Wed Apr 28 23:47:49 2010 -0700 +++ b/htdocs/allpics.bml.text Thu Apr 29 00:14:59 2010 -0700 @@ -29,5 +29,9 @@ .pics.owner=Here are the userpics for [[user]]. +.sort.default=Upload Order + +.sort.keyword=Keyword Order + .title=User Pictures diff -r 079aa6f23dae -r a8d460b97735 htdocs/editicons.bml --- a/htdocs/editicons.bml Wed Apr 28 23:47:49 2010 -0700 +++ b/htdocs/editicons.bml Thu Apr 29 00:14:59 2010 -0700 @@ -61,6 +61,12 @@ use strict; # extra arguments for get requests my $getextra = $authas ne $remote->{'user'} ? "?authas=$authas" : ''; + + # see if we're sorting by default order or by keyword + my $keyword_sort = $GET{'keywordSort'}; + if ( $keyword_sort ) { + $getextra = $getextra ? $getextra . "&keywordSort=1" : "?keywordSort=1"; + } my $returl = LJ::CleanHTML::canonical_url($POST{'ret'}); my $picurl = LJ::CleanHTML::canonical_url($POST{'urlpic'}); @@ -491,12 +497,24 @@ use strict; $body .= "<p>".BML::ml('cprod.editpics.text7.v1',{ "num" => $max })."</p>"; } } + + # show sort options + $body .= "<p>"; + $body .= $keyword_sort ? '<a href = "/editicons">' . "$ML{'.sort.default'}</a>" : "$ML{'.sort.default'}"; + $body .=" | "; + $body .= $keyword_sort ? "$ML{'.sort.keyword'}" : '<a href = "/editicons?keywordSort=1">' . "$ML{'.sort.keyword'}</a>"; + $body .= "</p>\n"; + $body .= "</div>"; $body .= "<div id='list_userpics' style='width: 98%; float: left;'>"; my $display_rename = LJ::theschwartz() ? 1 : 0; - foreach my $pic (@userpics) { + if ( $keyword_sort ) { + @userpics = LJ::Userpic->sort( \@userpics ); + } + + foreach my $pic ( @userpics ) { my $pid = $pic->id; $body .= "<div class='pkg userpic_wrapper'>"; diff -r 079aa6f23dae -r a8d460b97735 htdocs/editicons.bml.text --- a/htdocs/editicons.bml.text Wed Apr 28 23:47:49 2010 -0700 +++ b/htdocs/editicons.bml.text Thu Apr 29 00:14:59 2010 -0700 @@ -124,6 +124,10 @@ .restriction.keywords.faq=Picture will be unusable if <a [[aopts]]>keywords</a> are not supplied +.sort.default=Upload Order + +.sort.keyword=Keyword Order + .title=Edit Userpics .title3|notes=This is the new page title. .title is used by multisearch.bml. --------------------------------------------------------------------------------
no subject
no subject