diff options
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rwxr-xr-x | bin/oxfordshire/archive-old-enquiries | 9 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Dashboard.pm | 35 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/ArchiveOldEnquiries.pm | 35 | ||||
-rwxr-xr-x | script/server | 2 | ||||
-rw-r--r-- | t/app/script/archive_old_enquiries.t | 16 | ||||
-rw-r--r-- | templates/email/warwickshire/archive.txt | 26 | ||||
-rw-r--r-- | templates/web/base/auth/2faform.html | 2 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/assets.js | 92 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 14 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/staff.js | 46 | ||||
-rw-r--r-- | web/js/map-OpenLayers.js | 7 |
13 files changed, 161 insertions, 126 deletions
diff --git a/.travis.yml b/.travis.yml index 479595cad..9641e2819 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ addons: install: - .travis/install - - 'if [ "$TRAVIS_PERL_VERSION" = "5.24" ]; then cpanm --quiet --notest https://github.com/mysociety/codecov-perl/tarball/cover-uncoverables; fi' + - 'if [ "$TRAVIS_PERL_VERSION" = "5.24" ]; then cpanm --quiet --notest Devel::Cover::Report::Codecov; fi' before_script: - commonlib/bin/gettext-makemo FixMyStreet - 'if [ "$TRAVIS_PERL_VERSION" = "5.24" ]; then export HARNESS_PERL_SWITCHES="-MDevel::Cover=+ignore,local/lib/perl5,commonlib,perllib/Catalyst/[^A],perllib/DBIx,perllib/Email,perllib/Template,^t"; fi' diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fa573292..003ec4bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Fix post-edit issues on admin report edit page. - Admin improvements: - Inspectors can set non_public status of reports. #1992 + - Default start date is shown on the dashboard. - Development improvements: - Add HTML email previewer. diff --git a/bin/oxfordshire/archive-old-enquiries b/bin/oxfordshire/archive-old-enquiries index 7fe66703a..e82aa984e 100755 --- a/bin/oxfordshire/archive-old-enquiries +++ b/bin/oxfordshire/archive-old-enquiries @@ -17,10 +17,11 @@ use Getopt::Long::Descriptive; my ($opts, $usage) = describe_options( '%c %o', ['commit|c', "actually close reports and send emails. Omitting this flag will do a dry-run"], - ['body|b=s', "which body ID to close reports for"], - ['cobrand=s', "which cobrand template to use for sent emails"], - ['closure-cutoff=s', "Anything before this will be closed with no email"], - ['email-cutoff=s', "Anything before this will be closed with an email sent to the reporter"], + ['body|b=s', "which body ID to close reports for", { required => 1 } ], + ['user|u=s', "which user ID to assign closure updates to", { required => 1 } ], + ['cobrand=s', "which cobrand template to use for sent emails", { required => 1 } ], + ['closure-cutoff=s', "Anything before this will be closed with no email", { required => 1 } ], + ['email-cutoff=s', "Anything before this will be closed with an email sent to the reporter", { required => 1 } ], ['limit|l=s', "limit to a certain number of reports/users to be closed"], ['help|h', "print usage message and exit" ], ); diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm index de55e0768..7cdf150aa 100644 --- a/perllib/FixMyStreet/App/Controller/Dashboard.pm +++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm @@ -103,7 +103,10 @@ sub index : Path : Args(0) { $c->stash->{bodies} = \@bodies; } - $c->stash->{start_date} = $c->get_param('start_date'); + my $days30 = DateTime->now(time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone)->subtract(days => 30); + $days30->truncate( to => 'day' ); + + $c->stash->{start_date} = $c->get_param('start_date') || $days30->strftime('%Y-%m-%d'); $c->stash->{end_date} = $c->get_param('end_date'); $c->stash->{q_state} = $c->get_param('state') || ''; @@ -136,30 +139,14 @@ sub construct_rs_filter : Private { } my $dtf = $c->model('DB')->storage->datetime_parser; - my $date = DateTime->now( time_zone => FixMyStreet->local_time_zone )->subtract(days => 30); - $date->truncate( to => 'day' ); - - $where{'me.confirmed'} = { '>=', $dtf->format_datetime($date) }; - - my $start_date = $c->stash->{start_date}; - my $end_date = $c->stash->{end_date}; - if ($start_date or $end_date) { - my @parts; - if ($start_date) { - my $date = $dtf->parse_datetime($start_date); - push @parts, { '>=', $dtf->format_datetime( $date ) }; - } - if ($end_date) { - my $one_day = DateTime::Duration->new( days => 1 ); - my $date = $dtf->parse_datetime($end_date); - push @parts, { '<', $dtf->format_datetime( $date + $one_day ) }; - } - if (scalar @parts == 2) { - $where{'me.confirmed'} = [ -and => $parts[0], $parts[1] ]; - } else { - $where{'me.confirmed'} = $parts[0]; - } + my $start_date = $dtf->parse_datetime($c->stash->{start_date}); + $where{'me.confirmed'} = { '>=', $dtf->format_datetime($start_date) }; + + if (my $end_date = $c->stash->{end_date}) { + my $one_day = DateTime::Duration->new( days => 1 ); + $end_date = $dtf->parse_datetime($end_date) + $one_day; + $where{'me.confirmed'} = [ -and => $where{'me.confirmed'}, { '<', $dtf->format_datetime($end_date) } ]; } $c->stash->{params} = \%where; diff --git a/perllib/FixMyStreet/Script/ArchiveOldEnquiries.pm b/perllib/FixMyStreet/Script/ArchiveOldEnquiries.pm index 5d1d45379..31876d83d 100644 --- a/perllib/FixMyStreet/Script/ArchiveOldEnquiries.pm +++ b/perllib/FixMyStreet/Script/ArchiveOldEnquiries.pm @@ -14,10 +14,6 @@ use FixMyStreet::Email; my $opts = { commit => 0, - body => '2237', - cobrand => 'oxfordshire', - closure_cutoff => "2015-01-01 00:00:00", - email_cutoff => "2016-01-01 00:00:00", }; sub query { @@ -84,11 +80,7 @@ sub archive { }); printf("Closing %d old reports, without sending emails: ", $problems_to_close->count); - - if ( $opts->{commit} ) { - $problems_to_close->update({ state => 'closed', send_questionnaire => 0 }); - } - + close_problems($problems_to_close); printf("done.\n") } @@ -132,10 +124,31 @@ sub send_email_and_close { unless ( $email_error ) { printf("done.\n Closing reports: "); - - $problems->update({ state => 'closed', send_questionnaire => 0 }); + close_problems($problems); printf("done.\n"); } else { printf("error! Not closing reports for this user.\n") } } + +sub close_problems { + return unless $opts->{commit}; + + my $problems = shift; + while (my $problem = $problems->next) { + my $timestamp = \'current_timestamp'; + $problem->add_to_comments( { + text => '', + created => $timestamp, + confirmed => $timestamp, + user_id => $opts->{user}, + name => _('an administrator'), + mark_fixed => 0, + anonymous => 0, + state => 'confirmed', + problem_state => 'closed', + extra => { is_superuser => 1 }, + } ); + $problem->update({ state => 'closed', send_questionnaire => 0 }); + } +} diff --git a/script/server b/script/server index b1d72269e..a8093fb8e 100755 --- a/script/server +++ b/script/server @@ -4,4 +4,4 @@ set -e cd "$(dirname "$0")/.." export FIXMYSTREET_APP_DEBUG=${FIXMYSTREET_APP_DEBUG=1} -bin/cron-wrapper local/bin/plackup -s Starman --listen :3000 --Reload perllib,conf/general.yml +bin/cron-wrapper local/bin/plackup -s Starman --listen :3000 --Reload perllib,conf diff --git a/t/app/script/archive_old_enquiries.t b/t/app/script/archive_old_enquiries.t index e1adeec85..0475cb9ea 100644 --- a/t/app/script/archive_old_enquiries.t +++ b/t/app/script/archive_old_enquiries.t @@ -5,15 +5,18 @@ my $mech = FixMyStreet::TestMech->new(); $mech->clear_emails_ok; -my $opts = { - commit => 1, -}; - my $user = $mech->create_user_ok('test@example.com', name => 'Test User'); my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council'); my $west_oxon = $mech->create_body_ok(2420, 'West Oxfordshire District Council'); -$opts->{body} = $oxfordshire->id; +my $opts = { + commit => 1, + body => $oxfordshire->id, + cobrand => 'oxfordshire', + closure_cutoff => "2015-01-01 00:00:00", + email_cutoff => "2016-01-01 00:00:00", + user => $user->id, +}; subtest 'sets reports to the correct status' => sub { FixMyStreet::override_config { @@ -65,6 +68,9 @@ subtest 'sets reports to the correct status' => sub { is $report4->state, 'closed', 'Report 4 has been set to closed'; is $report5->state, 'closed', 'Report 5 has been set to closed'; + my $comment = $report1->comments->first; + is $comment->problem_state, 'closed'; + is $report->state, 'confirmed', 'Recent report has been left alone'; }; }; diff --git a/templates/email/warwickshire/archive.txt b/templates/email/warwickshire/archive.txt new file mode 100644 index 000000000..51ad37453 --- /dev/null +++ b/templates/email/warwickshire/archive.txt @@ -0,0 +1,26 @@ +Subject: Your reports on Warwickshire FixMyStreet + +Hello [% user.name %], + +FixMyStreet is being updated in Warwickshire to improve how problems get fixed. + +As part of these updates, we are closing old reports that appear to be resolved but remain open in the system. + +We noticed that you have [% report_count %] old [% nget('report', 'reports', report_count) %] on the system, which we've listed below. + +If your report is no longer an issue, you don't need to do anything. + +If you believe that your report is still a problem, you can reopen it by clicking or copying and pasting +the link marked 'View report' by a report and leaving an update. + +[% FOR report IN reports %] + +[% report.title %] + +Reported [% report.time_ago %] ago. + +View report: [% cobrand.base_url_for_report( report ) %][% report.tokenised_url( user, { reopen => 'true' } ) %]#update_form + +---- + +[% END %] diff --git a/templates/web/base/auth/2faform.html b/templates/web/base/auth/2faform.html index bd8d60cdb..360883d49 100644 --- a/templates/web/base/auth/2faform.html +++ b/templates/web/base/auth/2faform.html @@ -17,7 +17,7 @@ <label for="2fa_code">[% loc('Code') %]</label> <div class="form-txt-submit-box"> - <input class="form-control" type="number" id="2fa_code" name="2fa_code" value="" required> + <input autofocus class="form-control" type="number" id="2fa_code" name="2fa_code" value="" required> <input type="submit" value="[% loc('Submit') %]" class="btn-primary"> </div> </form> diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js index 26a13dc1d..4854b902e 100644 --- a/web/cobrands/fixmystreet/assets.js +++ b/web/cobrands/fixmystreet/assets.js @@ -1,12 +1,54 @@ var fixmystreet = fixmystreet || {}; +/* Special USRN handling */ + (function(){ -var selected_feature = null; -var fault_popup = null; var selected_usrn = null; var usrn_field = null; +fixmystreet.usrn = { + select: function(evt, lonlat) { + var usrn_providers = fixmystreet.map.getLayersBy('fixmystreet', { + test: function(options) { + return options && options.usrn; + } + }); + if (usrn_providers.length) { + var usrn_layer = usrn_providers[0]; + usrn_field = usrn_layer.fixmystreet.usrn.field; + var point = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); + var feature = usrn_layer.getFeatureAtPoint(point); + if (feature == null) { + // The click wasn't directly over a road, try and find one + // nearby + feature = usrn_layer.getNearestFeature(point, 10); + } + if (feature !== null) { + selected_usrn = feature.attributes[usrn_layer.fixmystreet.usrn.attribute]; + } else { + selected_usrn = null; + } + fixmystreet.usrn.update_field(); + } + }, + + update_field: function() { + $("input[name="+usrn_field+"]").val(selected_usrn); + } +}; + +$(fixmystreet).on('maps:update_pin', fixmystreet.usrn.select); +$(fixmystreet).on('assets:selected', fixmystreet.usrn.select); +$(fixmystreet).on('report_new:category_change:extras_received', fixmystreet.usrn.update_field); + +})(); + +(function(){ + +var selected_feature = null; +var fault_popup = null; + function close_fault_popup() { if (!!fault_popup) { fixmystreet.map.removePopup(fault_popup); @@ -37,7 +79,7 @@ function asset_selected(e) { // Pick up the USRN for the location of this asset. NB we do this *before* // handling the attributes on the selected feature in case the feature has // its own USRN which should take precedence. - fixmystreet.assets.select_usrn(lonlat); + $(fixmystreet).trigger('assets:selected', [ lonlat ]); // Set the extra field to the value of the selected feature $.each(this.fixmystreet.attributes, function (field_name, attribute_name) { @@ -253,14 +295,15 @@ fixmystreet.assets = { var protocol_options; var protocol; if (options.http_options !== undefined) { - protocol_options = OpenLayers.Util.extend(options.http_options, {}); - if (protocol_options.format_class) { - protocol_options.format = new protocol_options.format_class(protocol_options.format_options); - } else { - protocol_options.format = new OpenLayers.Format.GML({ - geometryName: options.geometryName - }); + protocol_options = options.http_options; + OpenLayers.Util.applyDefaults(options, { + format_class: OpenLayers.Format.GML, + format_options: {} + }); + if (options.geometryName) { + options.format_options.geometryName = options.geometryName; } + protocol_options.format = new options.format_class(options.format_options); protocol = new OpenLayers.Protocol.HTTP(protocol_options); } else { protocol_options = { @@ -441,35 +484,6 @@ fixmystreet.assets = { fixmystreet.map.addControl(fixmystreet.assets.controls[i]); fixmystreet.assets.controls[i].activate(); } - }, - - select_usrn: function(lonlat) { - var usrn_providers = fixmystreet.map.getLayersBy('fixmystreet', { - test: function(options) { - return options && options.usrn; - } - }); - if (usrn_providers.length) { - var usrn_layer = usrn_providers[0]; - usrn_field = usrn_layer.fixmystreet.usrn.field; - var point = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat); - var feature = usrn_layer.getFeatureAtPoint(point); - if (feature == null) { - // The click wasn't directly over a road, try and find one - // nearby - feature = usrn_layer.getNearestFeature(point, 10); - } - if (feature !== null) { - selected_usrn = feature.attributes[usrn_layer.fixmystreet.usrn.attribute]; - } else { - selected_usrn = null; - } - fixmystreet.assets.update_usrn_field(); - } - }, - - update_usrn_field: function() { - $("input[name="+usrn_field+"]").val(selected_usrn); } }; diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index 1253af6b6..aae275ede 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -151,8 +151,6 @@ function isR2L() { }); })(jQuery); -fixmystreet.hooks = fixmystreet.hooks || {}; - fixmystreet.mobile_reporting = { apply_ui: function() { // Creates the "app-like" mobile reporting UI with full screen map @@ -417,18 +415,10 @@ $.extend(fixmystreet.set_up, { } else { $category_meta.empty(); } - if (fixmystreet.assets) { - fixmystreet.assets.update_usrn_field(); - } + $(fixmystreet).trigger('report_new:category_change:extras_received'); }); - if (fixmystreet.hooks.update_problem_fields) { - args.prefill_reports = $(this).data('prefill'); - args.role = $(this).data('role'); - args.body = $(this).data('body'); - - fixmystreet.hooks.update_problem_fields(args); - } + $(fixmystreet).trigger('report_new:category_change', [ $(this) ]); }); }, diff --git a/web/cobrands/fixmystreet/staff.js b/web/cobrands/fixmystreet/staff.js index 4577ab65e..dd65bc3ce 100644 --- a/web/cobrands/fixmystreet/staff.js +++ b/web/cobrands/fixmystreet/staff.js @@ -428,31 +428,33 @@ $.extend(fixmystreet.set_up, { }); -$.extend(fixmystreet.hooks, { - update_problem_fields: function(args) { - if (args.prefill_reports && args.role == 'inspector') { - var title = 'A ' + args.category + ' problem has been found'; - var description = 'A ' + args.category + ' problem has been found by ' + args.body; - - var $title_field = $('#form_title'); - var $description_field = $('#form_detail'); - - if ($title_field.val().length === 0 || $title_field.data('autopopulated') === true) { - $title_field.val(title); - $title_field.data('autopopulated', true); - } - - if ($description_field.val().length === 0 || $description_field.data('autopopulated') === true) { - $description_field.val(description); - $description_field.data('autopopulated', true); - } +$(fixmystreet).on('report_new:category_change', function(evt, $this) { + var category = $this.val(); + var prefill_reports = $this.data('prefill'); + var role = $this.data('role'); + var body = $this.data('body'); + + if (prefill_reports && role == 'inspector') { + var title = 'A ' + category + ' problem has been found'; + var description = 'A ' + category + ' problem has been found by ' + body; + + var $title_field = $('#form_title'); + var $description_field = $('#form_detail'); + + if ($title_field.val().length === 0 || $title_field.data('autopopulated') === true) { + $title_field.val(title); + $title_field.data('autopopulated', true); + } - $('#form_title, #form_detail').on('keyup', function() { - $(this).data('autopopulated', false); - }); + if ($description_field.val().length === 0 || $description_field.data('autopopulated') === true) { + $description_field.val(description); + $description_field.data('autopopulated', true); } - } + $('#form_title, #form_detail').on('keyup', function() { + $(this).data('autopopulated', false); + }); + } }); fixmystreet.maps = fixmystreet.maps || {}; diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js index 5ebb9a18e..0a1c947a0 100644 --- a/web/js/map-OpenLayers.js +++ b/web/js/map-OpenLayers.js @@ -59,12 +59,7 @@ $.extend(fixmystreet.utils, { document.getElementById('fixmystreet.latitude').value = lat; document.getElementById('fixmystreet.longitude').value = lon; - // This tight coupling isn't ideal. A better solution would be for the - // asset code to register an event handler somewhere, but the correct - // place isn't apparent. - if (fixmystreet.assets) { - fixmystreet.assets.select_usrn(lonlat); - } + $(fixmystreet).trigger('maps:update_pin', [ lonlat ]); return { 'url': { 'lon': lon, 'lat': lat }, |