hotsheet 0.1.1 → 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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +21 -34
- data/app/assets/hotsheet.css +1 -0
- data/app/assets/hotsheet.js +33 -0
- data/app/controllers/hotsheet/application_controller.rb +2 -4
- data/app/controllers/hotsheet/sheets_controller.rb +47 -0
- data/app/helpers/hotsheet/application_helper.rb +3 -3
- data/app/views/hotsheet/shared/_nav.html.erb +14 -0
- data/app/views/hotsheet/sheets/error.html.erb +1 -0
- data/app/views/hotsheet/sheets/index.html.erb +20 -0
- data/app/views/hotsheet/sheets/root.html.erb +1 -0
- data/app/views/layouts/hotsheet/application.html.erb +7 -7
- data/config/routes.rb +6 -5
- data/lib/generators/templates/hotsheet.rb +7 -4
- data/lib/hotsheet/column.rb +31 -0
- data/lib/hotsheet/config.rb +29 -0
- data/lib/hotsheet/engine.rb +5 -4
- data/lib/hotsheet/sheet.rb +44 -0
- data/lib/hotsheet/version.rb +1 -1
- data/lib/hotsheet.rb +38 -12
- metadata +17 -90
- data/CHANGELOG.md +0 -22
- data/app/assets/config/hotsheet.js +0 -2
- data/app/assets/javascripts/hotsheet/application.js +0 -1
- data/app/assets/javascripts/hotsheet/channels/consumer.js +0 -3
- data/app/assets/javascripts/hotsheet/channels/inline_edit_channel.js +0 -3
- data/app/assets/javascripts/hotsheet/controllers/application.js +0 -8
- data/app/assets/javascripts/hotsheet/controllers/editable_attribute_controller.js +0 -39
- data/app/assets/javascripts/hotsheet/controllers/flash_controller.js +0 -8
- data/app/assets/stylesheets/hotsheet/application.css +0 -153
- data/app/channels/application_cable/channel.rb +0 -6
- data/app/channels/application_cable/connection.rb +0 -6
- data/app/channels/inline_edit_channel.rb +0 -9
- data/app/controllers/hotsheet/pages_controller.rb +0 -43
- data/app/views/hotsheet/pages/_editable_attribute.html.erb +0 -15
- data/app/views/hotsheet/pages/index.html.erb +0 -27
- data/app/views/layouts/hotsheet/_flash.html.erb +0 -10
- data/app/views/layouts/hotsheet/_sidebar.html.erb +0 -11
- data/config/initializers/hotsheet/content_security_policy.rb +0 -14
- data/config/initializers/hotsheet/pagy.rb +0 -7
- data/config/locales/en.yml +0 -5
- data/lib/hotsheet/configuration.rb +0 -59
- data/lib/hotsheet/editable_attributes.rb +0 -24
- data/vendor/assets/stylesheets/hotsheet/pagy.css +0 -37
@@ -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[:success] = 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(*Hotsheet.editable_attributes_for(model: model))
|
37
|
-
end
|
38
|
-
|
39
|
-
def model
|
40
|
-
@model ||= params[:model]&.constantize
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
<%# locals: (attribute:, model:, record:) %>
|
2
|
-
|
3
|
-
<%= turbo_frame_tag "#{dom_id record}-#{attribute}" do %>
|
4
|
-
<%= form_for record, url: "#{root_path}#{model.table_name}/#{record.id}",
|
5
|
-
html: { 'data-controller': "editable-attribute",
|
6
|
-
'data-editable-attribute-broadcast-url-value': broadcast_edit_intent_path,
|
7
|
-
'data-editable-attribute-resource-name-value': model.table_name,
|
8
|
-
'data-editable-attribute-resource-id-value': record.id,
|
9
|
-
'data-editable-attribute-resource-initial-value-value': record.public_send(attribute) } do |f| %>
|
10
|
-
<%= f.text_field attribute, class: "editable-input", data: {
|
11
|
-
editable_attribute_target: "attributeFormInput",
|
12
|
-
action: "keydown.enter->editable-attribute#submitForm blur->editable-attribute#submitForm"
|
13
|
-
} %>
|
14
|
-
<% end %>
|
15
|
-
<% end %>
|
@@ -1,27 +0,0 @@
|
|
1
|
-
<% if @model.nil? %>
|
2
|
-
<h1>Hotsheet</h1>
|
3
|
-
<p>Welcome to the hottest sheet around. Select a model from the sidebar to view the spreadsheet.</p>
|
4
|
-
<% else %>
|
5
|
-
<h1><%= @model.model_name.human %></h1>
|
6
|
-
<table>
|
7
|
-
<thead>
|
8
|
-
<tr>
|
9
|
-
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
|
10
|
-
<th><%= attribute %></th>
|
11
|
-
<% end %>
|
12
|
-
</tr>
|
13
|
-
</thead>
|
14
|
-
<tbody>
|
15
|
-
<% @records.each do |record| %>
|
16
|
-
<tr>
|
17
|
-
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
|
18
|
-
<td>
|
19
|
-
<%= render "editable_attribute", model: @model, record: record, attribute: attribute %>
|
20
|
-
</td>
|
21
|
-
<% end %>
|
22
|
-
</tr>
|
23
|
-
<% end %>
|
24
|
-
</tbody>
|
25
|
-
</table>
|
26
|
-
<%== pagy_nav @pagy %>
|
27
|
-
<% end %>
|
@@ -1,10 +0,0 @@
|
|
1
|
-
<%# locals: () %>
|
2
|
-
|
3
|
-
<div class='flash-container'>
|
4
|
-
<% flash.each do |type, msg| %>
|
5
|
-
<div class='flash <%= type %>' data-controller='flash'>
|
6
|
-
<span><%= msg %></span>
|
7
|
-
<button class='btn-close' data-action='click->flash#close'>×</button>
|
8
|
-
</div>
|
9
|
-
<% end %>
|
10
|
-
</div>
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
Rails.application.configure do
|
4
|
-
config.content_security_policy do |csp|
|
5
|
-
csp.default_src :none
|
6
|
-
csp.connect_src :self
|
7
|
-
csp.img_src :self
|
8
|
-
csp.script_src :strict_dynamic
|
9
|
-
csp.style_src :self, :unsafe_inline
|
10
|
-
end
|
11
|
-
|
12
|
-
config.content_security_policy_nonce_directives = %w[script-src]
|
13
|
-
config.content_security_policy_nonce_generator = ->(_) { SecureRandom.base64 18 }
|
14
|
-
end
|
data/config/locales/en.yml
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hotsheet
|
4
|
-
class Configuration
|
5
|
-
include ActiveSupport::Configurable
|
6
|
-
|
7
|
-
config_accessor(:models) { {} }
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
self.models = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def model(name)
|
14
|
-
model_config = ModelConfig.new(name).tap do |config|
|
15
|
-
yield(config) if block_given?
|
16
|
-
Rails.application.config.to_prepare { config.validate! }
|
17
|
-
end
|
18
|
-
models[name.to_s] = model_config
|
19
|
-
end
|
20
|
-
|
21
|
-
class ModelConfig
|
22
|
-
attr_accessor :included_attributes, :excluded_attributes, :model_name
|
23
|
-
|
24
|
-
def initialize(model_name)
|
25
|
-
@model_name = model_name
|
26
|
-
end
|
27
|
-
|
28
|
-
def validate!
|
29
|
-
return unless ActiveRecord::Base.connection.table_exists?(model_class.table_name)
|
30
|
-
return if included_attributes.nil? && excluded_attributes.nil?
|
31
|
-
|
32
|
-
ensure_only_one_attribute_set
|
33
|
-
validate_attribute_existence
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def ensure_only_one_attribute_set
|
39
|
-
return if included_attributes.blank? || excluded_attributes.blank?
|
40
|
-
|
41
|
-
raise "Can only specify either included or excluded attributes for '#{model_name}'"
|
42
|
-
end
|
43
|
-
|
44
|
-
def validate_attribute_existence
|
45
|
-
all_attributes = model_class.column_names
|
46
|
-
|
47
|
-
[included_attributes, excluded_attributes].flatten.compact.each do |attr|
|
48
|
-
unless all_attributes.include?(attr.to_s)
|
49
|
-
raise "Attribute '#{attr}' doesn't exist on model '#{model_name}'"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def model_class
|
55
|
-
model_name.to_s.constantize
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hotsheet
|
4
|
-
class << self
|
5
|
-
def editable_attributes_for(model:)
|
6
|
-
@editable_attributes_for ||= {}
|
7
|
-
@editable_attributes_for[model] ||= fetch_editable_attributes(model)
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def fetch_editable_attributes(model)
|
13
|
-
model_config = Hotsheet.configuration.models[model.to_s]
|
14
|
-
|
15
|
-
if model_config&.included_attributes
|
16
|
-
model_config.included_attributes.map(&:to_s)
|
17
|
-
elsif model_config&.excluded_attributes
|
18
|
-
model.column_names - model_config.excluded_attributes.map(&:to_s)
|
19
|
-
else
|
20
|
-
model.column_names
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
/* https://ddnexus.github.io/pagy/docs/api/stylesheets */
|
2
|
-
|
3
|
-
.pagy {
|
4
|
-
color: #6b7280;
|
5
|
-
display: flex;
|
6
|
-
font-size: .875rem;
|
7
|
-
font-weight: 600;
|
8
|
-
margin-top: 1rem;
|
9
|
-
|
10
|
-
a ~ a {
|
11
|
-
margin-left: .25rem;
|
12
|
-
}
|
13
|
-
|
14
|
-
a:not(.gap) {
|
15
|
-
background-color: #e5e7eb;
|
16
|
-
border-radius: .5rem;
|
17
|
-
color: inherit;
|
18
|
-
display: block;
|
19
|
-
padding: .25rem .75rem;
|
20
|
-
text-decoration: none;
|
21
|
-
|
22
|
-
&:hover {
|
23
|
-
background-color: #d1d5db;
|
24
|
-
}
|
25
|
-
|
26
|
-
&:not([href]) {
|
27
|
-
background-color: #f3f4f6;
|
28
|
-
color: #d1d5db;
|
29
|
-
cursor: default;
|
30
|
-
}
|
31
|
-
|
32
|
-
&.current {
|
33
|
-
background-color: #9ca3af;
|
34
|
-
color: white;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
}
|