Compare commits

...

3 Commits

Author SHA1 Message Date
Trevor Vallender c5435ac412 Table notifications 2024-06-14 09:08:58 +01:00
Trevor Vallender 2002651e8a Broadcast dice rolls to table 2024-06-13 17:04:25 +01:00
Trevor Vallender dd49c79edf Tabs on table page 2024-06-13 14:18:12 +01:00
20 changed files with 135 additions and 23 deletions

View File

@ -69,9 +69,10 @@
margin: 0; margin: 0;
padding: .5em; padding: .5em;
} }
input { input, .stat-value {
text-align: center; text-align: center;
font-size: 3em; font-size: 3em;
width: 2.5em; width: 2.5em;
border: 1px solid var(--background-color);
} }
} }

View File

@ -9,6 +9,7 @@
--secondary-text-color: #777; --secondary-text-color: #777;
--inset-bg-color: #eee; --inset-bg-color: #eee;
--notification-bg-color: #eee;
--border-radius: .5em; --border-radius: .5em;

View File

@ -3,7 +3,7 @@ form, fieldset {
gap: 1rem; gap: 1rem;
grid-template-columns: 1fr 2fr; grid-template-columns: 1fr 2fr;
input, label { input, label, .stat-value {
padding: .5em; padding: .5em;
} }
@ -45,12 +45,8 @@ form.stat-form, form.counter-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
input:disabled { .stat-value {
color: var(--text-color); color: var(--text-color);
background-color: var(--input-background); background-color: var(--input-background);
} }
input[type=number]:disabled {
-moz-appearance: textfield;
}
} }

View File

@ -0,0 +1,13 @@
#table-notifications {
position: fixed;
width: 60em;
max-width: 80%;
top: 1em; left: 0;
transform: translate(calc(50vw - 50%));
li {
background-color: var(--notification-bg-color);
list-style-type: none;
padding: .5em;
border-radius: var(--border-radius);
}
}

View File

@ -0,0 +1,30 @@
#table-content{
padding: 1em;
background-color: var(--inset-bg-color);
border: 1px solid #000;
z-index: 1;
}
.table-tabs {
ul {
margin: 0;
}
li {
list-style-type: none;
display: inline;
a:link, a:visited {
color: inherit;
text-decoration: none;
background-color: var(--inset-bg-color);
padding: .5em 1em;
border: 1px solid black;
position: relative;
top: 1px;
}
a:link.active, a:visited.active {
display: inline-block;
z-index: 1000;
border-bottom: none;
}
}
}

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class DiceRollsController < ApplicationController
before_action :set_table
def create
rollable = dice_roll_params[:rollable_type].constantize.find(dice_roll_params[:rollable_id])
@table.dice_rolls.create!(
rollable:,
result: DiceRoller.new(rollable.roll_command, stat: rollable).roll,
)
head :ok
end
private
def set_table
@table = Current.user.owned_tables.find(params[:table_id])
end
def dice_roll_params
params.require(:dice_roll).permit(
:rollable_type,
:rollable_id,
)
end
end

View File

@ -17,6 +17,7 @@ class StatsController < ApplicationController
end end
def update def update
@editable = true
@stat.update(stat_params) @stat.update(stat_params)
end end

View File

@ -0,0 +1,9 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "input" ]
rollDice() {
this.element.requestSubmit()
}
}

View File

@ -0,0 +1,9 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
setTimeout(() => {
this.element.remove()
}, 5000)
}
}

View File

@ -7,6 +7,12 @@ class DiceRoll < ApplicationRecord
validates :result, presence: true, validates :result, presence: true,
numericality: { only_integer: true } numericality: { only_integer: true }
after_create_commit do
broadcast_append_to table, target: "events"
broadcast_append_to table, target: "table-notifications",
partial: "shared/notification", locals: { object: self }
end
def display_text def display_text
"#{rollable.character.name} rolled #{rollable.name}: <strong>#{result}</strong>".html_safe "#{rollable.character.name} rolled #{rollable.name}: <strong>#{result}</strong>".html_safe
end end

View File

@ -0,0 +1,2 @@
<%= turbo_stream.append("events", partial: "dice_rolls/dice_roll",
locals: { dice_roll: dice_roll }) %>

View File

@ -1,5 +1,5 @@
<% content_for :title, @table.name %> <% content_for :title, @table.name %>
<ul> <ul id="events">
<%= render @events %> <%= render @events %>
</ul> </ul>

View File

