hotsheet 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +32 -35
  4. data/app/assets/hotsheet.css +1 -0
  5. data/app/assets/hotsheet.js +33 -0
  6. data/app/controllers/hotsheet/application_controller.rb +2 -4
  7. data/app/controllers/hotsheet/sheets_controller.rb +47 -0
  8. data/app/helpers/hotsheet/application_helper.rb +3 -3
  9. data/app/views/hotsheet/shared/_nav.html.erb +14 -0
  10. data/app/views/hotsheet/sheets/error.html.erb +1 -0
  11. data/app/views/hotsheet/sheets/index.html.erb +20 -0
  12. data/app/views/hotsheet/sheets/root.html.erb +1 -0
  13. data/app/views/layouts/hotsheet/application.html.erb +7 -7
  14. data/config/routes.rb +6 -5
  15. data/lib/generators/templates/hotsheet.rb +7 -4
  16. data/lib/hotsheet/column.rb +31 -0
  17. data/lib/hotsheet/config.rb +29 -0
  18. data/lib/hotsheet/engine.rb +5 -4
  19. data/lib/hotsheet/sheet.rb +44 -0
  20. data/lib/hotsheet/version.rb +1 -1
  21. data/lib/hotsheet.rb +38 -11
  22. metadata +17 -89
  23. data/CHANGELOG.md +0 -17
  24. data/app/assets/config/hotsheet.js +0 -2
  25. data/app/assets/javascripts/hotsheet/application.js +0 -1
  26. data/app/assets/javascripts/hotsheet/channels/consumer.js +0 -3
  27. data/app/assets/javascripts/hotsheet/channels/inline_edit_channel.js +0 -3
  28. data/app/assets/javascripts/hotsheet/controllers/application.js +0 -6
  29. data/app/assets/javascripts/hotsheet/controllers/editable_attribute_controller.js +0 -51
  30. data/app/assets/stylesheets/hotsheet/application.css +0 -86
  31. data/app/channels/application_cable/channel.rb +0 -6
  32. data/app/channels/application_cable/connection.rb +0 -6
  33. data/app/channels/inline_edit_channel.rb +0 -9
  34. data/app/controllers/hotsheet/pages_controller.rb +0 -43
  35. data/app/views/hotsheet/pages/_editable_attribute.html.erb +0 -24
  36. data/app/views/hotsheet/pages/index.html.erb +0 -27
  37. data/app/views/layouts/hotsheet/_flash.html.erb +0 -7
  38. data/app/views/layouts/hotsheet/_sidebar.html.erb +0 -11
  39. data/config/initializers/hotsheet/content_security_policy.rb +0 -14
  40. data/config/initializers/hotsheet/editable_attributes.rb +0 -43
  41. data/config/initializers/hotsheet/pagy.rb +0 -7
  42. data/config/locales/en.yml +0 -5
  43. data/lib/hotsheet/configuration.rb +0 -19
  44. data/vendor/assets/stylesheets/hotsheet/pagy.css +0 -37
@@ -0,0 +1 @@
1
+ <h1><%= Hotsheet.t "title" %></h1>
@@ -1,21 +1,21 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="<%= I18n.locale %>">
3
3
  <head>
4
- <title>Hotsheet</title>
4
+ <title><%= Hotsheet.t "title" %></title>
5
5
  <meta charset="utf-8">
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1">
7
7
  <meta name="robots" content="noindex,nofollow">
8
8
  <meta name="turbo-prefetch" content="false">
9
+ <meta name="turbo-refresh-method" content="morph">
10
+ <meta name="turbo-refresh-scroll" content="preserve">
9
11
  <%= csrf_meta_tags %>
10
- <%= csp_meta_tag %>
11
- <%= stylesheet_link_tag "hotsheet/application" %>
12
- <%= javascript_include_tag "hotsheet/application", "data-turbolinks-track": :reload,
13
- type: :module, nonce: content_security_policy_nonce, defer: true %>
12
+ <%= stylesheet_link_tag "hotsheet", nonce: true %>
13
+ <%= javascript_include_tag "hotsheet", nonce: true, defer: true %>
14
14
  </head>
15
15
  <body>
16
- <%= render "layouts/hotsheet/sidebar" %>
17
- <%= render "layouts/hotsheet/flash" %>
16
+ <%= render "hotsheet/shared/nav" %>
18
17
  <main>
18
+ <div class="flash"></div>
19
19
  <%= yield %>
20
20
  </main>
21
21
  </body>
data/config/routes.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Hotsheet::Engine.routes.draw do
4
- root to: "pages#index"
4
+ next unless defined? Rails::Server
5
5
 
