MVP version. Added actioncables for counting.
This commit is contained in:
parent
6361a50230
commit
3f97cc59b2
26
app/channels/count_channel.rb
Normal file
26
app/channels/count_channel.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CountChannel < ApplicationCable::Channel
|
||||
def subscribed
|
||||
# TODO: check to make sure this is unique.
|
||||
stream_from 'chat'
|
||||
end
|
||||
|
||||
def increment(_payload = 1)
|
||||
cluster = Cluster.list.values.first
|
||||
cluster.increment
|
||||
ActionCable.server.broadcast 'chat', message: render(cluster)
|
||||
end
|
||||
|
||||
def decrement(_payload = 1)
|
||||
cluster = Cluster.list.values.first
|
||||
cluster.decrement
|
||||
ActionCable.server.broadcast 'chat', message: render(cluster)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render(cluster)
|
||||
ApplicationController.new.helpers.c('counter-count', cluster: cluster)
|
||||
end
|
||||
end
|
|
@ -9,7 +9,7 @@ class ClusterController < ApplicationController
|
|||
|
||||
def create
|
||||
cluster = Cluster.new(params[:cluster])
|
||||
session[:cluster_uuid] = cluster.uuid;
|
||||
session[:cluster_uuid] = cluster.uuid
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
class CounterController < ApplicationController
|
||||
before_action :associate!
|
||||
|
||||
def show; end
|
||||
def show
|
||||
@cluster = Cluster.get(session[:cluster_uuid])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title">
|
||||
Hello World
|
||||
</h1>
|
||||
<p class="subtitle">
|
||||
<span class="icon">
|
||||
<i class="fas fa-home"></i>
|
||||
</span>
|
||||
My first website with <strong>Bulma</strong>!
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<%= c("page") do %>
|
||||
<%= c("counter-view") %>
|
||||
<% end %>
|
||||
|
|
13
frontend/client/cable.js
Normal file
13
frontend/client/cable.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import cable from "actioncable";
|
||||
|
||||
let consumer;
|
||||
|
||||
const createChannel = (...args) => {
|
||||
if (!consumer) {
|
||||
consumer = cable.createConsumer();
|
||||
}
|
||||
|
||||
return consumer.subscriptions.create(...args);
|
||||
};
|
||||
|
||||
export default createChannel;
|
20
frontend/client/counter.js
Normal file
20
frontend/client/counter.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import createChannel from "client/cable";
|
||||
|
||||
let callback; // declaring a variable that will hold a function later
|
||||
|
||||
const chat2 = createChannel("CountChannel", {
|
||||
received({ message }) {
|
||||
if (callback) callback.call(null, message);
|
||||
},
|
||||
});
|
||||
|
||||
const sendIncrement = (message) => chat2.perform("increment", { message });
|
||||
const sendDecrement = (message) => chat2.perform("decrement", { message });
|
||||
|
||||
// Getting a message: this callback will be invoked once we receive
|
||||
// something over ChatChannel
|
||||
const setCallback = (fn) => {
|
||||
callback = fn;
|
||||
};
|
||||
|
||||
export { sendIncrement, sendDecrement, setCallback };
|
|
@ -33,3 +33,5 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -*- mode: css; -*- */
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<%= cluster.count %>
|
12
frontend/components/counter-count/counter-count.js
Normal file
12
frontend/components/counter-count/counter-count.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import "./counter-count.pcss";
|
||||
|
||||
import { setCallback } from "client/counter";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const currentCount = document.querySelector(".count");
|
||||
if (currentCount) {
|
||||
setCallback((message) => {
|
||||
currentCount.innerHTML = message;
|
||||
});
|
||||
}
|
||||
});
|
1
frontend/components/counter-count/counter-count.pcss
Normal file
1
frontend/components/counter-count/counter-count.pcss
Normal file
|
@ -0,0 +1 @@
|
|||
/* placeholder */
|
|
@ -0,0 +1,3 @@
|
|||
<a class="counter-down-btn">
|
||||
<i class="fas fa-angle-double-down"></i>
|
||||
</a>
|
13
frontend/components/counter-down-btn/counter-down-btn.js
Normal file
13
frontend/components/counter-down-btn/counter-down-btn.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import "./counter-down-btn.pcss";
|
||||
|
||||
import { sendDecrement } from "client/counter";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const btn = document.querySelector(".counter-down-btn");
|
||||
if (btn) {
|
||||
btn.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
sendDecrement(1);
|
||||
});
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
/* placeholder */
|
|
@ -0,0 +1,3 @@
|
|||
<a class="counter-up-btn">
|
||||
<i class="fas fa-angle-double-up"></i>
|
||||
</a>
|
13
frontend/components/counter-up-btn/counter-up-btn.js
Normal file
13
frontend/components/counter-up-btn/counter-up-btn.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
import "./counter-up-btn.pcss";
|
||||
|
||||
import { sendIncrement } from "client/counter";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
const btn = document.querySelector(".counter-up-btn");
|
||||
if (btn) {
|
||||
btn.addEventListener("click", (event) => {
|
||||
event.preventDefault();
|
||||
sendIncrement(-1);
|
||||
});
|
||||
}
|
||||
});
|
1
frontend/components/counter-up-btn/counter-up-btn.pcss
Normal file
1
frontend/components/counter-up-btn/counter-up-btn.pcss
Normal file
|
@ -0,0 +1 @@
|
|||
/* placeholder */
|
11
frontend/components/counter-view/_counter-view.html.erb
Normal file
11
frontend/components/counter-view/_counter-view.html.erb
Normal file
|
@ -0,0 +1,11 @@
|
|||
<div class="counter-view">
|
||||
<div class="row">
|
||||
<%= c("counter-up-btn") %>
|
||||
</div>
|
||||
<div class="row count">
|
||||
<%= c("counter-count", cluster: @cluster) %>
|
||||
</div>
|
||||
<div class="row">
|
||||
<%= c("counter-down-btn") %>
|
||||
</div>
|
||||
</div>
|
5
frontend/components/counter-view/counter-view.js
Normal file
5
frontend/components/counter-view/counter-view.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
import "./counter-view.pcss";
|
||||
|
||||
import "components/counter-up-btn/counter-up-btn";
|
||||
import "components/counter-count/counter-count";
|
||||
import "components/counter-down-btn/counter-down-btn";
|
16
frontend/components/counter-view/counter-view.pcss
Normal file
16
frontend/components/counter-view/counter-view.pcss
Normal file
|
@ -0,0 +1,16 @@
|
|||
.counter-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
& .row {
|
||||
display: flex;
|
||||
height: 33%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 4rem;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
.page {
|
||||
height: 100vh;
|
||||
width: 700px;
|
||||
margin: 0 auto;
|
||||
max-width: 700px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
@ -2,3 +2,4 @@ import "init";
|
|||
|
||||
import "components/page/page";
|
||||
import "components/cluster-view/cluster-view";
|
||||
import "components/counter-view/counter-view";
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"@rails/actioncable": "^6.0.0",
|
||||
"@rails/ujs": "^6.0.0",
|
||||
"@rails/webpacker": "4.2.2",
|
||||
"actioncable": "^5.2.4-3",
|
||||
"bulma": "^0.8.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss-flexbugs-fixes": "^4.2.1",
|
||||
|
|
10
test/channels/count_channel_test.rb
Normal file
10
test/channels/count_channel_test.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class CountChannelTest < ActionCable::Channel::TestCase
|
||||
# test "subscribes" do
|
||||
# subscribe
|
||||
# assert subscription.confirmed?
|
||||
# end
|
||||
end
|
|
@ -1115,6 +1115,11 @@ acorn@^7.1.1:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe"
|
||||
integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==
|
||||
|
||||
actioncable@^5.2.4-3:
|
||||
version "5.2.4-3"
|
||||
resolved "https://registry.yarnpkg.com/actioncable/-/actioncable-5.2.4-3.tgz#cb4d1f4a6a8164ac9abe623eca2c382fe05e7d47"
|
||||
integrity sha512-SrGfg2W2GKGfYOlsOUnqjdihUhIVoyb5ewsMtpfE/Z3ZK/j5Gj2e/YWp2A7Wo+aeB1aewhPxorFxIGVRowbX4w==
|
||||
|
||||
aggregate-error@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0"
|
||||
|
|
Reference in New Issue
Block a user