diff --git a/app/channels/count_channel.rb b/app/channels/count_channel.rb
new file mode 100644
index 0000000..055bec2
--- /dev/null
+++ b/app/channels/count_channel.rb
@@ -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
diff --git a/app/controllers/cluster_controller.rb b/app/controllers/cluster_controller.rb
index c6c8c6b..f0e132a 100644
--- a/app/controllers/cluster_controller.rb
+++ b/app/controllers/cluster_controller.rb
@@ -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
diff --git a/app/controllers/counter_controller.rb b/app/controllers/counter_controller.rb
index f00ec59..75273e4 100644
--- a/app/controllers/counter_controller.rb
+++ b/app/controllers/counter_controller.rb
@@ -3,7 +3,9 @@
class CounterController < ApplicationController
before_action :associate!
- def show; end
+ def show
+ @cluster = Cluster.get(session[:cluster_uuid])
+ end
private
diff --git a/app/views/counter/show.html.erb b/app/views/counter/show.html.erb
index b19cab6..92daa33 100644
--- a/app/views/counter/show.html.erb
+++ b/app/views/counter/show.html.erb
@@ -1,13 +1,3 @@
-
-
-
- Hello World
-
-
-
-
-
- My first website with Bulma!
-
-
-
+<%= c("page") do %>
+ <%= c("counter-view") %>
+<% end %>
diff --git a/frontend/client/cable.js b/frontend/client/cable.js
new file mode 100644
index 0000000..43fcd46
--- /dev/null
+++ b/frontend/client/cable.js
@@ -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;
diff --git a/frontend/client/counter.js b/frontend/client/counter.js
new file mode 100644
index 0000000..a4ed0c5
--- /dev/null
+++ b/frontend/client/counter.js
@@ -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 };
diff --git a/frontend/components/cluster-new/cluster-new.pcss b/frontend/components/cluster-new/cluster-new.pcss
index e3df3ed..fbc60c8 100644
--- a/frontend/components/cluster-new/cluster-new.pcss
+++ b/frontend/components/cluster-new/cluster-new.pcss
@@ -33,3 +33,5 @@
}
}
}
+
+/* -*- mode: css; -*- */
diff --git a/frontend/components/counter-count/_counter-count.html.erb b/frontend/components/counter-count/_counter-count.html.erb
new file mode 100644
index 0000000..dbad357
--- /dev/null
+++ b/frontend/components/counter-count/_counter-count.html.erb
@@ -0,0 +1 @@
+<%= cluster.count %>
diff --git a/frontend/components/counter-count/counter-count.js b/frontend/components/counter-count/counter-count.js
new file mode 100644
index 0000000..c29bbe1
--- /dev/null
+++ b/frontend/components/counter-count/counter-count.js
@@ -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;
+ });
+ }
+});
diff --git a/frontend/components/counter-count/counter-count.pcss b/frontend/components/counter-count/counter-count.pcss
new file mode 100644
index 0000000..545eb34
--- /dev/null
+++ b/frontend/components/counter-count/counter-count.pcss
@@ -0,0 +1 @@
+/* placeholder */
diff --git a/frontend/components/counter-down-btn/_counter-down-btn.html.erb b/frontend/components/counter-down-btn/_counter-down-btn.html.erb
new file mode 100644
index 0000000..265ad73
--- /dev/null
+++ b/frontend/components/counter-down-btn/_counter-down-btn.html.erb
@@ -0,0 +1,3 @@
+
+
+
diff --git a/frontend/components/counter-down-btn/counter-down-btn.js b/frontend/components/counter-down-btn/counter-down-btn.js
new file mode 100644
index 0000000..877c8e9
--- /dev/null
+++ b/frontend/components/counter-down-btn/counter-down-btn.js
@@ -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);
+ });
+ }
+});
diff --git a/frontend/components/counter-down-btn/counter-down-btn.pcss b/frontend/components/counter-down-btn/counter-down-btn.pcss
new file mode 100644
index 0000000..545eb34
--- /dev/null
+++ b/frontend/components/counter-down-btn/counter-down-btn.pcss
@@ -0,0 +1 @@
+/* placeholder */
diff --git a/frontend/components/counter-up-btn/_counter-up-btn.html.erb b/frontend/components/counter-up-btn/_counter-up-btn.html.erb
new file mode 100644
index 0000000..0e6c2e7
--- /dev/null
+++ b/frontend/components/counter-up-btn/_counter-up-btn.html.erb
@@ -0,0 +1,3 @@
+
+
+
diff --git a/frontend/components/counter-up-btn/counter-up-btn.js b/frontend/components/counter-up-btn/counter-up-btn.js
new file mode 100644
index 0000000..e9e26a3
--- /dev/null
+++ b/frontend/components/counter-up-btn/counter-up-btn.js
@@ -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);
+ });
+ }
+});
diff --git a/frontend/components/counter-up-btn/counter-up-btn.pcss b/frontend/components/counter-up-btn/counter-up-btn.pcss
new file mode 100644
index 0000000..545eb34
--- /dev/null
+++ b/frontend/components/counter-up-btn/counter-up-btn.pcss
@@ -0,0 +1 @@
+/* placeholder */
diff --git a/frontend/components/counter-view/_counter-view.html.erb b/frontend/components/counter-view/_counter-view.html.erb
new file mode 100644
index 0000000..c005fc2
--- /dev/null
+++ b/frontend/components/counter-view/_counter-view.html.erb
@@ -0,0 +1,11 @@
+
+
+ <%= c("counter-up-btn") %>
+
+
+ <%= c("counter-count", cluster: @cluster) %>
+
+
+ <%= c("counter-down-btn") %>
+
+
diff --git a/frontend/components/counter-view/counter-view.js b/frontend/components/counter-view/counter-view.js
new file mode 100644
index 0000000..c3293c9
--- /dev/null
+++ b/frontend/components/counter-view/counter-view.js
@@ -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";
diff --git a/frontend/components/counter-view/counter-view.pcss b/frontend/components/counter-view/counter-view.pcss
new file mode 100644
index 0000000..6bc2912
--- /dev/null
+++ b/frontend/components/counter-view/counter-view.pcss
@@ -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;
+ }
+}
diff --git a/frontend/components/page/page.pcss b/frontend/components/page/page.pcss
index 1247a4d..02fd664 100644
--- a/frontend/components/page/page.pcss
+++ b/frontend/components/page/page.pcss
@@ -1,6 +1,6 @@
.page {
height: 100vh;
- width: 700px;
margin: 0 auto;
+ max-width: 700px;
overflow: hidden;
}
diff --git a/frontend/packs/application.js b/frontend/packs/application.js
index f39197d..be20391 100644
--- a/frontend/packs/application.js
+++ b/frontend/packs/application.js
@@ -2,3 +2,4 @@ import "init";
import "components/page/page";
import "components/cluster-view/cluster-view";
+import "components/counter-view/counter-view";
diff --git a/package.json b/package.json
index d81cc5f..3a04330 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/test/channels/count_channel_test.rb b/test/channels/count_channel_test.rb
new file mode 100644
index 0000000..891e0d7
--- /dev/null
+++ b/test/channels/count_channel_test.rb
@@ -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
diff --git a/yarn.lock b/yarn.lock
index 25f8477..5ac797e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -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"