6
- post :broadcast_edit_intent, to: "pages#broadcast_edit_intent"
7
-
8
- Hotsheet.models.each do |model|
9
- resources model.table_name, controller: :pages, only: %i[index update], model: model.name
6
+ Hotsheet.sheets.each_key do |sheet_name|
7
+ resources sheet_name, sheet_name:, controller: :sheets, only: %i[index update]
10
8
  end
9
+
10
+ root "sheets#root"
11
+ match "*path", to: "sheets#error", via: :all
11
12
  end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- Hotsheet.configure do |config|
4
- # Configure the models to be used by Hotsheet (see https://github.com/renuo/hotsheet?tab=readme-ov-file#usage)
3
+ # Configure the models to be used by Hotsheet.
4
+ # See https://github.com/renuo/hotsheet?tab=readme-ov-file#usage.
5
+ # The ID is included by default. It is always the first column.
5
6
 
6
- # config.model :User do |model|
7
- # model.excluded_attributes = %i[created_at updated_at]
7
+ Hotsheet.configure do
8
+ # sheet :User do
9
+ # column :name
10
+ # column :birthdate, editable: false
8
11
  # end
9
12
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hotsheet::Column
4
+ include Hotsheet::Config
5
+
6
+ attr_reader :config
7
+
8
+ CONFIG = {
9
+ editable: { allowed_classes: [FalseClass, Proc], default: true },
10
+ visible: { allowed_classes: [FalseClass, Proc], default: true }
11
+ }.freeze
12
+
13
+ def initialize(config)
14
+ @config = merge_config! CONFIG, config
15
+ end
16
+
17
+ def editable?
18
+ is? :editable
19
+ end
20
+
21
+ def visible?
22
+ is? :visible
23
+ end
24
+
25
+ private
26
+
27
+ def is?(permission)
28
+ perm = @config[permission]
29
+ perm.is_a?(Proc) ? perm.call : perm
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hotsheet::Config
4
+ def merge_config!(default, custom)
5
+ config = default.transform_values { |value| value[:default] }
6
+
7
+ custom.each do |key, value|
8
+ unless default.key? key
9
+ raise Hotsheet::Error, "Config must be one of #{default.keys}, got '#{key}'"
10
+ end
11
+
12
+ ensure_allowed_value! key, value, default[key]
13
+ config[key] = value
14
+ end
15
+
16
+ config
17
+ end
18
+
19
+ private
20
+
21
+ def ensure_allowed_value!(key, value, config)
22
+ allowed = config[:allowed_classes]
23
+ value = value.class
24
+
25
+ return if allowed.include? value
26
+
27
+ raise Hotsheet::Error, "Config '#{key}' must be one of #{allowed}, got '#{value}'"
28
+ end
29
+ end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Hotsheet
4
- class Engine < ::Rails::Engine
5
- isolate_namespace Hotsheet
3
+ class Hotsheet::Engine < Rails::Engine
4
+ isolate_namespace Hotsheet
6
5
 
7
- config.assets.precompile += %w[hotsheet/application.css hotsheet/application.js]
6
+ if config.respond_to? :assets
7
+ config.assets.paths << Hotsheet::Engine.root.join("app/assets")
8
+ config.assets.precompile << %w[hotsheet.css hotsheet.js]
8
9
  end
9
10
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Hotsheet::Sheet
4
+ include Hotsheet::Config
5
+
6
+ CONFIG = {}.freeze
7
+
8
+ attr_reader :config, :model
9
+
10
+ def initialize(name, config, &columns)
11
+ @config = merge_config! CONFIG, config
12
+ @model = name.to_s.constantize
13
+ @columns = {}
14
+
15
+ column :id, editable: false
16
+ columns ? instance_eval(&columns) : use_default_configuration
17
+ end
18
+
19
+ def columns
20
+ @columns.select { |_name, column| column.visible? }
21
+ end
22
+
23
+ def cells_for(columns)
24
+ @model.pluck(*columns.keys).transpose
25
+ end
26
+
27
+ private
28
+
29
+ def use_default_configuration
30
+ @model.column_names[1..].each { |name| column name }
31
+ end
32
+
33
+ def column(name, config = {})
34
+ ensure_column_exists! name
35
+
36
+ @columns[name.to_s] = Hotsheet::Column.new config
37
+ end
38
+
39
+ def ensure_column_exists!(name)
40
+ return if @model.column_names.include? name.to_s
41
+
42
+ raise Hotsheet::Error, "Column must be one of #{@model.column_names}, got '#{name}'"
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hotsheet
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/hotsheet.rb CHANGED
@@ -1,26 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "sprockets/railtie"
4
- require "turbo-rails"
5
-
6
- require "hotsheet/configuration"
7
- require "hotsheet/engine"
8
3
  require "hotsheet/version"
