summaryrefslogtreecommitdiff
path: root/lib/lsg_web
diff options
context:
space:
mode:
authorhref <href@random.sh>2021-09-01 10:30:18 +0200
committerhref <href@random.sh>2021-09-01 10:30:18 +0200
commit75687711f35355bc30e4829439384aab28fcac6d (patch)
tree8f3256f472893c39720a684d390e890a152f7303 /lib/lsg_web
parentlink: post_* callbacks; html & pdftitle. (diff)
Commit all the changes that hasn't been committed + updates.
Diffstat (limited to 'lib/lsg_web')
-rw-r--r--lib/lsg_web/controllers/alcoolog_controller.ex263
-rw-r--r--lib/lsg_web/controllers/irc_controller.ex9
-rw-r--r--lib/lsg_web/router.ex11
-rw-r--r--lib/lsg_web/templates/alcoolog/index.html.eex222
-rw-r--r--lib/lsg_web/templates/alcoolog/user.html.eex170
-rw-r--r--lib/lsg_web/templates/irc/index.html.eex25
-rw-r--r--lib/lsg_web/templates/irc/txt.html.eex22
-rw-r--r--lib/lsg_web/templates/irc/txts.html.eex35
-rw-r--r--lib/lsg_web/templates/layout/app.html.eex135
-rw-r--r--lib/lsg_web/templates/page/user.html.eex2
-rw-r--r--lib/lsg_web/views/alcoolog_view.ex2
-rw-r--r--lib/lsg_web/views/layout_view.ex7
12 files changed, 800 insertions, 103 deletions
diff --git a/lib/lsg_web/controllers/alcoolog_controller.ex b/lib/lsg_web/controllers/alcoolog_controller.ex
index b88faa3..6542f15 100644
--- a/lib/lsg_web/controllers/alcoolog_controller.ex
+++ b/lib/lsg_web/controllers/alcoolog_controller.ex
@@ -16,6 +16,166 @@ defmodule LSGWeb.AlcoologController do
end
end
+ def nick(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ days = String.to_integer(Map.get(params, "days", "180"))
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ if friend? do
+ stats = LSG.IRC.AlcoologPlugin.get_full_statistics(profile_account.id)
+ history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- LSG.IRC.AlcoologPlugin.nick_history(profile_account) do
+ %{
+ at: ts |> DateTime.from_unix!(:millisecond),
+ points: points,
+ active: active,
+ cl: cl,
+ deg: deg,
+ type: type,
+ description: descr,
+ meta: meta
+ }
+ end
+ history = Enum.sort(history, &(DateTime.compare(&1.at, &2.at) != :lt))
+ |> IO.inspect()
+ conn
+ |> assign(:title, "alcoolog #{nick}")
+ |> render("user.html", network: network, profile: profile_account, days: days, nick: nick, history: history, stats: stats)
+ else
+ conn
+ |> put_status(404)
+ |> text("Page not found")
+ end
+ end
+
+ def nick_stats_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ if friend? do
+ stats = LSG.IRC.AlcoologPlugin.get_full_statistics(profile_account.id)
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(stats))
+ else
+ conn
+ |> put_status(404)
+ |> json([])
+ end
+ end
+
+ def nick_gls_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ count = String.to_integer(Map.get(params, "days", "180"))
+ if friend? do
+ data = LSG.IRC.AlcoologPlugin.user_over_time_gl(profile_account, count)
+ delay = count*((24 * 60)*60)
+ now = DateTime.utc_now()
+ start_date = DateTime.utc_now()
+ |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
+ |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase)
+ |> DateTime.to_date()
+ |> Date.to_erl()
+ filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl))
+ |> Enum.to_list
+ |> Enum.map(&(:calendar.gregorian_days_to_date(&1)))
+ |> Enum.map(&Date.from_erl!(&1))
+ |> Enum.map(fn(date) ->
+ %{date: date, gls: Map.get(data, date, 0)}
+ end)
+ |> Enum.sort(&(Date.compare(&1.date, &2.date) != :gt))
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(filled))
+ else
+ conn
+ |> put_status(404)
+ |> json([])
+ end
+ end
+
+
+
+ def nick_volumes_json(conn = %{assigns: %{account: account}}, params = %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ count = String.to_integer(Map.get(params, "days", "180"))
+ if friend? do
+ data = LSG.IRC.AlcoologPlugin.user_over_time(profile_account, count)
+ delay = count*((24 * 60)*60)
+ now = DateTime.utc_now()
+ start_date = DateTime.utc_now()
+ |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
+ |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase)
+ |> DateTime.to_date()
+ |> Date.to_erl()
+ filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl))
+ |> Enum.to_list
+ |> Enum.map(&(:calendar.gregorian_days_to_date(&1)))
+ |> Enum.map(&Date.from_erl!(&1))
+ |> Enum.map(fn(date) ->
+ %{date: date, volumes: Map.get(data, date, 0)}
+ end)
+ |> Enum.sort(&(Date.compare(&1.date, &2.date) != :gt))
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(filled))
+ else
+ conn
+ |> put_status(404)
+ |> json([])
+ end
+ end
+
+ def nick_log_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ if friend? do
+ history = for {{nick, ts}, points, active, cl, deg, type, descr, meta} <- LSG.IRC.AlcoologPlugin.nick_history(profile_account) do
+ %{
+ at: ts |> DateTime.from_unix!(:millisecond) |> DateTime.to_iso8601(),
+ points: points,
+ active: active,
+ cl: cl,
+ deg: deg,
+ type: type,
+ description: descr,
+ meta: meta
+ }
+ end
+ last = List.last(history)
+ {_, active} = LSG.IRC.AlcoologPlugin.user_stats(profile_account)
+ last = %{last | active: active, at: DateTime.utc_now() |> DateTime.to_iso8601()}
+ history = history ++ [last]
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(history))
+ else
+ conn
+ |> put_status(404)
+ |> json([])
+ end
+ end
+
+ def nick_history_json(conn = %{assigns: %{account: account}}, %{"network" => network, "nick" => nick}) do
+ profile_account = IRC.Account.find_always_by_nick(network, nick, nick)
+ friend? = Enum.member?(IRC.Membership.friends(account), profile_account.id)
+ if friend? do
+ history = for {_, date, value} <- LSG.IRC.AlcoologAnnouncerPlugin.log(profile_account) do
+ %{date: DateTime.to_iso8601(date), value: value}
+ end
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(history))
+ else
+ conn
+ |> put_status(404)
+ |> json([])
+ end
+ end
+
def index(conn = %{assigns: %{account: account}}, %{"network" => network, "chan" => channel}) do
index(conn, account, network, LSGWeb.reformat_chan(channel))
end
@@ -40,16 +200,22 @@ defmodule LSGWeb.AlcoologController do
#end
def index(conn, account, network, channel) do
- aday = 18*((24 * 60)*60)
+ aday = ((24 * 60)*60)
now = DateTime.utc_now()
- before = now
- |> DateTime.add(-aday, :second)
- |> DateTime.to_unix(:millisecond)
+ before7 = now
+ |> DateTime.add(-(7*aday), :second)
+ |> DateTime.to_unix(:millisecond)
+ before15 = now
+ |> DateTime.add(-(15*aday), :second)
+ |> DateTime.to_unix(:millisecond)
+ before31 = now
+ |> DateTime.add(-(31*aday), :second)
+ |> DateTime.to_unix(:millisecond)
#match = :ets.fun2ms(fn(obj = {{^nick, date}, _, _, _, _}) when date > before -> obj end)
match = [
- {{{:_, :"$1"}, :_, :_, :_, :_},
+ {{{:_, :"$1"}, :_, :_, :_, :_, :_, :_, :_},
[
- {:>, :"$1", {:const, before}},
+ {:>, :"$1", {:const, before15}},
], [:"$_"]}
]
@@ -58,13 +224,13 @@ defmodule LSGWeb.AlcoologController do
members_ids = Enum.map(members, fn({account, _, nick}) -> account.id end)
member_names = Enum.reduce(members, %{}, fn({account, _, nick}, acc) -> Map.put(acc, account.id, nick) end)
drinks = :ets.select(LSG.IRC.AlcoologPlugin.ETS, match)
- |> Enum.filter(fn({{account, _}, _, _, _, _}) -> Enum.member?(members_ids, account) end)
- |> Enum.map(fn({{account, _}, _, _, _, _} = object) -> {object, Map.get(member_names, account)} end)
- |> Enum.sort_by(fn({{{_, ts}, _, _, _, _}, _}) -> ts end, &>/2)
+ |> Enum.filter(fn({{account, _}, _vol, _cur, _cl, _deg, _name, _cmt, _meta}) -> Enum.member?(members_ids, account) end)
+ |> Enum.map(fn({{account, _}, _, _, _, _, _, _, _} = object) -> {object, Map.get(member_names, account)} end)
+ |> Enum.sort_by(fn({{{_, ts}, _, _, _, _, _, _, _}, _}) -> ts end, &>/2)
stats = LSG.IRC.AlcoologPlugin.get_channel_statistics(account, network, channel)
- top = Enum.reduce(drinks, %{}, fn({{{account_id, _}, vol, _, _, _}, _}, acc) ->
+ top = Enum.reduce(drinks, %{}, fn({{{account_id, _}, vol, _, _, _, _, _, _}, _}, acc) ->
nick = Map.get(member_names, account_id)
all = Map.get(acc, nick, 0)
Map.put(acc, nick, all + vol)
@@ -77,4 +243,81 @@ defmodule LSGWeb.AlcoologController do
|> render("index.html", network: network, channel: channel, drinks: drinks, top: top, stats: stats)
end
+ def index_gls_json(conn = %{assigns: %{account: account}}, %{"network" => network, "chan" => channel}) do
+ count = 30
+ channel = LSGWeb.reformat_chan(channel)
+ members = IRC.Membership.expanded_members_or_friends(account, network, channel)
+ members_ids = Enum.map(members, fn({account, _, nick}) -> account.id end)
+ member_names = Enum.reduce(members, %{}, fn({account, _, nick}, acc) -> Map.put(acc, account.id, nick) end)
+ delay = count*((24 * 60)*60)
+ now = DateTime.utc_now()
+ start_date = DateTime.utc_now()
+ |> DateTime.shift_zone!("Europe/Paris", Tzdata.TimeZoneDatabase)
+ |> DateTime.add(-delay, :second, Tzdata.TimeZoneDatabase)
+ |> DateTime.to_date()
+ |> Date.to_erl()
+ filled = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl))
+ |> Enum.to_list
+ |> Enum.map(&(:calendar.gregorian_days_to_date(&1)))
+ |> Enum.map(&Date.from_erl!(&1))
+ |> Enum.map(fn(date) ->
+ {date, (for {a, _, _} <- members, into: Map.new, do: {Map.get(member_names, a.id, a.id), 0})}
+ end)
+ |> Enum.into(Map.new)
+
+ gls = Enum.reduce(members, filled, fn({account, _, _}, gls) ->
+ Enum.reduce(LSG.IRC.AlcoologPlugin.user_over_time_gl(account, count), gls, fn({date, gl}, gls) ->
+ u = Map.get(gls, date, %{})
+ |> Map.put(Map.get(member_names, account.id, account.id), gl)
+ Map.put(gls, date, u)
+ end)
+ end)
+
+ dates = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl))
+ |> Enum.to_list
+ |> Enum.map(&(:calendar.gregorian_days_to_date(&1)))
+ |> Enum.map(&Date.from_erl!(&1))
+
+ filled2 = Enum.map(member_names, fn({_, name}) ->
+ history = (:calendar.date_to_gregorian_days(start_date) .. :calendar.date_to_gregorian_days(DateTime.utc_now |> DateTime.to_date() |> Date.to_erl))
+ |> Enum.to_list
+ |> Enum.map(&(:calendar.gregorian_days_to_date(&1)))
+ |> Enum.map(&Date.from_erl!(&1))
+ |> Enum.map(fn(date) ->
+ get_in(gls, [date, name]) #%{date: date, gl: get_in(gls, [date, name])}
+ end)
+ if Enum.all?(history, fn(x) -> x == 0 end) do
+ nil
+ else
+ %{name: name, history: history}
+ end
+ end)
+ |> Enum.filter(fn(x) -> x end)
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> text(Jason.encode!(%{labels: dates, data: filled2}))
+ end
+
+ def minisync(conn, %{"user_id" => user_id, "key" => key, "value" => value}) do
+ account = IRC.Account.get(user_id)
+ if account do
+ ds = LSG.IRC.AlcoologPlugin.data_state()
+ meta = LSG.IRC.AlcoologPlugin.get_user_meta(ds, account.id)
+ case Float.parse(value) do
+ {val, _} ->
+ new_meta = Map.put(meta, String.to_existing_atom(key), val)
+ LSG.IRC.AlcoologPlugin.put_user_meta(ds, account.id, new_meta)
+ _ ->
+ conn
+ |> put_status(:unprocessable_entity)
+ |> text("invalid value")
+ end
+ else
+ conn
+ |> put_status(:not_found)
+ |> text("not found")
+ end
+ end
+
end
diff --git a/lib/lsg_web/controllers/irc_controller.ex b/lib/lsg_web/controllers/irc_controller.ex
index e0bf24d..317bb27 100644
--- a/lib/lsg_web/controllers/irc_controller.ex
+++ b/lib/lsg_web/controllers/irc_controller.ex
@@ -52,11 +52,16 @@ defmodule LSGWeb.IrcController do
conn.assigns[:chan] -> "/#{conn.assigns.network}/#{LSGWeb.format_chan(conn.assigns.chan)}"
true -> "/-"
end
- if Map.has_key?(data, txt) do
+ if lines = Map.get(data, txt) do
+ lines = Enum.map(lines, fn(line) ->
+ line
+ |> String.split("\\\\")
+ |> Enum.intersperse(Phoenix.HTML.Tag.tag(:br))
+ end)
conn
|> assign(:breadcrumbs, [{"txt", "#{base_url}/txt"}])
|> assign(:title, "#{txt}.txt")
- |> render("txt.html", name: txt, data: data[txt], doc: nil)
+ |> render("txt.html", name: txt, data: lines, doc: nil)
else
conn
|> put_status(404)
diff --git a/lib/lsg_web/router.ex b/lib/lsg_web/router.ex
index de7fafb..d681ed9 100644
--- a/lib/lsg_web/router.ex
+++ b/lib/lsg_web/router.ex
@@ -33,13 +33,20 @@ defmodule LSGWeb.Router do
get "/-/alcoolog", AlcoologController, :index
get "/-/alcoolog/~/:account_name", AlcoologController, :index
get "/:network", NetworkController, :index
+ get "/:network/~:nick/alcoolog", AlcoologController, :nick
+ get "/:network/~:nick/alcoolog/log.json", AlcoologController, :nick_log_json
+ get "/:network/~:nick/alcoolog/gls.json", AlcoologController, :nick_gls_json
+ get "/:network/~:nick/alcoolog/volumes.json", AlcoologController, :nick_volumes_json
+ get "/:network/~:nick/alcoolog/history.json", AlcoologController, :nick_history_json
+ get "/:network/~:nick/alcoolog/stats.json", AlcoologController, :nick_stats_json
+ get "/:network/:chan/alcoolog", AlcoologController, :index
+ get "/:network/:chan/alcoolog/gls.json", AlcoologController, :index_gls_json
+ put "/api/alcoolog/minisync/:user_id/meta/:key", AlcoologController, :minisync_put_meta
get "/:network/:chan", IrcController, :index
get "/:network/:chan/txt", IrcController, :txt
get "/:network/:chan/txt/:name", IrcController, :txt
get "/:network/:channel/preums", IrcController, :preums
- get "/:network/:chan/alcoolog", AlcoologController, :index
get "/:network/:chan/alcoolog/t/:token", AlcoologController, :token
- get "/:network/alcoolog/~/:nick", AlcoologController, :nick
end
end
diff --git a/lib/lsg_web/templates/alcoolog/index.html.eex b/lib/lsg_web/templates/alcoolog/index.html.eex
index e656e64..3f522e9 100644
--- a/lib/lsg_web/templates/alcoolog/index.html.eex
+++ b/lib/lsg_web/templates/alcoolog/index.html.eex
@@ -5,54 +5,202 @@ ol li {
</style>
<%= if @stats == [] do %>
- </strong><i>:o personne ne boit</i></strong>
+ <div class="rounded-md bg-red-50 p-4">
+ <div class="flex">
+ <div class="flex-shrink-0">
+ <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
+ <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
+ </svg>
+ </div>
+ <div class="ml-3">
+ <h3 class="text-sm leading-5 font-medium text-red-800">
+ CATASTROPHE! Personne n'a bu!!!!
+ </h3>
+ </div>
+ </div>
+ </div>
<% end %>
-<ul>
+<ul class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
<%= for {nick, status} <- @stats do %>
- <li><strong><%= nick %> <%= status.user_status %> - <%= status.trend_symbol %> <%= status.active %> g/l</strong><br/>
- &mdash; 15m: <%= status.active15m %> g/l - 30m: <%= status.active30m %> g/l - 1h: <%= status.active1h %> g/l<br />
- &mdash; dernier verre: <%= status.last_type %> <%= status.last_descr %> (<%= status.last_points %>)
- <%= LSGWeb.LayoutView.format_time(status.last_at) %>
- <br />
- &mdash; sobre dans: <%= status.sober_in_s %>
- <br />
- <small>
- &mdash; aujourd'hui: <%= status.daily_volumes %> points, <%= status.daily_gl %> g/l
- </small>
+ <li class="col-span-1 bg-white rounded-lg shadow">
+ <div class="w-full flex items-center justify-between p-6 space-x-6">
+ <div class="flex-1 truncate">
+ <div class="flex items-center space-x-3">
+ <h3 class="text-gray-900 text-base leading-5 font-semibold truncate"><%= link nick, to: alcoolog_path(@conn, :nick, @network, nick) %></h3>
+ <% rising_class = if status.rising, do: "teal", else: "red" %>
+ <span class="flex-shrink-0 inline-block px-2 py-0.5 text-<%= rising_class %>-800 text-sm leading-4 font-medium bg-<%= rising_class %>-100 rounded-full">
+ <%= status.trend_symbol %> <%= Float.round(status.active, 4) %> g/l
+ </span>
+ </div>
+ <p class="mt-1 text-gray-700 text-sm leading-5 truncate">
+ <span class="text-base"><%= status.last_cl %>cl @ <%= status.last_deg %>°</span>
+ <%= if status.last_descr && status.last_descr != "" do %>
+ <br /><%= status.last_descr %>
+ <% end %>
+ <br/><small><%= LSGWeb.LayoutView.format_time(status.last_at) %></small>
+ </p>
+
+ <p class="mt-1 text-gray-500 text-sm leading-5 truncate">
+ <br />
+ &mdash; sobre dans: <%= status.sober_in_s %><br />
+ <%= if status.since do %>
+ &mdash; depuis: <%= status.since_s %><br />
+ <% end %>
+ <small>
+ &mdash; 15m: <%= status.active15m %> g/l - 30m: <%= status.active30m %> g/l - 1h: <%= status.active1h %> g/l<br />
+ &mdash; aujourd'hui: <%= status.daily_volumes %> points, <%= status.daily_gl %> g/l
+ </small>
+ </p>
+
+
+ </div>
+ </div>
</li>
<% end %>
</ul>
<%= if @stats == %{} do %>
- <strong><i>... et personne n'a bu :o :o :o</i></strong>
+ <div class="rounded-md bg-red-50 p-4">
+ <div class="flex">
+ <div class="flex-shrink-0">
+ <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
+ <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
+ </svg>
+ </div>
+ <div class="ml-3">
+ <h3 class="text-sm leading-5 font-medium text-red-800">
+ ENCORE PIRE! Aucune boisson enregistrée!
+ </h3>
+ </div>
+ </div>
+ </div>
<% else %>
- <p>
- top consommateur par volume, les 7 derniers jours: <%= Enum.intersperse(for({nick, count} <- @top, do: "#{nick}: #{Float.round(count,4)}"), ", ") %>
- </p>
-
- <table class="table">
- <thead>
- <tr>
- <th scope="col">date</th>
- <th scope="col">nick</th>
- <th scope="col">points</th>
- <th scope="col">nom</th>
- </tr>
- </thead>
- <tbody>
- <%= for {{{account, date}, points, _, nom, comment}, nick} <- @drinks do %>
- <% date = DateTime.from_unix!(date, :millisecond) %>
- <th scope="row"><%= LSGWeb.LayoutView.format_time(date, false) %></th>
- <td><%= nick %></td>
- <td><%= Float.round(points+0.0, 5) %></td>
- <td><%= nom||"" %> <%= comment||"" %></td>
- </tr>
- <% end %>
- </tbody>
- </table>
+
+<canvas id="myChart" class="w-full" height="200"></canvas>
+
+ <h2 class="leading-8 m-4 font-semibold text-2xl">Classement <span class="font-medium text-gray-600 text-lg">15 jours</span></h2>
+
+<ul class="grid grid-cols-1 gap-6 sm:grid-cols-5 lg:grid-cols-5">
+ <%= for {{nick, count}, rank} <- Enum.with_index(@top) do %>
+ <% rank = rank + 1 %>
+ <% trophy = rank <= 3 %>
+ <% {colour, text} = case rank do
+1 -> {"yellow-500", "font-semibold text-base"}
+2 -> {"gray-500", "font-medium text-base"}
+3 -> {"orange-300", "font-medium text-base"}
+_ -> {"gray-300", ""}
+ end %>
+ <li class="col-span-1 bg-white rounded-lg shadow text-center <%= text %>">
+ <%= if trophy do %>
+ <span class="text-<%= colour %>">
+ <svg style="width: 1.125em; height: 1.5em; display: inline-block;" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="trophy" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" data-fa-i2svg=""><path fill="currentColor" d="M552 64H448V24c0-13.3-10.7-24-24-24H152c-13.3 0-24 10.7-24 24v40H24C10.7 64 0 74.7 0 88v56c0 35.7 22.5 72.4 61.9 100.7 31.5 22.7 69.8 37.1 110 41.7C203.3 338.5 240 360 240 360v72h-48c-35.3 0-64 20.7-64 56v12c0 6.6 5.4 12 12 12h296c6.6 0 12-5.4 12-12v-12c0-35.3-28.7-56-64-56h-48v-72s36.7-21.5 68.1-73.6c40.3-4.6 78.6-19 110-41.7 39.3-28.3 61.9-65 61.9-100.7V88c0-13.3-10.7-24-24-24zM99.3 192.8C74.9 175.2 64 155.6 64 144v-16h64.2c1 32.6 5.8 61.2 12.8 86.2-15.1-5.2-29.2-12.4-41.7-21.4zM512 144c0 16.1-17.7 36.1-35.3 48.8-12.5 9-26.7 16.2-41.8 21.4 7-25 11.8-53.6 12.8-86.2H512v16z"></path></svg>
+ </span>
+ <% end %>
+ #<%= rank %>: <%= link nick, to: alcoolog_path(@conn, :nick, @network, nick) %>
+ <br />
+ <span class="text-xs"><%= Float.round(count, 4) %></span>
+ </li>
+ <% end %>
+</ul>
+
+ <h2 class="leading-8 m-4 font-semibold text-2xl">Historique</h2>
+<div class="flex flex-col">
+ <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
+ <div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200">
+ <table class="min-w-full divide-y divide-gray-200">
+ <thead>
+ <tr>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ date
+ </th>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ nick
+ </th>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ &nbsp;
+ </th>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ &nbsp;
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <%= for {{{{account, date}, points, _active, cl, deg, nom, comment, _meta}, nick}, index} <- Enum.with_index(@drinks) do %>
+ <% class = if(Integer.is_even(index), do: "bg-gray-50", else: "bg-white") %>
+ <% date = DateTime.from_unix!(date, :millisecond) %>
+ <tr class="<%= class %>">
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
+ <%= LSGWeb.LayoutView.format_time(date, false) %>
+ </td>
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
+ <%= link nick, to: alcoolog_path(@conn, :nick, @network, nick) %>
+ </td>
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500"><%= cl %>cl <%= deg %>°</td>
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500"><%= comment||"" %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
<% end %>
<%= if @conn.assigns.account && (@network || @channel) do %>
<%= link("alcoolog global", to: alcoolog_path(@conn, :index)) %>
<% end %>
+
+<link href='/assets/css/metricsgraphics.css' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.css" integrity="sha512-SUJFImtiT87gVCOXl3aGC00zfDl6ggYAw5+oheJvRJ8KBXZrr/TMISSdVJ5bBarbQDRC2pR5Kto3xTR0kpZInA==" crossorigin="anonymous" />
+<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js" integrity="sha512-vBmx0N/uQOXznm/Nbkp7h0P1RfLSj0HQrFSzV8m7rOGyj30fYAOKHYvCNez+yM8IrfnW0TCodDEjRqf6fodf/Q==" crossorigin="anonymous"></script>
+<script src="/assets/js/jquery3.1.0.min.js"></script>
+<script src="/assets/js/d3.v4.min.js"></script>
+<script src="/assets/js/metricsgraphics.min.js"></script>
+ <script type="text/javascript">
+ (function() {
+ // oui s trè moch :( :( :(
+var ctx = document.getElementById('myChart').getContext('2d');
+ d3.json('<%= alcoolog_path(@conn, :index_gls_json, @network, LSGWeb.format_chan(@channel)) %>', function(data) {
+
+ var dynamicColors = function() {
+ var r = Math.floor(Math.random() * 255);
+ var g = Math.floor(Math.random() * 255);
+ var b = Math.floor(Math.random() * 255);
+ return "rgb(" + r + "," + g + "," + b + ")";
+ };
+
+ labels = data.labels;
+ datasets = $.map($.makeArray(data.data), function(set) {
+ return {label: set.name, data: set.history, fill: false, borderColor: dynamicColors()}
+ });
+
+
+var myChart = new Chart(ctx, {
+ type: 'line',
+ data: {
+ labels: labels,
+ datasets: datasets
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ unit: 'day'
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ beginAtZero: true
+ }
+ }]
+ }
+ }
+});
+});
+
+
+})();
+</script>
+
diff --git a/lib/lsg_web/templates/alcoolog/user.html.eex b/lib/lsg_web/templates/alcoolog/user.html.eex
new file mode 100644
index 0000000..3b2b20b
--- /dev/null
+++ b/lib/lsg_web/templates/alcoolog/user.html.eex
@@ -0,0 +1,170 @@
+<%= if @stats.active > 0 do %>
+ <h3 class="text-gray-900 text-xl leading-5 font-semibold truncate">
+ <% rising_class = if @stats.rising, do: "teal", else: "red" %>
+ <span class="flex-shrink-0 inline-block px-3 py-3 text-<%= rising_class %>-800 text-2xl leading-4 font-medium bg-<%= rising_class %>-100 rounded-full">
+ <%= @stats.trend_symbol %> <%= Float.round(@stats.active, 4) %> g/l
+ </span>
+
+ <span class="px-3"><%= @stats.last_cl %>cl @ <%= @stats.last_deg %>°</span>
+
+ <span class="px-3 text-lg text-gray-700"><%= if @stats.last_descr && @stats.last_descr != "" do %>
+ <%= @stats.last_descr %>
+ <% end %>
+ </span>
+
+ <span class="px-3 text-gray-500 text-sm font-thin"><%= LSGWeb.LayoutView.format_time(@stats.last_at) %></span>
+
+ </h3>
+
+ <p class="text-gray-500 font-thin text-lg">
+ a commencé il y a <span class="text-gray-700 font-semibold"><%= @stats.since_s %></span>
+ &mdash;
+ sobre dans <span class="text-gray-700 font-semibold"><%= @stats.sober_in_s %></span>
+ </p>
+<% else %>
+ <h3 class="text-gray-900 text-xl leading-5 font-semibold truncate">
+ est sobre!
+
+ <p class="text-gray-500 font-thin text-lg">
+ dernier verre
+ <span class="px-3"><%= @stats.last_cl %>cl @ <%= @stats.last_deg %>°</span>
+
+ <span class="px-3 text-lg text-gray-700"><%= if @stats.last_descr && @stats.last_descr != "" do %>
+ <%= @stats.last_descr %>
+ <% end %>
+ </span>
+
+ <span class="px-3 text-gray-500 text-sm font-thin"><%= LSGWeb.LayoutView.format_time(@stats.last_at) %></span>
+ </h3>
+<% end %>
+
+<canvas id="myChart" class="w-full" height="200"></canvas>
+<canvas id="myChartGl" class="w-full" height="200"></canvas>
+
+
+<h2 class="leading-8 m-4 font-semibold text-2xl">Historique</h2>
+<div class="flex flex-col">
+ <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
+ <div class="align-middle inline-block min-w-full shadow overflow-hidden sm:rounded-lg border-b border-gray-200">
+ <table class="min-w-full divide-y divide-gray-200">
+ <thead>
+ <tr>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ date
+ </th>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ &nbsp;
+ </th>
+ <th class="px-6 py-3 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
+ &nbsp;
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <%= for {%{at: date, cl: cl, deg: deg, description: comment}, index} <- Enum.with_index(@history) do %>
+ <% class = if(Integer.is_even(index), do: "bg-gray-50", else: "bg-white") %>
+ <tr class="<%= class %>">
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
+ <%= LSGWeb.LayoutView.format_time(date, false) %>
+ </td>
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500"><%= cl %>cl <%= deg %>°</td>
+ <td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500"><%= comment||"" %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
+
+<div id="metrics-gl" class="w-full"></div>
+
+<link href='/assets/css/metricsgraphics.css' rel='stylesheet' type='text/css'>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.css" integrity="sha512-SUJFImtiT87gVCOXl3aGC00zfDl6ggYAw5+oheJvRJ8KBXZrr/TMISSdVJ5bBarbQDRC2pR5Kto3xTR0kpZInA==" crossorigin="anonymous" />
+<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js" integrity="sha512-vBmx0N/uQOXznm/Nbkp7h0P1RfLSj0HQrFSzV8m7rOGyj30fYAOKHYvCNez+yM8IrfnW0TCodDEjRqf6fodf/Q==" crossorigin="anonymous"></script>
+<script src="/assets/js/jquery3.1.0.min.js"></script>
+<script src="/assets/js/d3.v4.min.js"></script>
+<script src="/assets/js/metricsgraphics.min.js"></script>
+ <script type="text/javascript">
+ (function() {
+var ctx = document.getElementById('myChart').getContext('2d');
+ d3.json('<%= alcoolog_path(@conn, :nick_volumes_json, @network, @nick, days: @days) %>', function(data) {
+var myChart = new Chart(ctx, {
+ type: 'bar',
+ data: {
+ labels: data.map(function(data) { return new Date(data.date) }),
+ datasets: [{
+ label: 'Volumes d\'alcool',
+ data: data.map(function(data) { return data.volumes }),
+ borderWidth: 1
+ }]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ unit: 'day'
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ beginAtZero: true
+ }
+ }]
+ }
+ }
+});
+});
+
+
+
+
+var ctxgl = document.getElementById('myChartGl').getContext('2d');
+ d3.json('<%= alcoolog_path(@conn, :nick_gls_json, @network, @nick, days: @days) %>', function(data) {
+var myChartgl = new Chart(ctxgl, {
+ type: 'bar',
+ data: {
+ labels: data.map(function(data) { return new Date(data.date) }),
+ datasets: [{
+ label: 'g/l ingérés',
+ data: data.map(function(data) { return data.gls }),
+ borderWidth: 1
+ }]
+ },
+ options: {
+ scales: {
+ xAxes: [{
+ type: 'time',
+ time: {
+ unit: 'day'
+ }
+ }],
+ yAxes: [{
+ ticks: {
+ beginAtZero: true
+ }
+ }]
+ }
+ }
+});
+});
+
+
+ d3.json('<%= alcoolog_path(@conn, :nick_log_json, @network, @nick, days: @days) %>', function(data) {
+ data = data.map(function(d) {
+ date = new Date(d.at);
+ return {"date": date, "active": d.active};
+ });
+ MG.data_graphic({
+ title: "g/l, All Time",
+ data: data,
+ width: 1000,
+ height: 400,
+ target: document.getElementById('metrics-gl'),
+ x_accessor: 'date',
+ y_accessor: 'active',
+ });
+ });
+})();
+</script>
diff --git a/lib/lsg_web/templates/irc/index.html.eex b/lib/lsg_web/templates/irc/index.html.eex
index 9e4f724..a8544b3 100644
--- a/lib/lsg_web/templates/irc/index.html.eex
+++ b/lib/lsg_web/templates/irc/index.html.eex
@@ -1,19 +1,12 @@
-<style type="text/css">
-.help-entry h1 {
- font-size: 18px;
-}
-.help-entry h2 {
- font-size: 16px;
-}
-</style>
-
-<p>
+<div class="hidden sm:block">
+ <nav class="flex flex-wrap content-center">
<% list = for {identifier, _} <- @commands do %>
<% name = String.replace(identifier, "_", " ") %>
- <%= link(name, to: "##{identifier}") %>
+ <%= link(name, to: "##{identifier}", class: "px-3 py-2 font-medium text-sm leading-5 rounded-md text-gray-500 hover:text-gray-700 focus:outline-none focus:text-indigo-600 focus:bg-indigo-50") %>
<% end %>
- <small><%= Enum.intersperse(list, " - ") %></small>
-</p>
+ <%= list %>
+ </nav>
+</div>
<%= if @members != [] do %>
<% users = for {_acc, user, nick} <- @members, do: if(user, do: nick, else: content_tag(:i, nick)) %>
@@ -22,10 +15,12 @@
<% end %>
<% end %>
-<div class="irchelps">
+<div class="irchelps space-y-6">
<%= for {identifier, help} <- @commands do %>
<%= if help do %>
- <div class="help-entry" id="<%= identifier %>"><%= LSGWeb.LayoutView.liquid_markdown(@conn, help) %></div>
+ <div class="bg-white border-b border-gray-200" id="<%= identifier %>">
+ <div class="prose w-auto max-w-full"><%= LSGWeb.LayoutView.liquid_markdown(@conn, help) %></div>
+ </div>
<% end %>
<% end %>
</div>
diff --git a/lib/lsg_web/templates/irc/txt.html.eex b/lib/lsg_web/templates/irc/txt.html.eex
index e9df681..fd4ea00 100644
--- a/lib/lsg_web/templates/irc/txt.html.eex
+++ b/lib/lsg_web/templates/irc/txt.html.eex
@@ -1,15 +1,27 @@
<style type="text/css">
-ol li {
- margin-bottom: 5px
+:target {
+ background-color: #ffa;
+ font-weight: bold;
+}
+ol > li > a {
+ display: none;
+}
+ol > li:hover > a {
+ display: inline-block;
+ color: gray;
}
</style>
-<ol>
+<ol class="prose space-y-3 w-auto max-w-full list-outside list-decimal m-4 leading-loose">
<%= for {txt, id} <- Enum.with_index(@data) do %>
- <li id="<%= @name %>-<%= id %>"><%= txt %></li>
+ <li class="text-lg" id="q<%= id+1 %>">
+
+ <%= txt %>
+ <a href="#q<%= id+1 %>" class="text-xs text-gray-500 space-x-3">#</a>
+ </li>
<% end %>
</ol>
<p>
- <a href="/irc/txt/<%= @name %>.txt">télécharger au format texte</a>
+ <a href="/-/txt/<%= @name %>.txt" class="text-xs text-gray-500">télécharger au format texte</a>
</p>
diff --git a/lib/lsg_web/templates/irc/txts.html.eex b/lib/lsg_web/templates/irc/txts.html.eex
index 5971ffa..66321b5 100644
--- a/lib/lsg_web/templates/irc/txts.html.eex
+++ b/lib/lsg_web/templates/irc/txts.html.eex
@@ -1,25 +1,26 @@
-<style type="text/css">
-.help-entry h1 {
- font-size: 18px;
-}
-.help-entry h2 {
- font-size: 16px;
-}
-</style>
-
-<p><strong><%= @lines %></strong> lignes dans <strong><%= @files %></strong> fichiers.
-<a href="#help">Aide</a>.
-</p>
-
-<ul>
+<div>
+ <h2 class="text-gray-500 text-xs font-medium uppercase tracking-wide">
+ <strong><%= @lines %></strong> lignes dans <strong><%= @files %></strong> fichiers
+ &mdash;
+ <a href="#help">Aide</a>
+ </h2>
+ <ul class="mt-3 grid grid-cols-1 gap-5 sm:gap-6 sm:grid-cols-4 lg:grid-cols-6">
<%= for {txt, data} <- @data do %>
<% base_url = cond do
@conn.assigns[:chan] -> "/#{@conn.assigns.network}/#{LSGWeb.format_chan(@conn.assigns.chan)}"
true -> "/-"
end %>
- <li><a href="<%= base_url %>/txt/<%= txt %>"><%= txt %></a> <i>(<%= Enum.count(data) %>)</i></li>
+ <li class="col-span-1 flex shadow-sm rounded-m">
+ <div class="flex-1 flex items-center justify-between border-l border-t border-r border-b border-gray-200 bg-white rounded-md truncate">
+ <div class="flex-1 px-4 py-2 text-sm leading-5 truncate">
+ <a href="<%= base_url %>/txt/<%= txt %>" class="text-gray-900 text-lg font-medium hover:text-gray-600 transition ease-in-out duration-150"><%= txt %></a>
+ <p class="text-gray-500"><%= Enum.count(data) %> lignes</p>
+ </div>
+ </div>
+ </li>
<% end %>
-</ul>
+ </ul>
+</div>
-<div class="help-entry" id="help"><%= LSGWeb.LayoutView.liquid_markdown(@conn, @doc) %></div>
+<div class="prose" id="help"><%= LSGWeb.LayoutView.liquid_markdown(@conn, @doc) %></div>
diff --git a/lib/lsg_web/templates/layout/app.html.eex b/lib/lsg_web/templates/layout/app.html.eex
index 1871e8b..9e78e8e 100644
--- a/lib/lsg_web/templates/layout/app.html.eex
+++ b/lib/lsg_web/templates/layout/app.html.eex
@@ -8,28 +8,137 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, noarchive, nofollow, nosnippet" />
<title><%= Map.get(assigns, :title, "") %></title>
- <link rel="stylesheet" href="<%= static_path(@conn, "/assets/css/app.css") %>">
+ <link rel="stylesheet" href="<%= static_path(@conn, "/assets/css/tailwind-ui.min.css") %>">
</head>
<body>
- <div class="container">
- <main role="main">
- <%= if !@conn.assigns[:no_header] do %>
- <h1>
- <small style="font-size: 14px;">
- <a href="/"><%= Keyword.get(Application.get_env(:lsg, :irc), :name, "ircbot") %></a>
- <%= if @conn.assigns[:account], do: @conn.assigns.account.name %>
- &rsaquo;
+<div>
+ <div class="bg-gray-800 pb-32">
+ <nav class="bg-gray-800">
+ <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
+ <div class="border-b border-gray-700">
+ <div class="flex items-center justify-between h-16 px-4 sm:px-0">
+ <div class="flex items-center">
+ <div class="flex-shrink-0">
+ <img class="h-8 w-8" src="https://tailwindui.com/img/logos/workflow-mark-on-dark.svg" alt="Workflow logo">
+ </div>
+ <div class="hidden md:block">
+ <div class="ml-10 flex items-baseline">
+ <a href="/" class="px-3 py-2 rounded-md text-sm font-medium text-white bg-gray-900 focus:outline-none focus:text-white focus:bg-gray-700">bot.goulag.org</a>
+ <!--<a href="#" class="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Team</a>
+ <a href="#" class="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Projects</a>
+ <a href="#" class="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Calendar</a>
+ <a href="#" class="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Reports</a>-->
+ </div>
+ </div>
+ </div>
+ <div class="hidden md:block">
+ <div class="ml-4 flex items-center md:ml-6">
+ <!--<button class="p-1 border-2 border-transparent text-gray-400 rounded-full hover:text-white focus:outline-none focus:text-white focus:bg-gray-700" aria-label="Notifications">
+ <svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
+ </svg>
+ </button>-->
+ <!-- Profile dropdown -->
+ <div class="ml-3 relative">
+ <div>
+ <button class="max-w-xs flex items-center text-sm rounded-full text-white focus:outline-none focus:shadow-solid" id="user-menu" aria-label="User menu" aria-haspopup="true">
+ <!--<img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">-->
+ ~<%= if @conn.assigns[:account], do: @conn.assigns.account.name %>
+
+ </button>
+ </div>
+ <!--
+ Profile dropdown panel, show/hide based on dropdown state.
+
+ Entering: "transition ease-out duration-100"
+ From: "transform opacity-0 scale-95"
+ To: "transform opacity-100 scale-100"
+ Leaving: "transition ease-in duration-75"
+ From: "transform opacity-100 scale-100"
+ To: "transform opacity-0 scale-95"
+ -->
+ <!--<div class="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg">
+ <div class="py-1 rounded-md bg-white shadow-xs">
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Your Profile</a>
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Settings</a>
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Sign out</a>
+ </div>
+ </div>-->
+ </div>
+ </div>
+ </div>
+ <div class="-mr-2 flex md:hidden">
+ <!-- Mobile menu button -->
+ <button class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:bg-gray-700 focus:text-white">
+ <!-- Menu open: "hidden", Menu closed: "block" -->
+ <svg class="block h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
+ </svg>
+ <!-- Menu open: "block", Menu closed: "hidden" -->
+ <svg class="hidden h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
+ </svg>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!--
+ Mobile menu, toggle classes based on menu state.
+
+ Open: "block", closed: "hidden"
+ -->
+ <div class="hidden border-b border-gray-700 md:hidden">
+ <div class="px-2 py-3 sm:px-3">
+ <a href="#" class="block px-3 py-2 rounded-md text-base font-medium text-white bg-gray-900 focus:outline-none focus:text-white focus:bg-gray-700">Dashboard</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Team</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Projects</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Calendar</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Reports</a>
+ </div>
+ <div class="pt-4 pb-3 border-t border-gray-700">
+ <div class="flex items-center px-5">
+ <div class="flex-shrink-0">
+ <img class="h-10 w-10 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
+ </div>
+ <div class="ml-3">
+ <div class="text-base font-medium leading-none text-white">Tom Cook</div>
+ <div class="mt-1 text-sm font-medium leading-none text-gray-400">tom@example.com</div>
+ </div>
+ </div>
+ <div class="mt-3 px-2" role="menu" aria-orientation="vertical" aria-labelledby="user-menu">
+ <a href="#" class="block px-3 py-2 rounded-md text-base font-medium text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700" role="menuitem">Your Profile</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700" role="menuitem">Settings</a>
+ <a href="#" class="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700" role="menuitem">Sign out</a>
+ </div>
+ </div>
+ </div>
+ </nav>
+ <header class="py-10">
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
+ <h1 class="text-3xl leading-9 font-bold text-white">
<%= if n = @conn.assigns[:network] do %><a href="/<%= n %>"><%= n %></a> &rsaquo; <% end %>
<%= if c = @conn.assigns[:chan] do %><a href="/<%= @conn.assigns.network %>/<%= LSGWeb.format_chan(c) %>"><%= c %></a> &rsaquo; <% end %>
<%= for({name, href} <- @conn.assigns[:breadcrumbs]||[], do: [link(name, to: href), raw(" &rsaquo; ")]) %>
- </small><br />
<%= @conn.assigns[:title] || @conn.assigns[:chan] || @conn.assigns[:network] %>
- </h1>
- <% end %>
+ </h1>
+ </div>
+ </header>
+ </div>
+
+ <main class="-mt-32">
+ <div class="max-w-7xl mx-auto pb-12 px-4 sm:px-6 lg:px-8">
+ <!-- Replace with your content -->
+ <div class="bg-white rounded-lg shadow px-5 py-6 sm:px-6">
<%= render @view_module, @view_template, assigns %>
- </main>
+ </div>
+ <!-- /End replace -->
</div>
+ </main>
+</div>
+
<script src="<%= static_path(@conn, "/assets/js/app.js") %>"></script>
</body>
</html>
diff --git a/lib/lsg_web/templates/page/user.html.eex b/lib/lsg_web/templates/page/user.html.eex
index 8a043a0..56fc485 100644
--- a/lib/lsg_web/templates/page/user.html.eex
+++ b/lib/lsg_web/templates/page/user.html.eex
@@ -1,3 +1,4 @@
+<div class="prose prose-lg">
<ul>
<li><%= link("Help", to: "/-") %></li>
</ul>
@@ -36,3 +37,4 @@
<li><%= net %>: <%= to_string(predicate) %>, <%= v %></li>
<% end %>
</ul>
+</div>
diff --git a/lib/lsg_web/views/alcoolog_view.ex b/lib/lsg_web/views/alcoolog_view.ex
index 2c55c09..ed3c9b4 100644
--- a/lib/lsg_web/views/alcoolog_view.ex
+++ b/lib/lsg_web/views/alcoolog_view.ex
@@ -1,4 +1,6 @@
defmodule LSGWeb.AlcoologView do
use LSGWeb, :view
+ require Integer
+
end
diff --git a/lib/lsg_web/views/layout_view.ex b/lib/lsg_web/views/layout_view.ex
index b28d3c5..41c5341 100644
--- a/lib/lsg_web/views/layout_view.ex
+++ b/lib/lsg_web/views/layout_view.ex
@@ -60,11 +60,14 @@ defmodule LSGWeb.LayoutView do
now_last_week = {y, w-1}
now_last_roll = 7-Timex.days_to_beginning_of_week(now)
+ date_date = DateTime.to_date(date)
+ now_date = DateTime.to_date(date)
+
format = cond do
date.year != now.year -> "{D}/{M}/{YYYY} {h24}:{m}"
- date.day == now.day -> "{h24}:{m}"
+ date_date == now_date -> "{h24}:{m}"
(now_week == date_week) || (date_week == now_last_week && (Date.day_of_week(date) >= now_last_roll)) -> "{WDfull} {h24}:{m}"
- (now.month == date.month) -> "{WDfull} {D} {h24}:{m}"
+ (now.year == date.year && now.month == date.month) -> "{WDfull} {D} {h24}:{m}"
true -> "{WDfull} {D} {M} {h24}:{m}"
end