super_settings 0.0.0.rc1

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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +313 -0
  5. data/VERSION +1 -0
  6. data/app/helpers/super_settings/settings_helper.rb +32 -0
  7. data/app/views/layouts/super_settings/settings.html.erb +20 -0
  8. data/config/routes.rb +13 -0
  9. data/db/migrate/20210414004553_create_super_settings.rb +34 -0
  10. data/lib/super_settings/application/api.js +88 -0
  11. data/lib/super_settings/application/helper.rb +119 -0
  12. data/lib/super_settings/application/images/edit.svg +1 -0
  13. data/lib/super_settings/application/images/info.svg +1 -0
  14. data/lib/super_settings/application/images/plus.svg +1 -0
  15. data/lib/super_settings/application/images/slash.svg +1 -0
  16. data/lib/super_settings/application/images/trash.svg +1 -0
  17. data/lib/super_settings/application/index.html.erb +169 -0
  18. data/lib/super_settings/application/layout.html.erb +22 -0
  19. data/lib/super_settings/application/layout_styles.css +193 -0
  20. data/lib/super_settings/application/scripts.js +718 -0
  21. data/lib/super_settings/application/styles.css +122 -0
  22. data/lib/super_settings/application.rb +38 -0
  23. data/lib/super_settings/attributes.rb +24 -0
  24. data/lib/super_settings/coerce.rb +66 -0
  25. data/lib/super_settings/configuration.rb +144 -0
  26. data/lib/super_settings/controller_actions.rb +81 -0
  27. data/lib/super_settings/encryption.rb +76 -0
  28. data/lib/super_settings/engine.rb +70 -0
  29. data/lib/super_settings/history_item.rb +26 -0
  30. data/lib/super_settings/local_cache.rb +306 -0
  31. data/lib/super_settings/rack_middleware.rb +210 -0
  32. data/lib/super_settings/rest_api.rb +195 -0
  33. data/lib/super_settings/setting.rb +599 -0
  34. data/lib/super_settings/storage/active_record_storage.rb +123 -0
  35. data/lib/super_settings/storage/http_storage.rb +279 -0
  36. data/lib/super_settings/storage/redis_storage.rb +293 -0
  37. data/lib/super_settings/storage/test_storage.rb +158 -0
  38. data/lib/super_settings/storage.rb +254 -0
  39. data/lib/super_settings/version.rb +5 -0
  40. data/lib/super_settings.rb +213 -0
  41. data/lib/tasks/super_settings.rake +9 -0
  42. data/super_settings.gemspec +35 -0
  43. metadata +113 -0
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-slash"><circle cx="12" cy="12" r="10"></circle><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-trash-2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
@@ -0,0 +1,169 @@
1
+ <%= style_tag %>
2
+
3
+ <main>
4
+ <form class="form-inline" style="display:block;" onsubmit="return false">
5
+ <div class="super-settings-sticky-top">
6
+ <span class="js-settings-count" style="display:inline-block; margin-right:1rem;"></span>
7
+
8
+ <label for="filter" class="super-settings-sr-only">Filter</label>
9
+ <input type="text" name="filter" value="" placeholder="Filter Keys" size="20" class="form-control" title="Filter Keys" id="filter" style="margin-right:1rem;">
10
+
11
+ <button type="button" class="btn btn-default" id="add-setting"><%= icon_image(:plus) %> Add Setting</button>
12
+
13
+ <button type="button" class="btn btn-default" id="discard-changes" disabled>
14
+ Discard Changes
15
+ </button>
16
+
17
+ <button type="button" class="btn btn-primary" id="save-settings" disabled>
18
+ Save <span class="count"></span> Changes
19
+ </button>
20
+
21
+ <strong class="js-flash" style="display:none; margin-left:3rem;"></strong>
22
+ </div>
23
+
24
+ <table class="table table-striped" id="settings-table">
25
+ <thead>
26
+ <tr>
27
+ <th scope="col" class="super-settings-key">Key</th>
28
+ <th scope="col" class="super-settings-value">Value</th>
29
+ <th scope="col" class="super-settings-value-type">Type</th>
30
+ <th scope="col" class="super-settings-description">Description</th>
31
+ <th scope="col" class="super-settings-controls"><span class="super-settings-sr-only">Controls</span></th>
32
+ </tr>
33
+ </thead>
34
+ <tbody translate="no">
35
+ </tbody>
36
+ </table>
37
+ </form>
38
+ </main>
39
+
40
+ <div id="modal" class="super-settings-modal js-close-modal" aria-hidden="true" aria-role="dialog">
41
+ <div class="super-settings-modal-dialog">
42
+ <button type="button" title="Close Dialog" class="super-settings-modal-close js-close-modal">&times;</button>
43
+ <div class="super-settings-modal-content">
44
+ </div>
45
+ </div>
46
+ </div>
47
+
48
+ <template id="setting-row-template" style="display:none;">
49
+ <tr>
50
+ <td class="super-settings-key">
51
+ <div class="js-value-placeholder"></div>
52
+ <input type="hidden" value="" name="settings[{{id}}][key]" class="js-setting-key">
53
+ <input type="hidden" value="" name="settings[{{id}}][delete]" class="js-setting-deleted">
54
+ </td>
55
+
56
+ <td class="super-settings-value">
57
+ <div class="js-value-placeholder"></div>
58
+ </td>
59
+
60
+ <td class="super-settings-value-type">
61
+ <div class="js-value-placeholder"></div>
62
+ </td>
63
+
64
+ <td class="super-settings-description">
65
+ <div class="js-value-placeholder"></div>
66
+ </td>
67
+
68
+ <td class="super-settings-controls">
69
+ <%= icon_button(:info, title: "Setting Info", color: "royalblue", js_class: "js-show-history") %>
70
+ <%= icon_button(:edit, title: "Edit Setting", color: "green", js_class: "js-edit-setting") %>
71
+ <%= icon_button(:trash, title: "Remove Setting", color: "firebrick", js_class: "js-remove-setting") %>
72
+ <%= icon_button(:slash, title: "Cancel Changes", color: "firebrick", js_class: "js-restore-setting", link_style: "display:none;") %>
73
+ </td>
74
+ </tr>
75
+ </template>
76
+
77
+ <template id="setting-row-edit-template" style="display:none;">
78
+ <tr data-edited="true" class="super-settings-edit-row">
79
+ <td class="super-settings-key">
80
+ <div>
81
+ <label for="settings_{{id}}_key" class="super-settings-sr-only">Key</label>
82
+ <input type="text" id="settings_{{id}}_key" name="settings[{{id}}][key]" value="" maxlength="190" class="form-control js-setting-key" required>
83
+ </div>
84
+ </td>
85
+
86
+ <td class="super-settings-value">
87
+ <div>
88
+ <label for="settings_{{id}}_value" class="super-settings-sr-only">Value</label>
89
+ <span class="js-value-placeholder"></span>
90
+ </div>
91
+ <div class="container text-danger js-setting-errors" style="display:none;">
92
+ </div>
93
+ </td>
94
+
95
+ <td class="super-settings-value-type">
96
+ <div>
97
+ <label for="settings_{{id}}_value_type" class="super-settings-sr-only">Value Type</label>
98
+ <select name="settings[{{id}}][value_type]" class="form-control js-setting-value-type" id="settings_{{id}}_value_type">
99
+ <% SuperSettings::Setting::VALUE_TYPES.each do |value_type| %>
100
+ <option value="<%= ERB::Util.html_escape(value_type) %>"><%= ERB::Util.html_escape(value_type) %></option>
101
+ <% end %>
102
+ </select>
103
+ </div>
104
+ </td>
105
+
106
+ <td class="super-settings-description">
107
+ <div>
108
+ <label for="settings_{{id}}_description" class="super-settings-sr-only">Description</label>
109
+ <textarea id="settings_{{id}}_description" name="settings[{{id}}][description]" value="" class="form-control" rows="4"></textarea>
110
+ </div>
111
+ </td>
112
+
113
+ <td class="super-settings-controls">
114
+ <%= icon_button(:info, title: "Setting Info", color: "royalblue", js_class: "js-show-history") %>
115
+ <%= icon_button(:edit, title: "Edit Setting", color: "gray", js_class: "js-no-op", disabled: true) %>
116
+ <%= icon_button(:slash, title: "Cancel Changes", color: "firebrick", js_class: "js-restore-setting") %>
117
+ </td>
118
+ </tr>
119
+ </template>
120
+
121
+ <template id="setting-value-field-template" style="display:none;">
122
+ <textarea id="settings_{{id}}_value" name="settings[{{id}}][value]" class="form-control js-setting-value" rows="4"></textarea>
123
+ </template>
124
+
125
+ <template id="setting-value-field-integer-template" style="display:none;">
126
+ <input type="number" step="1" id="settings_{{id}}_value" name="settings[{{id}}][value]" value="" class="form-control js-setting-value">
127
+ </template>
128
+
129
+ <template id="setting-value-field-float-template" style="display:none;">
130
+ <input type="number" step="any" id="settings_{{id}}_value" name="settings[{{id}}][value]" value="" class="form-control js-setting-value">
131
+ </template>
132
+
133
+ <template id="setting-value-field-datetime-template" style="display:none;">
134
+ <span>
135
+ <input type="date" id="settings_{{id}}_value" name="_settings[{{id}}][date]" value="" class="form-control js-date-input">
136
+ <label for="settings_{{id}}_value_time" class="super-settings-sr-only">Time</label>
137
+ <input type="time" id="settings_{{id}}_value_time" name="_settings[{{id}}][time]" value="" class="form-control js-time-input" aria-label="Time">
138
+ <input type="hidden" name="settings[{{id}}][value]" value="" class="js-setting-value">
139
+ <small class="text-muted">Time in UTC</small>
140
+ </span>
141
+ </template>
142
+
143
+ <template id="setting-value-field-boolean-template" style="display:none;">
144
+ <span class="form-check">
145
+ <input type="checkbox" id="settings_{{id}}_value" name="settings[{{id}}][value]" value="true" class="js-setting-value">
146
+ <label for="settings_{{id}}_value">Enabled</label>
147
+ </span>
148
+ </template>
149
+
150
+ <template id="setting-value-field-array-template" style="display:none;">
151
+ <textarea id="settings_{{id}}_value" name="settings[{{id}}][value]" value="" class="form-control js-setting-value" rows="8" placeholder="one entry per line"></textarea>
152
+ </template>
153
+
154
+ <template id="setting-history-table" style="display:none">
155
+ <h3>Setting History: <span class="super-settings-history-key"></span></h3>
156
+ <table class="table table-striped" id="super-settings-history">
157
+ <thead>
158
+ <tr>
159
+ <th scope="col" class="super-settings-text-nowrap">Time</th>
160
+ <th scope="col">Changed By</th>
161
+ <th scope="col">Value</th>
162
+ </tr>
163
+ </thead>
164
+ <tbody>
165
+ </tbody>
166
+ </table>
167
+ </template>
168
+
169
+ <%= javascript_tag %>
@@ -0,0 +1,22 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title><%= application_name %> Settings</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="pinterest" content="nopin" />
7
+ <meta name="format-detection" content="telephone=no">
8
+ <%= layout_style_tag %>
9
+ <%= add_to_head %>
10
+ </head>
11
+
12
+ <body class="super_settings">
13
+ <header>
14
+ <h1 class="logo">
15
+ <%= application_header %>
16
+ </h1>
17
+ </header>
18
+ <div class="container">
19
+ <%= yield %>
20
+ </div>
21
+ </body>
22
+ </html>
@@ -0,0 +1,193 @@
1
+ * {box-sizing:border-box;}
2
+
3
+ body {
4
+ font-family: sans-serif;
5
+ font-size: 1rem;
6
+ line-height: 1.5;
7
+ text-align: left;
8
+ color: #212529;
9
+ background-color: #ffffff;
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+
14
+ header {
15
+ background-color: #666;
16
+ color: white;
17
+ padding: 1rem;
18
+ }
19
+
20
+ header h1.logo {
21
+ font-size: 20px;
22
+ margin: 0;
23
+ }
24
+
25
+ header h1.logo a {
26
+ color: #ffffff;
27
+ text-decoration: none;
28
+ }
29
+ header h1.logo a:visited {
30
+ color: #ffffff;
31
+ }
32
+
33
+ header h1.logo img {
34
+ max-height: 3rem;
35
+ vertical-align: middle;
36
+ display: inline-block;
37
+ margin-right: 1rem;
38
+ }
39
+
40
+ .align-center {
41
+ text-align: center;
42
+ }
43
+
44
+ .container {
45
+ padding-left: 15px;
46
+ padding-right: 15px;
47
+ margin-left: auto;
48
+ margin-right: auto;
49
+ }
50
+
51
+ a {
52
+ text-decoration: none;
53
+ color: #369;
54
+ }
55
+
56
+ a:visited {
57
+ color: #369;n
58
+ }
59
+
60
+ .btn {
61
+ box-shadow:inset 0px 1px 0px 0px #ffffff;
62
+ background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%);
63
+ background-color:#f9f9f9;
64
+ border-radius:6px;
65
+ border:1px solid #dcdcdc;
66
+ display:inline-block;
67
+ color:#666666;
68
+ font-family:Arial;
69
+ font-size:15px;
70
+ font-weight:bold;
71
+ padding:9px 16px;
72
+ text-decoration:none;
73
+ text-shadow:0px 1px 0px #ffffff;
74
+ vertical-align: middle;
75
+ }
76
+ .btn:hover {
77
+ background:linear-gradient(to bottom, #e9e9e9 5%, #f9f9f9 100%);
78
+ background-color:#e9e9e9;
79
+ }
80
+ .btn:active {
81
+ position:relative;
82
+ top:1px;
83
+ }
84
+ .btn:disabled {
85
+ background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%);
86
+ background-color:#f9f9f9;
87
+ opacity: 0.65;
88
+ box-shadow: none;
89
+ }
90
+
91
+ .btn-primary {
92
+ box-shadow:inset 0px 1px 0px 0px #9fb4f2;
93
+ background:linear-gradient(to bottom, #7892c2 5%, #476e9e 100%);
94
+ background-color:#7892c2;
95
+ color:#ffffff;
96
+ text-shadow:0px 1px 0px #283966;
97
+ }
98
+ .btn-primary:hover {
99
+ background:linear-gradient(to bottom, #476e9e 5%, #7892c2 100%);
100
+ background-color:#476e9e;
101
+ }
102
+ .btn-primary:disabled {
103
+ background:linear-gradient(to bottom, #7892c2 5%, #476e9e 100%);
104
+ background-color:#7892c2;
105
+ }
106
+
107
+ .btn:not(:disabled) {
108
+ cursor: pointer;
109
+ }
110
+ .btn:disabled {
111
+ opacity: .65;
112
+ }
113
+
114
+ .table {
115
+ width: 100%;
116
+ max-width: 100%;
117
+ margin-bottom: 1rem;
118
+ border-collapse: collapse;
119
+ }
120
+
121
+ .table thead th {
122
+ vertical-align: bottom;
123
+ border-bottom: 2px solid #dee2e6;
124
+ }
125
+
126
+ .table td, .table th {
127
+ padding: 0.75rem;
128
+ vertical-align: top;
129
+ border-top: 1px solid #dee2e6;
130
+ }
131
+
132
+ .table-striped tbody tr:nth-of-type(odd) {
133
+ background-color: rgba(0, 0, 0, .05);
134
+ }
135
+
136
+ textarea {
137
+ font-family: inherit;
138
+ margin: 0;
139
+ overflow: auto;
140
+ resize: vertical;
141
+ }
142
+
143
+ .form-control {
144
+ font-family: inherit;
145
+ margin: 0;
146
+ overflow: visible;
147
+ display: block;
148
+ width: 100%;
149
+ padding: .375rem .75rem;
150
+ font-size: 1rem;
151
+ line-height: 1.5;
152
+ color: #495057;
153
+ background-color: #fff;
154
+ background-clip: padding-box;
155
+ border: 1px solid #ced4da;
156
+ border-radius: .25rem;
157
+ transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
158
+ }
159
+
160
+ select.form-control:not([size]):not([multiple]) {
161
+ height: calc(2.25rem + 2px);
162
+ }
163
+
164
+ .form-check {
165
+ margin-top: .5rem;
166
+ display: inline-block;
167
+ }
168
+
169
+ .form-check input[type=checkbox] {
170
+ vertical-align: middle;
171
+ }
172
+
173
+ .form-inline {
174
+ display: inline-block;
175
+ }
176
+
177
+ .form-inline .form-control {
178
+ display: inline-block;
179
+ width: auto;
180
+ vertical-align: middle;
181
+ }
182
+
183
+ .text-success {
184
+ color: green !important;
185
+ }
186
+
187
+ .text-danger {
188
+ color: firebrick !important;
189
+ }
190
+
191
+ .text-muted {
192
+ color: #666 !important;
193
+ }