4
+ require "hotsheet/engine"
5
+ require "hotsheet/config"
6
+ require "hotsheet/sheet"
7
+ require "hotsheet/column"
9
8
 
10
9
  module Hotsheet
11
10
  class Error < StandardError; end
12
11
 
13
12
  class << self
14
- def configuration
15
- @configuration ||= Configuration.new
13
+ include Config
14
+
15
+ CONFIG = {}.freeze
16
+
17
+ attr_reader :config
18
+
19
+ def configure(config = {}, &sheets)
20
+ @config = [merge_config!(CONFIG, config), sheets]
21
+ self
16
22
  end
17
23
 
18
- def configure
19
- yield configuration
24
+ def sheets
25
+ @sheets ||= begin
26
+ @sheets = {}
27
+ instance_eval(&@config.pop)
28
+ @sheets
29
+ end
20
30
  end
21
31
 
22
- def models
23
- @models ||= configuration.models.each_key.map(&:constantize)
32
+ def t(key)
33
+ I18n.t key, scope: "hotsheet"
34
+ rescue I18n::MissingTranslationData
35
+ I18n.with_locale(:en) { I18n.t key, scope: "hotsheet" }
36
+ end
37
+
38
+ private
39
+
40
+ def sheet(name, config = {}, &)
41
+ ensure_sheet_exists! name
42
+
43
+ sheet = Sheet.new(name, config, &)
44
+ @sheets[sheet.model.table_name] = sheet
45
+ end
46
+
47
+ def ensure_sheet_exists!(name)
48
+ return if Object.const_defined? name
49
+
50
+ raise Hotsheet::Error, "Unknown model '#{name}'"
24
51
  end
25
52
  end
26
53
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Renuo AG
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-08 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rails
@@ -24,64 +23,7 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: 6.1.0
27
- - !ruby/object:Gem::Dependency
28
- name: pagy
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: sprockets-rails
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: stimulus-rails
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: turbo-rails
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- description: This gem allows you to mount a view to manage your database using atable
84
- view where you can edit DB records inline.
26
+ description: Manage your Rails database through a spreadsheet-like interface.
85
27
  email:
86
28
  - ignacio.sfeir@renuo.ch
87
29
  - simon.isler@renuo.ch
@@ -91,49 +33,36 @@ executables: []
91
33
  extensions: []
92
34
  extra_rdoc_files: []
93
35
  files:
94
- - CHANGELOG.md
95
36
  - LICENSE
96
37
  - README.md
97
- - app/assets/config/hotsheet.js
98
- - app/assets/javascripts/hotsheet/application.js
99
- - app/assets/javascripts/hotsheet/channels/consumer.js
100
- - app/assets/javascripts/hotsheet/channels/inline_edit_channel.js
101
- - app/assets/javascripts/hotsheet/controllers/application.js
102
- - app/assets/javascripts/hotsheet/controllers/editable_attribute_controller.js
103
- - app/assets/stylesheets/hotsheet/application.css
104
- - app/channels/application_cable/channel.rb
105
- - app/channels/application_cable/connection.rb
106
- - app/channels/inline_edit_channel.rb
38
+ - app/assets/hotsheet.css
39
+ - app/assets/hotsheet.js
107
40
  - app/controllers/hotsheet/application_controller.rb
108
- - app/controllers/hotsheet/pages_controller.rb
41
+ - app/controllers/hotsheet/sheets_controller.rb
109
42
  - app/helpers/hotsheet/application_helper.rb
110
- - app/views/hotsheet/pages/_editable_attribute.html.erb
111
- - app/views/hotsheet/pages/index.html.erb
112
- - app/views/layouts/hotsheet/_flash.html.erb
113
- - app/views/layouts/hotsheet/_sidebar.html.erb
43
+ - app/views/hotsheet/shared/_nav.html.erb
44
+ - app/views/hotsheet/sheets/error.html.erb
45
+ - app/views/hotsheet/sheets/index.html.erb
46
+ - app/views/hotsheet/sheets/root.html.erb
114
47
  - app/views/layouts/hotsheet/application.html.erb
115
- - config/initializers/hotsheet/content_security_policy.rb
116
- - config/initializers/hotsheet/editable_attributes.rb
117
- - config/initializers/hotsheet/pagy.rb
118
- - config/locales/en.yml
119
48
  - config/routes.rb
120
49
  - lib/generators/hotsheet/install_generator.rb
121
50
  - lib/generators/templates/hotsheet.rb
