Commit graph

539 commits

Author SHA1 Message Date
Daniel Friesel
94ea5a089f Commute stats: count days, not journeys 2020-04-19 17:03:02 +02:00
Daniel Friesel
94932c4102 add commute stats. not linked from nav yet. 2020-04-19 16:49:31 +02:00
Daniel Friesel
a3ea4fde95 fix a typo 2020-04-16 16:52:19 +02:00
Daniel Friesel
da05a0e981 maintenance: backpropagate polylines to route entries using pre-1.9.4 format 2020-04-16 16:29:34 +02:00
Daniel Friesel
4cc510d710 use polyline when computing monthly/yearly distance travelled
Closes #40
2020-04-14 18:22:49 +02:00
Daniel Friesel
56f355741c Well, that was stupid 2020-03-14 14:57:30 +01:00
Daniel Friesel
e7a6cfa931 Correctly encode non-ASCII e-mail content. Fixes spamfilter issues.
New dependency: MIME::Entity
2020-03-14 14:56:02 +01:00
Daniel Friesel
871a44f15e Do not hardcode From mail address 2020-03-13 18:28:13 +01:00
Daniel Friesel
d7f251e51f public user status: show polyline if available 2020-02-26 18:43:34 +01:00
Daniel Friesel
5c05ed609f journey details: show route on map if available 2020-02-23 19:04:05 +01:00
Daniel Friesel
82f043e734 Move map data generation to a global helper function 2020-02-23 18:35:56 +01:00
Daniel Friesel
a15dc1791c calculate journey distance using polyline, if available 2020-02-21 23:31:50 +01:00
Daniel Friesel
0011e4a18d user_status: Improve TS lookup performance 2020-02-20 20:58:58 +01:00
Daniel Friesel
57f686b688 allow showing past journeys on shared status page 2020-02-19 20:58:38 +01:00
Daniel Friesel
2652ea6bab auto-checkout for cancelled departure: guard against destination changes 2020-02-18 17:38:53 +01:00
Daniel Friesel
cc7439dd5e handle departure cancellation after checkin 2020-02-17 21:13:07 +01:00
Daniel Friesel
a1865fa69e add privacy setting for showing history and latest arrival timestamp 2020-02-14 16:29:44 +01:00
Daniel Friesel
6cbbc2b16f avoid stale data when marking cancelled arrivals 2020-02-13 18:35:42 +01:00
Daniel Friesel
a830acc698 Handle cancelled arrival at checkout when departure at checkin is not cancelled 2020-02-12 20:38:24 +01:00
Daniel Friesel
7564ec34db munin: Add polyline compression ratio 2020-02-10 20:06:55 +01:00
Daniel Friesel
3ddd1a1cf4 Improve map performance by passing actual polylines for train routes 2020-02-07 23:19:01 +01:00
Daniel Friesel
c2e0f377be maintenance: consider station renames whan backpropagating polylines 2020-02-06 17:54:23 +01:00
Daniel Friesel
0457a53f65 maintenance: only fetch polylines from journeys which were not edited 2020-02-04 21:23:22 +01:00
Daniel Friesel
eb3f4aed05 allow checkin and checkout station to be edited 2020-02-01 16:15:20 +01:00
Daniel Friesel
aa7a7db2bc map: show polylines by default 2020-01-31 18:16:00 +01:00
Daniel Friesel
7e92e6b5d4 retroactively add polylines to non-polyline journeys 2020-01-30 18:06:04 +01:00
Daniel Friesel
dadb0f6637 map: improve polyline duplicate detection 2020-01-29 19:54:32 +01:00
Daniel Friesel
993f6be6c9 map: set bounds on stations; move polyline feature to staging 2020-01-29 18:48:58 +01:00
Daniel Friesel
297718603c munin: return number of stored polylines 2020-01-27 20:33:35 +01:00
Daniel Friesel
b47a29d484 Store journey polylines in DB
Squashed commit of the following:

commit d60c7d3c98d88a8f5b0e3ced6c11b56053e1e44b
Author: Daniel Friesel <derf@finalrewind.org>
Date:   Mon Jan 27 20:22:46 2020 +0100

    fix bugs related to users without past journeys

commit 707fcc937ac7f6bc3dc29024273f5e74963f7f15
Author: Daniel Friesel <derf@finalrewind.org>
Date:   Mon Jan 27 20:19:14 2020 +0100

    work around Cache::file turning floats into strings

