super_settings 1.0.2 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +128 -26
- data/VERSION +1 -1
- data/app/helpers/super_settings/settings_helper.rb +13 -3
- data/app/views/layouts/super_settings/settings.html.erb +1 -1
- data/config/routes.rb +1 -1
- data/db/migrate/20210414004553_create_super_settings.rb +1 -7
- data/lib/super_settings/application/api.js +4 -1
- data/lib/super_settings/application/helper.rb +56 -17
- data/lib/super_settings/application/images/arrow-down-short.svg +3 -0
- data/lib/super_settings/application/images/arrow-up-short.svg +3 -0
- data/lib/super_settings/application/images/info-circle.svg +4 -0
- data/lib/super_settings/application/images/pencil-square.svg +4 -0
- data/lib/super_settings/application/images/plus.svg +3 -1
- data/lib/super_settings/application/images/trash3.svg +3 -0
- data/lib/super_settings/application/images/x-circle.svg +4 -0
- data/lib/super_settings/application/index.html.erb +54 -37
- data/lib/super_settings/application/layout.html.erb +5 -2
- data/lib/super_settings/application/layout_styles.css +7 -151
- data/lib/super_settings/application/layout_vars.css.erb +21 -0
- data/lib/super_settings/application/scripts.js +162 -37
- data/lib/super_settings/application/style_vars.css.erb +62 -0
- data/lib/super_settings/application/styles.css +183 -14
- data/lib/super_settings/application.rb +18 -11
- data/lib/super_settings/attributes.rb +1 -8
- data/lib/super_settings/configuration.rb +9 -0
- data/lib/super_settings/controller_actions.rb +2 -2
- data/lib/super_settings/engine.rb +1 -1
- data/lib/super_settings/history_item.rb +1 -1
- data/lib/super_settings/http_client.rb +165 -0
- data/lib/super_settings/rack_application.rb +3 -3
- data/lib/super_settings/rest_api.rb +5 -4
- data/lib/super_settings/setting.rb +13 -2
- data/lib/super_settings/storage/active_record_storage.rb +7 -0
- data/lib/super_settings/storage/history_attributes.rb +31 -0
- data/lib/super_settings/storage/http_storage.rb +60 -184
- data/lib/super_settings/storage/json_storage.rb +201 -0
- data/lib/super_settings/storage/mongodb_storage.rb +238 -0
- data/lib/super_settings/storage/redis_storage.rb +49 -111
- data/lib/super_settings/storage/s3_storage.rb +165 -0
- data/lib/super_settings/storage/storage_attributes.rb +64 -0
- data/lib/super_settings/storage/test_storage.rb +3 -5
- data/lib/super_settings/storage/transaction.rb +67 -0
- data/lib/super_settings/storage.rb +13 -6
- data/lib/super_settings/time_precision.rb +36 -0
- data/lib/super_settings.rb +11 -0
- data/super_settings.gemspec +4 -2
- metadata +22 -9
- data/lib/super_settings/application/images/edit.svg +0 -1
- data/lib/super_settings/application/images/info.svg +0 -1
- data/lib/super_settings/application/images/slash.svg +0 -1
- data/lib/super_settings/application/images/trash.svg +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7e5362ee5262805e4178be0485c0a3fba4d3f5468a793b8819abd1bb0322399
|
4
|
+
data.tar.gz: 1051e29b721ffb12a431b14ad660b13b25673abd766f7f987838030f665807cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f29c06dc13802640cb1b7edd51b2fc8d8f2ed01f1e354fc6fe1eb50f58c32baa331ebb21fed9c42858c86a4d0a8a1b5a220aa1ca6bd1fe1c7a17fe2217cbcdf5
|
7
|
+
data.tar.gz: e5f5d481458271761744533629e504c93b8c4a3b4b70da048881ac1b272de1f8266e1da10444a55d5af7c60415c2de11eba9ba33fdf8f9d637ff3e33adc7b616
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,34 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## 2.0.1
|
8
|
+
|
9
|
+
### Added
|
10
|
+
|
11
|
+
- Added support for targeting a editing a specific setting in the web UI by passing `#edit=key` in the URL hash.
|
12
|
+
|
13
|
+
## 2.0.0
|
14
|
+
|
15
|
+
### Added
|
16
|
+
|
17
|
+
- Added controls for sorting settings in the web UI by keys or last modified time.
|
18
|
+
- Isolated of CSS classes in the web UI to prevent conflicts with other CSS libraries.
|
19
|
+
- Dark mode support in web UI.
|
20
|
+
- Added ability to embed the web UI in a view to allow tighter integration with your application's UI.
|
21
|
+
- Added storage adapter for storing settings in an S3 object.
|
22
|
+
- Added storage adapter for storing settings in MongoDB.
|
23
|
+
- HTTP storage adapter now uses keep-alive connections to improve performance.
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Changing a key now works as expected. Previously, a new setting was created with the new key and the old setting was left unchanged. Now, the old setting is properly marked as deleted.
|
28
|
+
- Consistently handle converting floating point number to timestamps in Redis storage.
|
29
|
+
|
30
|
+
### Removed
|
31
|
+
|
32
|
+
- Rails 4.2, 5.0, and 5.1 support has been removed.
|
33
|
+
- Removed support for Ruby 2.5.
|
34
|
+
|
7
35
|
## 1.0.2
|
8
36
|
|
9
37
|
### Added
|
data/README.md
CHANGED
@@ -1,44 +1,49 @@
|
|
1
1
|
# SuperSettings
|
2
2
|
|
3
3
|
[![Continuous Integration](https://github.com/bdurand/super_settings/actions/workflows/continuous_integration.yml/badge.svg)](https://github.com/bdurand/super_settings/actions/workflows/continuous_integration.yml)
|
4
|
-
[![Regression Test](https://github.com/bdurand/super_settings/actions/workflows/regression_test.yml/badge.svg)](https://github.com/bdurand/super_settings/actions/workflows/regression_test.yml)
|
5
4
|
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
6
5
|
[![Gem Version](https://badge.fury.io/rb/super_settings.svg)](https://badge.fury.io/rb/super_settings)
|
7
6
|
|
8
|
-
|
7
|
+
SuperSettings is a Ruby gem that provides a scalable framework for maintaining runtime application settings. Settings are persisted in a database but cached in memory for quick, efficient access. This design ensures settings can be updated dynamically without requiring code deployment or process restarts, making it ideal for high-throughput environments.
|
9
8
|
|
10
|
-
As applications grow, they
|
9
|
+
As applications grow, they often accumulate a large number of configuration options. Common approaches such as environment variables, YAML files, or additional database columns all have their place:
|
11
10
|
|
12
|
-
|
11
|
+
- **Environment variables** are suitable for environment-specific configuration, but require restarts for changes to take effect and can only store string values.
|
12
|
+
- **YAML files** offer support for complex data structures and can be bundled with application code but typically require a new release to update.
|
13
|
+
- **Database columns** - These are great for settings tied to data models; however, they don’t apply well outside of the data model, and you need to build custom tools to manage them in your application.
|
13
14
|
|
14
|
-
|
15
|
+
Key features include:
|
15
16
|
|
16
|
-
- **
|
17
|
+
- **Caching:** A thread-safe, in-memory caching mechanism ensures high-performance access to settings, while minimizing database load. Cache refreshes are highly efficient and configurable.
|
18
|
+
- **Dynamic Updates:** Settings can be changed on the fly, with automatic logging of changes to maintain an audit trail for compliance.
|
19
|
+
- **Data Types and Validation:** Settings can be defined with specific data types (string, integer, float, boolean, datetime, or array) to ensure validity.
|
20
|
+
- **Documentation:** Each setting can include a description to explain its purpose and usage.
|
21
|
+
- **Web UI and REST API:** Manage settings via a built-in web interface or REST API.
|
22
|
+
- **Custom Callbacks:** Execute custom logic whenever a setting changes, enabling more sophisticated behavior for logging and compliance.
|
23
|
+
- **Pluggable Data Storage:** SuperSettings supports multiple storage engines, including ActiveRecord, Redis, and S3. You can also chain it to another application running SuperSettings via the HTTP storage engine to allow microservices to share settings.
|
17
24
|
|
18
|
-
|
25
|
+
For projects that require a combination of runtime settings, environment variables, and YAML files, SuperSettings integrates seamlessly with [ultra_settings](https://github.com/bdurand/ultra_settings), creating a flexible and powerful configuration system.
|
19
26
|
|
20
|
-
|
27
|
+
## Table Of Contents
|
21
28
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
- [Usage](#usage)
|
30
|
+
- [Getting Value](#getting-values)
|
31
|
+
- [Hashes](#hashes)
|
32
|
+
- [Defaults](#defaults)
|
33
|
+
- [Caching](#caching)
|
34
|
+
- [Data Model](#data-model)
|
35
|
+
- [Storage Engines](#storage-engines)
|
36
|
+
- [Web UI](#web-ui)
|
37
|
+
- [REST API](#rest-api)
|
38
|
+
- [Authentication](#authentication)
|
39
|
+
- [Rails Engine](#rails-engine)
|
40
|
+
- [Configuration](#configuration)
|
41
|
+
- [Installation](#installation)
|
42
|
+
- [Contributing](#contributing)
|
43
|
+
- [License](#license)
|
27
44
|
|
28
45
|
## Usage
|
29
46
|
|
30
|
-
- [Getting Value](#getting-values)
|
31
|
-
- [Hashes](#hashes)
|
32
|
-
- [Defaults](#defaults)
|
33
|
-
- [Caching](#caching)
|
34
|
-
- [Data Model](#data-model)
|
35
|
-
- [Storage Engines](#storage-engines)
|
36
|
-
- [Web UI](#web-ui)
|
37
|
-
- [REST API](#rest-api)
|
38
|
-
- [Authentication](#authentication)
|
39
|
-
- [Rails Engine](#rails-engine)
|
40
|
-
- [Configuration](#configuration)
|
41
|
-
|
42
47
|
### Getting Values
|
43
48
|
|
44
49
|
This gem is, in essence, a key/value store. Settings are identified by unique keys and contain a typed value. You can access setting values using methods on the `SuperSettings` object.
|
@@ -148,10 +153,11 @@ This gem abstracts out the storage engine and can support multiple storage mecha
|
|
148
153
|
* `SuperSettings::Storage::ActiveRecordStorage` - Stores the settings in a relational database using ActiveRecord. This is the default storage engine for Rails applications.
|
149
154
|
* `SuperSettings::Storage::RedisStorage` - Stores the settings in a Redis database using the [redis](https://github.com/redis/redis-rb) gem.
|
150
155
|
* `SuperSettings::Storage::HttpStorage` - Uses the SuperSettings REST API running on another server. This is useful in a microservices architecture so you can have a central settings server used by all the services.
|
156
|
+
* `SuperSettings::Storage::S3Storage` - Stores the settings in JSON in an S3 object. This is useful for applications running on AWS that want to store settings in a central location since it does not require a dedicated database. It is possible to read the settings directly from S3 from another application.
|
151
157
|
|
152
158
|
Additional storage engines can be built by creating a class that includes `SuperSettings::Storage` and implements the unimplemented methods in that module.
|
153
159
|
|
154
|
-
The storage engine is defined by setting `SuperSettings::Setting.storage` to a storage class. Note that each storage class may also require additional configuration. For instance, the Redis storage class requires you to provide a connection to a Redis database. If you are running a Rails application, then the storage engine will be set to ActiveRecord by default. Otherwise, you will need to define the storage class somewhere in your application's initialization.
|
160
|
+
The storage engine is defined by setting `SuperSettings::Setting.storage` to a storage class. Note that each storage class may also require additional configuration. For instance, the Redis storage class requires you to provide a connection to a Redis database. If you are running a Rails application, then the storage engine will be set to ActiveRecord by default. Otherwise, you will need to define the storage class somewhere in your application's initialization. See the storage class documentation for more information.
|
155
161
|
|
156
162
|
### Web UI
|
157
163
|
|
@@ -175,6 +181,8 @@ You can change the layout used by the Web UI. However, if you do this, you will
|
|
175
181
|
|
176
182
|
It is not required to use the bundled Web UI. You can implement your own UI using the `SuperSettings::Setting` model.
|
177
183
|
|
184
|
+
You can link directly to editing a setting by passing `#edit=key` in the URL hash. This will open the Web UI with the setting with the key `key` selected for editing.
|
185
|
+
|
178
186
|
#### REST API
|
179
187
|
|
180
188
|
You can mount a REST API for exposing and managing the settings. This API is required for the Web UI and is mounted along with the Web UI. The REST interface is documented in the `SuperSettings::RestAPI` class.
|
@@ -242,6 +250,9 @@ SuperSettings.configure do |config|
|
|
242
250
|
# Set the superclass to use for the controller. Defaults to using `ApplicationController`.
|
243
251
|
config.controller.superclass = Admin::BaseController
|
244
252
|
|
253
|
+
# Set the color scheme to use for the Web UI. Options are :light (default), :dark, or :system.
|
254
|
+
config.controller.color_scheme = :dark
|
255
|
+
|
245
256
|
# Add additional code to the controller. In this case we are adding code to ensure only
|
246
257
|
# admins can access the functionality and changing the layout to use one defined by the application.
|
247
258
|
config.controller.enhance do
|
@@ -289,6 +300,54 @@ SuperSettings.configure do |config|
|
|
289
300
|
end
|
290
301
|
```
|
291
302
|
|
303
|
+
#### Using your own controller
|
304
|
+
|
305
|
+
You can embed the SuperSettings web UI into your own templates. This gives you the option to more tightly integrate it with your application's navigation and look and feel.
|
306
|
+
|
307
|
+
First disable the web UI in the configuration since you won't need it.
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
# config/initializers/super_settings.rb
|
311
|
+
|
312
|
+
SuperSettings.configure do |config|
|
313
|
+
# Disable the built in web UI since you won't be using it.
|
314
|
+
config.controller.web_ui_enabled = false
|
315
|
+
end
|
316
|
+
```
|
317
|
+
|
318
|
+
Create your controller that will render the SuperSettings web UI.
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
class AppSettingsController < ApplicationController
|
322
|
+
def index
|
323
|
+
end
|
324
|
+
end
|
325
|
+
```
|
326
|
+
|
327
|
+
Mount the engine routes in your `config/routes.rb` file.
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
# config/routes.rb
|
331
|
+
|
332
|
+
Rails.application.routes.draw do
|
333
|
+
mount SuperSettings::Engine => "/settings"
|
334
|
+
|
335
|
+
controller :app_settings do
|
336
|
+
get "/app_settings", action: :index
|
337
|
+
end
|
338
|
+
end
|
339
|
+
```
|
340
|
+
|
341
|
+
Create a view that embeds the SuperSettings web UI using the `SuperSettings::Application` class. You need to specify the path you mounted the engine at as the base URL for the REST API.
|
342
|
+
|
343
|
+
```erb
|
344
|
+
# app/views/app_settings/index.html.erb
|
345
|
+
|
346
|
+
<h1>Application Settings</h1>
|
347
|
+
|
348
|
+
<%= SuperSettings::Application.new(api_base_url: "/settings").render %>
|
349
|
+
```
|
350
|
+
|
292
351
|
## Installation
|
293
352
|
|
294
353
|
Add this line to your application's Gemfile:
|
@@ -313,6 +372,49 @@ Open a pull request on GitHub.
|
|
313
372
|
|
314
373
|
Please use the [standardrb](https://github.com/testdouble/standard) syntax and lint your code with `standardrb --fix` before submitting.
|
315
374
|
|
375
|
+
You can run a local Rails development using ActiveRecord storage with
|
376
|
+
|
377
|
+
```bash
|
378
|
+
# Initialize the database (one time only)
|
379
|
+
bin/rails bin/rails super_settings:install:migrations
|
380
|
+
bin/rails db:migrate
|
381
|
+
|
382
|
+
# Start the server
|
383
|
+
bin/rails s
|
384
|
+
```
|
385
|
+
|
386
|
+
You can also bring up a local rack server with
|
387
|
+
|
388
|
+
```bash
|
389
|
+
bundle exec rackup
|
390
|
+
```
|
391
|
+
|
392
|
+
By default this will use Redis for storage using the default Redis URL. You can change the storage engine with the `STORAGE` environment variable.
|
393
|
+
|
394
|
+
- `redis` - Use the Redis storage engine. The Redis URL can be set with the `REDIS_URL` environment variable.
|
395
|
+
- `http` - Use the HTTP storage engine. The URL for the REST API can be set with the `REST_API_URL` environment variable.
|
396
|
+
- `s3` - Use the S3 storage engine. The S3 URL can be set with the `S3_URL` environment variable.
|
397
|
+
- `mongodb` - Use the MongoDB storage engine. The MongoDB URL can be set with the `MONGODB_URL` environment variable.
|
398
|
+
|
399
|
+
You can bring up all of these storage engines locally with the included docker-compose configuration.
|
400
|
+
|
401
|
+
```bash
|
402
|
+
docker-compose up
|
403
|
+
```
|
404
|
+
|
405
|
+
This will work out of the box with the defaults for the storage engines when running the rack server.:
|
406
|
+
|
407
|
+
- `REDIS_URL` - `redis://localhost:6379/0`
|
408
|
+
- `REST_API_URL` - `http://localhost:3000/settings` (this is the default URL for the Rails application)
|
409
|
+
- `S3_URL` - `s3://accesskey:secretkey@region-1/settings/settings.json` (the S3 endpoint will be set to `http://localhost:9000`)
|
410
|
+
- `MONGODB_URL` - `mongodb://localhost:27017/super_settings`
|
411
|
+
|
412
|
+
Finally, you can run the application in dark mode by setting the `COLOR_SCHEME` environment variable.
|
413
|
+
|
414
|
+
```bash
|
415
|
+
COLOR_SCHEME=dark bundle exec rackup
|
416
|
+
```
|
417
|
+
|
316
418
|
## License
|
317
419
|
|
318
420
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.1
|
@@ -5,19 +5,20 @@ module SuperSettings
|
|
5
5
|
# Render the styles.css as an inline <style> tag.
|
6
6
|
def super_settings_layout_style_tag
|
7
7
|
application_dir = File.expand_path(File.join("..", "..", "..", "lib", "super_settings", "application"), __dir__)
|
8
|
+
css = render(file: File.join(application_dir, "layout_styles.css"))
|
8
9
|
content_tag(:style, type: "text/css") do
|
9
|
-
|
10
|
+
(layout_css_vars + css).html_safe
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
13
14
|
# Return the application name set by the configuration or a default value.
|
14
15
|
def super_settings_application_name
|
15
|
-
|
16
|
+
SuperSettings.configuration.controller.application_name || "Application"
|
16
17
|
end
|
17
18
|
|
18
19
|
# Render the header for the web pages using values set in the configuration.
|
19
20
|
def super_settings_application_header
|
20
|
-
config =
|
21
|
+
config = SuperSettings.configuration.controller
|
21
22
|
content = "#{super_settings_application_name} Settings"
|
22
23
|
if Coerce.present?(config.application_logo)
|
23
24
|
content = image_tag(config.application_logo, alt: "").concat(content)
|
@@ -28,5 +29,14 @@ module SuperSettings
|
|
28
29
|
content
|
29
30
|
end
|
30
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def layout_css_vars
|
36
|
+
application_dir = File.expand_path(File.join("..", "..", "..", "lib", "super_settings", "application"), __dir__)
|
37
|
+
erb = ERB.new(File.read(File.join(application_dir, "layout_vars.css.erb")))
|
38
|
+
color_scheme = SuperSettings.configuration.controller.color_scheme
|
39
|
+
erb.result(binding).html_safe
|
40
|
+
end
|
31
41
|
end
|
32
42
|
end
|
data/config/routes.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
SuperSettings::Engine.routes.draw do
|
4
4
|
controller :settings do
|
5
|
-
if SuperSettings
|
5
|
+
if SuperSettings.configuration.controller.web_ui_enabled?
|
6
6
|
get "/", action: :root, as: :root
|
7
7
|
end
|
8
8
|
get "/settings", action: :index
|
@@ -1,12 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
migration_class = ActiveRecord::Migration
|
5
|
-
if migration_class.respond_to?(:[])
|
6
|
-
migration_class = migration_class[4.2]
|
7
|
-
end
|
8
|
-
|
9
|
-
class CreateSuperSettings < migration_class
|
3
|
+
class CreateSuperSettings < ActiveRecord::Migration[5.0]
|
10
4
|
def up
|
11
5
|
create_table :super_settings do |t|
|
12
6
|
t.string :key, null: false, limit: 190, index: {unique: true}
|
@@ -9,7 +9,10 @@
|
|
9
9
|
(function() {
|
10
10
|
// Get the URL for making an API call to the specified action and id.
|
11
11
|
function apiURL(action, params) {
|
12
|
-
let url =
|
12
|
+
let url = document.querySelector(".super-settings[data-api-base-url]")?.dataset?.apiBaseUrl;
|
13
|
+
if (!url) {
|
14
|
+
url = window.location.pathname;
|
15
|
+
}
|
13
16
|
if (url.endsWith("/")) {
|
14
17
|
url = url.substring(0, url.length - 1);
|
15
18
|
}
|
@@ -5,13 +5,14 @@ module SuperSettings
|
|
5
5
|
# are mixed in to the Application class so they are accessible from the ERB templates.
|
6
6
|
module Helper
|
7
7
|
ICON_SVG = Dir.glob(File.join(__dir__, "images", "*.svg")).each_with_object({}) do |file, cache|
|
8
|
-
|
8
|
+
svg = File.read(file).chomp
|
9
|
+
cache[File.basename(file, ".svg")] = svg
|
9
10
|
end.freeze
|
10
11
|
|
11
12
|
ICON_BUTTON_STYLE = {
|
12
13
|
cursor: "pointer",
|
13
|
-
width: "1.
|
14
|
-
height: "1.
|
14
|
+
width: "1.35rem",
|
15
|
+
height: "1.35rem",
|
15
16
|
"min-width": "20px",
|
16
17
|
"min-height": "20px",
|
17
18
|
"margin-top": "0.25rem",
|
@@ -21,8 +22,7 @@ module SuperSettings
|
|
21
22
|
DEFAULT_ICON_STYLE = {
|
22
23
|
width: "1rem",
|
23
24
|
height: "1rem",
|
24
|
-
display: "inline-block"
|
25
|
-
"vertical-align": "middle"
|
25
|
+
display: "inline-block"
|
26
26
|
}.freeze
|
27
27
|
|
28
28
|
# Render the scripts.js file as an inline <script> tag.
|
@@ -41,6 +41,7 @@ module SuperSettings
|
|
41
41
|
def style_tag
|
42
42
|
<<~HTML
|
43
43
|
<style type="text/css">
|
44
|
+
#{render_partial("style_vars.css.erb")}
|
44
45
|
#{File.read(File.join(__dir__, "styles.css"))}
|
45
46
|
</style>
|
46
47
|
HTML
|
@@ -50,39 +51,61 @@ module SuperSettings
|
|
50
51
|
def layout_style_tag
|
51
52
|
<<~HTML
|
52
53
|
<style type="text/css">
|
54
|
+
#{render_partial("layout_vars.css.erb")}
|
53
55
|
#{File.read(File.join(__dir__, "layout_styles.css"))}
|
54
56
|
</style>
|
55
57
|
HTML
|
56
58
|
end
|
57
59
|
|
60
|
+
# Render an ERB template.
|
61
|
+
#
|
62
|
+
# @param erb_file [String] the path to the ERB file to render
|
63
|
+
# @return [String] the rendered HTML
|
64
|
+
def render_partial(erb_file)
|
65
|
+
template = ERB.new(File.read(File.expand_path(erb_file, __dir__)))
|
66
|
+
template.result(binding)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Escape text for use in HTML.
|
70
|
+
#
|
71
|
+
# @param text [String] the text to escape
|
72
|
+
# @return [String] the escaped text
|
73
|
+
def html_escape(text)
|
74
|
+
ERB::Util.html_escape(text)
|
75
|
+
end
|
76
|
+
|
58
77
|
# Render an image tag for one of the SVG images in the images directory. If the :color option
|
59
78
|
# is specified, it will be applied to the SVG image.
|
60
79
|
def icon_image(name, options = {})
|
61
80
|
svg = ICON_SVG[name.to_s]
|
62
|
-
|
63
|
-
|
81
|
+
style = (options[:style] || {})
|
82
|
+
css = DEFAULT_ICON_STYLE.merge(style).map { |name, value| "#{name}: #{value}" }.join("; ")
|
83
|
+
options = options.merge(style: css, class: "super-settings-icon")
|
84
|
+
if options[:data].is_a?(Hash)
|
85
|
+
options[:data].each do |key, value|
|
86
|
+
options["data-#{key}"] = value
|
87
|
+
end
|
88
|
+
options.delete(:data)
|
64
89
|
end
|
65
|
-
|
66
|
-
options = {alt: ""}.merge(options).merge(src: "data:image/svg+xml;utf8,#{svg}", style: css)
|
67
|
-
tag(:img, options)
|
90
|
+
content_tag(:span, svg, options)
|
68
91
|
end
|
69
92
|
|
70
93
|
# Render an icon image as a link tag.
|
71
94
|
def icon_button(icon, title:, color:, js_class:, url: nil, disabled: false, style: {}, link_style: nil)
|
72
95
|
url = "#" if Coerce.blank?(url)
|
73
|
-
image = icon_image(icon, alt: title,
|
74
|
-
content_tag(:a, image, href: url, class: js_class, disabled: disabled, style: link_style)
|
96
|
+
image = icon_image(icon, alt: title, style: ICON_BUTTON_STYLE.merge(style).merge(color: color))
|
97
|
+
content_tag(:a, image, href: url, class: js_class, disabled: disabled, style: link_style, title: title)
|
75
98
|
end
|
76
99
|
|
77
100
|
# Return the application name set by the configuration or a default value.
|
78
101
|
def application_name
|
79
|
-
|
102
|
+
html_escape(SuperSettings.configuration.controller.application_name || "Application")
|
80
103
|
end
|
81
104
|
|
82
105
|
# Render the header for the web pages using values set in the configuration.
|
83
106
|
def application_header
|
84
|
-
config =
|
85
|
-
content =
|
107
|
+
config = SuperSettings.configuration.controller
|
108
|
+
content = html_escape("#{application_name} Settings")
|
86
109
|
if Coerce.present?(config.application_logo)
|
87
110
|
content = tag(:img, src: config.application_logo, alt: "") + content
|
88
111
|
end
|
@@ -107,14 +130,30 @@ module SuperSettings
|
|
107
130
|
def html_attributes(options)
|
108
131
|
html_options = []
|
109
132
|
options.each do |name, value|
|
110
|
-
html_options << "#{name}=\"#{
|
133
|
+
html_options << "#{name}=\"#{html_escape(value.to_s)}\""
|
111
134
|
end
|
112
135
|
html_options.join(" ")
|
113
136
|
end
|
114
137
|
|
115
|
-
#
|
138
|
+
# Additional HTML code that should go into the <head> element on the page.
|
139
|
+
#
|
140
|
+
# @return [String]
|
116
141
|
def add_to_head
|
117
142
|
@add_to_head if defined?(@add_to_head)
|
118
143
|
end
|
144
|
+
|
145
|
+
# The base URL for the REST API.
|
146
|
+
#
|
147
|
+
# @return [String]
|
148
|
+
def api_base_url
|
149
|
+
@api_base_url if defined?(@api_base_url)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Whether to use dark mode for the application UI.
|
153
|
+
#
|
154
|
+
# @return [Boolean, nil]
|
155
|
+
def color_scheme
|
156
|
+
@color_scheme if defined?(@color_scheme)
|
157
|
+
end
|
119
158
|
end
|
120
159
|
end
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-down-short" viewBox="0 0 16 16">
|
2
|
+
<path fill-rule="evenodd" d="M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-up-short" viewBox="0 0 16 16">
|
2
|
+
<path fill-rule="evenodd" d="M8 12a.5.5 0 0 0 .5-.5V5.707l2.146 2.147a.5.5 0 0 0 .708-.708l-3-3a.5.5 0 0 0-.708 0l-3 3a.5.5 0 1 0 .708.708L7.5 5.707V11.5a.5.5 0 0 0 .5.5"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle" viewBox="0 0 16 16">
|
2
|
+
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
|
3
|
+
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0"/>
|
4
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil-square" viewBox="0 0 16 16">
|
2
|
+
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
|
3
|
+
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5z"/>
|
4
|
+
</svg>
|
@@ -1 +1,3 @@
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
|
2
|
+
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash3" viewBox="0 0 16 16">
|
2
|
+
<path d="M6.5 1h3a.5.5 0 0 1 .5.5v1H6v-1a.5.5 0 0 1 .5-.5M11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3A1.5 1.5 0 0 0 5 1.5v1H1.5a.5.5 0 0 0 0 1h.538l.853 10.66A2 2 0 0 0 4.885 16h6.23a2 2 0 0 0 1.994-1.84l.853-10.66h.538a.5.5 0 0 0 0-1zm1.958 1-.846 10.58a1 1 0 0 1-.997.92h-6.23a1 1 0 0 1-.997-.92L3.042 3.5zm-7.487 1a.5.5 0 0 1 .528.47l.5 8.5a.5.5 0 0 1-.998.06L5 5.03a.5.5 0 0 1 .47-.53Zm5.058 0a.5.5 0 0 1 .47.53l-.5 8.5a.5.5 0 1 1-.998-.06l.5-8.5a.5.5 0 0 1 .528-.47M8 4.5a.5.5 0 0 1 .5.5v8.5a.5.5 0 0 1-1 0V5a.5.5 0 0 1 .5-.5"/>
|
3
|
+
</svg>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
|
2
|
+
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
|
3
|
+
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708"/>
|
4
|
+
</svg>
|