From d07857c0113603b380c658cf1299d770994658f2 Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Sun, 5 Feb 2023 21:01:07 +0100 Subject: [PATCH] feat: added counts and instant update and destroy Signed-off-by: Louis Vallat --- app/channels/application_cable/connection.rb | 14 ++++++ app/channels/count_channel.rb | 33 ++++++++++++- app/controllers/count/home_controller.rb | 6 --- app/controllers/count_controller.rb | 51 ++++++++++++++++++++ app/controllers/home_controller.rb | 1 + app/javascript/add_bootstrap.js | 2 + app/javascript/add_jquery.js | 3 ++ app/javascript/application.js | 2 + app/javascript/channels/count_channel.js | 25 +++++++++- app/models/total.rb | 30 ++++++++++++ app/views/count/edit.html.erb | 4 ++ app/views/count/home/index.html.erb | 2 - app/views/count/index.html.erb | 22 +++++++++ app/views/count/new.html.erb | 4 ++ app/views/count/shared/_form.html.erb | 17 +++++++ app/views/home/index.html.erb | 12 ++++- app/views/layouts/application.html.erb | 11 +++-- config/locales/en/fields.en.yml | 6 ++- config/locales/en/flashes.en.yml | 12 +++++ config/locales/fr/fields.fr.yml | 4 ++ config/locales/fr/flashes.fr.yml | 12 +++++ config/routes.rb | 5 +- db/migrate/20230204135557_create_totals.rb | 10 ++++ db/schema.rb | 10 +++- package.json | 1 + yarn.lock | 5 ++ 26 files changed, 283 insertions(+), 21 deletions(-) delete mode 100644 app/controllers/count/home_controller.rb create mode 100644 app/controllers/count_controller.rb create mode 100644 app/javascript/add_bootstrap.js create mode 100644 app/javascript/add_jquery.js create mode 100644 app/models/total.rb create mode 100644 app/views/count/edit.html.erb delete mode 100644 app/views/count/home/index.html.erb create mode 100644 app/views/count/index.html.erb create mode 100644 app/views/count/new.html.erb create mode 100644 app/views/count/shared/_form.html.erb create mode 100644 config/locales/en/flashes.en.yml create mode 100644 config/locales/fr/flashes.fr.yml create mode 100644 db/migrate/20230204135557_create_totals.rb diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 0ff5442..4435513 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,4 +1,18 @@ module ApplicationCable class Connection < ActionCable::Connection::Base + identified_by :current_user + + def connect + self.current_user = find_verified_user + end + + private + def find_verified_user + if (verified_user = env['warden'].user) + verified_user + else + nil + end + end end end diff --git a/app/channels/count_channel.rb b/app/channels/count_channel.rb index 131c501..013cb0a 100644 --- a/app/channels/count_channel.rb +++ b/app/channels/count_channel.rb @@ -1,9 +1,40 @@ class CountChannel < ApplicationCable::Channel def subscribed - # stream_from "some_channel" + stream_from "counts" end def unsubscribed # Any cleanup needed when channel is unsubscribed end + + def plus_one(params) + unless current_user.nil? + total = Total.find(params["id"]) + unless total.nil? + total.update(count: total.count + 1) + end + end + end + + def minus_one(params) + unless current_user.nil? + total = Total.find(params["id"]) + unless total.nil? + total.update(count: total.count - 1) + end + end + end + + def self.create(total) + + end + + def self.update(total) + ActionCable.server.broadcast("counts", {"update": total}) + end + + def self.destroy(total) + ActionCable.server.broadcast("counts", {"destroy": total.id}) + end + end diff --git a/app/controllers/count/home_controller.rb b/app/controllers/count/home_controller.rb deleted file mode 100644 index 8e45f92..0000000 --- a/app/controllers/count/home_controller.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Count::HomeController < ApplicationController - before_action :authenticate_user! - - def index - end -end diff --git a/app/controllers/count_controller.rb b/app/controllers/count_controller.rb new file mode 100644 index 0000000..15679a3 --- /dev/null +++ b/app/controllers/count_controller.rb @@ -0,0 +1,51 @@ +class CountController < ApplicationController + before_action :authenticate_user! + + def index + @counts = Total.all + end + + def edit + @count = Total.find(params[:id]) + end + + def destroy + if Total.find(params[:id]).destroy + flash[:notice] = I18n.translate("flashes.count.destroy.success") + redirect_to count_index_path + else + flash[:alert] = I18n.translate("flashes.count.destroy.fail") + redirect_to edit_count_path + end + end + + def new + @count = Total.new + end + + def update + if Total.find(params[:id]).update(validated_params(params)) + flash[:notice] = I18n.translate("flashes.count.update.success") + redirect_to count_index_path + else + flash[:alert] = I18n.translate("flashes.count.update.fail") + redirect_to edit_count_path + end + end + + def create + if Total.new(validated_params(params)).save + flash[:notice] = I18n.translate("flashes.count.create.success") + redirect_to count_index_path + else + flash[:alert] = I18n.translate("flashes.count.create.fail") + redirect_to new_count_path + end + end + + private + + def validated_params(params) + params.require(:total).permit([:name, :count]) + end +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 95f2992..ffa553c 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -1,4 +1,5 @@ class HomeController < ApplicationController def index + @counts = Total.all end end diff --git a/app/javascript/add_bootstrap.js b/app/javascript/add_bootstrap.js new file mode 100644 index 0000000..9fc3350 --- /dev/null +++ b/app/javascript/add_bootstrap.js @@ -0,0 +1,2 @@ +import * as bootstrap from "bootstrap" +window.bootstrap = require('bootstrap/dist/js/bootstrap.bundle.js'); diff --git a/app/javascript/add_jquery.js b/app/javascript/add_jquery.js new file mode 100644 index 0000000..788c0f9 --- /dev/null +++ b/app/javascript/add_jquery.js @@ -0,0 +1,3 @@ +import jquery from 'jquery' +window.jQuery = jquery +window.$ = jquery diff --git a/app/javascript/application.js b/app/javascript/application.js index f4a553e..955db87 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -1,5 +1,7 @@ // Entry point for the build script in your package.json +import "./add_jquery" import "@hotwired/turbo-rails" import "./controllers" import * as bootstrap from "bootstrap" import "./channels" + diff --git a/app/javascript/channels/count_channel.js b/app/javascript/channels/count_channel.js index 2204e38..4b9fd3f 100644 --- a/app/javascript/channels/count_channel.js +++ b/app/javascript/channels/count_channel.js @@ -1,6 +1,6 @@ import consumer from "./consumer" -consumer.subscriptions.create("CountChannel", { +const count_channel = consumer.subscriptions.create("CountChannel", { connected() { // Called when the subscription is ready for use on the server console.warn("Connected to CountChannel."); @@ -12,5 +12,26 @@ consumer.subscriptions.create("CountChannel", { received(data) { // Called when there's incoming data on the websocket for this channel - } + console.log(data) + if (data.update !== undefined) + this.update(data.update) + + if (data.destroy !== undefined) + this.destroy(data.destroy) + }, + + update(data) { + $("[data-count-id='"+ data.id + "'] .count").text(data.count) + $("[data-count-id='"+ data.id + "'] .name").text(data.name) + }, + + destroy(data) { + $("[data-count-id='"+ data + "']").remove() + }, }); + +$(document).on('turbo:load', function() { + if (count_channel !== undefined && !count_channel.consumer.connection.disconnected) { + $("") + } +}) diff --git a/app/models/total.rb b/app/models/total.rb new file mode 100644 index 0000000..6410551 --- /dev/null +++ b/app/models/total.rb @@ -0,0 +1,30 @@ +# == Schema Information +# +# Table name: totals +# +# id :integer not null, primary key +# count :integer default(0), not null +# name :text not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_totals_on_name (name) +# +class Total < ApplicationRecord + validates_uniqueness_of :name + validates_length_of :name, in: 1..32 + + after_save do + CountChannel.create(self) + end + + after_update do + CountChannel.update(self) + end + + after_destroy do + CountChannel.destroy(self) + end +end diff --git a/app/views/count/edit.html.erb b/app/views/count/edit.html.erb new file mode 100644 index 0000000..758cac0 --- /dev/null +++ b/app/views/count/edit.html.erb @@ -0,0 +1,4 @@ + +