commit 55831121eb30bc30ed20134bbb48e4bee9772feb
Author: Daniel Friesel <derf@finalrewind.org>
Date:   Mon Jan 27 19:43:29 2020 +0100

    store journey polylines for later use

commit 1971d511037ff2b8fbc9699cb98e4f8fd51261e5
Author: Daniel Friesel <derf@finalrewind.org>
Date:   Sat Jan 25 16:49:48 2020 +0100

    set preliminary database schema for polyline storage.

    deduplication will follow at a later stage
2020-01-27 20:32:15 +01:00
Daniel Friesel
cc25a56864 Api: Import: Set correct route key for add_journey 2020-01-26 16:04:08 +01:00
Daniel Friesel
d7c69acf41 import API: route -> intermediateStops 2020-01-26 10:50:21 +01:00
Daniel Friesel
c31254e996 import API: Add deprecated field, remove development check 2020-01-26 10:47:51 +01:00
Daniel Friesel
1723f8c1fb import API: invalidate stats cache after adding a journey 2020-01-26 10:08:46 +01:00
Daniel Friesel
3e9807b393 map, journey view: handle renamed stations 2020-01-25 15:46:42 +01:00
Daniel Friesel
1028e47a35 map: list skipped journeys 2020-01-25 14:55:51 +01:00
Daniel Friesel
ee1285e8fa map: support multiple polyline groups with different colors 2020-01-25 14:41:33 +01:00
Daniel Friesel
75363c35cc work: Fix race condition
When a user changes their destination station or checks into a new train
while work is updating data for their in_transit entry, values for no longer
valid database entrie would be entered.
2020-01-23 17:14:01 +01:00
Daniel Friesel
9232cdaa5f Return HTTP 404 for unknown journeys 2020-01-19 19:21:14 +01:00
Daniel Friesel
2764826da0 /journey/🆔 verify that id is numeric
As a side effect, this turns the response of GET /journey/edit (which should
never happen in the first place) from an exception into a 404 error (#36)
2020-01-19 19:15:53 +01:00
Daniel Friesel
a9a7fa4492 Release Travel API 2019-12-31 13:27:14 +01:00
Daniel Friesel
61889603f7 Checkin API: error out if fromStation / toStation are ambiguous 2019-12-30 01:31:26 +01:00
Daniel Friesel
d9126b927f fix connections display 2019-12-26 22:48:50 +01:00
Daniel Friesel
f9f1eec499 Use EVA IDs instead of travelynx-internal station IDs. Not 100% tested yet. 2019-12-23 22:57:45 +01:00
Daniel Friesel
c6634b4097 maintenance: remove checkins which were entered more than 48 hours ago 2019-12-20 18:56:57 +01:00
Daniel Friesel
e7f278574f more travel API documentation 2019-12-20 18:33:59 +01:00
Daniel Friesel
11a2e94a04 travel API: more helpful errors on invalid input 2019-12-20 16:39:15 +01:00
Daniel Friesel
bd372d57e2 Travel API: Add "deprecated" field 2019-12-20 16:23:41 +01:00
Daniel Friesel
ebb7c22a4b checkin api: only set comment if checkin was successful 2019-12-20 16:18:32 +01:00
Daniel Friesel
b0ddada5d1 munin: Add 'currently checked in' counter 2019-12-19 19:22:56 +01:00
Daniel Friesel
69f961a23c disable import and checkin API endpoints in production mode 2019-12-19 19:20:06 +01:00
Daniel Friesel
c8695ecb1c travel, import API: Verify that payload is a hash 2019-12-17 20:41:36 +01:00
Daniel Friesel
934a9ac21a api/import: More helpful errors, fix "lax" support 2019-12-17 20:09:02 +01:00
Daniel Friesel
ae21896982 API: Add lax option 2019-12-17 20:01:39 +01:00
Daniel Friesel
cabf159f46 Handle Berlin Ringbahn and other transfer-at-destination trains
Requires Travel::Status::DE::IRIS v1.38 (not released yet)
2019-12-15 13:42:11 +01:00
Daniel Friesel
7ae60f2ea4 Travel API: comment support 2019-12-14 23:46:36 +01:00
Daniel Friesel
46fc64de48 Add travel (checkin/checkout/undo) API 2019-12-14 21:53:23 +01:00
Daniel Friesel
5fe4174feb Add API entry point for journey import 2019-12-14 20:46:02 +01:00
Daniel Friesel
315a94affe allow a journey's cancellation status to be edited
Closes #27
2019-12-08 19:46:45 +01:00
Daniel Friesel
561ff4574b Allow status visibility to be limited to travelynx users 2019-12-08 11:06:17 +01:00
Daniel Friesel
402a5597f5 Account: unset public_comment when public_status is disabled 2019-12-08 10:32:22 +01:00
Daniel Friesel
fb126c6928 optionally show journey comment in public user status
Closes #19
2019-12-06 21:44:31 +01:00
Daniel Friesel
094c536eb4 Allow comments to be entered while still in transit 2019-12-06 21:40:51 +01:00
Daniel Friesel
119f0a6b7d Do not show cancelled journeys without substitute in passengerrights list 2019-11-27 21:09:49 +01:00
Daniel Friesel
0e2e8cd78e history map: Add checkbox to display manually added journeys 2019-11-27 18:26:15 +01:00
Daniel Friesel
613f7d6087 Passengerrights: Fix typo 2019-11-24 20:32:24 +01:00
Daniel Friesel
b3b0a055b9 improve get_user_travels performance, most notably when rendering map
only create DateTime objects when needed
2019-11-24 20:29:52 +01:00
Daniel Friesel
57f47d2a3c allow routes to be edited after recording a journey 2019-11-20 17:41:21 +01:00
Daniel Friesel
b80613b8a8 allow route input when adding journeys manually (#26) 2019-11-19 19:46:39 +01:00
Daniel Friesel
13e59b3aa1 add journey: make realtime data optional (default to schedule data)
Closes #25
2019-11-18 21:02:57 +01:00
Daniel Friesel
783a540cb0 history map: show time range; handle users with no journeys 2019-11-16 23:47:18 +01:00
Daniel Friesel
e0187c5308 history map: Do not show route for manually added journeys 2019-11-16 23:46:45 +01:00
Daniel Friesel
cea4b71ca3 history map: skip duplicates earlier 2019-11-16 21:24:35 +01:00
Daniel Friesel
4f2eac9cef map_history: uniq_by_route did not consider the actual passenger route, scrap it 2019-11-16 16:03:03 +01:00
Daniel Friesel
733fe2d853 map: add legend, link to history map from history page 2019-11-16 15:57:09 +01:00
Daniel Friesel
77e4998708 move station -> location map to generic helper 2019-11-16 15:24:16 +01:00
Daniel Friesel
45f747961e map: add station names to points 2019-11-16 14:50:07 +01:00
Daniel Friesel
0bfb71d78d add map view of past journeys. unfinished and unreferenced. 2019-11-16 00:01:50 +01:00
Daniel Friesel
4ba82b51d3 Fix invalid geolocation list when less than 5 unique station names are nearby
This issue was introduced in 7c7b5e9f95 and
caused the client-side javascript code to crash
2019-10-19 16:47:33 +02:00
Daniel Friesel
780cdafcf5 show related stations in departure list 2019-10-19 10:15:18 +02:00
Daniel Friesel
6d45533c14 mark cancelled stops in checkin view 2019-10-04 23:27:45 +02:00
Daniel Friesel
1cb26e2053 handle substitute connections in passenger rights form 2019-09-18 20:21:16 +02:00
Daniel Friesel
8e6ee729e0 passengerrights: improve support for cancelled trains
To do: also do so in form generation
2019-09-18 18:19:54 +02:00
Daniel Friesel
a9850d073e improve connection detection heuristic 2019-09-14 12:27:36 +02:00
Daniel Friesel
35cc18dfae add passenger rights heuristic for missed connections 2019-09-13 23:39:28 +02:00
Daniel Friesel
0822cfc993 add auto-generated passenger rights forms 2019-09-12 18:07:21 +02:00
Daniel Friesel
8c160f6854 Fix wagon order and direction display
This was broken by a database migration introduced in
commit f6d56d3134
2019-08-31 09:18:49 +02:00
Daniel Friesel
a40aa1936b Allow comments to be edited 2019-08-23 12:02:22 +02:00
Daniel Friesel
f6d56d3134 Add proper journey comment support 2019-08-23 10:34:02 +02:00
Daniel Friesel
e259a5e5dd Fix beeline distance calculation when start/stop has no geo-coordinates 2019-08-13 21:30:59 +02:00
Daniel Friesel
7c7b5e9f95
Do not show station duplicates in geolocation list 2019-07-20 15:42:49 +02:00
Daniel Friesel
b12b5a821b Show departures of all linked stations
Not well-tested yet, deployment will have to wait a bit. Issue #15
2019-07-14 21:29:52 +02:00
Daniel Friesel
0bbdd768f4 prepare for wagon order support 2019-06-17 20:59:57 +02:00
Daniel Friesel
b54c977e08 increase checkout delay to work around IRIS information lag 2019-06-10 18:09:54 +02:00
Daniel Friesel
7be3a4219e checked in: Show QoS messages before departure and HIM messages at all times 2019-06-04 21:12:36 +02:00
Daniel Friesel
f355a8d95e disappearing trains are no longer critical with the latest change 2019-06-01 12:38:26 +02:00
Daniel Friesel
b1591eed54 show current/next stop while checked in 2019-05-31 20:18:22 +02:00
Daniel Friesel
155f9f39cc use journey-specific status links -> one twitter card per journey 2019-05-29 20:01:52 +02:00
Daniel Friesel
146b3a2682 add twitter preview tags to public user status page 2019-05-29 18:11:25 +02:00
Daniel Friesel
7fe95532c1 Use JSON for messages and route storage, prepare for extended route data 2019-05-26 17:28:21 +02:00
Daniel Friesel
1dc04eb45a show journey suggestions on departure board as well 2019-05-20 19:15:21 +02:00
Daniel Friesel
d9d3aac792 allow checkin from connections view 2019-05-19 10:32:57 +02:00
Daniel Friesel
7486920a6a Proactively recompute yearly stats to avoid long user wait times 2019-05-18 17:11:28 +02:00
Daniel Friesel
e68043b8fb Show arrival/departure platform in journey card 2019-05-18 17:10:53 +02:00
Daniel Friesel
b85db3a10d Show web-hook test result immediately after saving it
Closes #12
2019-05-14 20:05:45 +02:00
Daniel Friesel
59c677ba12 history: validate year and month 2019-05-11 01:35:57 +02:00
Daniel Friesel
269b8536f4 Add webhook to account page 2019-05-10 19:03:18 +02:00
Daniel Friesel
2ddab75644 basic webhook support, onwards to betatesting 2019-05-06 16:59:48 +02:00
Daniel Friesel
b36ba45aef WiP webhook support 2019-05-05 18:09:11 +02:00
Daniel Friesel
954638e7c7 data export: use station names, not IDs 2019-05-03 21:14:49 +02:00
Daniel Friesel
709919a962 Experimental PWA support (#13) 2019-05-03 20:43:46 +02:00
Daniel Friesel
b4bb68b7c3 Add worker command for Docker setups (#9) 2019-05-03 18:26:05 +02:00
Daniel Friesel
bf2dae7c45 Add changelog 2019-05-03 10:32:58 +02:00
Daniel Friesel
af5c26bf8a Do not error out when receiving UIDs > INT_MAX 2019-05-02 11:34:52 +02:00
Daniel Friesel
be1e5dda23 Public API documentation 2019-05-02 11:29:43 +02:00
Daniel Friesel
fb2a06c59c work: Not finding a train at the destination is usually not an error 2019-05-02 10:05:49 +02:00
Daniel Friesel
3de5de7db2 Finish public-facing exposed user status (opt-in) 2019-05-02 10:05:15 +02:00
Daniel Friesel
f0d61a4083 Prepare settings and templates for opt-in public travel status 2019-04-30 23:23:49 +02:00
Daniel Friesel
2d7c75f877 show imprint and version on landing page 2019-04-30 18:18:09 +02:00
Daniel Friesel
048767149e use a separate table for registration tokens 2019-04-30 18:05:07 +02:00
Daniel Friesel
a57a24c2d6 add "active user count" munin command 2019-04-30 12:56:11 +02:00
Daniel Friesel
99aa3a4a0d Implement deletion of inactive accounts 2019-04-30 12:48:23 +02:00
Daniel Friesel
867a5d4afb allow users to change their mail address
Closes #6
2019-04-30 12:08:51 +02:00
Daniel Friesel
4ad1a1d20e Move invalid input errors into common sub-template 2019-04-30 10:46:46 +02:00
Daniel Friesel
0226eba60a maintenance: Also delete pending_passwords entries 2019-04-29 20:32:04 +02:00
Daniel Friesel
25d0530e86 Add password reset functionality
Closes #5
2019-04-29 20:12:59 +02:00
Daniel Friesel
6ff397c9b3 add database table/column comments 2019-04-29 10:25:17 +02:00
Daniel Friesel
fd6d12d355 Handle inconsistent data when calculating monthly/yearly stats
Closes #11
2019-04-28 22:33:09 +02:00
Daniel Friesel
e500c2e537 work: Update route and messages 2019-04-26 22:12:34 +02:00
Daniel Friesel
e07063c52c Add manual journey entry
Closes #3
2019-04-26 19:53:01 +02:00
Daniel Friesel
2cae5a51d2 undo: Redirect to departure station when undoing a checkin 2019-04-25 09:22:54 +02:00
Daniel Friesel
b992a6dc75 $render(status => ...) is a special variable. derp. 2019-04-24 09:00:30 +02:00
Daniel Friesel
fd314e327d maintenance, munin: Use journeys, not user_actions 2019-04-24 08:45:56 +02:00
Daniel Friesel
438319e63a Bump API to v1 2019-04-24 07:34:41 +02:00
Daniel Friesel
906ec60ea2 export: Add in_transit field 2019-04-24 07:13:38 +02:00
Daniel Friesel
3389ca2bcf Fix checkin/checkout of cancelled journeys 2019-04-23 23:02:57 +02:00
Daniel Friesel
6c1cae86f4 Primitive auto-refresh of current journey status
Todo: Redirect user to destination station upon arrival
2019-04-23 22:27:13 +02:00
Daniel Friesel
ffaa0c44a7 Automatic checkout \o/ 2019-04-23 21:30:31 +02:00
Daniel Friesel
e168d9cd39 Use one row per journey instead of split checkin/checkout entries
Whether a user is in transit or not is now determined by an entry in the
in_transit table instead of a dangling checkin.

All completed journeys are stored in the "journeys" table.

This does most of the work needed for automatic checkout. However, note that
the corresponding worker process is not implemented yet.
2019-04-23 18:08:07 +02:00
Daniel Friesel
812be4f0cb Finish transition from DBI to Mojo::Pg 2019-04-22 13:42:41 +02:00
Daniel Friesel
c65232904f Use Mojo::Pg for migrations 2019-04-22 12:30:05 +02:00
Daniel Friesel
2aece36803 Use Mojo::Pg for all remaining Controller and Helper logic 2019-04-22 12:11:22 +02:00
Daniel Friesel
fb3fda9736 More Mojo::Pg migrations 2019-04-22 09:58:39 +02:00
Daniel Friesel
b860b46e52 database migrate: Use truncate 2019-04-21 17:45:25 +02:00
Daniel Friesel
78b2d995ef Ignore stations without coordinates in distance calculation
Reported by @marudor
2019-04-21 15:46:19 +02:00
Daniel Friesel
24d0943cdc refactor set_status_query and get_token_query 2019-04-19 15:56:54 -04:00
Daniel Friesel
eff979081c Add a registration test 2019-04-18 14:51:45 -04:00
Daniel Friesel
065c844fde Refactor munin command to use Mojo::Pg 2019-04-17 13:36:01 -04:00
Daniel Friesel
8ad05720a2 Refactor user_actions insert/update/delete statements with Mojo::Pg 2019-04-17 13:35:38 -04:00
Daniel Friesel
ecedc6a4f2 Add a dumpconfig command, mostly useful to debug Docker setups 2019-04-17 07:11:04 -04:00
Daniel Friesel
d9b82a4133 Sendmail: Actually print info log messages as documented 2019-04-17 07:07:05 -04:00
Daniel Friesel
e1e07d5811 Set version via config 2019-04-14 17:34:30 -04:00
Daniel Friesel
c19f239d1d Do not print error when encountering an empty database 2019-04-14 08:44:27 +02:00
Markus Witt
ed397093c2 database setup: merge setup and migration code paths 2019-04-13 23:36:58 +02:00
Daniel Friesel
13dbcf8761 add explicit config toggle to disable sendmail 2019-04-13 18:56:06 +02:00
Daniel Friesel
4d413d06a3 "database" sub-command: Provide an exit status 2019-04-13 17:17:44 +02:00
Daniel Friesel
ee53b8f37e Pass config to sendmail helper 2019-04-13 17:09:10 +02:00
Markus Witt
4bf62cf2a8 fix dbschema: add type for edited 2019-04-13 16:56:15 +02:00
Daniel Friesel
80a6317ac5 Use travelynx.conf for configuration and secrets
This avoids having to specify secrets in the environment, where they can leak
easily.
2019-04-13 12:18:26 +02:00
Daniel Friesel
61b1ef398e maintenance: Fix stats table name 2019-04-13 11:52:26 +02:00
Daniel Friesel
1ee185d26b work-in-progress manual journey entry. incomplete and not enabled yet. 2019-04-13 10:43:05 +02:00
Daniel Friesel
bba6721754 Allow journey editing, keep track of edited journey attributes
Provides a workaround for #2
2019-04-09 18:37:21 +02:00
Daniel Friesel
c0c7b1a589 Work-in-progress journey editor. Not ready for deployment. 2019-04-08 21:20:04 +02:00
Daniel Friesel
beb17acb84 Prepare forms for manual journey entry and editing 2019-04-07 20:20:37 +02:00
Daniel Friesel
ffee7177ac Refactor history template, add yearly stats 2019-04-07 18:44:33 +02:00
Daniel Friesel
d0b6b7e052 Cache journey stats 2019-04-07 16:55:35 +02:00
Daniel Friesel
8096c33c00 Add a note about updating travelynx 2019-04-07 14:18:56 +02:00
Daniel Friesel
4e7f7a1d0e detect development mode for travelynx_dev* databases 2019-04-06 21:21:35 +02:00
Daniel Friesel
c4a60375f4 Add a database command for database setup and migrations 2019-04-06 21:08:36 +02:00
Daniel Friesel
1405eb6ea3 Add password change form 2019-04-06 11:20:10 +02:00
Daniel Friesel
45f409e3df Fix export layout 2019-04-05 21:42:54 +02:00
Daniel Friesel
e2598df25b Allow journey deletion
See issue #3
2019-04-04 18:26:53 +02:00
Daniel Friesel
b0ad209a23 Fix intentional typo in dev mode check (left over from testing) 2019-04-02 20:11:34 +02:00
Daniel Friesel
4787dbae15 move mailing to sendmail helper 2019-04-02 20:10:48 +02:00
Daniel Friesel
8d843dc432 Fix another journey error 2019-03-31 19:38:21 +02:00
Daniel Friesel
10c995e15f journey: show error for _all_ invalid IDs 2019-03-31 19:34:29 +02:00
Daniel Friesel
3ce1cfc55f Select journeys by ID 2019-03-31 19:32:41 +02:00
Daniel Friesel
76f6922e82 maintenance: delete accounts which requested deletion 2019-03-31 17:58:05 +02:00
Daniel Friesel
a8a3aa17ce Perform undo by deleting the erroneous database entry 2019-03-31 08:45:51 +02:00
Daniel Friesel
eb929811b2 add per-month links to history 2019-03-27 21:46:52 +01:00
Daniel Friesel
1aa5e786ed add history per month 2019-03-27 21:20:59 +01:00
Daniel Friesel
00efb2e320 Move maintenance script to Mojolicious command 2019-03-25 19:54:49 +01:00
Daniel Friesel
edf4642933 Migrate munin command 2019-03-25 18:17:54 +01:00
Daniel Friesel
e2b78170a5 Postgres does not require decode() calls 2019-03-25 18:11:48 +01:00
Daniel Friesel
62929a570a Remove unused login controller 2019-03-25 17:18:28 +01:00
Daniel Friesel
632f731940 Migrate to postgresql 2019-03-25 17:04:39 +01:00
Daniel Friesel
e53ab5f781 move munin-stats to a mojolicious command 2019-03-22 21:18:03 +01:00
Daniel Friesel
32cc2f0f81 More refactoring 2019-03-22 16:56:49 +01:00
Daniel Friesel
21fe8a6990 Initiate transition to a Mojolicious MVC web application 2019-03-21 22:12:45 +01:00