~ihabunek/triglav

19aa6b92522a1db5ba5613a225ad32e1eb03b058 — Ivan Habunek 1 year, 9 months ago 67ed650 public-transport
Improve stops page
M assets/js/pt_stops.js => assets/js/pt_stops.js +4 -1
@@ 3,7 3,9 @@ import { GeoJSON, Icon, Map, Marker, TileLayer } from "leaflet"
const map = new Map("stops-map")
const tilesUrl = "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
const attribution = '&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
const icon = new Icon({ iconUrl: "/images/stop.svg", iconSize: [14, 14] })
const blueIcon = new Icon({ iconUrl: "/images/stop.svg", iconSize: [14, 14] })
const redIcon = new Icon({ iconUrl: "/images/stop_red.svg", iconSize: [14, 14] })


const platformsData = JSON.parse(document.getElementById("platforms-geojson").innerHTML)
const platforms = new GeoJSON(platformsData, {


@@ 13,6 15,7 @@ const platforms = new GeoJSON(platformsData, {
      GTFS ID: ${feature.properties.ref}<br />
      Use count: ${feature.properties.use_count}
    `
    const icon = feature.properties.matched ? blueIcon : redIcon

    return new Marker(latlng, { icon }).bindPopup(popup).bindTooltip(feature.properties.name)
  },

M lib/triglav/public_transport/schemas/platform.ex => lib/triglav/public_transport/schemas/platform.ex +6 -1
@@ 19,6 19,11 @@ defmodule Triglav.PublicTransport.Schemas.Platform do
  end

  def to_feature(%__MODULE__{} = platform) do
    GeoJSON.feature(platform.geometry, Map.take(platform, [:ref, :name, :use_count]))
    properties =
      platform
      |> Map.take([:ref, :name, :use_count])
      |> Map.put(:matched, platform.mappings != [])

    GeoJSON.feature(platform.geometry, properties)
  end
end

M lib/triglav_web/templates/public_transport/stops.html.heex => lib/triglav_web/templates/public_transport/stops.html.heex +66 -52
@@ 2,62 2,76 @@

<.navbar conn={@conn} feed={@feed} />

<main role="main" class="container">
  <h1>Stops</h1>
<main role="main" class="">
  <div class="grid grid-cols-2">
    <div id="stops-map" class="h-full w-full"></div>

  <p>
    Showing stops imported from operator data and corresponding OSM platforms,
    matched using the <code>gtfs:stop_id</code> tag on OSM platforms.
  </p>
    <div style="height: calc(100vh - 60px - 48px)" class="px-5 py-3 overflow-y-scroll">
      <h1>Stops</h1>

  <div id="stops-map" class="h-[600px] w-full my-4"></div>
      <p>
        Showing stops imported from operator data and corresponding OSM platforms,
        matched using the <code>gtfs:stop_id</code> tag on OSM platforms.
      </p>

  <%= if @show_unused do %>
    <p>
      Showing <%= @count %> stops, including those which are not used in any route.<br />
      <a href="?" class="h-6 button">Show used</a>
    </p>
  <% else %>
    <p>
      Showing <%= length(@platforms) %> stops which are used in a route.<br />
      <a href="?show_unused=1" class="h-6 button">Show all</a>
    </p>
  <% end %>

  <table>
    <thead>
      <tr>
        <th>Stop ID</th>
        <th>Name</th>
        <th>Use count</th>
        <th>OSM platform</th>
        <th>Distance</th>
      </tr>
    </thead>
    <tbody>
      <%= for platform <- @platforms,
              mappings = (if length(platform.mappings) > 0, do: platform.mappings, else: [nil]),
              mapping <- mappings do %>
        <tr>
          <td><%= platform.ref %></td>
          <td><%= platform.name %></td>
          <td class="text-right"><%= platform.use_count %></td>
          <td>
            <%= if mapping do %>
              <%= osm_link(mapping.way || mapping.node, name: true) %>
            <% else %>
              <p class="text-red-700 m-0">Not found</p>
            <% end %>
          </td>
          <td class="text-right">
            <%= if mapping do %>
              <%= format_float(mapping.distance, 1) %>m
            <% end %>
          </td>
        </tr>
      <%= if @show_unused do %>
        <p>
          Showing <%= @count %> stops, including those which are not used in any route.<br />
          <a href="?" class="h-6 button">Show used</a>
        </p>
      <% else %>
        <p>
          Showing <%= length(@platforms) %> stops which are used in a route.<br />
          <a href="?show_unused=1" class="h-6 button">Show all</a>
        </p>
      <% end %>
    </tbody>
  </table>

      <table>
        <thead>
          <tr>
            <th>Stop ID</th>
            <th>Name</th>
            <th>Use count</th>
            <th>OSM platform</th>
            <th>Distance</th>
            <th>JOSM</th>
          </tr>
        </thead>
        <tbody>
          <%= for platform <- @platforms,
                  mappings = (if length(platform.mappings) > 0, do: platform.mappings, else: [nil]),
                  mapping <- mappings do %>
            <tr>
              <td><%= platform.ref %></td>
              <td><%= platform.name %></td>
              <td class="text-right"><%= platform.use_count %></td>
              <td>
                <%= if mapping do %>
                  <%= osm_link(mapping.way || mapping.node, name: true) %>
                <% else %>
                  <p class="text-red-700 m-0">Not found</p>
                <% end %>
              </td>
              <td class="text-right">
                <%= if mapping do %>
                  <%= format_float(mapping.distance, 1) %>m
                <% end %>
              </td>
              <td>
                <% {lon, lat} = platform.geometry.coordinates %>
                <%= josm_zoom(lat, lon, title: "Zoom") %>
                <%= if mapping do %>
                  <%= josm_load_objects([mapping.way || mapping.node], title: "Load") %>
                <% else %>
                  <%= josm_add_platform_node(@feed.operator, platform) %>
                <% end %>
              </td>
            </tr>
          <% end %>
        </tbody>
      </table>
    </div>
  </div>
</main>

<script id="platforms-geojson" type="application/json"><%= raw(@platforms_geojson) %></script>

A priv/static/images/stop_red.svg => priv/static/images/stop_red.svg +6 -0
@@ 0,0 1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Adapted from Font Awesome https://fontawesome.com/license -->
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="0 0 512 512" version="1.1">
  <circle cx="256" cy="256" r="256" fill="#b91c1c" />
  <path fill="#ffffff" d="m 415.83471,167.81533 h -5.51154 v -33.06925 c 0,-30.86464 -68.34312,-55.11542 -154.32317,-55.11542 -85.98005,0 -154.32317,24.25078 -154.32317,55.11542 v 33.06925 h -5.511545 c -9.128491,0 -16.534625,7.39924 -16.534625,16.53462 v 55.11542 c 0,9.1285 7.406134,16.53463 16.534625,16.53463 h 5.511545 v 110.23084 c 0,12.17361 9.87255,22.04616 22.04616,22.04616 v 22.04617 c 0,12.17361 9.87256,22.04617 22.04617,22.04617 h 22.04617 c 12.17362,0 22.04617,-9.87256 22.04617,-22.04617 V 388.277 h 132.277 v 22.04617 c 0,12.17361 9.87255,22.04617 22.04616,22.04617 h 22.04618 c 12.17361,0 22.04616,-9.87256 22.04616,-22.04617 V 388.277 h 4.40923 c 11.02309,0 17.63694,-8.81847 17.63694,-17.63693 V 256 h 5.51154 c 9.12849,0 16.53463,-7.40613 16.53463,-16.53463 v -55.11542 c 0,-9.13538 -7.40614,-16.53462 -16.53463,-16.53462 z M 189.8615,129.23453 c 0,-3.04512 2.46641,-5.51154 5.51154,-5.51154 h 121.25392 c 3.04512,0 5.51154,2.46642 5.51154,5.51154 v 11.02309 c 0,3.04513 -2.46642,5.51154 -5.51154,5.51154 H 195.37304 c -3.04513,0 -5.51154,-2.46641 -5.51154,-5.51154 z m -33.06925,225.97322 c -12.17363,0 -22.04617,-9.87255 -22.04617,-22.04617 0,-12.17362 9.87254,-22.04616 22.04617,-22.04616 12.17362,0 22.04616,9.87254 22.04616,22.04616 0,12.17362 -9.87254,22.04617 -22.04616,22.04617 z m 88.18466,-77.16159 h -77.16158 c -12.17362,0 -22.04617,-9.87254 -22.04617,-22.04616 v -66.1385 c 0,-12.17362 9.87255,-22.04617 22.04617,-22.04617 h 77.16158 z m 22.04618,0 V 167.81533 h 77.16157 c 12.17362,0 22.04618,9.87255 22.04618,22.04617 V 256 c 0,12.17362 -9.87256,22.04616 -22.04618,22.04616 z m 88.18466,77.16159 c -12.17362,0 -22.04617,-9.87255 -22.04617,-22.04617 0,-12.17362 9.87255,-22.04616 22.04617,-22.04616 12.17362,0 22.04617,9.87254 22.04617,22.04616 0,12.17362 -9.87255,22.04617 -22.04617,22.04617 z" />
</svg>