Perform undo by deleting the erroneous database entry
This commit is contained in:
parent
341665c79b
commit
a8a3aa17ce
8 changed files with 46 additions and 54 deletions
|
@ -269,7 +269,8 @@ sub startup {
|
||||||
|
|
||||||
return $self->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
select action_id, extract(epoch from action_time), stations.ds100, stations.name,
|
select user_actions.id, action_id, extract(epoch from action_time),
|
||||||
|
stations.ds100, stations.name,
|
||||||
train_type, train_line, train_no, train_id,
|
train_type, train_line, train_no, train_id,
|
||||||
extract(epoch from sched_time), extract(epoch from real_time),
|
extract(epoch from sched_time), extract(epoch from real_time),
|
||||||
route, messages
|
route, messages
|
||||||
|
@ -287,7 +288,8 @@ sub startup {
|
||||||
|
|
||||||
return $self->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
select action_id, extract(epoch from action_time), stations.ds100, stations.name,
|
select user_actions.id, action_id, extract(epoch from action_time),
|
||||||
|
stations.ds100, stations.name,
|
||||||
train_type, train_line, train_no, train_id,
|
train_type, train_line, train_no, train_id,
|
||||||
extract(epoch from sched_time), extract(epoch from real_time),
|
extract(epoch from sched_time), extract(epoch from real_time),
|
||||||
route, messages
|
route, messages
|
||||||
|
@ -309,7 +311,8 @@ sub startup {
|
||||||
# lack both sched_time and real_time.
|
# lack both sched_time and real_time.
|
||||||
return $self->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
select action_id, extract(epoch from action_time), stations.ds100, stations.name,
|
select user_actions.id, action_id, extract(epoch from action_time),
|
||||||
|
stations.ds100, stations.name,
|
||||||
train_type, train_line, train_no, train_id,
|
train_type, train_line, train_no, train_id,
|
||||||
extract(epoch from sched_time), extract(epoch from real_time),
|
extract(epoch from sched_time), extract(epoch from real_time),
|
||||||
route, messages
|
route, messages
|
||||||
|
@ -329,7 +332,8 @@ sub startup {
|
||||||
|
|
||||||
return $self->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
select action_id, extract(epoch from action_time), stations.ds100, stations.name,
|
select user_actions.id, action_id, extract(epoch from action_time),
|
||||||
|
stations.ds100, stations.name,
|
||||||
train_type, train_line, train_no, train_id,
|
train_type, train_line, train_no, train_id,
|
||||||
extract(epoch from sched_time), extract(epoch from real_time),
|
extract(epoch from sched_time), extract(epoch from real_time),
|
||||||
route, messages
|
route, messages
|
||||||
|
@ -483,11 +487,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
|
|
||||||
return $self->app->dbh->prepare(
|
return $self->app->dbh->prepare(
|
||||||
qq{
|
qq{
|
||||||
insert into user_actions (
|
delete from user_actions where id = ?
|
||||||
user_id, action_id, action_time
|
|
||||||
) values (
|
|
||||||
?, $self->app->action_type->{undo}, to_timestamp(?)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -609,36 +609,24 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
|
|
||||||
$self->helper(
|
$self->helper(
|
||||||
'undo' => sub {
|
'undo' => sub {
|
||||||
my ($self) = @_;
|
my ($self, $action_id) = @_;
|
||||||
|
|
||||||
my $uid = $self->current_user->{id};
|
my $status = $self->get_user_status;
|
||||||
$self->app->get_last_actions_query->execute($uid);
|
|
||||||
my $rows = $self->app->get_last_actions_query->fetchall_arrayref;
|
|
||||||
|
|
||||||
if ( @{$rows} and $rows->[0][0] == $self->app->action_type->{undo} )
|
if ($action_id < 1 or $status->{action_id} != $action_id) {
|
||||||
{
|
return "Invalid action ID: $action_id != $status->{action_id}. Note that you can only undo your latest action.";
|
||||||
return 'Nested undo (undoing an undo) is not supported';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( @{$rows} > 1
|
my $success = $self->app->undo_query->execute($action_id);
|
||||||
and $rows->[1][0] == $self->app->action_type->{undo} )
|
|
||||||
{
|
|
||||||
return 'Repeated undo is not supported';
|
|
||||||
}
|
|
||||||
|
|
||||||
my $success = $self->app->undo_query->execute(
|
if (defined $success) {
|
||||||
$self->current_user->{id},
|
|
||||||
DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( defined $success ) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
my $uid = $self->current_user->{id};
|
my $uid = $self->current_user->{id};
|
||||||
my $err = $self->app->action_query->errstr;
|
my $err = $self->app->undo_query->errstr;
|
||||||
$self->app->log->error("Undo($uid): INSERT failed: $err");
|
$self->app->log->error("Undo($uid): DELETE failed: $err");
|
||||||
return 'INSERT failed: ' . $err;
|
return 'DELETE failed: ' . $err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -962,7 +950,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
|
|
||||||
while ( my @row = $query->fetchrow_array ) {
|
while ( my @row = $query->fetchrow_array ) {
|
||||||
my (
|
my (
|
||||||
$action, $raw_ts, $ds100,
|
$action_id, $action, $raw_ts, $ds100,
|
||||||
$name, $train_type, $train_line,
|
$name, $train_type, $train_line,
|
||||||
$train_no, $train_id, $raw_sched_ts,
|
$train_no, $train_id, $raw_sched_ts,
|
||||||
$raw_real_ts, $raw_route, $raw_messages
|
$raw_real_ts, $raw_route, $raw_messages
|
||||||
|
@ -977,6 +965,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
push(
|
push(
|
||||||
@travels,
|
@travels,
|
||||||
{
|
{
|
||||||
|
ids => [undef, $action_id],
|
||||||
to_name => $name,
|
to_name => $name,
|
||||||
sched_arrival => epoch_to_dt($raw_sched_ts),
|
sched_arrival => epoch_to_dt($raw_sched_ts),
|
||||||
rt_arrival => epoch_to_dt($raw_real_ts),
|
rt_arrival => epoch_to_dt($raw_real_ts),
|
||||||
|
@ -1004,6 +993,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
my $ref = $travels[-1];
|
my $ref = $travels[-1];
|
||||||
|
$ref->{ids}->[0] = $action_id;
|
||||||
$ref->{from_name} = $name;
|
$ref->{from_name} = $name;
|
||||||
$ref->{completed} = 1;
|
$ref->{completed} = 1;
|
||||||
$ref->{sched_departure} = epoch_to_dt($raw_sched_ts);
|
$ref->{sched_departure} = epoch_to_dt($raw_sched_ts);
|
||||||
|
@ -1091,16 +1081,16 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
|
|
||||||
my @cols = @{ $rows->[0] };
|
my @cols = @{ $rows->[0] };
|
||||||
if ( @{$rows} > 2
|
if ( @{$rows} > 2
|
||||||
and $rows->[0][0] == $self->app->action_type->{undo} )
|
and $rows->[0][1] == $self->app->action_type->{undo} )
|
||||||
{
|
{
|
||||||
@cols = @{ $rows->[2] };
|
@cols = @{ $rows->[2] };
|
||||||
}
|
}
|
||||||
|
|
||||||
my $action_ts = epoch_to_dt( $cols[1] );
|
my $action_ts = epoch_to_dt( $cols[2] );
|
||||||
my $sched_ts = epoch_to_dt( $cols[8] );
|
my $sched_ts = epoch_to_dt( $cols[9] );
|
||||||
my $real_ts = epoch_to_dt( $cols[9] );
|
my $real_ts = epoch_to_dt( $cols[10] );
|
||||||
my $checkin_station_name = $cols[3];
|
my $checkin_station_name = $cols[4];
|
||||||
my @route = split( qr{[|]}, $cols[10] // q{} );
|
my @route = split( qr{[|]}, $cols[11] // q{} );
|
||||||
my @route_after;
|
my @route_after;
|
||||||
my $is_after = 0;
|
my $is_after = 0;
|
||||||
for my $station (@route) {
|
for my $station (@route) {
|
||||||
|
@ -1114,19 +1104,20 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
checked_in =>
|
checked_in =>
|
||||||
( $cols[0] == $self->app->action_type->{checkin} ),
|
( $cols[1] == $self->app->action_type->{checkin} ),
|
||||||
cancelled =>
|
cancelled =>
|
||||||
( $cols[0] == $self->app->action_type->{cancelled_from} ),
|
( $cols[1] == $self->app->action_type->{cancelled_from} ),
|
||||||
timestamp => $action_ts,
|
timestamp => $action_ts,
|
||||||
timestamp_delta => $now->epoch - $action_ts->epoch,
|
timestamp_delta => $now->epoch - $action_ts->epoch,
|
||||||
|
action_id => $cols[0],
|
||||||
sched_ts => $sched_ts,
|
sched_ts => $sched_ts,
|
||||||
real_ts => $real_ts,
|
real_ts => $real_ts,
|
||||||
station_ds100 => $cols[2],
|
station_ds100 => $cols[3],
|
||||||
station_name => $checkin_station_name,
|
station_name => $checkin_station_name,
|
||||||
train_type => $cols[4],
|
train_type => $cols[5],
|
||||||
train_line => $cols[5],
|
train_line => $cols[6],
|
||||||
train_no => $cols[6],
|
train_no => $cols[7],
|
||||||
train_id => $cols[7],
|
train_id => $cols[8],
|
||||||
route => \@route,
|
route => \@route,
|
||||||
route_after => \@route_after,
|
route_after => \@route_after,
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,7 +117,7 @@ sub log_action {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ( $params->{action} eq 'undo' ) {
|
elsif ( $params->{action} eq 'undo' ) {
|
||||||
my $error = $self->undo;
|
my $error = $self->undo( $params->{undo_id} );
|
||||||
if ($error) {
|
if ($error) {
|
||||||
$self->render(
|
$self->render(
|
||||||
json => {
|
json => {
|
||||||
|
|
|
@ -43,6 +43,7 @@ $(document).ready(function() {
|
||||||
var link = $(this);
|
var link = $(this);
|
||||||
var req = {
|
var req = {
|
||||||
action: 'undo',
|
action: 'undo',
|
||||||
|
undo_id: link.data('id'),
|
||||||
};
|
};
|
||||||
tvly_run(link, req, '/');
|
tvly_run(link, req, '/');
|
||||||
});
|
});
|
||||||
|
|
2
public/static/js/travelynx-actions.min.js
vendored
2
public/static/js/travelynx-actions.min.js
vendored
|
@ -1 +1 @@
|
||||||
function tvly_run(n,t,a,c){var i='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');n.hide(),n.after(o),$.post("/action",t,function(t){t.success?$(location).attr("href",a):(M.toast({html:i+" "+t.error}),o.remove(),c&&c(),n.append(" "+i),n.show())})}$(document).ready(function(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")},"/")}),$(".action-checkout").click(function(){var t=$(this),n={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,n,"/s/"+n.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){tvly_run($(this),{action:"undo"},"/")}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")},"/")}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0},"/")})});
|
function tvly_run(t,a,n,c){var i='<i class="material-icons">error</i>',o=$('<div class="progress"><div class="indeterminate"></div></div>');t.hide(),t.after(o),$.post("/action",a,function(a){a.success?$(location).attr("href",n):(M.toast({html:i+" "+a.error}),o.remove(),c&&c(),t.append(" "+i),t.show())})}$(document).ready(function(){$(".action-checkin").click(function(){var t=$(this);tvly_run(t,{action:"checkin",station:t.data("station"),train:t.data("train")},"/")}),$(".action-checkout").click(function(){var t=$(this),a={action:"checkout",station:t.data("station"),force:t.data("force")};tvly_run(t,a,"/s/"+a.station,function(){t.append(" – Ohne Echtzeitdaten auschecken?"),t.data("force",!0)})}),$(".action-undo").click(function(){var t=$(this);tvly_run(t,{action:"undo",undo_id:t.data("id")},"/")}),$(".action-cancelled-from").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_from",station:t.data("station"),train:t.data("train")},"/")}),$(".action-cancelled-to").click(function(){var t=$(this);tvly_run(t,{action:"cancelled_to",station:t.data("station"),force:!0},"/")})});
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% }
|
% }
|
||||||
% elsif ($status->{timestamp_delta} < 600) {
|
% elsif ($status->{timestamp_delta} < 180) {
|
||||||
<div class="card grey darken-4">
|
<div class="card grey darken-4">
|
||||||
<div class="card-content white-text">
|
<div class="card-content white-text">
|
||||||
<span class="card-title">Ausgecheckt</span>
|
<span class="card-title">Ausgecheckt</span>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
bis <%= $status->{station_name} %></p>
|
bis <%= $status->{station_name} %></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
<a class="action-undo">
|
<a class="action-undo" data-id="<%= $status->{action_id} %>">
|
||||||
<i class="material-icons">undo</i> Rückgängig?
|
<i class="material-icons">undo</i> Rückgängig?
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<p>Du bist gerade eingecheckt in
|
<p>Du bist gerade eingecheckt in
|
||||||
<%= $status->{train_type} %> <%= $status->{train_no} %>
|
<%= $status->{train_type} %> <%= $status->{train_no} %>
|
||||||
ab <%= $status->{station_name} %>.
|
ab <%= $status->{station_name} %>.
|
||||||
% if ($status->{timestamp_delta} < 3600) {
|
% if ($status->{timestamp_delta} < 180) {
|
||||||
<a class="action-undo"><i class="material-icons">undo</i> Rückgängig</a>
|
<a class="action-undo" data-id="<%= $status->{action_id} %>"><i class="material-icons">undo</i> Rückgängig</a>
|
||||||
% }
|
% }
|
||||||
</p>
|
</p>
|
||||||
<p>Bei Ankunft: Station auswählen zum Auschecken.</p>
|
<p>Bei Ankunft: Station auswählen zum Auschecken.</p>
|
||||||
|
@ -44,8 +44,8 @@
|
||||||
<p>Prinzipiell wärest du nun eingecheckt in
|
<p>Prinzipiell wärest du nun eingecheckt in
|
||||||
<%= $status->{train_type} %> <%= $status->{train_no} %>
|
<%= $status->{train_type} %> <%= $status->{train_no} %>
|
||||||
ab <%= $status->{station_name} %>, doch dieser Zug fällt aus.
|
ab <%= $status->{station_name} %>, doch dieser Zug fällt aus.
|
||||||
% if ($status->{timestamp_delta} < 3600) {
|
% if ($status->{timestamp_delta} < 180) {
|
||||||
<a class="action-undo"><i class="material-icons">undo</i> Checkinversuch rückgängig</a>
|
<a class="action-undo" data-id="<%= $status->{action_id} %>"><i class="material-icons">undo</i> Checkinversuch rückgängig</a>
|
||||||
% }
|
% }
|
||||||
</p>
|
</p>
|
||||||
<p>Falls du den Zugausfall z.B. für ein Fahrgastrechteformular
|
<p>Falls du den Zugausfall z.B. für ein Fahrgastrechteformular
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="theme-color" content="#673ab7">
|
<meta name="theme-color" content="#673ab7">
|
||||||
% my $av = 'v4'; # asset version
|
% my $av = 'v5'; # asset version
|
||||||
%= stylesheet "/static/${av}/css/materialize.min.css"
|
%= stylesheet "/static/${av}/css/materialize.min.css"
|
||||||
%= stylesheet "/static/${av}/css/material-icons.css"
|
%= stylesheet "/static/${av}/css/material-icons.css"
|
||||||
%= stylesheet "/static/${av}/css/local.css"
|
%= stylesheet "/static/${av}/css/local.css"
|
||||||
|
|
Loading…
Reference in a new issue