<%= t("fields.edit") %>

+ +<%= render "count/shared/form" %> diff --git a/app/views/count/home/index.html.erb b/app/views/count/home/index.html.erb deleted file mode 100644 index 4e6ef08..0000000 --- a/app/views/count/home/index.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Count::Home#index

-

Find me in app/views/count/home/index.html.erb

diff --git a/app/views/count/index.html.erb b/app/views/count/index.html.erb new file mode 100644 index 0000000..7c6beed --- /dev/null +++ b/app/views/count/index.html.erb @@ -0,0 +1,22 @@ +
+ <% @counts.each { |c| %> +
+
+
+ +
+ <%= c.count %> +
+ +
+
+
+ <%= c.name %> + <%= link_to "", edit_count_path(c), class: "btn btn-sm btn-primary bi-pen-fill" %> +
+
+ <% } %> +
+
+ <%= link_to "", new_count_path, class: "btn btn-lg btn-success fs-3 bi-plus-lg" %> +
diff --git a/app/views/count/new.html.erb b/app/views/count/new.html.erb new file mode 100644 index 0000000..af07f10 --- /dev/null +++ b/app/views/count/new.html.erb @@ -0,0 +1,4 @@ + +

<%= t("fields.new") %>

+ +<%= render "count/shared/form" %> \ No newline at end of file diff --git a/app/views/count/shared/_form.html.erb b/app/views/count/shared/_form.html.erb new file mode 100644 index 0000000..f97d659 --- /dev/null +++ b/app/views/count/shared/_form.html.erb @@ -0,0 +1,17 @@ +
+ <%= form_for @count, url: @count.id ? count_path : count_index_path, class: "row" do |f| %> +
+ <%= f.label :name, t("fields.name") %> + <%= f.text_field :name, class: "form-control" %> +
+
+ <%= f.label :count, t("fields.count") %> + <%= f.number_field :count, class: "form-control" %> +
+ <%= f.submit t("fields.save"), class: "btn btn-primary" %> + <% end %> +
+ +<% if @count.id %> + <%= button_to "", count_path(@count), method: :delete, class: "bi-trash-fill btn btn-danger" %> +<% end %> diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 2085730..d06f199 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -1,2 +1,10 @@ -