@ -14,6 +14,7 @@
<body> <body>
<header> <header>
<%= yield(:header_content) if content_for?(:header_content) %>
<h1><%= link_to t("site_name"), root_path %></h1> <h1><%= link_to t("site_name"), root_path %></h1>
<nav> <nav>
<ul> <ul>

View File

@ -1,12 +1,18 @@
<%= content_for :header_content do %>
<ul id="table-notifications"></ul>
<% end %>
<% content_for :submenu do %> <% content_for :submenu do %>
<%= turbo_stream_from @table %>
<h2><%= @table.name %></h2> <h2><%= @table.name %></h2>
<nav> <nav class="table-tabs">
<ul> <ul>
<li><%= link_to t(".overview"), @table %></li> <li><%= link_to t(".overview"), @table, class: class_names(active: params[:controller] == "tables") %></li>
<% @characters.each do |character| %> <% @characters.each do |character| %>
<li><%= link_to character.name, table_character_character_sheet_sections_path(@table, character) %></li> <li><%= link_to character.name, table_character_character_sheet_sections_path(@table, character),
class: class_names(active: params[:controller] == "character_sheet_sections") %></li>
<% end %> <% end %>
<li><%= link_to t(".events"), table_events_path(@table) %></li> <li><%= link_to t(".events"), table_events_path(@table), class: class_names(active: params[:controller] == "events") %></li>
</ul> </ul>
</nav> </nav>
<% end %> <% end %>

View File

@ -0,0 +1,3 @@
<div data-controller="notifications">
<%= render object %>
</div>

View File

@ -4,8 +4,16 @@
data: { turbo_method: :delete, turbo_confirm: t(".confirm_delete", name: stat.name) }) %> data: { turbo_method: :delete, turbo_confirm: t(".confirm_delete", name: stat.name) }) %>
<% end %> <% end %>
<h6><%= stat.name %></h6> <h6><%= stat.name %></h6>
<%= form_with model: stat, class: "stat-form", <% if @editable %>
data: { controller: "auto-update", auto_update_update_url_value: stat_path(stat) } do |f| %> <%= form_with model: stat, class: "stat-form", data: { controller: "auto-update" } do |f| %>
<%= f.number_field :value, disabled: !@editable %> <%= f.number_field :value %>
<% end %>
<% else %>
<%= form_with model: DiceRoll.new, url: table_dice_rolls_path(stat.character.table), class: "stat-form",
data: { controller: "dice-roll" } do |f| %>
<%= f.hidden_field :rollable_type, value: "Stat" %>
<%= f.hidden_field :rollable_id, value: stat.id %>
<div class="stat-value" data-action="click->dice-roll#rollDice"><%= stat.value %></div>
<% end %>
<% end %> <% end %>
</div> </div>

View File

@ -1,7 +1,7 @@
<% content_for :title, @table.name %> <% content_for :title, @table.name %>
<%= link_to t(".invite_user"), new_table_table_invite_path(@table) %> <%= link_to t(".invite_user"), new_table_table_invite_path(@table), data: { turbo_frame: "_top" } %>
<%= link_to t(".edit_table"), edit_table_path(@table) %> <%= link_to t(".edit_table"), edit_table_path(@table), data: { turbo_frame: "_top" } %>
<dl> <dl>
<dt><%= t(".game_system") %>:</dt> <dt><%= t(".game_system") %>:</dt>
@ -21,7 +21,7 @@
<% if @table.users.any? %> <% if @table.users.any? %>
<ul> <ul>
<% @table.users.each do |user| %> <% @table.users.each do |user| %>
<li><%= link_to user.username, user %></li> <li><%= link_to user.username, user, data: { turbo_frame: "_top" } %></li>
<% end %> <% end %>
</ul> </ul>
<% else %> <% else %>

View File

@ -5,6 +5,4 @@ test:
adapter: test adapter: test
production: production:
adapter: redis adapter: postgresql
url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
channel_prefix: tabletop_companion_production

View File

@ -29,6 +29,7 @@ Rails.application.routes.draw do
resources :characters, only: [] do resources :characters, only: [] do
resources :character_sheet_sections, only: [ :index ] resources :character_sheet_sections, only: [ :index ]
end end
resources :dice_rolls
resources :events, only: [ :index ] resources :events, only: [ :index ]
resources :table_invites, only: [ :new, :create ] resources :table_invites, only: [ :new, :create ]
end end

View File

@ -1,5 +1,5 @@
- character sheet on table - test for rolls controller & system tests
- table tabs - table notifications for rolls
- roll on click - roll on click
- Sheets - Sheets
- Lists - Lists