keystone_ui-preferences 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dffbd18d9f90fc3020e69bfbb093379b348a2acd0b8d12d805d751c40c59f1ca
4
+ data.tar.gz: 8ecb76a3a5fa72a67c7751e14c73a6af4b2e7fb5343b9582cc10a341de886542
5
+ SHA512:
6
+ metadata.gz: ad669daede81eed26e2134742d0cb8ee84fb9f931e1777e26e49a9e9167dcce4731fc6bb8b607c0c742e9f1773146f98c07e8e29666f809c8d6ea5ffc84dae9f
7
+ data.tar.gz: cd87ce9b9ce0e390ca927d88a7f3b3e7b02a5bbc667147cf352dff22467c45e25c2e6a93fdc8b328b268fb4134c08f7f5cb0614920804bcc65404d45d3439eef
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2026 Tyler Schneider
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # keystone_ui-preferences
2
+
3
+ Per-user saved choices for Keystone UI components, such as a data table's hidden columns.
4
+
5
+ A page gives a `ui_data_table` a `key:`. This gem saves each signed-in person's layout for that key and hands it back to keystone_ui, so the table renders from it and shows a Columns menu that saves to it. A person with nothing saved sees the hidden columns the table's own call names.
6
+
7
+ ## Installation
8
+
9
+ Add the gem and run its install generator, which copies a migration for its table:
10
+
11
+ ```ruby
12
+ gem "keystone_ui-preferences"
13
+ ```
14
+
15
+ ```bash
16
+ bundle install
17
+ bin/rails generate keystone_ui:preferences:install
18
+ bin/rails db:migrate
19
+ ```
20
+
21
+ Mount the engine in `config/routes.rb`. A table's Columns menu saves to it:
22
+
23
+ ```ruby
24
+ mount KeystoneUi::Preferences::Engine => "/keystone_ui_preferences"
25
+ ```
26
+
27
+ Include the concern in `ApplicationController`. It gives views the lookup keystone_ui calls for a table's key:
28
+
29
+ ```ruby
30
+ class ApplicationController < ActionController::Base
31
+ include KeystoneUi::Preferences::ComponentPreferences
32
+ end
33
+ ```
34
+
35
+ ## Configuration
36
+
37
+ The gem asks the host for the signed-in person and for its sign-in check. Both default to Devise's names:
38
+
39
+ ```ruby
40
+ KeystoneUi::Preferences.configure do |config|
41
+ config.current_owner_method = :current_user # returns the person a value is saved for
42
+ config.authentication_method = :authenticate_user! # runs before every save
43
+ end
44
+ ```
45
+
46
+ ## Using it
47
+
48
+ Give a table a key, and the hidden columns it shows a person with nothing saved:
49
+
50
+ ```erb
51
+ <%= ui_data_table(
52
+ items: @months,
53
+ columns: [
54
+ Keystone::Ui::Column.new(:month, "Month"),
55
+ Keystone::Ui::Column.new(:pipeline, "Pipeline", hideable: true)
56
+ ],
57
+ key: :revenue_projection_months,
58
+ hidden_columns: [ :pipeline ]
59
+ ) %>
60
+ ```
61
+
62
+ A signed-in person sees a Columns menu above the table. Ticking or unticking a column saves `{ "hidden_columns": [...] }` for that person and key, replacing what they saved before, and reloads the page. Another person viewing the same table sees only their own saved layout. With nobody signed in, the table renders from its own call and shows no menu.
63
+
64
+ ## What is stored
65
+
66
+ One row per owner and component key, in `keystone_ui_preferences_component_preferences`:
67
+
68
+ | Column | Holds |
69
+ |--------|-------|
70
+ | `owner` | the person the value belongs to (polymorphic) |
71
+ | `component_key` | the key the page gave the component |
72
+ | `value` | the JSON object last saved |
73
+ | `members_choose` | whether an account's members may keep their own value, on by default |
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "test"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ end
10
+
11
+ task default: :test
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module KeystoneUi
6
+ module Preferences
7
+ module ComponentPreferences
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ helper_method :keystone_component_preference if respond_to?(:helper_method)
12
+ end
13
+
14
+ def keystone_component_preference(component_key)
15
+ owner = send(KeystoneUi::Preferences.configuration.current_owner_method)
16
+ return unless owner
17
+
18
+ {
19
+ value: ComponentPreference.find_by(owner: owner, component_key: component_key.to_s)&.value,
20
+ save_url: keystone_ui_preferences.component_preference_path(component_key: component_key)
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class ApplicationController < ::ApplicationController
6
+ before_action { send(KeystoneUi::Preferences.configuration.authentication_method) }
7
+
8
+ private
9
+
10
+ def current_owner
11
+ send(KeystoneUi::Preferences.configuration.current_owner_method)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class ComponentPreferencesController < ApplicationController
6
+ def update
7
+ preference = ComponentPreference.find_or_initialize_by(owner: current_owner, component_key: params[:component_key])
8
+ preference.update!(value: JSON.parse(request.raw_post))
9
+ head :no_content
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class ComponentPreference < ApplicationRecord
6
+ self.table_name = "keystone_ui_preferences_component_preferences"
7
+
8
+ belongs_to :owner, polymorphic: true
9
+ end
10
+ end
11
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ KeystoneUi::Preferences::Engine.routes.draw do
2
+ patch "/:component_key", to: "component_preferences#update", as: :component_preference
3
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module KeystoneUi
7
+ module Preferences
8
+ module Generators
9
+ class InstallGenerator < Rails::Generators::Base
10
+ include ActiveRecord::Generators::Migration
11
+
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ desc "Installs KeystoneUi::Preferences: copies its migration."
15
+
16
+ def copy_migration
17
+ migration_template(
18
+ "create_keystone_ui_preferences_component_preferences.rb.erb",
19
+ "db/migrate/create_keystone_ui_preferences_component_preferences.rb"
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,14 @@
1
+ class CreateKeystoneUiPreferencesComponentPreferences < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :keystone_ui_preferences_component_preferences do |t|
4
+ t.references :owner, polymorphic: true, null: false
5
+ t.string :component_key, null: false
6
+ t.json :value, null: false, default: {}
7
+ t.boolean :members_choose, default: true, null: false
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :keystone_ui_preferences_component_preferences, %i[owner_type owner_id component_key], unique: true,
12
+ name: "index_keystone_ui_prefs_on_owner_and_key"
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class Configuration
6
+ attr_accessor :current_owner_method, :authentication_method
7
+
8
+ def initialize
9
+ @current_owner_method = :current_user
10
+ @authentication_method = :authenticate_user!
11
+ end
12
+ end
13
+
14
+ def self.configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def self.configure
19
+ yield(configuration)
20
+ end
21
+
22
+ def self.reset_configuration!
23
+ @configuration = Configuration.new
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace KeystoneUi::Preferences
7
+
8
+ initializer "keystone_ui.preferences.supplier" do
9
+ KeystoneUi.configure do |config|
10
+ config.preference_supplier = lambda do |view, component_key|
11
+ view.keystone_component_preference(component_key) if view.respond_to?(:keystone_component_preference)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KeystoneUi
4
+ module Preferences
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ require "keystone_ui"
2
+ require "keystone_ui/preferences/version"
3
+ require "keystone_ui/preferences/configuration"
4
+ require "keystone_ui/preferences/engine"
5
+
6
+ module KeystoneUi
7
+ module Preferences
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require "keystone_ui/preferences"
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: keystone_ui-preferences
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tyler Schneider
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: keystone_ui
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.33.1
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 0.33.1
26
+ - !ruby/object:Gem::Dependency
27
+ name: railties
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '7.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: activerecord
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '7.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '7.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: activesupport
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '7.0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '7.0'
68
+ description: A companion engine for keystone_ui that saves each person's choices for
69
+ a component, such as a data table's hidden columns, and supplies them back to keystone_ui.
70
+ email:
71
+ - tylercschneider@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - MIT-LICENSE
77
+ - README.md
78
+ - Rakefile
79
+ - app/controllers/concerns/keystone_ui/preferences/component_preferences.rb
80
+ - app/controllers/keystone_ui/preferences/application_controller.rb
81
+ - app/controllers/keystone_ui/preferences/component_preferences_controller.rb
82
+ - app/models/keystone_ui/preferences/application_record.rb
83
+ - app/models/keystone_ui/preferences/component_preference.rb
84
+ - config/routes.rb
85
+ - lib/generators/keystone_ui/preferences/install/install_generator.rb
86
+ - lib/generators/keystone_ui/preferences/install/templates/create_keystone_ui_preferences_component_preferences.rb.erb
87
+ - lib/keystone_ui-preferences.rb
88
+ - lib/keystone_ui/preferences.rb
89
+ - lib/keystone_ui/preferences/configuration.rb
90
+ - lib/keystone_ui/preferences/engine.rb
91
+ - lib/keystone_ui/preferences/version.rb
92
+ homepage: https://github.com/DYB-Development/keystone_ui-preferences
93
+ licenses:
94
+ - MIT
95
+ metadata:
96
+ homepage_uri: https://github.com/DYB-Development/keystone_ui-preferences
97
+ source_code_uri: https://github.com/DYB-Development/keystone_ui-preferences
98
+ changelog_uri: https://github.com/DYB-Development/keystone_ui-preferences/blob/main/CHANGELOG.md
99
+ bug_tracker_uri: https://github.com/DYB-Development/keystone_ui-preferences/issues
100
+ documentation_uri: https://github.com/DYB-Development/keystone_ui-preferences#readme
101
+ rubygems_mfa_required: 'true'
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 3.1.0
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubygems_version: 4.0.20
117
+ specification_version: 4
118
+ summary: Per-user saved choices for Keystone UI components.
119
+ test_files: []