Home#index

-

Find me in app/views/home/index.html.erb

+
+ <% @counts.each { |c| %> +
+ <%= c.count %> +
+ <%= c.name %> +
+
+ <% } %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index fc485d4..f33302e 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -18,7 +18,7 @@ @@ -37,12 +37,17 @@
<% if notice %> -

<%= notice %>

+ <% end %> <% if alert %> -

<%= alert %>

+ <% end %> + <%= yield %>
diff --git a/config/locales/en/fields.en.yml b/config/locales/en/fields.en.yml index a010b66..9ec575d 100644 --- a/config/locales/en/fields.en.yml +++ b/config/locales/en/fields.en.yml @@ -4,4 +4,8 @@ en: login: "Login" logout: "Logout" count: "Count" - profile: "Profile" \ No newline at end of file + profile: "Profile" + edit: "Edit" + new: "New" + name: "Name" + save: "Save" \ No newline at end of file diff --git a/config/locales/en/flashes.en.yml b/config/locales/en/flashes.en.yml new file mode 100644 index 0000000..a5188fd --- /dev/null +++ b/config/locales/en/flashes.en.yml @@ -0,0 +1,12 @@ +en: + flashes: + count: + update: + success: "Count has been successfully saved." + fail: "The update failed for the count." + create: + success: "Count creation was successful." + fail: "Count creation failed." + destroy: + fail: "Count deletion has failed." + success: "Count has been deleted successfully." \ No newline at end of file diff --git a/config/locales/fr/fields.fr.yml b/config/locales/fr/fields.fr.yml index 5df770f..0e46a0d 100644 --- a/config/locales/fr/fields.fr.yml +++ b/config/locales/fr/fields.fr.yml @@ -5,3 +5,7 @@ fr: logout: "Se déconnecter" count: "Compte" profile: "Profil" + edit: "Éditer" + new: "Nouveau" + name: "Nom" + save: "Sauvegarder" diff --git a/config/locales/fr/flashes.fr.yml b/config/locales/fr/flashes.fr.yml new file mode 100644 index 0000000..1193b3c --- /dev/null +++ b/config/locales/fr/flashes.fr.yml @@ -0,0 +1,12 @@ +fr: + flashes: + count: + update: + success: "Le compte a bien été sauvegardé." + fail: "La mise à jour du compte a échoué." + create: + success: "La création du compte a été faite avec succès." + fail: "La création du compte a échoué." + destroy: + fail: "La suppression du compte a échoué." + success: "Le compte a été supprimé avec succès." \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index b200c24..cb94004 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,11 +1,10 @@ Rails.application.routes.draw do + namespace :profile do root "home#index" end - namespace :count do - root "home#index" - end + resources :count, except: [:show] root "home#index" diff --git a/db/migrate/20230204135557_create_totals.rb b/db/migrate/20230204135557_create_totals.rb new file mode 100644 index 0000000..7b67132 --- /dev/null +++ b/db/migrate/20230204135557_create_totals.rb @@ -0,0 +1,10 @@ +class CreateTotals < ActiveRecord::Migration[7.0] + def change + create_table :totals do |t| + t.integer :count, null: false, default: 0 + t.text :name, index: true, null: false + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index c68cedf..efd5971 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,15 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_02_04_125140) do +ActiveRecord::Schema[7.0].define(version: 2023_02_04_135557) do + create_table "totals", force: :cascade do |t| + t.integer "count", default: 0, null: false + t.text "name", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name"], name: "index_totals_on_name" + end + create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false diff --git a/package.json b/package.json index 4bb702c..6f8ae50 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@rails/actioncable": "^7.0.4-2", "bootstrap": "^5.2.3", "bootstrap-icons": "^1.10.3", + "jquery": "^3.6.3", "esbuild": "^0.17.5", "sass": "^1.58.0" }, diff --git a/yarn.lock b/yarn.lock index 5990ac2..7770fc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -266,6 +266,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +jquery@^3.6.3: + version "3.6.3" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.3.tgz#23ed2ffed8a19e048814f13391a19afcdba160e6" + integrity sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"