keystone_ui 0.35.0 → 0.37.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 +4 -4
- data/app/assets/javascripts/keystone_ui/column_picker_controller.js +19 -2
- data/app/components/keystone/ui/column.rb +4 -2
- data/app/components/keystone/ui/column_picker_component.html.erb +1 -0
- data/app/components/keystone/ui/column_picker_component.rb +5 -5
- data/app/components/keystone/ui/data_table_component.rb +10 -19
- data/app/components/keystone/ui/saved_layout.rb +46 -0
- data/lib/keystone_ui/version.rb +1 -1
- data/the_local/agents/keystone_ui-develop.md +27 -7
- data/the_local/agents/keystone_ui-info.md +13 -2
- data/the_local/agents/keystone_ui-install.md +9 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f1534a3f721376c82b75b22a653e8bcee3a0509bcd3b09cd137c93c78e15110f
|
|
4
|
+
data.tar.gz: 0df6e2e29387563688ba68bc53d8c29dc69aa322aa86c84b6416c0e3af36f703
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1869494c71af590cd1fa49fcd1062b024df02950f571e5dcbd7deaaa508574ad0f0aa2bfc8e23b0dc10d35ca440a50bc12e5d18063c62888de9eb29c42c09b45
|
|
7
|
+
data.tar.gz: 45563016cb89280c2e97cca008236c9fc50ba4681486a53f0d82fc4066e7db68368ad412c43b512cb2ca4ccd4f359dd29339890e24854eae2ead04ed9db7f6db
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Controller } from "@hotwired/stimulus"
|
|
2
2
|
|
|
3
3
|
export default class extends Controller {
|
|
4
|
-
static targets = ["menu", "option"]
|
|
4
|
+
static targets = ["menu", "option", "error"]
|
|
5
5
|
static values = { saveUrl: String }
|
|
6
6
|
|
|
7
7
|
connect() {
|
|
8
|
+
this.shown = this.optionTargets.map(option => [ option, this.checkboxIn(option).checked ])
|
|
8
9
|
this._close = this.close.bind(this)
|
|
9
10
|
document.addEventListener("click", this._close)
|
|
10
11
|
}
|
|
@@ -66,6 +67,10 @@ export default class extends Controller {
|
|
|
66
67
|
|
|
67
68
|
moved() {
|
|
68
69
|
this.changed = true
|
|
70
|
+
this.refreshMoveButtons()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
refreshMoveButtons() {
|
|
69
74
|
const options = this.optionTargets
|
|
70
75
|
options.forEach((option, index) => {
|
|
71
76
|
option.querySelector('[data-action="click->column-picker#moveUp"]').disabled = index === 0
|
|
@@ -99,8 +104,20 @@ export default class extends Controller {
|
|
|
99
104
|
"X-CSRF-Token": token
|
|
100
105
|
},
|
|
101
106
|
body: JSON.stringify({ hidden_columns: this.hiddenColumns(), column_order: this.columnOrder() })
|
|
102
|
-
}).then(() => {
|
|
107
|
+
}).then((response) => {
|
|
108
|
+
if (!response.ok) return this.failed()
|
|
109
|
+
|
|
103
110
|
Turbo.visit(window.location.href, { action: "replace" })
|
|
111
|
+
}).catch(() => this.failed())
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
failed() {
|
|
115
|
+
this.errorTarget.classList.remove("hidden")
|
|
116
|
+
this.shown.forEach(([ option, checked ]) => {
|
|
117
|
+
option.parentNode.insertBefore(option, null)
|
|
118
|
+
this.checkboxIn(option).checked = checked
|
|
119
|
+
option.querySelector("label").classList.toggle("ks-menu-option-hidden", !checked)
|
|
104
120
|
})
|
|
121
|
+
this.refreshMoveButtons()
|
|
105
122
|
}
|
|
106
123
|
}
|
|
@@ -5,17 +5,19 @@ module Keystone
|
|
|
5
5
|
class Column
|
|
6
6
|
attr_reader :key, :header_text
|
|
7
7
|
|
|
8
|
-
def initialize(key, header_text, mobile_hidden: false, sortable: false, hideable: false)
|
|
8
|
+
def initialize(key, header_text, mobile_hidden: false, sortable: false, hideable: false, locked: false)
|
|
9
9
|
@key = key
|
|
10
10
|
@header_text = header_text
|
|
11
11
|
@mobile_hidden = mobile_hidden
|
|
12
12
|
@sortable = sortable
|
|
13
13
|
@hideable = hideable
|
|
14
|
+
@locked = locked
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def mobile_hidden? = @mobile_hidden
|
|
17
18
|
def sortable? = @sortable
|
|
18
|
-
def hideable? = @hideable
|
|
19
|
+
def hideable? = @hideable && !@locked
|
|
20
|
+
def locked? = @locked
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
|
@@ -11,6 +11,7 @@ module Keystone
|
|
|
11
11
|
OPTION_HIDDEN_CLASSES = "ks-menu-option-hidden"
|
|
12
12
|
OPTION_ROW_CLASSES = "flex items-center"
|
|
13
13
|
MOVE_BUTTON_CLASSES = "ks-menu-move text-sm"
|
|
14
|
+
ERROR_CLASSES = "ks-error hidden"
|
|
14
15
|
|
|
15
16
|
COLUMNS_ICON = <<~SVG.freeze
|
|
16
17
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4">
|
|
@@ -20,18 +21,17 @@ module Keystone
|
|
|
20
21
|
|
|
21
22
|
attr_reader :save_url
|
|
22
23
|
|
|
23
|
-
def initialize(columns:, hidden_columns: [], save_url: nil)
|
|
24
|
-
@
|
|
25
|
-
@hidden_keys = Array(hidden_columns).map(&:to_sym).to_set
|
|
24
|
+
def initialize(columns:, hidden_columns: [], save_url: nil, layout: nil)
|
|
25
|
+
@layout = layout || SavedLayout.new(columns: columns, value: nil, default_hidden: hidden_columns)
|
|
26
26
|
@save_url = save_url
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def hideable_columns
|
|
30
|
-
@columns.select(&:hideable?)
|
|
30
|
+
@layout.columns.select(&:hideable?)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def hidden?(key)
|
|
34
|
-
@
|
|
34
|
+
@layout.hidden?(key)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
def option_classes(key)
|
|
@@ -17,6 +17,8 @@ module Keystone
|
|
|
17
17
|
ROW_CLASSES_LAST = "ks-table-cell-last text-right text-sm whitespace-nowrap"
|
|
18
18
|
|
|
19
19
|
MOBILE_HIDDEN_CLASSES = "hidden sm:table-cell"
|
|
20
|
+
HEADER_LOCKED_CLASSES = "ks-table-header-locked sticky left-0"
|
|
21
|
+
CELL_LOCKED_CLASSES = "ks-table-cell-locked sticky left-0"
|
|
20
22
|
|
|
21
23
|
SORT_LINK_CLASSES = "ks-table-sort-link group inline-flex items-center"
|
|
22
24
|
SORT_ICON_CLASSES = "h-4 w-4 flex-shrink-0"
|
|
@@ -30,8 +32,9 @@ module Keystone
|
|
|
30
32
|
def initialize(items:, columns:, empty_message: nil, sort: nil, sort_direction: nil, sort_url: nil, hidden_columns: [], key: nil)
|
|
31
33
|
@items = items.to_a
|
|
32
34
|
@all_columns = columns.map { |col| normalize_column(col) }
|
|
33
|
-
@
|
|
34
|
-
@
|
|
35
|
+
@default_hidden = hidden_columns
|
|
36
|
+
@layout = SavedLayout.new(columns: @all_columns, value: nil, default_hidden: hidden_columns)
|
|
37
|
+
@columns = @layout.visible_columns
|
|
35
38
|
@key = key
|
|
36
39
|
@empty_message = empty_message
|
|
37
40
|
@sort = sort&.to_sym
|
|
@@ -61,7 +64,7 @@ module Keystone
|
|
|
61
64
|
def column_picker
|
|
62
65
|
return unless @save_url
|
|
63
66
|
|
|
64
|
-
@column_picker ||= ColumnPickerComponent.new(columns: @all_columns,
|
|
67
|
+
@column_picker ||= ColumnPickerComponent.new(columns: @all_columns, layout: @layout, save_url: @save_url)
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
def column_keys
|
|
@@ -76,6 +79,7 @@ module Keystone
|
|
|
76
79
|
cells = @columns.map.with_index do |column, index|
|
|
77
80
|
tokens = [ header_classes_for(index) ]
|
|
78
81
|
tokens << MOBILE_HIDDEN_CLASSES if column.mobile_hidden?
|
|
82
|
+
tokens << HEADER_LOCKED_CLASSES if index.zero? && column.locked?
|
|
79
83
|
|
|
80
84
|
cell = {
|
|
81
85
|
label: column.header_text,
|
|
@@ -119,6 +123,7 @@ module Keystone
|
|
|
119
123
|
@columns.map.with_index do |column, index|
|
|
120
124
|
tokens = [ row_classes_for(index) ]
|
|
121
125
|
tokens << MOBILE_HIDDEN_CLASSES if column.mobile_hidden?
|
|
126
|
+
tokens << CELL_LOCKED_CLASSES if index.zero? && column.locked?
|
|
122
127
|
|
|
123
128
|
cell = {
|
|
124
129
|
value: resolve_value(item, column.key),
|
|
@@ -147,25 +152,11 @@ module Keystone
|
|
|
147
152
|
saved = KeystoneUi.configuration.supplied_preference(helpers, @key)
|
|
148
153
|
return unless saved
|
|
149
154
|
|
|
150
|
-
@
|
|
151
|
-
@
|
|
152
|
-
@columns = visible_columns(@hidden_columns)
|
|
155
|
+
@layout = SavedLayout.new(columns: @all_columns, value: saved[:value], default_hidden: @default_hidden)
|
|
156
|
+
@columns = @layout.visible_columns
|
|
153
157
|
@save_url = saved[:save_url]
|
|
154
158
|
end
|
|
155
159
|
|
|
156
|
-
def ordered_columns(column_order)
|
|
157
|
-
return @all_columns unless column_order
|
|
158
|
-
|
|
159
|
-
positions = Array(column_order).map(&:to_sym).each_with_index.to_h
|
|
160
|
-
hideable = @all_columns.select(&:hideable?).sort_by.with_index { |col, index| [ positions.fetch(col.key, positions.size + index) ] }
|
|
161
|
-
@all_columns.map { |col| col.hideable? ? hideable.shift : col }
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
def visible_columns(hidden_columns)
|
|
165
|
-
hidden_keys = Array(hidden_columns).map(&:to_sym).to_set
|
|
166
|
-
@all_columns.reject { |col| col.hideable? && hidden_keys.include?(col.key) }
|
|
167
|
-
end
|
|
168
|
-
|
|
169
160
|
def visual_column_count
|
|
170
161
|
@columns.length + (actions? ? 1 : 0)
|
|
171
162
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Keystone
|
|
4
|
+
module Ui
|
|
5
|
+
class SavedLayout
|
|
6
|
+
def initialize(columns:, value:, default_hidden:)
|
|
7
|
+
@columns = columns
|
|
8
|
+
@value = value.is_a?(Hash) ? value : {}
|
|
9
|
+
@default_hidden = default_hidden
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def columns
|
|
13
|
+
@ordered_columns ||= ordered_columns
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def visible_columns
|
|
17
|
+
columns.reject { |column| hidden?(column.key) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def hidden?(key)
|
|
21
|
+
column = @columns.find { |col| col.key == key.to_sym }
|
|
22
|
+
column&.hideable? && hidden_keys.include?(key.to_sym)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def ordered_columns
|
|
28
|
+
column_order = saved_list("column_order")
|
|
29
|
+
return @columns unless column_order
|
|
30
|
+
|
|
31
|
+
positions = Array(column_order).map(&:to_sym).each_with_index.to_h
|
|
32
|
+
hideable = @columns.select(&:hideable?).sort_by.with_index { |col, index| positions.fetch(col.key, positions.size + index) }
|
|
33
|
+
@columns.map { |col| col.hideable? ? hideable.shift : col }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def hidden_keys
|
|
37
|
+
@hidden_keys ||= Array(saved_list("hidden_columns") || @default_hidden).map(&:to_sym).to_set
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def saved_list(name)
|
|
41
|
+
list = @value[name]
|
|
42
|
+
list if list.is_a?(Array)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/keystone_ui/version.rb
CHANGED
|
@@ -240,16 +240,24 @@ outer element. See Conventions before using it.
|
|
|
240
240
|
and the hideable ones fill the remaining places. With no `"column_order"` the
|
|
241
241
|
columns keep their declared order. Whenever the supplier
|
|
242
242
|
returns a save address, the table renders a "Columns" menu in a row above
|
|
243
|
-
itself, aligned right, that saves to it as `ui_column_picker` does
|
|
244
|
-
for a person with nothing saved
|
|
243
|
+
itself, aligned right, that saves to it as `ui_column_picker` does and shows
|
|
244
|
+
the same message when a save fails, including for a person with nothing saved
|
|
245
|
+
yet. That menu lists the hideable columns in
|
|
246
|
+
the order the table shows them and leaves ticked exactly the ones the table
|
|
247
|
+
shows. When the
|
|
245
248
|
supplier returns nothing, when no supplier is set, or when no `key:` is
|
|
246
249
|
passed, the table renders from `hidden_columns:` with no Columns menu. In
|
|
247
250
|
every case `hidden_columns:` is the table's default layout.
|
|
248
|
-
- `Keystone::Ui::Column.new(key, header_text, mobile_hidden: false, sortable: false, hideable: false)`
|
|
251
|
+
- `Keystone::Ui::Column.new(key, header_text, mobile_hidden: false, sortable: false, hideable: false, locked: false)`
|
|
249
252
|
— a column with per-column options, for when a `{ key: "Label" }` hash is not
|
|
250
253
|
enough. `mobile_hidden:` hides the column below `sm:`; `sortable:` opts it into
|
|
251
254
|
sort headers; `hideable:` lets the Columns menu hide it and move it, and a
|
|
252
|
-
saved `"column_order"` place it.
|
|
255
|
+
saved `"column_order"` place it. `locked: true` on the table's first column
|
|
256
|
+
keeps its header and cells in view while the rest of the table scrolls
|
|
257
|
+
sideways. A locked column that is not first renders as an ordinary column. A
|
|
258
|
+
locked column is never hideable, even with `hideable: true`: it is left out of
|
|
259
|
+
the Columns menu, `hidden_columns:` and a saved layout cannot hide it, and a
|
|
260
|
+
saved `"column_order"` cannot move it.
|
|
253
261
|
- `ui_column_picker(columns:, hidden_columns: [], save_url: nil)` — a "Columns"
|
|
254
262
|
dropdown with one row per `hideable` column, in the order `columns:` lists
|
|
255
263
|
them. Each row has a checkbox and an up and a down button that move the
|
|
@@ -264,7 +272,11 @@ outer element. See Conventions before using it.
|
|
|
264
272
|
`X-CSRF-Token` header, then reloads the page. A menu closed with nothing
|
|
265
273
|
changed sends nothing. `column_order` lists every hideable column's key in
|
|
266
274
|
the menu's order when it closes. With no `save_url:` it sends nothing. The app must provide that endpoint and persist
|
|
267
|
-
both lists. The
|
|
275
|
+
both lists. The endpoint must answer with a success status when it has saved
|
|
276
|
+
them. When it answers with an error status, or the request cannot reach the
|
|
277
|
+
server, the menu does not reload the page: it shows "Your column changes were
|
|
278
|
+
not saved." under the Columns button, and puts its boxes and its order back
|
|
279
|
+
to what the table shows. The picker does not reorder the table: beside a table without
|
|
268
280
|
`key:`, the app must pass the table and the picker its columns in the saved
|
|
269
281
|
order itself. A table
|
|
270
282
|
given `key:` renders its own Columns menu when the supplier gives a save
|
|
@@ -540,8 +552,16 @@ outer element. See Conventions before using it.
|
|
|
540
552
|
|
|
541
553
|
6. For a table, decide how columns are declared. Use `{ key: "Label" }` hashes
|
|
542
554
|
when every column is plain. Switch the whole set to `Keystone::Ui::Column`
|
|
543
|
-
objects as soon as one column needs `mobile_hidden:`, `sortable:`,
|
|
544
|
-
`hideable:`.
|
|
555
|
+
objects as soon as one column needs `mobile_hidden:`, `sortable:`,
|
|
556
|
+
`hideable:`, or `locked:`.
|
|
557
|
+
|
|
558
|
+
To keep a wide table's first column, such as a name, in view while the rest
|
|
559
|
+
scrolls sideways, declare it first with `locked: true`. Whether a table locks
|
|
560
|
+
its first column is the developer's choice, so ask rather than pick. If the
|
|
561
|
+
locked column stays in place but the scrolled columns show through its
|
|
562
|
+
cells, the app's keystone_ui-styles version does not define the
|
|
563
|
+
`ks-table-header-locked` and `ks-table-cell-locked` classes, so stop and hand
|
|
564
|
+
that part to `keystone_ui-install`, and add no classes to fix it.
|
|
545
565
|
|
|
546
566
|
For a table whose hideable columns a user should be able to choose and keep,
|
|
547
567
|
check whether the app's Keystone UI initializer sets a
|
|
@@ -127,6 +127,13 @@ holds the catalog.
|
|
|
127
127
|
- **The last table column is right-aligned.** In a data table with no actions
|
|
128
128
|
column, the last column's header is right-aligned like the cells beneath it,
|
|
129
129
|
so a figure or total placed in that header lines up with the figures below.
|
|
130
|
+
- **A locked first column.** A table column can be marked locked. When it is
|
|
131
|
+
the table's first column, its header and cells stay in view while the rest
|
|
132
|
+
of the table scrolls sideways, styled by keystone_ui-styles' locked header
|
|
133
|
+
and cell classes. A locked column anywhere else renders as an ordinary
|
|
134
|
+
column. A locked column cannot be hidden or moved, so it never appears in the
|
|
135
|
+
"Columns" menu and a saved layout leaves it where it is, even when it is also
|
|
136
|
+
marked hideable.
|
|
130
137
|
- **Saved table layouts.** A data table can be given a key naming it. A table
|
|
131
138
|
with a key asks the app, or another gem such as keystone_ui-preferences, for
|
|
132
139
|
the layout saved under that key for the request. A saved layout lists the
|
|
@@ -143,11 +150,15 @@ holds the catalog.
|
|
|
143
150
|
table, at its right, and saves the user's choice there, even before anything
|
|
144
151
|
has been saved. The menu lists the hideable columns in the order the table
|
|
145
152
|
shows them, each with a box to show or hide it and buttons to move it up or
|
|
146
|
-
down.
|
|
153
|
+
down. The menu and the table read the same saved layout, so the menu's
|
|
154
|
+
ticked boxes and order always match the columns the table shows. An unticked column's name is greyed at once. Ticking boxes and moving
|
|
147
155
|
columns sends nothing while the menu is open. Closing the menu, with its
|
|
148
156
|
Columns button or by clicking anywhere outside it, saves the hidden columns
|
|
149
157
|
and the order together once, then reloads the page. Closing it with nothing
|
|
150
|
-
changed saves nothing.
|
|
158
|
+
changed saves nothing. When the save is refused or cannot reach the server,
|
|
159
|
+
the page does not reload. The Columns menu shows the message "Your
|
|
160
|
+
column changes were not saved." and puts its boxes and order back to what
|
|
161
|
+
the table shows.
|
|
151
162
|
A table with no key, or an app with no supplier, renders from its own call
|
|
152
163
|
alone. Setting up the supplier belongs to the install local.
|
|
153
164
|
- **Suggestions.** A form field can carry a list of suggested values. The
|
|
@@ -43,7 +43,7 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
43
43
|
## How to use it
|
|
44
44
|
|
|
45
45
|
1. Confirm the prerequisites: Ruby >= 3.2 and **tailwindcss-rails v4+** in the
|
|
46
|
-
host app. The gem brings ViewComponent and keystone_ui-styles 0.
|
|
46
|
+
host app. The gem brings ViewComponent and keystone_ui-styles 0.12.0 or later with it.
|
|
47
47
|
Tailwind does not have to be initialized first, because the generator creates
|
|
48
48
|
the stylesheet if it is missing.
|
|
49
49
|
|
|
@@ -248,6 +248,9 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
248
248
|
`"hidden_columns"`, such as `{ "hidden_columns" => ["sku"] }`. That list
|
|
249
249
|
replaces the hidden columns the table's own call passes, and an empty list
|
|
250
250
|
shows every column. Only columns marked hideable are hidden.
|
|
251
|
+
- A column marked locked is never hideable, even when it is also marked
|
|
252
|
+
hideable. A saved layout cannot hide it or move it, and the Columns menu
|
|
253
|
+
does not list it.
|
|
251
254
|
- When `value` is `nil`, or has no `"hidden_columns"` string key, the table
|
|
252
255
|
keeps the hidden columns its own call passes. A symbol key is not read, so
|
|
253
256
|
`{ hidden_columns: [...] }` also keeps them.
|
|
@@ -279,6 +282,11 @@ built on ViewComponent; hook it in before building any screen with those helpers
|
|
|
279
282
|
string keys, `"hidden_columns"` and `"column_order"`, or the saved order
|
|
280
283
|
is not applied. With no `save_url`, the saved layout applies and no menu
|
|
281
284
|
is shown.
|
|
285
|
+
- The action at `save_url` must answer a stored layout with a 2xx status.
|
|
286
|
+
Any other status, or a request that cannot reach the server, leaves the
|
|
287
|
+
page unreloaded. The table then shows "Your column changes were not
|
|
288
|
+
saved." beside its Columns button, and the menu's boxes and order go back
|
|
289
|
+
to what the table shows.
|
|
282
290
|
- A companion preferences gem may set this supplier for the app. Ask the
|
|
283
291
|
developer whether the app uses one, or which code stores each user's table
|
|
284
292
|
layouts, before writing the callable.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: keystone_ui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.37.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Tyler Schneider
|
|
@@ -175,6 +175,7 @@ files:
|
|
|
175
175
|
- app/components/keystone/ui/progress_component.rb
|
|
176
176
|
- app/components/keystone/ui/radio_card_component.html.erb
|
|
177
177
|
- app/components/keystone/ui/radio_card_component.rb
|
|
178
|
+
- app/components/keystone/ui/saved_layout.rb
|
|
178
179
|
- app/components/keystone/ui/section_component.html.erb
|
|
179
180
|
- app/components/keystone/ui/section_component.rb
|
|
180
181
|
- app/components/keystone/ui/select_component.html.erb
|