Author: kake
Date: 2012-07-05 08:37:57 +0100 (Thu, 05 Jul 2012)
New Revision: 1421
Added:
trunk/t/710_missing_metadata_map.t
trunk/templates/search_results_leaflet.tt
Modified:
trunk/Build.PL
trunk/MANIFEST
trunk/lib/OpenGuides.pm
trunk/templates/map_index_leaflet.tt
trunk/templates/missing_metadata.tt
trunk/wiki.cgi
Log:
Split out 'plot nodes on map' code, added map display to missing metadata search (fixes #296).
Modified: trunk/Build.PL
===================================================================
--- trunk/Build.PL 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/Build.PL 2012-07-05 07:37:57 UTC (rev 1421)
@@ -426,6 +426,7 @@
"read_only.tt",
"recent_changes.tt",
"search_results.tt",
+ "search_results_leaflet.tt",
"site_index.tt",
"search.tt",
"spam_detected.tt",
Modified: trunk/MANIFEST
===================================================================
--- trunk/MANIFEST 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/MANIFEST 2012-07-05 07:37:57 UTC (rev 1421)
@@ -82,6 +82,7 @@
templates/read_only.tt
templates/recent_changes.tt
templates/search_results.tt
+templates/search_results_leaflet.tt
templates/site_index.tt
templates/search.tt
templates/spam_detected.tt
@@ -158,6 +159,7 @@
t/707_send_email.t
t/708_about.t
t/709_host_blacklist.t
+t/710_missing_metadata_map.t
t/801_node_moderate_whitelist.t
t/802_stylesheet.t
t/803_show_delete_to_admins_only.t
Modified: trunk/lib/OpenGuides.pm
===================================================================
--- trunk/lib/OpenGuides.pm 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/lib/OpenGuides.pm 2012-07-05 07:37:57 UTC (rev 1421)
@@ -2240,12 +2240,17 @@
my $wiki = $self->wiki;
my $formatter = $self->wiki->formatter;
my $script_name = $self->config->script_name;
+ my $use_leaflet = $self->config->use_leaflet;
- my ($metadata_type, $metadata_value, $exclude_locales, $exclude_categories)
- = @args{ qw( metadata_type metadata_value exclude_locales exclude_categories ) };
+ my ( $metadata_type, $metadata_value, $exclude_locales,
+ $exclude_categories, $format)
+ = @args{ qw( metadata_type metadata_value exclude_locales
+ exclude_categories format ) };
+ $format ||= "";
my @nodes;
my $done_search = 0;
+ my $nodes_on_map;
# Only search if they supplied at least a metadata type
if($metadata_type) {
@@ -2257,45 +2262,67 @@
);
# Filter out redirects; also filter out locales/categories if required.
- foreach my $node ( @all_nodes ) {
+ foreach my $node ( sort @all_nodes ) {
next if ( $exclude_locales && $node =~ /^Locale / );
next if ( $exclude_categories && $node =~ /^Category / );
- my $content = $wiki->retrieve_node( $node );
- next if OpenGuides::Utils->detect_redirect( content => $content );
- push @nodes, $node;
+ my %data = $wiki->retrieve_node( $node );
+ next if OpenGuides::Utils->detect_redirect(
+ content => $data{content} );
+ my $node_param = $formatter->node_name_to_node_param( $node );
+ my %this_node = (
+ name => $node,
+ param => $node_param,
+ address => $data{metadata}{address}[0],
+ view_url => "$script_name?$node_param",
+ edit_url => "$script_name?id=$node_param;action=edit",
+ );
+ if ( $format eq "map" && $use_leaflet ) {
+ my ( $wgs84_long, $wgs84_lat )
+ = OpenGuides::Utils->get_wgs84_coords(
+ latitude => $data{metadata}{latitude}[0],
+ longitude => $data{metadata}{longitude}[0],
+ config => $self->config );
+ if ( defined $wgs84_lat ) {
+ $this_node{has_geodata} = 1;
+ $this_node{wgs84_lat} = $wgs84_lat;
+ $this_node{wgs84_long} = $wgs84_long;
+ $nodes_on_map++;
+ }
+ }
+ push @nodes, \%this_node;
}
}
- # Build nice edit etc links for our nodes
- my @tt_nodes;
- for my $node (sort @nodes) {
- my %n;
-
- # Make the URLs
- my $node_param = uri_escape( $formatter->node_name_to_node_param( $node ) );
-
- # Save into the hash
- $n{'name'} = $node;
- $n{'view_url'} = $script_name . "?id=" . $node_param;
- $n{'edit_url'} = $script_name . "?id=" . $node_param . ";action=edit";
- push @tt_nodes, \%n;
- }
-
# Set up our TT variables, including the search parameters
my %tt_vars = (
not_editable => 1,
not_deletable => 1,
deter_robots => 1,
-
- nodes => \@tt_nodes,
+ nodes => \@nodes,
done_search => $done_search,
+ no_nodes_on_map => !$nodes_on_map,
metadata_type => $metadata_type,
metadata_value => $metadata_value,
exclude_locales => $exclude_locales,
exclude_categories => $exclude_categories,
-
script_name => $script_name
);
+
+ # Figure out the map boundaries and centre, if applicable.
+ if ( $format eq "map" ) {
+ if ( $use_leaflet ) {
+ my %minmaxdata = OpenGuides::Utils->get_wgs84_min_max(
+ nodes => \@nodes );
+ if ( scalar %minmaxdata ) {
+ %tt_vars = ( %tt_vars, %minmaxdata );
+ }
+ $tt_vars{display_google_maps} = 1; # to get the JavaScript in
+ }
+ # Set the show_map var even if we don't have Leaflet enabled, so
+ # people aren't left wondering why there's no map.
+ $tt_vars{show_map} = 1;
+ }
+
return %tt_vars if $return_tt_vars;
# Render to the page
@@ -2303,6 +2330,7 @@
id => "",
template => "missing_metadata.tt",
tt_vars => \%tt_vars,
+ noheaders => $args{noheaders} || 0,
);
return $output if $return_output;
print $output;
Added: trunk/t/710_missing_metadata_map.t
===================================================================
--- trunk/t/710_missing_metadata_map.t (rev 0)
+++ trunk/t/710_missing_metadata_map.t 2012-07-05 07:37:57 UTC (rev 1421)
@@ -0,0 +1,122 @@
+use strict;
+use OpenGuides;
+use OpenGuides::Test;
+use Test::More;
+
+eval { require DBD::SQLite; };
+if ( $@ ) {
+ my ($error) = $@ =~ /^(.*?)\n/;
+ plan skip_all => "DBD::SQLite not available ($error)";
+}
+
+eval { require Test::HTML::Content; };
+if ( $@ ) {
+ plan skip_all => "Test::HTML::Content not available";
+}
+
+plan tests => 18;
+
+OpenGuides::Test::refresh_db();
+
+my $config = OpenGuides::Test->make_basic_config;
+my $guide = OpenGuides->new( config => $config );
+my $wiki = $guide->wiki;
+
+# Write four nodes, all with geodata and two with a phone number.
+# Also write one with no geodata and no phone number.
+# All five have summaries.
+OpenGuides::Test->write_data( guide => $guide, node => "Page 1",
+ summary => "A page", latitude => 51, longitude => 1, phone => "123",
+ return_output => 1 );
+OpenGuides::Test->write_data( guide => $guide, node => "Page 2",
+ summary => "A page", latitude => 51.1, longitude => 1.1, phone => "456",
+ return_output => 1 );
+OpenGuides::Test->write_data( guide => $guide, node => "Page 3",
+ summary => "A page", latitude => 51.2, longitude => 1.2,
+ return_output => 1 );
+OpenGuides::Test->write_data( guide => $guide, node => "Page 4",
+ summary => "A page", latitude => 51.3, longitude => 1.3,
+ return_output => 1 );
+OpenGuides::Test->write_data( guide => $guide, node => "Page 5",
+ summary => "A page", return_output => 1 );
+
+# Note: map output is only enabled if Leaflet is enabled.
+
+# Make sure the checkbox only appears if Leaflet is enabled.
+$config->use_leaflet( 0 );
+my $output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1 );
+Test::HTML::Content::no_tag( $output, "input",
+ { type => "checkbox", name => "format", value => "map" },
+ "Map checkbox doesn't appear if Leaflet isn't enabled" );
+
+$config->use_leaflet( 1 );
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1 );
+Test::HTML::Content::tag_ok( $output, "input",
+ { type => "checkbox", name => "format", value => "map" },
+ "...but it does appear if it is" );
+
+# If map is requested but Leaflet isn't enabled, there should be an apology.
+$config->use_leaflet( 0 );
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "phone", format => "map" );
+Test::HTML::Content::tag_ok( $output, "span",
+ { class => "map_results_no_leaflet" },
+ "span.map_results_no_leaflet appears if Leaflet's not enabled" );
+
+$config->use_leaflet( 1 );
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "phone", format => "map" );
+Test::HTML::Content::no_tag( $output, "span",
+ { class => "map_results_no_leaflet" },
+ "...but doesn't if it is" );
+
+### All tests from here on are with Leaflet enabled.
+$config->use_leaflet( 1 );
+
+# Make sure that there's a message if nodes are returned but none of them
+# have geodata.
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "latitude", format => "map" );
+Test::HTML::Content::tag_ok( $output, "p", { class => "no_nodes_on_map" },
+ "p.no_nodes_on_map appears if no returned nodes have geodata" );
+
+# Make sure the map does show up properly if we have nodes with geodata.
+# Pages 3 & 4 have geodata but no phone; Page 5 has neither phone nor geodata.
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "phone", format => "map" );
+like( $output, qr/page\s+5\s+\(not\s+on\s+map/i,
+ "when map shown, pages with no geodata are marked 'not on map'" );
+Test::HTML::Content::link_ok( $output, "?Page_5", "...and are linked to" );
+unlike( $output, qr/page\s+4\s+\(not\s+on\s+map/i,
+ "pages with geodata are _not_ marked 'not on map'" );
+like( $output, qr/param:[\s"]*Page_4/, "...and are included in JavaScript" );
+
+# Navbar shouldn't appear if map does.
+Test::HTML::Content::no_tag( $output, "div", { id => "navbar" },
+ "navbar doesn't appear when map shows" );
+Test::HTML::Content::no_tag( $output, "div", { id => "maincontent" },
+ "...and no div#maincontent" );
+Test::HTML::Content::tag_ok( $output, "div", { id => "maincontent_no_navbar" },
+ "...we get div#maincontent_no_navbar instead" );
+
+# But it should be there when we're listing instead of mapping.
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "phone" );
+Test::HTML::Content::tag_ok( $output, "div", { id => "navbar" },
+ "navbar shown when no map" );
+Test::HTML::Content::tag_ok( $output, "div", { id => "maincontent" },
+ "...div#maincontent too" );
+Test::HTML::Content::no_tag( $output, "div", { id => "maincontent_no_navbar" },
+ "...but no div#maincontent_no_navbar" );
+
+# It should also be there if we get no results from our search.
+$output = $guide->show_missing_metadata( return_output => 1,
+ noheaders => 1, metadata_type => "summary", format => "map" );
+Test::HTML::Content::tag_ok( $output, "div", { id => "navbar" },
+ "navbar shown when no search results" );
+Test::HTML::Content::tag_ok( $output, "div", { id => "maincontent" },
+ "...div#maincontent too" );
+Test::HTML::Content::no_tag( $output, "div", { id => "maincontent_no_navbar" },
+ "...but no div#maincontent_no_navbar" );
Modified: trunk/templates/map_index_leaflet.tt
===================================================================
--- trunk/templates/map_index_leaflet.tt 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/templates/map_index_leaflet.tt 2012-07-05 07:37:57 UTC (rev 1421)
@@ -1,5 +1,3 @@
-[% USE JSON.Escape %]
-
[% IF criteria %]
[% page_title = "Map of $criteria_title - $site_name" %]
[% ELSE %]
@@ -27,76 +25,8 @@
</h2>
[% INCLUDE index_form.tt %]
+ [% INCLUDE search_results_leaflet.tt %]
- <div id="map_index_node_list">
- <ul>
- [% IF no_nodes_on_map %]
- [% FOREACH node = nodes %]
- <li><a href="?[% node.param %]">[% node.name %]</a></li>
- [% END %]
- [% ELSE %]
- [% i = 0 %]
- [% FOREACH node = nodes %]
- [% i = i + 1 %]
- <li>
- [% IF node.has_geodata %]
- <a href="#" onclick="return show_marker( [% i %] )">[% node.name | html %]</a>
- [% ELSE %]
- [% node.name | html %] (not on map —
- <a href="?[% node.param %]">view info</a>)
- [% END %]
- </li>
- [% END %]
- [% END %]
- </ul>
- </div>
-
- <div id="map_index_canvas">
- [% IF no_nodes_on_map %]
- <p class="no_nodes_on_map">No pages with geodata - nothing to display
- on map!</p>
- [% ELSE %]
- <span id="map_index_no_js">
- <p>Sorry! JavaScript is required to view the map - you may prefer to
- <a href="[% feed_base %]">view the results as a list</a> instead.</p>
- </span>
-
- <script type="text/javascript">
-
- $('#map_index_no_js').hide();
-
- map_div_id = 'map_index_canvas';
- centre_lat = [% centre_lat %];
- centre_long = [% centre_long %];
- min_lat = [% min_lat %];
- max_lat = [% max_lat %];
- min_long = [% min_long %];
- max_long = [% max_long %];
-
- function add_markers() {
- var node;
- [% i = 0 %]
- [% FOREACH node = nodes %]
- [% i = i + 1 %]
- [% IF node.has_geodata %]
- node = {
- name: [% node.name.json %],
- param: [% node.param.json %],
- [% address = node.node_data.metadata.address.list.first %]
- [% IF address %]
- address: [% address.json %],
- [% END %]
- lat: [% node.wgs84_lat.json %],
- long: [% node.wgs84_long.json %],
- };
- add_marker( [% i %], node );
- [% END %]
- [% END %]
- }
- </script>
- [% END %]
- </div>
-
</div>
[% INCLUDE footer.tt %]
Modified: trunk/templates/missing_metadata.tt
===================================================================
--- trunk/templates/missing_metadata.tt 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/templates/missing_metadata.tt 2012-07-05 07:37:57 UTC (rev 1421)
@@ -1,8 +1,14 @@
[% INCLUDE header.tt page_title = "Missing Metadata - $site_name" %]
[% INCLUDE banner.tt %]
<div id="content">
-[% INCLUDE navbar.tt %]
-<div id="maincontent">
+
+[% IF no_nodes_on_map OR !show_map %]
+ [% INCLUDE navbar.tt %]
+ <div id="maincontent">
+[% ELSE %]
+ <div id="maincontent_no_navbar">
+[% END %]
+
<h2>Pages Missing Metadata</h2>
[% options = [ "category", "locale", "address", "postcode", "phone", "fax",
@@ -43,6 +49,12 @@
<label for="exclude_categories">Exclude Categories:</label>
<input type="checkbox" name="exclude_categories" id="exclude_categories" [% IF exclude_categories %]checked="true"[% END %] />
</div>
+ [% IF config.use_leaflet %]
+ <div>
+ <label for="show_map">Show results on a map:</label>
+ <input type="checkbox" name="format" value="map" id="show_map"[% IF show_map %] checked="true"[% END %] />
+ </div>
+ [% END %]
<div>
<input type="submit" value="Find Nodes" />
</div>
@@ -50,17 +62,26 @@
[% IF done_search %]
<h3>Pages</h3>
- <a name="nodes"></a>
- <table id="nodes">
- <tr><th>Node name</th><th>View</th><th>Edit</th></tr>
- [% FOREACH node = nodes %]
- <tr>
- <td><a href="[% node.view_url %]">[% node.name %]</a></td>
- <td><a href="[% node.view_url %]">view</a></td>
- <td><a href="[% node.edit_url %]">edit</a></td>
- </tr>
+ [% IF show_map %]
+ [% IF config.use_leaflet %]
+ [% INCLUDE search_results_leaflet.tt %]
+ [% ELSE %]
+ <span class="map_results_no_leaflet">Sorry! Map output is only available
+ for sites using the Leaflet mapping library.</span>
[% END %]
- </table>
+ [% ELSE %]
+ <a name="nodes"></a>
+ <table id="nodes">
+ <tr><th>Node name</th><th>View</th><th>Edit</th></tr>
+ [% FOREACH node = nodes %]
+ <tr>
+ <td><a href="[% node.view_url %]">[% node.name %]</a></td>
+ <td><a href="[% node.view_url %]">view</a></td>
+ <td><a href="[% node.edit_url %]">edit</a></td>
+ </tr>
+ [% END %]
+ </table>
+ [% END %]
[% END %]
</div>
Added: trunk/templates/search_results_leaflet.tt
===================================================================
--- trunk/templates/search_results_leaflet.tt (rev 0)
+++ trunk/templates/search_results_leaflet.tt 2012-07-05 07:37:57 UTC (rev 1421)
@@ -0,0 +1,70 @@
+[% USE JSON.Escape %]
+
+<div id="map_index_node_list">
+ <ul>
+ [% IF no_nodes_on_map %]
+ [% FOREACH node = nodes %]
+ <li><a href="?[% node.param %]">[% node.name %]</a></li>
+ [% END %]
+ [% ELSE %]
+ [% i = 0 %]
+ [% FOREACH node = nodes %]
+ [% i = i + 1 %]
+ <li>
+ [% IF node.has_geodata %]
+ <a href="#" onclick="return show_marker( [% i %] )">[% node.name | html %]</a>
+ [% ELSE %]
+ [% node.name | html %] (not on map —
+ <a href="?[% node.param %]">view info</a>)
+ [% END %]
+ </li>
+ [% END %]
+ [% END %]
+ </ul>
+</div>
+
+<div id="map_index_canvas">
+ [% IF no_nodes_on_map %]
+ <p class="no_nodes_on_map">No pages with geodata - nothing to display
+ on map!</p>
+ [% ELSE %]
+ <span id="map_index_no_js">
+ <p>Sorry! JavaScript is required to view the map - you may prefer to
+ <a href="[% feed_base %]">view the results as a list</a> instead.</p>
+ </span>
+
+ <script type="text/javascript">
+
+ $('#map_index_no_js').hide();
+
+ map_div_id = 'map_index_canvas';
+ centre_lat = [% centre_lat %];
+ centre_long = [% centre_long %];
+ min_lat = [% min_lat %];
+ max_lat = [% max_lat %];
+ min_long = [% min_long %];
+ max_long = [% max_long %];
+
+ function add_markers() {
+ var node;
+ [% i = 0 %]
+ [% FOREACH node = nodes %]
+ [% i = i + 1 %]
+ [% IF node.has_geodata %]
+ node = {
+ name: [% node.name.json %],
+ param: [% node.param.json %],
+ [% address = node.node_data.metadata.address.list.first %]
+ [% IF address %]
+ address: [% address.json %],
+ [% END %]
+ lat: [% node.wgs84_lat.json %],
+ long: [% node.wgs84_long.json %],
+ };
+ add_marker( [% i %], node );
+ [% END %]
+ [% END %]
+ }
+ </script>
+ [% END %]
+</div>
Modified: trunk/wiki.cgi
===================================================================
--- trunk/wiki.cgi 2012-07-04 10:01:45 UTC (rev 1420)
+++ trunk/wiki.cgi 2012-07-05 07:37:57 UTC (rev 1421)
@@ -121,7 +121,8 @@
metadata_type => $q->param("metadata_type") || "",
metadata_value => $q->param("metadata_value") || "",
exclude_locales => $q->param("exclude_locales") || "",
- exclude_categories => $q->param("exclude_categories") || ""
+ exclude_categories => $q->param("exclude_categories") || "",
+ format => $q->param( "format" ) || "",
);
} elsif ( $action eq 'set_moderation' ) {
$guide->set_node_moderation(