system_settings 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -11
- data/app/assets/config/manifest.js +1 -0
- data/app/assets/stylesheets/system_settings/application.css +227 -0
- data/app/controllers/system_settings/application_controller.rb +0 -6
- data/app/controllers/system_settings/settings_controller.rb +19 -13
- data/app/helpers/system_settings/application_helper.rb +34 -0
- data/app/models/system_settings/list_of_decimals_validator.rb +1 -1
- data/app/models/system_settings/string_setting.rb +5 -0
- data/app/views/layouts/system_settings/application.html.erb +21 -0
- data/app/views/system_settings/settings/_common_attributes.html.erb +14 -0
- data/app/views/system_settings/settings/_form.html.erb +18 -0
- data/app/views/system_settings/settings/edit.html.erb +2 -0
- data/app/views/system_settings/settings/index.html.erb +29 -0
- data/app/views/system_settings/settings/show.html.erb +9 -0
- data/config/locales/system_settings.en.yml +20 -1
- data/config/routes.rb +5 -4
- data/lib/system_settings.rb +1 -0
- data/lib/system_settings/engine.rb +3 -12
- data/lib/system_settings/version.rb +1 -1
- metadata +12 -18
- data/app/controllers/system_settings/root_controller.rb +0 -13
- data/app/models/system_settings/pagination.rb +0 -20
- data/frontend/build/asset-manifest.json +0 -21
- data/frontend/build/favicon.ico +0 -0
- data/frontend/build/index.html +0 -1
- data/frontend/build/precache-manifest.2a3085e0df9528a5989319fa25e318b5.js +0 -22
- data/frontend/build/service-worker.js +0 -39
- data/frontend/build/static/css/main.04fc5f62.chunk.css +0 -2
- data/frontend/build/static/css/main.04fc5f62.chunk.css.map +0 -1
- data/frontend/build/static/js/2.bb361686.chunk.js +0 -2
- data/frontend/build/static/js/2.bb361686.chunk.js.map +0 -1
- data/frontend/build/static/js/main.7e8676c5.chunk.js +0 -2
- data/frontend/build/static/js/main.7e8676c5.chunk.js.map +0 -1
- data/frontend/build/static/js/runtime-main.ffc5e8a3.js +0 -2
- data/frontend/build/static/js/runtime-main.ffc5e8a3.js.map +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 321c73f1b71d88e67c98191025ac69b6fa58ea6dbbaa838cb5a6eaea6622337a
|
4
|
+
data.tar.gz: 17bd42a54230f37063f618fe2cfebc3875410d3879757e9ed38138990c6a952d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4231c986165f29d944aec79b4cc5239ccc9f7d614ef710ec77e452a238f8579ec3afcf20c09c0701ec49b3a89547ebbfcc3e4f395a71d024b1349fadb8df1cfc
|
7
|
+
data.tar.gz: bab2dd0fbf7b7f5f38ea38e4ebdcb1d732eb0254a2e3278925ac16408cca8d3c05c898137c92e7916c2b4f85c6105a9ad1e1ec5be0e51eb9d8a0fa617ff3fd47
|
data/README.md
CHANGED
@@ -105,13 +105,8 @@ And if you modify settings values in test example you can reset to defaults with
|
|
105
105
|
|
106
106
|
## Development
|
107
107
|
|
108
|
-
Required development dependencies:
|
109
|
-
* [Node.js](https://nodejs.org/) - JavaScript runtime
|
110
|
-
* [Yarn](https://yarnpkg.com/) - package manager
|
111
|
-
|
112
108
|
Optional development tools:
|
113
|
-
* [
|
114
|
-
* [direnv](https://direnv.net/) - Unclutter your .profile
|
109
|
+
* [direnv](https://direnv.net/) - Unclutter your .profile
|
115
110
|
|
116
111
|
Required environment variables:
|
117
112
|
* `RAILS_VERSION`
|
@@ -126,16 +121,13 @@ Getting started with development:
|
|
126
121
|
1) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 bundle`
|
127
122
|
2) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 ./bin/rails db:create db:migrate`
|
128
123
|
3) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 ./bin/rails test`
|
129
|
-
4) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 ./bin/rails frontend:install`
|
130
|
-
4) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 ./bin/rails app:system_settings:load`
|
131
|
-
4) `RAILS_VERSION=5.2.3 SQLITE3_VERSION=1.4.1 overmind start`
|
132
|
-
|
133
124
|
|
134
125
|
## Build status
|
135
126
|
System Settings is being tested with Rails versions - `5.0`, `5.1`, `5.2`, `6.0`, `rails repo master branch`
|
136
127
|
|
137
128
|
[![Build Status](https://dev.azure.com/kristsozols/System%20Settings/_apis/build/status/krists.system_settings?branchName=master)](https://dev.azure.com/kristsozols/System%20Settings/_build/latest?definitionId=1&branchName=master)
|
138
|
-
|
129
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/3ad889ca36f62bad04dc/maintainability)](https://codeclimate.com/github/krists/system_settings/maintainability)
|
130
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/3ad889ca36f62bad04dc/test_coverage)](https://codeclimate.com/github/krists/system_settings/test_coverage)
|
139
131
|
|
140
132
|
## License
|
141
133
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets .css
|
@@ -0,0 +1,227 @@
|
|
1
|
+
html {
|
2
|
+
box-sizing: border-box;
|
3
|
+
font-size: 14px;
|
4
|
+
font-family: Arial, Helvetica, sans-serif;
|
5
|
+
overflow-y: scroll;
|
6
|
+
}
|
7
|
+
|
8
|
+
*, *:before, *:after {box-sizing: inherit;}
|
9
|
+
|
10
|
+
body {
|
11
|
+
margin: 0;
|
12
|
+
padding: 0;
|
13
|
+
font-weight: normal;
|
14
|
+
min-height: 100vh;
|
15
|
+
position: relative;
|
16
|
+
display: flex;
|
17
|
+
flex-direction: column;
|
18
|
+
color: #233656;
|
19
|
+
background: white;
|
20
|
+
font-size: 1rem;
|
21
|
+
line-height: 1.5rem;
|
22
|
+
}
|
23
|
+
|
24
|
+
header {
|
25
|
+
border-bottom: 1px solid #e1e1e1;
|
26
|
+
height: 2rem;
|
27
|
+
padding: 0.5rem 0;
|
28
|
+
box-sizing: content-box;
|
29
|
+
background: white;
|
30
|
+
position: sticky;
|
31
|
+
top: 0;
|
32
|
+
width: 100%;
|
33
|
+
}
|
34
|
+
|
35
|
+
main {
|
36
|
+
padding: 3rem 0;
|
37
|
+
}
|
38
|
+
|
39
|
+
header .container,
|
40
|
+
main .container {
|
41
|
+
max-width: 1020px;
|
42
|
+
margin: 0 auto;
|
43
|
+
}
|
44
|
+
|
45
|
+
a { color: #233656; text-decoration: none; }
|
46
|
+
a:hover { text-decoration: underline; }
|
47
|
+
|
48
|
+
.app-name, .app-name:hover, .app-name:active {
|
49
|
+
font-size: 1.5rem;
|
50
|
+
line-height: 2rem;
|
51
|
+
font-weight: bold;
|
52
|
+
user-select: none;
|
53
|
+
text-decoration: none;
|
54
|
+
}
|
55
|
+
|
56
|
+
.sys-name {
|
57
|
+
display: inline-block;
|
58
|
+
background: #f2f2f2;
|
59
|
+
border-radius: 3px;
|
60
|
+
padding: 0 0.5em;
|
61
|
+
font-family: "Courier New", Courier, monospace;
|
62
|
+
font-size: 0.75em;
|
63
|
+
max-width: 100%;
|
64
|
+
}
|
65
|
+
|
66
|
+
table th {
|
67
|
+
text-align: left;
|
68
|
+
}
|
69
|
+
|
70
|
+
.settings-table {
|
71
|
+
width: 100%;
|
72
|
+
table-layout: fixed;
|
73
|
+
white-space: nowrap;
|
74
|
+
user-select: none;
|
75
|
+
}
|
76
|
+
|
77
|
+
.settings-table td:empty:after {
|
78
|
+
content: "-";
|
79
|
+
}
|
80
|
+
|
81
|
+
.settings-table td {
|
82
|
+
overflow: hidden;
|
83
|
+
text-overflow: ellipsis;
|
84
|
+
}
|
85
|
+
|
86
|
+
.settings-table .description { width: 35% }
|
87
|
+
.settings-table .value { width: 25% }
|
88
|
+
|
89
|
+
.settings-table tbody td.no-entries {
|
90
|
+
color: #737373;
|
91
|
+
padding-top: 1rem;
|
92
|
+
margin-bottom: 1rem;
|
93
|
+
}
|
94
|
+
|
95
|
+
.settings-table tfoot td {
|
96
|
+
font-size: 0.8em;
|
97
|
+
padding-top: 1rem;
|
98
|
+
margin-bottom: 1rem;
|
99
|
+
}
|
100
|
+
|
101
|
+
.settings-table .value .value-part, .attribute .value .value-part {
|
102
|
+
max-width: 100%;
|
103
|
+
margin-right: 0.25em;
|
104
|
+
}
|
105
|
+
|
106
|
+
.settings-table .value .value-part:last-child, .attribute .value .value-part:last-child {
|
107
|
+
margin-right: 0;
|
108
|
+
}
|
109
|
+
|
110
|
+
.attribute {
|
111
|
+
display: flex;
|
112
|
+
flex-direction: column;
|
113
|
+
margin-bottom: 1rem;
|
114
|
+
}
|
115
|
+
|
116
|
+
.attribute .name {
|
117
|
+
font-size: 0.8em;
|
118
|
+
color: #737373;
|
119
|
+
user-select: none;
|
120
|
+
}
|
121
|
+
|
122
|
+
.attribute .value {
|
123
|
+
align-self: flex-start;
|
124
|
+
}
|
125
|
+
.attribute .value:empty:after {
|
126
|
+
content: "-";
|
127
|
+
}
|
128
|
+
|
129
|
+
.attribute .field_with_errors .name, .attribute .errors {
|
130
|
+
color: #d01d1d;
|
131
|
+
}
|
132
|
+
.attribute .hint {
|
133
|
+
font-size: 0.8em;
|
134
|
+
display: block;
|
135
|
+
}
|
136
|
+
|
137
|
+
.buttons {
|
138
|
+
border-top: 1px dotted #f2f2f2;
|
139
|
+
padding-top: 1rem;
|
140
|
+
margin-bottom: 1rem;
|
141
|
+
}
|
142
|
+
.buttons > * {
|
143
|
+
margin-right: 0.5rem;
|
144
|
+
}
|
145
|
+
|
146
|
+
button, input[type=submit], input[type=button], a.button {
|
147
|
+
display: inline-block;
|
148
|
+
cursor: pointer;
|
149
|
+
border: none;
|
150
|
+
border-radius: 3px;
|
151
|
+
padding: 0.375rem 0.75rem;
|
152
|
+
font-size: 1rem;
|
153
|
+
line-height: 1.5;
|
154
|
+
user-select: none;
|
155
|
+
white-space: nowrap;
|
156
|
+
}
|
157
|
+
|
158
|
+
button, input[type=submit], input[type=button] {
|
159
|
+
color: #4d4d4d;
|
160
|
+
background-color: #d9d9d9;
|
161
|
+
transition: background-color 0.1s ease-in-out;
|
162
|
+
outline: none;
|
163
|
+
}
|
164
|
+
|
165
|
+
button:focus, button:hover, input[type=submit]:focus, input[type=submit]:hover, input[type=button]:focus, input[type=button]:hover {
|
166
|
+
background-color: #b8b8b8;
|
167
|
+
}
|
168
|
+
|
169
|
+
button:active, input[type=submit]:active, input[type=button]:active {
|
170
|
+
background-color: #828282;
|
171
|
+
}
|
172
|
+
|
173
|
+
a.button {
|
174
|
+
color: #4d4d4d;
|
175
|
+
background-color: transparent;
|
176
|
+
transition: background-color 0.1s ease-in-out;
|
177
|
+
outline: none;
|
178
|
+
text-decoration: none;
|
179
|
+
}
|
180
|
+
|
181
|
+
a.button:focus, a.button:hover {
|
182
|
+
background-color: rgba(0, 0, 0, 0.15);
|
183
|
+
}
|
184
|
+
|
185
|
+
a.button:active {
|
186
|
+
background-color: rgba(0, 0, 0, 0.4);
|
187
|
+
}
|
188
|
+
|
189
|
+
button.primary, input[type=submit].primary, input[type=button].primary, a.button.primary {
|
190
|
+
color: #4d4d4d;
|
191
|
+
background-color: #a6a6a6;
|
192
|
+
transition: background-color 0.1s ease-in-out;
|
193
|
+
outline: none;
|
194
|
+
}
|
195
|
+
|
196
|
+
button.primary:focus, button.primary:hover, input[type=submit].primary:focus, input[type=submit].primary:hover, input[type=button].primary:focus, input[type=button].primary:hover, a.button.primary:focus, a.button.primary:hover {
|
197
|
+
background-color: #8d8d8d;
|
198
|
+
}
|
199
|
+
|
200
|
+
button.primary:active, input[type=submit].primary:active, input[type=button].primary:active, a.button.primary:active {
|
201
|
+
background-color: #646464;
|
202
|
+
}
|
203
|
+
|
204
|
+
input[type=text] {
|
205
|
+
border: none;
|
206
|
+
border-radius: 3px;
|
207
|
+
padding: 0.5em;
|
208
|
+
font-size: 1rem;
|
209
|
+
line-height: normal;
|
210
|
+
color: #4d4d4d;
|
211
|
+
background-color: #e6e6e6;
|
212
|
+
transition: background-color 0.1s ease-in-out;
|
213
|
+
outline: none;
|
214
|
+
box-sizing: content-box;
|
215
|
+
width: auto;
|
216
|
+
min-width: 12ch;
|
217
|
+
max-width: calc(100% - 2em);
|
218
|
+
will-change: width;
|
219
|
+
}
|
220
|
+
|
221
|
+
input[type=text]:focus {
|
222
|
+
background-color: #c4c4c4;
|
223
|
+
}
|
224
|
+
|
225
|
+
input[type=text]:active {
|
226
|
+
background-color: #bfbfbf;
|
227
|
+
}
|
@@ -3,11 +3,5 @@
|
|
3
3
|
module SystemSettings
|
4
4
|
class ApplicationController < ActionController::Base
|
5
5
|
protect_from_forgery with: :exception
|
6
|
-
|
7
|
-
private
|
8
|
-
|
9
|
-
def add_authenticity_token
|
10
|
-
response.headers["Authenticity-Token"] = form_authenticity_token if protect_against_forgery?
|
11
|
-
end
|
12
6
|
end
|
13
7
|
end
|
@@ -2,27 +2,33 @@
|
|
2
2
|
|
3
3
|
module SystemSettings
|
4
4
|
class SettingsController < SystemSettings::ApplicationController
|
5
|
-
RETURN_ATTRIBUTES = [
|
5
|
+
RETURN_ATTRIBUTES = %w[id name type value description].freeze
|
6
|
+
before_action :set_setting, only: [:edit, :show, :update]
|
6
7
|
|
7
8
|
def index
|
8
|
-
@
|
9
|
-
@settings = SystemSettings::Setting.order(:name).extending(SystemSettings::Pagination).page(params[:page], per_page: params[:per])
|
10
|
-
render json: {items: @settings.map { |s| s.as_json(only: RETURN_ATTRIBUTES) }, total_count: @total_count}
|
9
|
+
@settings = SystemSettings::Setting.order(:name)
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
render json: @setting.as_json(only: RETURN_ATTRIBUTES)
|
17
|
-
end
|
12
|
+
def edit; end
|
13
|
+
|
14
|
+
def show; end
|
18
15
|
|
19
16
|
def update
|
20
|
-
@setting
|
21
|
-
|
22
|
-
render json: @setting.as_json(only: RETURN_ATTRIBUTES)
|
17
|
+
if @setting.update(setting_params)
|
18
|
+
redirect_to setting_path(@setting)
|
23
19
|
else
|
24
|
-
render
|
20
|
+
render :edit
|
25
21
|
end
|
26
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def set_setting
|
27
|
+
@setting = SystemSettings::Setting.find(params[:id])
|
28
|
+
end
|
29
|
+
|
30
|
+
def setting_params
|
31
|
+
params.require(:setting).permit(:value)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module SystemSettings::ApplicationHelper
|
2
|
+
SEPARATOR = ";".freeze
|
3
|
+
|
4
|
+
def format_value(value)
|
5
|
+
if value.respond_to?(:each)
|
6
|
+
capture do
|
7
|
+
value.each do |v|
|
8
|
+
concat content_tag(:span, v, class: "value-part")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
else
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_value_for_form(record)
|
17
|
+
case record
|
18
|
+
when SystemSettings::StringListSetting
|
19
|
+
record.value.map { |v| v.gsub(SEPARATOR, "\\#{SEPARATOR}") }.join(SEPARATOR)
|
20
|
+
when SystemSettings::IntegerListSetting, SystemSettings::DecimalListSetting
|
21
|
+
record.value.join(SEPARATOR)
|
22
|
+
else
|
23
|
+
record.value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def display_settings_file_path
|
28
|
+
if SystemSettings.settings_file_path.to_s.include?(Rails.root.to_s)
|
29
|
+
Pathname.new(SystemSettings.settings_file_path).relative_path_from(Rails.root)
|
30
|
+
else
|
31
|
+
SystemSettings.settings_file_path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -20,7 +20,7 @@ module SystemSettings
|
|
20
20
|
|
21
21
|
def record_attribute_changed_in_place?(record, attr_name)
|
22
22
|
record.respond_to?(:attribute_changed_in_place?) &&
|
23
|
-
|
23
|
+
record.attribute_changed_in_place?(attr_name.to_s)
|
24
24
|
end
|
25
25
|
|
26
26
|
def matches_list_of_decimals_regexp?(raw_value)
|
@@ -4,5 +4,10 @@ module SystemSettings
|
|
4
4
|
class StringSetting < SystemSettings::Setting
|
5
5
|
attribute :value, :string
|
6
6
|
validates :value, presence: true
|
7
|
+
|
8
|
+
def value=(original_value)
|
9
|
+
next_value = original_value.to_s.blank? ? nil : original_value.to_s.strip
|
10
|
+
super(next_value)
|
11
|
+
end
|
7
12
|
end
|
8
13
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>System Settings - <%= SystemSettings::VERSION %></title>
|
6
|
+
<%= csrf_meta_tags %>
|
7
|
+
<%= stylesheet_link_tag 'system_settings/application', media: 'all' %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<header>
|
11
|
+
<div class="container">
|
12
|
+
<%= link_to "System Settings", root_path, class: "app-name" %>
|
13
|
+
</div>
|
14
|
+
</header>
|
15
|
+
<main>
|
16
|
+
<div class="container">
|
17
|
+
<%= yield %>
|
18
|
+
</div>
|
19
|
+
</main>
|
20
|
+
</body>
|
21
|
+
</html>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="attribute">
|
2
|
+
<div class="name"><%= setting.class.human_attribute_name(:name) %></div>
|
3
|
+
<div class="value">
|
4
|
+
<span class="sys-name"><%= setting.name %></span>
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
<div class="attribute">
|
8
|
+
<div class="name"><%= setting.class.human_attribute_name(:type) %></div>
|
9
|
+
<div class="value"><%= setting.model_name.human %></div>
|
10
|
+
</div>
|
11
|
+
<div class="attribute">
|
12
|
+
<div class="name"><%= setting.class.human_attribute_name(:description) %></div>
|
13
|
+
<div class="value"><%= setting.description %></div>
|
14
|
+
</div>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<%= form_for setting, as: :setting, url: setting_path(setting), method: "post" do |f| %>
|
2
|
+
<div class="attribute">
|
3
|
+
<%= f.label :value, class: "name" %>
|
4
|
+
<% if f.object.is_a?(SystemSettings::BooleanSetting) %>
|
5
|
+
<%= f.check_box :value, value: f.object.value %>
|
6
|
+
<% else %>
|
7
|
+
<%= f.text_field :value, value: format_value_for_form(f.object), class: "value" %>
|
8
|
+
<% end %>
|
9
|
+
<% if f.object.errors.messages[:value].any? %>
|
10
|
+
<div class="errors"><%= f.object.errors.messages[:value].join("; ") %></div>
|
11
|
+
<% end %>
|
12
|
+
<div class="hint"><%= t(f.object.type, scope: "system_settings.settings.form.hints_by_type", default: "").html_safe %></div>
|
13
|
+
</div>
|
14
|
+
<div class="buttons">
|
15
|
+
<%= f.submit t(".save"), class: "primary" %>
|
16
|
+
<%= link_to t(".back"), setting_path(setting), class: "button" %>
|
17
|
+
</div>
|
18
|
+
<% end %>
|