rewrite
This commit is contained in:
parent
ba8f072d23
commit
2c935df494
110 changed files with 1350 additions and 8011 deletions
9
eisrom_ui/lib/eisrom_ui.ex
Normal file
9
eisrom_ui/lib/eisrom_ui.ex
Normal file
|
@ -0,0 +1,9 @@
|
|||
defmodule EisromUi do
|
||||
@moduledoc """
|
||||
EisromUi keeps the contexts that define your domain
|
||||
and business logic.
|
||||
|
||||
Contexts are also responsible for managing your data, regardless
|
||||
if it comes from the database, an external API or others.
|
||||
"""
|
||||
end
|
33
eisrom_ui/lib/eisrom_ui/application.ex
Normal file
33
eisrom_ui/lib/eisrom_ui/application.ex
Normal file
|
@ -0,0 +1,33 @@
|
|||
defmodule EisromUi.Application do
|
||||
# See https://hexdocs.pm/elixir/Application.html
|
||||
# for more information on OTP Applications
|
||||
@moduledoc false
|
||||
|
||||
use Application
|
||||
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
children = [
|
||||
# Start the Telemetry supervisor
|
||||
EisromUiWeb.Telemetry,
|
||||
# Start the PubSub system
|
||||
{Phoenix.PubSub, name: EisromUi.PubSub},
|
||||
# Start the Endpoint (http/https)
|
||||
EisromUiWeb.Endpoint,
|
||||
{Eisrom.Morse.Server, nil}
|
||||
]
|
||||
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: EisromUi.Supervisor]
|
||||
Supervisor.start_link(children, opts)
|
||||
end
|
||||
|
||||
# Tell Phoenix to update the endpoint configuration
|
||||
# whenever the application is updated.
|
||||
@impl true
|
||||
def config_change(changed, _new, removed) do
|
||||
EisromUiWeb.Endpoint.config_change(changed, removed)
|
||||
:ok
|
||||
end
|
||||
end
|
64
eisrom_ui/lib/eisrom_ui/morse/server.ex
Normal file
64
eisrom_ui/lib/eisrom_ui/morse/server.ex
Normal file
|
@ -0,0 +1,64 @@
|
|||
defmodule Eisrom.Morse.Server do
|
||||
use GenServer
|
||||
|
||||
def start_link(_) do
|
||||
GenServer.start_link(__MODULE__, {nil, 0}, name: __MODULE__)
|
||||
end
|
||||
|
||||
def toggle_morse do
|
||||
GenServer.call(__MODULE__, :toggle)
|
||||
end
|
||||
|
||||
def update_progress(progress) do
|
||||
GenServer.cast(__MODULE__, {:progress, progress})
|
||||
end
|
||||
|
||||
def progress do
|
||||
GenServer.call(__MODULE__, :progress)
|
||||
end
|
||||
|
||||
def in_progress? do
|
||||
GenServer.call(__MODULE__, :in_progress?)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(state) do
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_call(:toggle, _from, {pid, _progress}) do
|
||||
if worker_alive?(pid) do
|
||||
EisromUi.Morse.Worker.kill(pid)
|
||||
Phoenix.PubSub.broadcast(EisromUi.PubSub, "morse_progress", 0)
|
||||
# apply(pubsub(), :broadcast, [EisromUi.PubSub, "morse_progress", 0])
|
||||
{:reply, :ok, {nil, 0}}
|
||||
else
|
||||
pid = spawn(&Eisrom.Morse.Worker.signal/0)
|
||||
{:reply, :ok, {pid, 0}}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call(:progress, _from, {_pid, progress} = state) do
|
||||
{:reply, progress, state}
|
||||
end
|
||||
|
||||
def handle_call(:in_progress?, _from, {pid, _progress} = state) do
|
||||
{:reply, worker_alive?(pid), state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_cast({:progress, new_progress}, {pid, _progress}) do
|
||||
Phoenix.PubSub.broadcast(EiromUi.PubSub, "morse_progress", new_progress)
|
||||
# apply(pubsub(), :broadcast, [EisromUi.PubSub, "morse_progress", new_progress])
|
||||
{:noreply, {pid, new_progress}}
|
||||
end
|
||||
|
||||
defp pubsub do
|
||||
Application.fetch_env!(:eisrom_ui, :pubsub)
|
||||
end
|
||||
|
||||
defp worker_alive?(pid) do
|
||||
pid != nil and Process.alive?(pid)
|
||||
end
|
||||
end
|
90
eisrom_ui/lib/eisrom_ui/morse/worker.ex
Normal file
90
eisrom_ui/lib/eisrom_ui/morse/worker.ex
Normal file
|
@ -0,0 +1,90 @@
|
|||
defmodule Eisrom.Morse.Worker do
|
||||
@moduledoc """
|
||||
Functions to control the signal lamp connected with GPIO.
|
||||
"""
|
||||
|
||||
@sleep_short 200
|
||||
@sleep_delay 400
|
||||
@sleep_long 700
|
||||
@sleep_pause 1000
|
||||
@sleep_start 3000
|
||||
|
||||
@on 0
|
||||
@off 1
|
||||
|
||||
@doc """
|
||||
Signal the provided morse symbols using the GPIO.
|
||||
"""
|
||||
|
||||
def signal do
|
||||
code = secret_code()
|
||||
code_length = length(code)
|
||||
|
||||
update_progress(0, 100)
|
||||
|
||||
toggle_lamp(@off)
|
||||
Process.sleep(@sleep_start)
|
||||
|
||||
code
|
||||
|> Enum.with_index()
|
||||
|> Enum.each(&signal_symbol(&1, code_length))
|
||||
|
||||
update_progress(100, 100)
|
||||
end
|
||||
|
||||
def kill(pid) do
|
||||
Process.exit(pid, :kill)
|
||||
toggle_lamp(@off)
|
||||
end
|
||||
|
||||
defp signal_symbol({?., _index}, _length) do
|
||||
toggle_lamp(@on)
|
||||
Process.sleep(@sleep_short)
|
||||
toggle_lamp(@off)
|
||||
Process.sleep(@sleep_delay)
|
||||
end
|
||||
|
||||
defp signal_symbol({?-, _index}, _length) do
|
||||
toggle_lamp(@on)
|
||||
Process.sleep(@sleep_long)
|
||||
toggle_lamp(@off)
|
||||
Process.sleep(@sleep_delay)
|
||||
end
|
||||
|
||||
defp signal_symbol({?\s, index}, length) do
|
||||
update_progress(index, length)
|
||||
Process.sleep(@sleep_pause)
|
||||
end
|
||||
|
||||
defp update_progress(index, length) do
|
||||
Eisrom.Morse.Server.update_progress(index / length * 100)
|
||||
end
|
||||
|
||||
defp secret_code do
|
||||
Application.fetch_env!(:eisrom_ui, :morse_message)
|
||||
|> String.to_charlist()
|
||||
end
|
||||
|
||||
# Communicate with a deployed esrom node, if running on a host.
|
||||
case Application.get_env(:eisrom_ui, :target) do
|
||||
:host ->
|
||||
@esrom_node :"esrom@esrom.lan"
|
||||
|
||||
def toggle_lamp(state) do
|
||||
# Check if the deployed esrom node is online.
|
||||
if :pong == Node.ping(@esrom_node) do
|
||||
:rpc.call(@esrom_node, Eisrom.Morse.Worker, :toggle_lamp, [state])
|
||||
end
|
||||
end
|
||||
|
||||
_ ->
|
||||
def toggle_lamp(state) do
|
||||
{:ok, gpio} = Circuits.GPIO.open(relay_pin(), :output)
|
||||
Circuits.GPIO.write(gpio, state)
|
||||
end
|
||||
|
||||
defp relay_pin() do
|
||||
Application.fetch_env!(:eisrom_ui, :relay_pin)
|
||||
end
|
||||
end
|
||||
end
|
107
eisrom_ui/lib/eisrom_ui_web.ex
Normal file
107
eisrom_ui/lib/eisrom_ui_web.ex
Normal file
|
@ -0,0 +1,107 @@
|
|||
defmodule EisromUiWeb do
|
||||
@moduledoc """
|
||||
The entrypoint for defining your web interface, such
|
||||
as controllers, views, channels and so on.
|
||||
|
||||
This can be used in your application as:
|
||||
|
||||
use EisromUiWeb, :controller
|
||||
use EisromUiWeb, :view
|
||||
|
||||
The definitions below will be executed for every view,
|
||||
controller, etc, so keep them short and clean, focused
|
||||
on imports, uses and aliases.
|
||||
|
||||
Do NOT define functions inside the quoted expressions
|
||||
below. Instead, define any helper function in modules
|
||||
and import those modules here.
|
||||
"""
|
||||
|
||||
def controller do
|
||||
quote do
|
||||
use Phoenix.Controller, namespace: EisromUiWeb
|
||||
|
||||
import Plug.Conn
|
||||
alias EisromUiWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
def view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
root: "lib/eisrom_ui_web/templates",
|
||||
namespace: EisromUiWeb
|
||||
|
||||
# Import convenience functions from controllers
|
||||
import Phoenix.Controller,
|
||||
only: [get_flash: 1, get_flash: 2, view_module: 1, view_template: 1]
|
||||
|
||||
# Include shared imports and aliases for views
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def live_view do
|
||||
quote do
|
||||
use Phoenix.LiveView,
|
||||
layout: {EisromUiWeb.LayoutView, "live.html"}
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def live_component do
|
||||
quote do
|
||||
use Phoenix.LiveComponent
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def component do
|
||||
quote do
|
||||
use Phoenix.Component
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def router do
|
||||
quote do
|
||||
use Phoenix.Router
|
||||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
import Phoenix.LiveView.Router
|
||||
end
|
||||
end
|
||||
|
||||
def channel do
|
||||
quote do
|
||||
use Phoenix.Channel
|
||||
end
|
||||
end
|
||||
|
||||
defp view_helpers do
|
||||
quote do
|
||||
# Use all HTML functionality (forms, tags, etc)
|
||||
use Phoenix.HTML
|
||||
|
||||
# Import LiveView and .heex helpers (live_render, live_patch, <.form>, etc)
|
||||
import Phoenix.LiveView.Helpers
|
||||
|
||||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
||||
import EisromUiWeb.ErrorHelpers
|
||||
alias EisromUiWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
When used, dispatch to the appropriate controller/view/etc.
|
||||
"""
|
||||
defmacro __using__(which) when is_atom(which) do
|
||||
apply(__MODULE__, which, [])
|
||||
end
|
||||
end
|
15
eisrom_ui/lib/eisrom_ui_web/controllers/page_controller.ex
Normal file
15
eisrom_ui/lib/eisrom_ui_web/controllers/page_controller.ex
Normal file
|
@ -0,0 +1,15 @@
|
|||
defmodule EisromUiWeb.PageController do
|
||||
use EisromUiWeb, :controller
|
||||
|
||||
def index(conn, _params) do
|
||||
send_resp(conn, 204, "")
|
||||
end
|
||||
|
||||
def instructions(conn, _params) do
|
||||
render(conn, :instructions)
|
||||
end
|
||||
|
||||
def morse(conn, _params) do
|
||||
Phoenix.LiveView.Controller.live_render(conn, EisromUiWeb.MorseLive)
|
||||
end
|
||||
end
|
49
eisrom_ui/lib/eisrom_ui_web/endpoint.ex
Normal file
49
eisrom_ui/lib/eisrom_ui_web/endpoint.ex
Normal file
|
@ -0,0 +1,49 @@
|
|||
defmodule EisromUiWeb.Endpoint do
|
||||
use Phoenix.Endpoint, otp_app: :eisrom_ui
|
||||
|
||||
# The session will be stored in the cookie and signed,
|
||||
# this means its contents can be read but not tampered with.
|
||||
# Set :encryption_salt if you would also like to encrypt it.
|
||||
@session_options [
|
||||
store: :cookie,
|
||||
key: "_eisrom_ui_key",
|
||||
signing_salt: "lolEkmxx"
|
||||
]
|
||||
|
||||
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
|
||||
|
||||
# Serve at "/" the static files from "priv/static" directory.
|
||||
#
|
||||
# You should set gzip to true if you are running phx.digest
|
||||
# when deploying your static files in production.
|
||||
plug Plug.Static,
|
||||
at: "/",
|
||||
from: :eisrom_ui,
|
||||
gzip: false,
|
||||
only: ~w(assets fonts images favicon.ico robots.txt)
|
||||
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
|
||||
plug Phoenix.LiveReloader
|
||||
plug Phoenix.CodeReloader
|
||||
end
|
||||
|
||||
plug Phoenix.LiveDashboard.RequestLogger,
|
||||
param_key: "request_logger",
|
||||
cookie_key: "request_logger"
|
||||
|
||||
plug Plug.RequestId
|
||||
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
|
||||
|
||||
plug Plug.Parsers,
|
||||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Phoenix.json_library()
|
||||
|
||||
plug Plug.MethodOverride
|
||||
plug Plug.Head
|
||||
plug Plug.Session, @session_options
|
||||
plug EisromUiWeb.Router
|
||||
end
|
39
eisrom_ui/lib/eisrom_ui_web/live/morse_live.ex
Normal file
39
eisrom_ui/lib/eisrom_ui_web/live/morse_live.ex
Normal file
|
@ -0,0 +1,39 @@
|
|||
defmodule EisromUiWeb.MorseLive do
|
||||
use Phoenix.LiveView
|
||||
require Logger
|
||||
|
||||
@topic "morse_progress"
|
||||
|
||||
def render(assigns) do
|
||||
EisromUiWeb.PageView.render("morse.html", assigns)
|
||||
end
|
||||
|
||||
def mount(_params, _session, socket) do
|
||||
EisromUiWeb.Endpoint.subscribe(@topic)
|
||||
{:ok, assign(socket, default_assigns())}
|
||||
end
|
||||
|
||||
def handle_event("toggle_morse", _value, socket) do
|
||||
Logger.info("Button pressed!")
|
||||
|
||||
Eisrom.Morse.Server.toggle_morse()
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
|
||||
def handle_event("toggle_hint", _value, socket) do
|
||||
{:noreply, update(socket, :hints_visible, &(not &1))}
|
||||
end
|
||||
|
||||
def handle_info(progress, socket) do
|
||||
{:noreply, assign(socket, progress: progress, in_progress?: Eisrom.Morse.Server.in_progress?())}
|
||||
end
|
||||
|
||||
defp default_assigns do
|
||||
[
|
||||
progress: Eisrom.Morse.Server.progress(),
|
||||
in_progress?: Eisrom.Morse.Server.in_progress?(),
|
||||
hints_visible: false
|
||||
]
|
||||
end
|
||||
end
|
52
eisrom_ui/lib/eisrom_ui_web/router.ex
Normal file
52
eisrom_ui/lib/eisrom_ui_web/router.ex
Normal file
|
@ -0,0 +1,52 @@
|
|||
defmodule EisromUiWeb.Router do
|
||||
use EisromUiWeb, :router
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_live_flash
|
||||
plug :put_root_layout, {EisromUiWeb.LayoutView, :root}
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
end
|
||||
|
||||
scope "/", EisromUiWeb do
|
||||
pipe_through :browser
|
||||
|
||||
get "/", PageController, :index
|
||||
|
||||
get "/ZZZZ", PageController, :instructions
|
||||
get "/morse", PageController, :instructions
|
||||
get "/esrom", PageController, :instructions
|
||||
|
||||
get "/0B13", PageController, :morse
|
||||
get "/OB13", PageController, :morse
|
||||
get "/seinlamp", PageController, :morse
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
# scope "/api", EisromUiWeb do
|
||||
# pipe_through :api
|
||||
# end
|
||||
|
||||
# Enables LiveDashboard only for development
|
||||
#
|
||||
# If you want to use the LiveDashboard in production, you should put
|
||||
# it behind authentication and allow only admins to access it.
|
||||
# If your application does not have an admins-only section yet,
|
||||
# you can use Plug.BasicAuth to set up some basic authentication
|
||||
# as long as you are also using SSL (which you should anyway).
|
||||
if Mix.env() in [:dev, :test] do
|
||||
import Phoenix.LiveDashboard.Router
|
||||
|
||||
scope "/" do
|
||||
pipe_through :browser
|
||||
|
||||
live_dashboard "/dashboard", metrics: EisromUiWeb.Telemetry
|
||||
end
|
||||
end
|
||||
end
|
48
eisrom_ui/lib/eisrom_ui_web/telemetry.ex
Normal file
48
eisrom_ui/lib/eisrom_ui_web/telemetry.ex
Normal file
|
@ -0,0 +1,48 @@
|
|||
defmodule EisromUiWeb.Telemetry do
|
||||
use Supervisor
|
||||
import Telemetry.Metrics
|
||||
|
||||
def start_link(arg) do
|
||||
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
|
||||
end
|
||||
|
||||
@impl true
|
||||
def init(_arg) do
|
||||
children = [
|
||||
# Telemetry poller will execute the given period measurements
|
||||
# every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
|
||||
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
|
||||
# Add reporters as children of your supervision tree.
|
||||
# {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
|
||||
]
|
||||
|
||||
Supervisor.init(children, strategy: :one_for_one)
|
||||
end
|
||||
|
||||
def metrics do
|
||||
[
|
||||
# Phoenix Metrics
|
||||
summary("phoenix.endpoint.stop.duration",
|
||||
unit: {:native, :millisecond}
|
||||
),
|
||||
summary("phoenix.router_dispatch.stop.duration",
|
||||
tags: [:route],
|
||||
unit: {:native, :millisecond}
|
||||
),
|
||||
|
||||
# VM Metrics
|
||||
summary("vm.memory.total", unit: {:byte, :kilobyte}),
|
||||
summary("vm.total_run_queue_lengths.total"),
|
||||
summary("vm.total_run_queue_lengths.cpu"),
|
||||
summary("vm.total_run_queue_lengths.io")
|
||||
]
|
||||
end
|
||||
|
||||
defp periodic_measurements do
|
||||
[
|
||||
# A module, function and arguments to be invoked periodically.
|
||||
# This function must call :telemetry.execute/3 and a metric must be added above.
|
||||
# {EisromUiWeb, :count_users, []}
|
||||
]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
<main role="main" class="container">
|
||||
<p class="alert alert-info" role="alert"><%= get_flash(@conn, :info) %></p>
|
||||
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
|
||||
<%= @inner_content %>
|
||||
</main>
|
11
eisrom_ui/lib/eisrom_ui_web/templates/layout/live.html.heex
Normal file
11
eisrom_ui/lib/eisrom_ui_web/templates/layout/live.html.heex
Normal file
|
@ -0,0 +1,11 @@
|
|||
<main role="main" class="container">
|
||||
<p class="alert alert-info" role="alert"
|
||||
phx-click="lv:clear-flash"
|
||||
phx-value-key="info"><%= live_flash(@flash, :info) %></p>
|
||||
|
||||
<p class="alert alert-danger" role="alert"
|
||||
phx-click="lv:clear-flash"
|
||||
phx-value-key="error"><%= live_flash(@flash, :error) %></p>
|
||||
|
||||
<%= @inner_content %>
|
||||
</main>
|
15
eisrom_ui/lib/eisrom_ui_web/templates/layout/root.html.heex
Normal file
15
eisrom_ui/lib/eisrom_ui_web/templates/layout/root.html.heex
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta name="csrf-token" content={csrf_token_value()}>
|
||||
<title>Esrom Geocache</title>
|
||||
<link phx-track-static rel="stylesheet" href={Routes.static_path(@conn, "/assets/app.css")}/>
|
||||
<script defer phx-track-static type="text/javascript" src={Routes.static_path(@conn, "/assets/app.js")}></script>
|
||||
</head>
|
||||
<body>
|
||||
<%= @inner_content %>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
<p>Welcome geocacher, you will need to go to the first coordinate and start from there.</p>
|
||||
<p>Good luck!</p>
|
28
eisrom_ui/lib/eisrom_ui_web/templates/page/morse.html.heex
Normal file
28
eisrom_ui/lib/eisrom_ui_web/templates/page/morse.html.heex
Normal file
|
@ -0,0 +1,28 @@
|
|||
<h1>Welcome to <a href="https://www.geocaching.com/geocache/GC7C642_esrom">Esrom</a>!</h1>
|
||||
<h2>en:<br>Push the Start button below to get <span style="color:red">UVW</span><span style="color:blue">XYZ</span>. You can find the geocache at N 52° 40.<span style="color:red">UVW</span>' E 004° 53.<span style="color:blue">XYZ</span>'</h2>
|
||||
<h2>nl:<br>Druk op de Start knop hieronder om <span style="color:red">UVW</span><span style="color:blue">XYZ</span> te vinden. Je kunt dan de geocache vinden op N 52° 40.<span style="color:red">UVW</span>' E 004° 53.<span style="color:blue">XYZ</span>'</h2>
|
||||
|
||||
<div id="buttonwrap">
|
||||
<%= if @in_progress? do %>
|
||||
<button phx-click="toggle_morse" class="button stop">Stop</button>
|
||||
<% else %>
|
||||
<button phx-click="toggle_morse" class="button">Start</button>
|
||||
<% end %>
|
||||
<div id="response-block">
|
||||
<h2>Progress:</h2>
|
||||
<progress max="100" value={@progress}>
|
||||
<%= @progress %>%
|
||||
</progress>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="http://www.geochecker.com/index.php?code=de602fd6ce063e4acdfd69dacd1f081e&action=check&wp=47433743363432&name=4573726f6d">en: check your coordinate on GeoChecker.com nl: controleer je coördinaat op GeoChecker.</a>
|
||||
<br>
|
||||
<br>
|
||||
<button phx-click="toggle_hint" id="hintButton">Click here for a hint!</button>
|
||||
<div id="givehint" style={"visibility:" <> (if @hints_visible, do: "visible", else: "hidden")}>
|
||||
<p>en: Position yourself on the bridge. Watch carefully around to windows of houses, remember this is a nightly geocache. During daytime it is quite hard to see, but not impossible. After pushing the button, it takes 3
|
||||
seconds to start. The whole process takes about 35 sec. You can start it all over again as much as you like. In case you are really stuck, you could try to contact me via WhatsApp on number +31 6 41633689. Best of luck to you!</p>
|
||||
<p>nl: Ga op de brug staan. Kijk goed om je heen naar ramen van woningen en realiseer je dat dit een een nachtcache is. Overdag is het slecht te zien, maar niet onmogelijk. Na het indrukken van de knop duurt het 3 seconden
|
||||
voordat het begint. Het hele proces duurt ongeveer 35 sec. Je kunt het zo vaak starten als je wilt. Als het helemaal niet lukt zou je me kunnen proberen te bereiken via WhatsApp nummer 06-41633689. Veel plezier!</p>
|
||||
</div>
|
30
eisrom_ui/lib/eisrom_ui_web/views/error_helpers.ex
Normal file
30
eisrom_ui/lib/eisrom_ui_web/views/error_helpers.ex
Normal file
|
@ -0,0 +1,30 @@
|
|||
defmodule EisromUiWeb.ErrorHelpers do
|
||||
@moduledoc """
|
||||
Conveniences for translating and building error messages.
|
||||
"""
|
||||
|
||||
use Phoenix.HTML
|
||||
|
||||
@doc """
|
||||
Generates tag for inlined form input errors.
|
||||
"""
|
||||
def error_tag(form, field) do
|
||||
Enum.map(Keyword.get_values(form.errors, field), fn error ->
|
||||
content_tag(:span, translate_error(error),
|
||||
class: "invalid-feedback",
|
||||
phx_feedback_for: input_name(form, field)
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Translates an error message.
|
||||
"""
|
||||
def translate_error({msg, opts}) do
|
||||
# Because the error messages we show in our forms and APIs
|
||||
# are defined inside Ecto, we need to translate them dynamically.
|
||||
Enum.reduce(opts, msg, fn {key, value}, acc ->
|
||||
String.replace(acc, "%{#{key}}", fn _ -> to_string(value) end)
|
||||
end)
|
||||
end
|
||||
end
|
16
eisrom_ui/lib/eisrom_ui_web/views/error_view.ex
Normal file
16
eisrom_ui/lib/eisrom_ui_web/views/error_view.ex
Normal file
|
@ -0,0 +1,16 @@
|
|||
defmodule EisromUiWeb.ErrorView do
|
||||
use EisromUiWeb, :view
|
||||
|
||||
# If you want to customize a particular status code
|
||||
# for a certain format, you may uncomment below.
|
||||
# def render("500.html", _assigns) do
|
||||
# "Internal Server Error"
|
||||
# end
|
||||
|
||||
# By default, Phoenix returns the status message from
|
||||
# the template name. For example, "404.html" becomes
|
||||
# "Not Found".
|
||||
def template_not_found(template, _assigns) do
|
||||
Phoenix.Controller.status_message_from_template(template)
|
||||
end
|
||||
end
|
7
eisrom_ui/lib/eisrom_ui_web/views/layout_view.ex
Normal file
7
eisrom_ui/lib/eisrom_ui_web/views/layout_view.ex
Normal file
|
@ -0,0 +1,7 @@
|
|||
defmodule EisromUiWeb.LayoutView do
|
||||
use EisromUiWeb, :view
|
||||
|
||||
# Phoenix LiveDashboard is available only in development by default,
|
||||
# so we instruct Elixir to not warn if the dashboard route is missing.
|
||||
@compile {:no_warn_undefined, {Routes, :live_dashboard_path, 2}}
|
||||
end
|
3
eisrom_ui/lib/eisrom_ui_web/views/page_view.ex
Normal file
3
eisrom_ui/lib/eisrom_ui_web/views/page_view.ex
Normal file
|
@ -0,0 +1,3 @@
|
|||
defmodule EisromUiWeb.PageView do
|
||||
use EisromUiWeb, :view
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue