hotsheet 0.1.0 → 0.1.1
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/CHANGELOG.md +7 -2
- data/README.md +19 -9
- data/app/assets/javascripts/hotsheet/controllers/application.js +2 -0
- data/app/assets/javascripts/hotsheet/controllers/editable_attribute_controller.js +4 -16
- data/app/assets/javascripts/hotsheet/controllers/flash_controller.js +8 -0
- data/app/assets/stylesheets/hotsheet/application.css +73 -6
- data/app/controllers/hotsheet/pages_controller.rb +2 -2
- data/app/views/hotsheet/pages/_editable_attribute.html.erb +11 -20
- data/app/views/hotsheet/pages/index.html.erb +2 -2
- data/app/views/layouts/hotsheet/_flash.html.erb +8 -5
- data/app/views/layouts/hotsheet/application.html.erb +1 -1
- data/lib/hotsheet/configuration.rb +44 -4
- data/lib/hotsheet/editable_attributes.rb +24 -0
- data/lib/hotsheet/version.rb +1 -1
- data/lib/hotsheet.rb +4 -3
- metadata +5 -4
- data/config/initializers/hotsheet/editable_attributes.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b1cc53c691cd9b61d1361342ba5ce7be20d3992dafa47bd770cd12cf0976158
|
4
|
+
data.tar.gz: 2db750a0be71817cb2d2ce9dd02153d559813e810cade288b85d8f41728fe509
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e8e1ad31860f0145d8d6128107c70fcee0cd5c8cf2b86d4ad29dabd6a6619e41d5e71371268e27465d5d27d46ed6191e96ce86a40dd87958462e0225f1824f4
|
7
|
+
data.tar.gz: eddc23e4ce169c549aa43446e77c7206bc3d20c1bbe52c9472052be98e90fc14fa69e1a92c879b874151717c5befca37b0d8b69905b154d9a769f6f57bb71642
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
-
## [Unreleased](https://github.com/renuo/hotsheet/compare/v0.1.0..HEAD)
|
1
|
+
<!-- ## [Unreleased](https://github.com/renuo/hotsheet/compare/v0.1.0..HEAD) -->
|
2
2
|
|
3
|
-
-
|
3
|
+
## [0.1.1](https://github.com/renuo/hotsheet/releases/tag/v0.1.1) (2025-02-03)
|
4
|
+
|
5
|
+
- Improve configuration file usage and logic ([@simon-isler])
|
6
|
+
- Configure compatible Ruby/Rails versions for testing ([@ignaciosy])
|
7
|
+
- Improve flash messages layout ([@ignaciosy])
|
8
|
+
- Form inputs are now always visible for usage simplicity ([@ignaciosy])
|
4
9
|
|
5
10
|
## [0.1.0](https://github.com/renuo/hotsheet/releases/tag/v0.1.0) (2024-11-05)
|
6
11
|
|
data/README.md
CHANGED
@@ -5,6 +5,13 @@
|
|
5
5
|
This gem allows you to mount a view to manage your database using a table view
|
6
6
|
where you can edit database records inline.
|
7
7
|
|
8
|
+
- Look at and modify your DB within the app itself (no rails console required!).
|
9
|
+
- Give controlled DB access to your admin users without having to create CRUD views for each table.
|
10
|
+
- Lightweight and fast. We keep usage simple and configuration to the minimum.
|
11
|
+
|
12
|
+