122
51
  - lib/hotsheet.rb
123
- - lib/hotsheet/configuration.rb
52
+ - lib/hotsheet/column.rb
53
+ - lib/hotsheet/config.rb
124
54
  - lib/hotsheet/engine.rb
55
+ - lib/hotsheet/sheet.rb
125
56
  - lib/hotsheet/version.rb
126
- - vendor/assets/stylesheets/hotsheet/pagy.css
127
57
  homepage: https://github.com/renuo/hotsheet
128
58
  licenses:
129
59
  - MIT
130
60
  metadata:
131
- homepage_uri: https://github.com/renuo/hotsheet
132
61
  source_code_uri: https://github.com/renuo/hotsheet
62
+ bug_tracker_uri: https://github.com/renuo/hotsheet/issues
133
63
  changelog_uri: https://github.com/renuo/hotsheet/blob/main/CHANGELOG.md
134
64
  documentation_uri: https://github.com/renuo/hotsheet/blob/main/README.md
135
65
  rubygems_mfa_required: 'true'
136
- post_install_message:
137
66
  rdoc_options: []
138
67
  require_paths:
139
68
  - lib
@@ -141,15 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
70
  requirements:
142
71
  - - ">="
143
72
  - !ruby/object:Gem::Version
144
- version: 3.0.0
73
+ version: 3.1.0
145
74
  required_rubygems_version: !ruby/object:Gem::Requirement
146
75
  requirements:
147
76
  - - ">="
148
77
  - !ruby/object:Gem::Version
149
78
  version: '0'
150
79
  requirements: []
151
- rubygems_version: 3.5.16
152
- signing_key:
80
+ rubygems_version: 3.6.9
153
81
  specification_version: 4
154
- summary: Manage your database with a simple and familiar web interface
82
+ summary: Database GUI for Rails.
155
83
  test_files: []
data/CHANGELOG.md DELETED
@@ -1,17 +0,0 @@
1
- ## [Unreleased](https://github.com/renuo/hotsheet/compare/v0.1.0..HEAD)
2
-
3
- -
4
-
5
- ## [0.1.0](https://github.com/renuo/hotsheet/releases/tag/v0.1.0) (2024-11-05)
6
-
7
- - Gem structure and initial configuration ([@ignaciosy])
8
- - Inline editing table (([@simon-isler]) and ([@edmunteanu]))
9
- - Dummy app for development and test ([@hunchr])
10
- - Configuration for initializer, CI, lint, tests ([@hunchr])
11
- - Generator `bin/rails g hotsheet:install` for copying initializer and mounting engine in routes ([@hunchr])
12
- - Pagination for data tables ([@hunchr])
13
-
14
- [@ignaciosy]: https://github.com/ignaciosy
15
- [@hunchr]: https://github.com/hunchr
16
- [@simon-isler]: https://github.com/simon-isler
17
- [@edmunteanu]: https://github.com/edmunteanu
@@ -1,2 +0,0 @@
1
- //= link_directory ../stylesheets/hotsheet .css
2
- //= link_directory ../javascripts/hotsheet .js
@@ -1 +0,0 @@
1
- //= require ./controllers/application
@@ -1,3 +0,0 @@
1
- import { createConsumer } from "https://unpkg.com/@rails/actioncable@7.1.3-4/app/assets/javascripts/actioncable.esm.js"
2
-
3
- export default createConsumer()
@@ -1,3 +0,0 @@
1
- import consumer from "channels/consumer"
2
-
3
- consumer.subscriptions.create({ channel: "InlineEditChannel" })
@@ -1,6 +0,0 @@
1
- import { Application } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
2
- import EditableAttributeController from "./controllers/editable_attribute_controller"
3
-
4
- window.Stimulus = Application.start()
5
-
6
- Stimulus.register("editable-attribute", EditableAttributeController)
@@ -1,51 +0,0 @@
1
- import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
2
-
3
- export default class extends Controller {
4
- static values = {
5
- broadcastUrl: String,
6
- resourceName: String,
7
- resourceId: Number,
8
- }
9
-
10
- static targets = ["readonlyAttribute", "attributeForm", "attributeFormInput"]
11
-
12
- displayInputField() {
13
- // this.broadcastEditIntent()
14
- this.readonlyAttributeTarget.style.display = "none"
15
- this.attributeFormTarget.style.display = "block"
16
- this.attributeFormInputTarget.focus()
17
- }
18
-
19
- broadcastEditIntent() {
20
- const headers = {
21
- "Content-Type": "application/json",
22
- "X-CSRF-Token": document.querySelector("meta[name=csrf-token]").content,
23
- }
24
- const body = JSON.stringify({
25
- broadcast: {
26
- resource_name: this.resourceNameValue,
27
- resource_id: this.resourceIdValue,
28
- },
29
- })
30
-
31
- fetch(this.broadcastUrlValue, { method: "POST", headers, body })
32
- }
33
-
34
- submitForm(event) {
35
- // Prevent standard submission triggered by Enter press
36
- event.preventDefault()
37
-
38
- const previousValue = this.readonlyAttributeTarget.innerText.trim()
39
- const newValue = this.attributeFormInputTarget.value
40
-
41
- if (previousValue && previousValue === newValue) {
42
- this.readonlyAttributeTarget.style.display = "block"
43
- this.attributeFormTarget.style.display = "none"
44
- return
45
- }
46
-
47
- // It's important to use requestSubmit() instead of simply submit() as the latter will circumvent the
48
- // Turbo mechanism, causing the PATCH request to be submitted as HTML instead of TURBO_STREAM
49
- this.attributeFormInputTarget.form.requestSubmit()
50
- }
51
- }
@@ -1,86 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- *= require_tree .
6
- *= require_self
7
- *= require hotsheet/pagy
8
- */
9
-
10
- :root {
11
- --bg-color: lightgray;
12
- --sidebar-width: 12rem;
13
- }
14
-
15
- body {
16
- font: 400 16px system-ui, Roboto, Helvetica, Arial, sans-serif;
17
- margin: 0;
18
- }
19
-
20
- main {
21
- margin-left: var(--sidebar-width);
22
- padding: 1rem;
23
- }
24
-
25
- aside {
26
- background-color: var(--bg-color);
27
- border-right: 1px solid gray;
28
- height: 100%;
29
- left: 0;
30
- overflow-y: auto;
31
- position: fixed;
32
- top: 0;
33
- width: var(--sidebar-width);
34
-
35
- ul {
36
- display: flex;
37
- flex-direction: column;
38
- margin: 0;
39
- padding: 0.25rem;
40
-
41
- a {
42
- border-radius: 0.5rem;
43
- color: green;
44
- font-weight: 700;
45
- overflow: hidden;
46
- padding: 0.5rem;
47
- text-decoration: none;
48
- text-overflow: ellipsis;
49
- white-space: nowrap;
50
-
51
- &:hover {
52
- background-color: darkgray;
53
- }
54
- }
55
- }
56
- }
57
-
58
- h1 {
59
- margin: 0 0 1rem 0;
60
- }
61
-
62
- table {
63
- border-collapse: collapse;
64
-
65
- th,
66
- td {
67
- border: 1px solid var(--bg-color);
68
- padding: 0.5rem;
69
- text-align: left;
70
- }
71
-
72
- th {
73
- background-color: var(--bg-color);
74
- }
75
-
76
- .readonly-attribute {
77
- min-height: 1rem;
78
- min-width: 1rem;
79
- }
80
-
81
- .editable-input {
82
- background-color: transparent;
83
- border: none;
84
- width: 100%;
85
- }
86
- }
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ApplicationCable
4
- class Channel < ActionCable::Channel::Base
5
- end
6
- end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ApplicationCable
4
- class Connection < ActionCable::Connection::Base
5
- end
6
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class InlineEditChannel < ApplicationCable::Channel
4
- STREAM_NAME = "inline_edit"
5
-
6
- def subscribed
7
- stream_from STREAM_NAME
8
- end
9
- end
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hotsheet
4
- class PagesController < ApplicationController
5
- def index
6
- @pagy, @records = pagy model.all if model
7
- end
8
-
9
- def broadcast_edit_intent
10
- ActionCable.server.broadcast InlineEditChannel::STREAM_NAME, {
11
- resource_name: broadcast_params[:resource_name],
12
- resource_id: broadcast_params[:resource_id]
13
- }
14
- end
15
-
16
- def update # rubocop:disable Metrics/AbcSize
17
- record = model.find params[:id]
18
-
19
- if record.update model_params
20
- flash[:notice] = t("hotsheet.success", record: model.model_name.human)
21
- else
22
- flash[:alert] = t("hotsheet.error", record: model.model_name.human,
23
- errors: record.errors.full_messages.join(", "))
24
- end
25
-
26
- redirect_to "#{root_path}#{model.table_name}"
27
- end
28
-
29
- private
30
-
31
- def broadcast_params
32
- params.require(:broadcast).permit :resource_name, :resource_id
33
- end
34
-
35
- def model_params
36
- params.require(model.name.underscore).permit(*model.editable_attributes)
37
- end
38
-
39
- def model
40
- @model ||= params[:model]&.constantize
41
- end
42
- end
43
- end