|
13
|
+
|
14
|
+
|
8
15
|
## Installation
|
9
16
|
|
10
17
|
Add this line to your application's Gemfile:
|
@@ -22,6 +29,10 @@ bin/rails g hotsheet:install
|
|
22
29
|
|
23
30
|
## Usage
|
24
31
|
|
32
|
+
After installing, you can directly go to `/hotsheet` within your app by default.
|
33
|
+
|
34
|
+
### Configuration
|
35
|
+
|
25
36
|
You can configure which models this gem should manage, and specify which
|
26
37
|
attributes (database columns) should be editable in the Hotsheet. This can be
|
27
38
|
done by configuring the initializer file created by the install command:
|
@@ -41,16 +52,15 @@ end
|
|
41
52
|
|
42
53
|
See [Contributing Guide] for information on how to set up hotsheet locally.
|
43
54
|
|
44
|
-
## Roadmap
|
55
|
+
## Roadmap
|
56
|
+
|
57
|
+
This is a newly created gem which we are actively working on, and we will firstly focus on:
|
58
|
+
|
59
|
+
1. Single-user experience (styles and usability)
|
60
|
+
2. Configuration and access permissions
|
61
|
+
3. Concurrent users (broadcasting, conflict resolution)
|
45
62
|
|
46
|
-
|
47
|
-
- Support live updates (show when someone has the intention to edit a resource) via ActionCable
|
48
|
-
- Conflict resolution strategy (locking / merging / latest change etc.)
|
49
|
-
- Fine grained access / permissions (cancancan)
|
50
|
-
- Type-specific input fields
|
51
|
-
- Undo feature (or confirm / discard changes icons)
|
52
|
-
- Configure visibility of non-editable (excluded) fields
|
53
|
-
- Use importmap-rails for JS dependencies
|
63
|
+
Feel free to look at our [planned enhancements](https://github.com/renuo/hotsheet/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) or add your own.
|
54
64
|
|
55
65
|
## License
|
56
66
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import { Application } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
|
2
2
|
import EditableAttributeController from "./controllers/editable_attribute_controller"
|
3
|
+
import FlashController from "./controllers/flash_controller"
|
3
4
|
|
4
5
|
window.Stimulus = Application.start()
|
5
6
|
|
6
7
|
Stimulus.register("editable-attribute", EditableAttributeController)
|
8
|
+
Stimulus.register("flash", FlashController)
|
@@ -5,18 +5,12 @@ export default class extends Controller {
|
|
5
5
|
broadcastUrl: String,
|
6
6
|
resourceName: String,
|
7
7
|
resourceId: Number,
|
8
|
+
resourceInitialValue: String
|
8
9
|
}
|
9
10
|
|
10
|
-
static targets = ["
|
11
|
+
static targets = ["attributeFormInput"]
|
11
12
|
|
12
|
-
|
13
|
-
// this.broadcastEditIntent()
|
14
|
-
this.readonlyAttributeTarget.style.display = "none"
|
15
|
-
this.attributeFormTarget.style.display = "block"
|
16
|
-
this.attributeFormInputTarget.focus()
|
17
|
-
}
|
18
|
-
|
19
|
-
broadcastEditIntent() {
|
13
|
+
broadcastEditIntent() { // TODO: trigger on input focus
|
20
14
|
const headers = {
|
21
15
|
"Content-Type": "application/json",
|
22
16
|
"X-CSRF-Token": document.querySelector("meta[name=csrf-token]").content,
|
@@ -35,14 +29,8 @@ export default class extends Controller {
|
|
35
29
|
// Prevent standard submission triggered by Enter press
|
36
30
|
event.preventDefault()
|
37
31
|
|
38
|
-
const previousValue = this.readonlyAttributeTarget.innerText.trim()
|
39
32
|
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
|
-
}
|
33
|
+
if (this.resourceInitialValueValue === newValue) return;
|
46
34
|
|
47
35
|
// It's important to use requestSubmit() instead of simply submit() as the latter will circumvent the
|
48
36
|
// Turbo mechanism, causing the PATCH request to be submitted as HTML instead of TURBO_STREAM
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
close() {
|
5
|
+
this.element.addEventListener("animationend", () => { this.element.remove(); });
|
6
|
+
this.element.classList.add("closing");
|
7
|
+
}
|
8
|
+
}
|
@@ -8,18 +8,28 @@
|
|
8
8
|
*/
|
9
9
|
|
10
10
|
:root {
|
11
|
-
--bg-color: lightgray;
|
12
11
|
--sidebar-width: 12rem;
|
12
|
+
--main-padding-x: 2rem;
|
13
|
+
--main-padding-y: 2rem;
|
14
|
+
|
15
|
+
--body-font: 400 16px system-ui, Roboto, Helvetica, Arial, sans-serif;
|
16
|
+
--bg-color: lightgray;
|
17
|
+
--success-color: green;
|
18
|
+
--alert-color: yellow;
|
19
|
+
--notice-color: blue;
|
20
|
+
--error-color: red;
|
21
|
+
|
22
|
+
--td-padding: 0.5rem;
|
13
23
|
}
|
14
24
|
|
15
25
|
body {
|
16
|
-
font:
|
26
|
+
font: var(--body-font);
|
17
27
|
margin: 0;
|
18
28
|
}
|
19
29
|
|
20
30
|
main {
|
21
31
|
margin-left: var(--sidebar-width);
|
22
|
-
padding:
|
32
|
+
padding: var(--main-padding-y) var(--main-padding-x);
|
23
33
|
}
|
24
34
|
|
25
35
|
aside {
|
@@ -36,7 +46,7 @@ aside {
|
|
36
46
|
display: flex;
|
37
47
|
flex-direction: column;
|
38
48
|
margin: 0;
|
39
|
-
padding: 0.
|
49
|
+
padding: 0.5rem;
|
40
50
|
|
41
51
|
a {
|
42
52
|
border-radius: 0.5rem;
|
@@ -65,12 +75,12 @@ table {
|
|
65
75
|
th,
|
66
76
|
td {
|
67
77
|
border: 1px solid var(--bg-color);
|
68
|
-
padding: 0.5rem;
|
69
78
|
text-align: left;
|
70
79
|
}
|
71
80
|
|
72
81
|
th {
|
73
82
|
background-color: var(--bg-color);
|
83
|
+
padding: var(--td-padding);
|
74
84
|
}
|
75
85
|
|
76
86
|
.readonly-attribute {
|
@@ -81,6 +91,63 @@ table {
|
|
81
91
|
.editable-input {
|
82
92
|
background-color: transparent;
|
83
93
|
border: none;
|
84
|
-
|
94
|
+
font: var(--body-font);
|
95
|
+
padding: var(--td-padding);
|
96
|
+
width: calc(100% - var(--td-padding) * 2);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
.flash-container {
|
101
|
+
position: fixed;
|
102
|
+
display: flex;
|
103
|
+
flex-direction: column;
|
104
|
+
bottom: 1rem;
|
105
|
+
right: 1rem;
|
106
|
+
gap: 1rem;
|
107
|
+
max-width: calc(100% - var(--sidebar-width) - var(--main-padding-x));
|
108
|
+
|
109
|
+
.flash {
|
110
|
+
border-radius: 0.4rem;
|
111
|
+
padding: 0.75rem 1.25rem;
|
112
|
+
display: flex;
|
113
|
+
justify-content: space-between;
|
114
|
+
align-items: center;
|
115
|
+
gap: 1rem;
|
116
|
+
|
117
|
+
&.success {
|
118
|
+
background-color: rgb(from var(--success-color) r g b / 80%);
|
119
|
+
}
|
120
|
+
|
121
|
+
&.alert {
|
122
|
+
background-color: rgb(from var(--alert-color) r g b / 80%);
|
123
|
+
}
|
124
|
+
|
125
|
+
&.notice {
|
126
|
+
background-color: rgb(from var(--notice-color) r g b / 80%);
|
127
|
+
}
|
128
|
+
|
129
|
+
&.error {
|
130
|
+
background-color: rgb(from var(--error-color) r g b / 80%);
|
131
|
+
}
|
132
|
+
|
133
|
+
.btn-close {
|
134
|
+
background-color: transparent;
|
135
|
+
border: none;
|
136
|
+
cursor: pointer;
|
137
|
+
font-size: 1.5rem;
|
138
|
+
}
|
139
|
+
|
140
|
+
&.closing {
|
141
|
+
animation: fade-out 0.5s ease-in forwards;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
@keyframes fade-out {
|
147
|
+
from {
|
148
|
+
opacity: 1;
|
149
|
+
}
|
150
|
+
to {
|
151
|
+
opacity: 0;
|
85
152
|
}
|
86
153
|
}
|
@@ -17,7 +17,7 @@ module Hotsheet
|
|
17
17
|
record = model.find params[:id]
|
18
18
|
|
19
19
|
if record.update model_params
|
20
|
-
flash[:
|
20
|
+
flash[:success] = t("hotsheet.success", record: model.model_name.human)
|
21
21
|
else
|
22
22
|
flash[:alert] = t("hotsheet.error", record: model.model_name.human,
|
23
23
|
errors: record.errors.full_messages.join(", "))
|
@@ -33,7 +33,7 @@ module Hotsheet
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def model_params
|
36
|
-
params.require(model.name.underscore).permit(*model
|
36
|
+
params.require(model.name.underscore).permit(*Hotsheet.editable_attributes_for(model: model))
|
37
37
|
end
|
38
38
|
|
39
39
|
def model
|
@@ -1,24 +1,15 @@
|
|
1
1
|
<%# locals: (attribute:, model:, record:) %>
|
2
2
|
|
3
3
|
<%= turbo_frame_tag "#{dom_id record}-#{attribute}" do %>
|
4
|
-
|
5
|
-
data-editable-attribute
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
<div data-editable-attribute-target="attributeForm" style="display:none">
|
16
|
-
<%= form_for record, url: "#{root_path}#{model.table_name}/#{record.id}" do |f| %>
|
17
|
-
<%= f.text_field attribute, class: "editable-input", data: {
|
18
|
-
editable_attribute_target: "attributeFormInput",
|
19
|
-
action: "keydown.enter->editable-attribute#submitForm blur->editable-attribute#submitForm"
|
20
|
-
} %>
|
21
|
-
<% end %>
|
22
|
-
</div>
|
23
|
-
</div>
|
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 %>
|
24
15
|
<% end %>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<table>
|
7
7
|
<thead>
|
8
8
|
<tr>
|
9
|
-
<% @model.
|
9
|
+
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
|
10
10
|
<th><%= attribute %></th>
|
11
11
|
<% end %>
|
12
12
|
</tr>
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<tbody>
|
15
15
|
<% @records.each do |record| %>
|
16
16
|
<tr>
|
17
|
-
<% @model.
|
17
|
+
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
|
18
18
|
<td>
|
19
19
|
<%= render "editable_attribute", model: @model, record: record, attribute: attribute %>
|
20
20
|
</td>
|
@@ -1,7 +1,10 @@
|
|
1
1
|
<%# locals: () %>
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
<
|
6
|
-
|
7
|
-
|
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>
|
@@ -6,14 +6,54 @@ module Hotsheet
|
|
6
6
|
|
7
7
|
config_accessor(:models) { {} }
|
8
8
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
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
|
12
18
|
models[name.to_s] = model_config
|
13
19
|
end
|
14
20
|
|
15
21
|
class ModelConfig
|
16
|
-
attr_accessor :included_attributes, :excluded_attributes
|
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
|
17
57
|
end
|
18
58
|
end
|
19
59
|
end
|
@@ -0,0 +1,24 @@
|
|
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
|
data/lib/hotsheet/version.rb
CHANGED
data/lib/hotsheet.rb
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
require "sprockets/railtie"
|
4
4
|
require "turbo-rails"
|
5
5
|
|
6
|
-
require "hotsheet/configuration"
|
7
6
|
require "hotsheet/engine"
|
8
7
|
require "hotsheet/version"
|
8
|
+
require "hotsheet/configuration"
|
9
|
+
require "hotsheet/editable_attributes"
|
9
10
|
|
10
11
|
module Hotsheet
|
11
12
|
class Error < StandardError; end
|
@@ -15,8 +16,8 @@ module Hotsheet
|
|
15
16
|
@configuration ||= Configuration.new
|
16
17
|
end
|
17
18
|
|
18
|
-
def configure
|
19
|
-
|
19
|
+
def configure(&block)
|
20
|
+
@configuration = Configuration.new.tap(&block)
|
20
21
|
end
|
21
22
|
|
22
23
|
def models
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotsheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Renuo AG
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
description: This gem allows you to mount a view to manage your database using
|
83
|
+
description: This gem allows you to mount a view to manage your database using a table
|
84
84
|
view where you can edit DB records inline.
|
85
85
|
email:
|
86
86
|
- ignacio.sfeir@renuo.ch
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- app/assets/javascripts/hotsheet/channels/inline_edit_channel.js
|
101
101
|
- app/assets/javascripts/hotsheet/controllers/application.js
|
102
102
|
- app/assets/javascripts/hotsheet/controllers/editable_attribute_controller.js
|
103
|
+
- app/assets/javascripts/hotsheet/controllers/flash_controller.js
|
103
104
|
- app/assets/stylesheets/hotsheet/application.css
|
104
105
|
- app/channels/application_cable/channel.rb
|
105
106
|
- app/channels/application_cable/connection.rb
|
@@ -113,7 +114,6 @@ files:
|
|
113
114
|
- app/views/layouts/hotsheet/_sidebar.html.erb
|
114
115
|
- app/views/layouts/hotsheet/application.html.erb
|
115
116
|
- config/initializers/hotsheet/content_security_policy.rb
|
116
|
-
- config/initializers/hotsheet/editable_attributes.rb
|
117
117
|
- config/initializers/hotsheet/pagy.rb
|
118
118
|
- config/locales/en.yml
|
119
119
|
- config/routes.rb
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- lib/generators/templates/hotsheet.rb
|
122
122
|
- lib/hotsheet.rb
|
123
123
|
- lib/hotsheet/configuration.rb
|
124
|
+
- lib/hotsheet/editable_attributes.rb
|
124
125
|
- lib/hotsheet/engine.rb
|
125
126
|
- lib/hotsheet/version.rb
|
126
127
|
- vendor/assets/stylesheets/hotsheet/pagy.css
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
Rails.application.config.after_initialize do # rubocop:disable Metrics/BlockLength
|
4
|
-
# Only run this initializer when running the Rails server
|
5
|
-
next unless Rails.env.test? || defined? Rails::Server
|
6
|
-
|
7
|
-
Hotsheet.configuration.models.each_key do |model| # rubocop:disable Metrics/BlockLength
|
8
|
-
model.constantize.class_eval do
|
9
|
-
class << self
|
10
|
-
def editable_attributes
|
11
|
-
@editable_attributes ||= fetch_editable_attributes
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def fetch_editable_attributes
|
17
|
-
config = Hotsheet.configuration.models[name]
|
18
|
-
excluded_attributes = config.excluded_attributes
|
19
|
-
|
20
|
-
if config.included_attributes.present?
|
21
|
-
raise "Can only specify either included or excluded attributes" if excluded_attributes.present?
|
22
|
-
|
23
|
-
attrs_to_s(config.included_attributes)
|
24
|
-
elsif excluded_attributes.present?
|
25
|
-
column_names - attrs_to_s(excluded_attributes)
|
26
|
-
else
|
27
|
-
column_names
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def attrs_to_s(attrs)
|
32
|
-
attrs.map do |attr|
|
33
|
-
raise "Attribute '#{attr}' doesn't exist on model '#{name}'" if column_names.exclude? attr.to_s
|
34
|
-
|
35
|
-
attr.to_s
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
model.constantize.editable_attributes
|
42
|
-
end
|
43
|
-
end
|