satis 1.0.67 → 1.0.68
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/components/satis/application_component.rb +27 -0
- data/app/components/satis/card/component.html.slim +15 -7
- data/app/components/satis/card/component.rb +9 -2
- data/app/components/satis/dropdown/component.rb +2 -2
- data/app/components/satis/dropdown/component.scss +11 -1
- data/app/components/satis/dropdown/component_controller.js +38 -5
- data/app/components/satis/input/component.rb +4 -4
- data/app/components/satis/input/component.scss +16 -0
- data/app/components/satis/menu/component.html.slim +2 -2
- data/app/components/satis/menu/component.rb +3 -2
- data/app/components/satis/menu_item/component.html.slim +5 -1
- data/app/components/satis/tab/component.rb +4 -1
- data/app/components/satis/tabs/component.html.slim +2 -2
- data/app/components/satis/tabs/component.rb +3 -2
- data/app/components/satis/tabs/component_controller.js +14 -50
- data/app/controllers/satis/user_data_controller.rb +30 -0
- data/app/models/satis/user_data.rb +11 -0
- data/config/routes.rb +1 -3
- data/db/migrate/20220929142147_create_satis_user_data.rb +13 -0
- data/db/migrate/20221212083110_change_satis_user_data.rb +10 -0
- data/lib/satis/active_record_helpers.rb +20 -0
- data/lib/satis/configuration.rb +8 -1
- data/lib/satis/engine.rb +8 -0
- data/lib/satis/menus/menu.rb +2 -2
- data/lib/satis/satisfied.rb +17 -0
- data/lib/satis/version.rb +1 -1
- data/lib/satis.rb +12 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a777d25ac010446a7e69a55f9d0468ce45a462e7d69df395673f3e1d7ad40e84
|
4
|
+
data.tar.gz: 1857b13676a3952e4afcc709df9eacfbea2d97c475837676ba9a4141ede7c2da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b739ca26a38df0d714339b0c09ad14ed5c25b0a352fd4a0a8a6a8c26292e314da3388d81f0a63d92a39c7808d4d2c9a2c20837579fcd2256b50aec4ad8f41ea
|
7
|
+
data.tar.gz: 98ec19c8bfb70f0ce66875b9ad15a2ca3233e1b576971a5cce7c4bd7f7eb1ddff9dedf14a3d7b93ca92ff85f1441f1dec6e995f5889e69be022da1063658ec87
|
@@ -7,6 +7,9 @@ module Satis
|
|
7
7
|
|
8
8
|
attr_accessor :original_view_context
|
9
9
|
|
10
|
+
delegate :add_helper, to: :class
|
11
|
+
|
12
|
+
|
10
13
|
#
|
11
14
|
# This provides us with a translation helper which scopes into the original view
|
12
15
|
# and thereby conveniently scopes the translations.
|
@@ -46,5 +49,29 @@ module Satis
|
|
46
49
|
def i18n_scope
|
47
50
|
self.class.name.split('::').second.underscore.to_sym
|
48
51
|
end
|
52
|
+
|
53
|
+
def component_name
|
54
|
+
self.class.name.sub(/::Component$/, "").sub(/^Satis::/, "").underscore
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.add_helper(name, component)
|
58
|
+
if respond_to?(name)
|
59
|
+
Satis.config.logger.warn("Helper #{name} already defined, skipping.")
|
60
|
+
return
|
61
|
+
end
|
62
|
+
define_method(name) do |*args, **kwargs, &block|
|
63
|
+
original_args = args.dup
|
64
|
+
options = args.extract_options!
|
65
|
+
instance = if options.key? :variant
|
66
|
+
variant_component = component.to_s.sub(/::Component$/, "::#{options[:variant].to_s.camelize}::Component").safe_constantize
|
67
|
+
(variant_component || component).new(*original_args, **kwargs)
|
68
|
+
else
|
69
|
+
kwargs[component_name.to_sym] = self
|
70
|
+
component.new(*original_args, **kwargs)
|
71
|
+
end
|
72
|
+
original_view_context.render(instance, &block)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
49
76
|
end
|
50
77
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.sts-card.sts-tabs data-controller="satis-tabs" data-satis-tabs-persist-value="false"
|
1
|
+
.sts-card.sts-tabs data-controller="satis-tabs" data-satis-tabs-persist-value="false" data-satis-tabs-key-value="#{key}"
|
2
2
|
- if header?
|
3
3
|
.sts-card__header class="#{tabs? ? '' : 'border-b border-gray-200'} #{header_background_color[:light]} dark:#{header_background_color[:dark]}"
|
4
4
|
.-ml-4.-mt-4.flex.justify-between.items-center.flex-wrap.sm:flex-nowrap
|
@@ -33,19 +33,27 @@
|
|
33
33
|
option selected=tab.selected? = t(tab.name, scope: [:tabs])
|
34
34
|
.hidden.sm:block
|
35
35
|
nav.-mb-px.flex.space-x-8.overflow-x-auto aria-label="Tabs"
|
36
|
-
- tabs.
|
37
|
-
|
36
|
+
- tabs.each_with_index do |tab, index|
|
37
|
+
- id = tab.id.present? ? tab.id : tab.name
|
38
|
+
.flex
|
39
|
+
a.tab id="#{id}" class="#{index == (tab.selected_tab_index) ? 'selected' : ''}" href="#" aria-current="#{tab.selected? ? "page" : ''}" data-satis-tabs-target="tab" data-action="click->satis-tabs#select"
|
38
40
|
- if tab.icon
|
39
41
|
i.mr-2 class=tab.icon
|
40
|
-
=
|
42
|
+
span id="tab_label_#{tab.id}"
|
43
|
+
= t(tab.name, scope: [:tabs], default: tab.title || tab.name)
|
41
44
|
i.fal.fa-triangle-exclamation.ml-2.hidden
|
42
45
|
- if tab.badge
|
43
|
-
span.badge
|
46
|
+
span.badge id="tab_badge_#{tab.id}"
|
44
47
|
= tab.badge
|
48
|
+
- if tab.tab_menu
|
49
|
+
= render(Satis::Menu::Component.new(tab.tab_menu, icon: 'fa-thin fa-square-chevron-down'))
|
50
|
+
- if custom_tabs_link_html.present?
|
51
|
+
= custom_tabs_link_html
|
45
52
|
|
46
|
-
- tabs.
|
47
|
-
div id="#{tab.name}-content" class="tab-content #{tab.options[:padding] == true ? 'px-6 py-6' : ''}" data-satis-tabs-target="content"
|
53
|
+
- tabs.each_with_index do |tab, index|
|
54
|
+
div id="#{tab.name}-content" class="tab-content #{tab.options[:padding] == true ? 'px-6 py-6' : ''} #{index == (tab.selected_tab_index) ? 'selected' : ''}" data-satis-tabs-target="content"
|
48
55
|
= tab.to_s
|
56
|
+
|
49
57
|
- else
|
50
58
|
div class="#{content_padding ? 'px-6 py-6' : ''}"
|
51
59
|
= content
|
@@ -7,7 +7,7 @@ module Satis
|
|
7
7
|
renders_many :tabs, Tab::Component
|
8
8
|
renders_one :footer
|
9
9
|
|
10
|
-
attr_reader :icon, :title, :description, :menu, :content_padding, :header_background_color, :initial_actions
|
10
|
+
attr_reader :icon, :title, :description, :menu, :content_padding, :header_background_color, :initial_actions, :key, :custom_tabs_link_html
|
11
11
|
|
12
12
|
def initialize(icon: nil,
|
13
13
|
title: nil,
|
@@ -17,7 +17,8 @@ module Satis
|
|
17
17
|
header_background_color: {
|
18
18
|
dark: 'bg-gray-800', light: 'bg-white'
|
19
19
|
},
|
20
|
-
actions: []
|
20
|
+
actions: [],
|
21
|
+
key: nil)
|
21
22
|
super
|
22
23
|
@title = title
|
23
24
|
@title = @title.reject(&:blank?).compact.join(' ') if @title.is_a?(Array)
|
@@ -27,6 +28,12 @@ module Satis
|
|
27
28
|
@content_padding = content_padding
|
28
29
|
@header_background_color = header_background_color
|
29
30
|
@initial_actions = actions
|
31
|
+
@key = key
|
32
|
+
end
|
33
|
+
|
34
|
+
def custom_tabs_link(&block)
|
35
|
+
return unless block_given?
|
36
|
+
@custom_tabs_link_html = block.call.html_safe
|
30
37
|
end
|
31
38
|
|
32
39
|
def tabs?
|
@@ -27,8 +27,8 @@ module Satis
|
|
27
27
|
options[:input_html].delete(:autofocus)
|
28
28
|
end
|
29
29
|
|
30
|
-
actions =
|
31
|
-
'focus->satis-dropdown#focus'].join(' ')
|
30
|
+
actions = [options[:input_html]['data-action'], 'change->satis-dropdown#display',
|
31
|
+
'focus->satis-dropdown#focus'].join(' ') unless options[:input_html]['data-reflex']
|
32
32
|
|
33
33
|
options[:input_html].merge!('data-satis-dropdown-target' => 'hiddenInput',
|
34
34
|
'data-action' => actions)
|
@@ -184,6 +184,12 @@ export default class extends ApplicationController {
|
|
184
184
|
} else {
|
185
185
|
this.debouncedLocalResults(event)
|
186
186
|
}
|
187
|
+
|
188
|
+
if (this.searchInputTarget.value) {
|
189
|
+
this.searchInputTarget.closest(".bg-white").classList.add("warning")
|
190
|
+
} else {
|
191
|
+
this.searchInputTarget.closest(".bg-white").classList.remove("warning")
|
192
|
+
}
|
187
193
|
}
|
188
194
|
|
189
195
|
// User presses reset button
|
@@ -211,6 +217,10 @@ export default class extends ApplicationController {
|
|
211
217
|
event.preventDefault()
|
212
218
|
}
|
213
219
|
|
220
|
+
if (this.searchInputTarget.closest(".bg-white").classList.contains("warning")) {
|
221
|
+
this.searchInputTarget.closest(".bg-white").classList.remove("warning")
|
222
|
+
}
|
223
|
+
|
214
224
|
return false
|
215
225
|
}
|
216
226
|
|
@@ -245,6 +255,10 @@ export default class extends ApplicationController {
|
|
245
255
|
this.lastSearch = this.searchInputTarget.value
|
246
256
|
|
247
257
|
this.hiddenInputTarget.dispatchEvent(new Event("change"))
|
258
|
+
|
259
|
+
if (this.searchInputTarget.closest(".bg-white").classList.contains("warning")) {
|
260
|
+
this.searchInputTarget.closest(".bg-white").classList.remove("warning")
|
261
|
+
}
|
248
262
|
}
|
249
263
|
|
250
264
|
// --- Helpers
|
@@ -257,11 +271,17 @@ export default class extends ApplicationController {
|
|
257
271
|
this.searchInputTarget.value = currentItem.getAttribute("data-satis-dropdown-item-text")
|
258
272
|
|
259
273
|
Array.prototype.slice.call(currentItem.attributes).forEach((attr) => {
|
260
|
-
if (
|
274
|
+
if (
|
275
|
+
attr.name.startsWith("data") &&
|
276
|
+
!attr.name.startsWith("data-satis") &&
|
277
|
+
!attr.name.startsWith("data-action")
|
278
|
+
) {
|
261
279
|
this.hiddenInputTarget.setAttribute(attr.name, attr.value)
|
262
280
|
}
|
263
281
|
})
|
264
|
-
this.hiddenInputTarget.
|
282
|
+
if (!this.hiddenInputTarget.getAttribute("data-reflex")) {
|
283
|
+
this.hiddenInputTarget.dispatchEvent(new CustomEvent("change", { detail: { src: "satis-dropdown" } }))
|
284
|
+
}
|
265
285
|
}
|
266
286
|
}
|
267
287
|
|
@@ -362,7 +382,10 @@ export default class extends ApplicationController {
|
|
362
382
|
this.hiddenInputTarget.value = this.lastSearch
|
363
383
|
}
|
364
384
|
|
365
|
-
if (
|
385
|
+
if (
|
386
|
+
matches.length == 1 &&
|
387
|
+
matches[0].getAttribute("data-satis-dropdown-item-text").toLowerCase().indexOf(this.lastSearch.toLowerCase()) >= 0
|
388
|
+
) {
|
366
389
|
this.selectItem(matches[0].closest('[data-satis-dropdown-target="item"]'))
|
367
390
|
} else if (matches.length > 1) {
|
368
391
|
this.showResultsList(event)
|
@@ -372,7 +395,11 @@ export default class extends ApplicationController {
|
|
372
395
|
// Remote search
|
373
396
|
fetchResults(event) {
|
374
397
|
const promise = new Promise((resolve, reject) => {
|
375
|
-
if (
|
398
|
+
if (
|
399
|
+
(this.searchInputTarget.value == this.lastSearch &&
|
400
|
+
(this.currentPage == this.lastPage || this.currentPage == this.endPage)) ||
|
401
|
+
!this.hasUrlValue
|
402
|
+
) {
|
376
403
|
return
|
377
404
|
}
|
378
405
|
|
@@ -401,7 +428,13 @@ export default class extends ApplicationController {
|
|
401
428
|
this.highLightSelected()
|
402
429
|
this.showResultsList()
|
403
430
|
|
404
|
-
if (
|
431
|
+
if (
|
432
|
+
this.nrOfItems == 1 &&
|
433
|
+
this.itemTargets[0]
|
434
|
+
.getAttribute("data-satis-dropdown-item-text")
|
435
|
+
.toLowerCase()
|
436
|
+
.indexOf(this.searchInputTarget.value.toLowerCase()) >= 0
|
437
|
+
) {
|
405
438
|
this.selectItem(this.itemTargets[0].closest('[data-satis-dropdown-target="item"]'))
|
406
439
|
} else if (this.nrOfItems == 1) {
|
407
440
|
this.moveDown()
|
@@ -6,8 +6,8 @@ module Satis
|
|
6
6
|
attr_reader :classes
|
7
7
|
|
8
8
|
def initialize(classes: nil, colored: true)
|
9
|
-
@classes = classes ||
|
10
|
-
@classes +=
|
9
|
+
@classes = classes || ""
|
10
|
+
@classes += " colored" if colored
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -27,11 +27,11 @@ module Satis
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def input_class
|
30
|
-
[@options.fetch(:input_html, {}).fetch(:class,
|
30
|
+
[@options.fetch(:input_html, {}).fetch(:class, ""), "sts-input__input", form.has_error?(attribute) ? "is-invalid" : ""].join(" ")
|
31
31
|
end
|
32
32
|
|
33
33
|
def input_container_class
|
34
|
-
form.has_error?(attribute) &&
|
34
|
+
form.has_error?(attribute) && "is-invalid"
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -20,6 +20,14 @@
|
|
20
20
|
&:focus {
|
21
21
|
box-shadow: none;
|
22
22
|
}
|
23
|
+
|
24
|
+
&.white {
|
25
|
+
background: rgb(255, 255, 255);
|
26
|
+
|
27
|
+
.dark & {
|
28
|
+
background: rgba(255, 255, 255, 0.1);
|
29
|
+
}
|
30
|
+
}
|
23
31
|
}
|
24
32
|
|
25
33
|
&__element {
|
@@ -33,6 +41,14 @@
|
|
33
41
|
}
|
34
42
|
}
|
35
43
|
|
44
|
+
&.white {
|
45
|
+
background: rgb(255, 255, 255);
|
46
|
+
|
47
|
+
.dark & {
|
48
|
+
background: rgba(255, 255, 255, 0.1);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
36
52
|
input {
|
37
53
|
@apply -ml-3 -mr-3 -mt-2 -mb-2 w-full;
|
38
54
|
|
@@ -1,9 +1,9 @@
|
|
1
|
-
div data-controller="satis-menu" data-action="
|
1
|
+
div data-controller="satis-menu" data-action="#{menu.event}->satis-menu#show mouseleave->satis-menu#hide"
|
2
2
|
- if content
|
3
3
|
= content
|
4
4
|
- else
|
5
5
|
button.inline-flex.items-center.justify-center.h-8.w-8.rounded-full.focus:outline-none.focus:ring-2.focus:ring-offset-2.focus:ring-primary-500.dark:text-gray-500 aria-expanded="false" aria-haspopup="true" type="button"
|
6
|
-
span.font-semibold.flex-1 class="#{menu.items.present? ? '' : 'text-gray-200'}"
|
6
|
+
span.font-semibold.flex-1 id="#{icon_id}" class="#{menu.items.present? ? '' : 'text-gray-200'}"
|
7
7
|
i class=icon
|
8
8
|
|
9
9
|
- if menu.items.present?
|
@@ -4,12 +4,13 @@ module Satis
|
|
4
4
|
module Menu
|
5
5
|
class Component < Satis::ApplicationComponent
|
6
6
|
# renders_many :tabs, Tab::Component
|
7
|
-
attr_reader :menu, :icon
|
7
|
+
attr_reader :menu, :icon, :icon_id
|
8
8
|
|
9
|
-
def initialize(menu, icon: nil)
|
9
|
+
def initialize(menu, icon: nil, icon_id: nil)
|
10
10
|
super
|
11
11
|
@menu = menu
|
12
12
|
@icon = icon || 'fa-solid fa-ellipsis-vertical'
|
13
|
+
@icon_id = icon_id
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
li.rounded-sm.px-3.py-1.hover:bg-gray-100.dark:hover:bg-gray-200.flex.items-center data-controller="satis-menu" data-action="mouseover->satis-menu#show mouseleave->satis-menu#hide"
|
2
2
|
a.cursor-pointer.py-1.w-full.text-left.flex.items-center.outline-none.focus:outline-none href=item.link *item.link_attributes
|
3
|
+
- if item.type == :custom
|
4
|
+
= render(partial: item.link_attributes[:data][:path], locals: item.link_attributes[:data][:parameters])
|
3
5
|
span.pr-1.flex-shrink-0.w-6
|
4
6
|
- if item.icon.present?
|
5
7
|
i class=item.icon
|
6
|
-
span.pr-1.flex-1
|
8
|
+
span.pr-1.flex-1
|
9
|
+
- unless item.type == :custom
|
10
|
+
= item.label
|
7
11
|
span.pr-1.flex-shrink-0.w-6
|
8
12
|
- if item.type == :toggle
|
9
13
|
i.fal.fa-check.hidden data-satis-menu-target="toggle" id="#{item.id}"
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Satis
|
4
4
|
module Tab
|
5
5
|
class Component < Satis::ApplicationComponent
|
6
|
-
attr_reader :options, :name, :icon, :badge
|
6
|
+
attr_reader :options, :name, :icon, :badge, :id, :tab_menu, :selected_tab_index
|
7
7
|
|
8
8
|
def initialize(name, *args, &block)
|
9
9
|
super
|
@@ -11,8 +11,11 @@ module Satis
|
|
11
11
|
@options = args.extract_options!
|
12
12
|
@args = args
|
13
13
|
@icon = options[:icon]
|
14
|
+
@id = options[:id]
|
14
15
|
@badge = options[:badge]
|
16
|
+
@tab_menu = options[:tab_menu]
|
15
17
|
@block = block
|
18
|
+
@selected_tab_index = options[:selected_tab_index]
|
16
19
|
end
|
17
20
|
|
18
21
|
def responsive?
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.sts-tabs id="#{group}" data-controller="satis-tabs" data-satis-tabs-persist-value="#{persist}"
|
1
|
+
.sts-tabs id="#{group}" data-controller="satis-tabs" data-satis-tabs-persist-value="#{persist}" data-satis-tabs-key-value="#{key}"
|
2
2
|
.sm:hidden
|
3
3
|
label.sr-only for="tabs" Select a tab
|
4
4
|
select#tabs.block.w-full.pl-3.pr-10.py-2.text-base.border-gray-300.focus:outline-none.focus:ring-primary-500.focus:border-primary-500.sm:text-sm.rounded-md name="tabs" data-action="change->satis-tabs#select" data-satis-tabs-target="select"
|
@@ -20,4 +20,4 @@
|
|
20
20
|
div
|
21
21
|
- tabs.each do |tab|
|
22
22
|
div id="#{tab.name}-content" class="tab-content #{tab.options[:padding] == false ? '' : 'mt-4'}" data-satis-tabs-target="content"
|
23
|
-
= tab.to_s
|
23
|
+
= tab.to_s
|
@@ -4,12 +4,13 @@ module Satis
|
|
4
4
|
module Tabs
|
5
5
|
class Component < Satis::ApplicationComponent
|
6
6
|
renders_many :tabs, Tab::Component
|
7
|
-
attr_reader :group, :persist
|
7
|
+
attr_reader :group, :persist, :key
|
8
8
|
|
9
|
-
def initialize(group: :main, persist: false)
|
9
|
+
def initialize(group: :main, persist: false, key: nil)
|
10
10
|
super
|
11
11
|
@group = group
|
12
12
|
@persist = persist
|
13
|
+
@key = key
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -5,7 +5,7 @@ import ApplicationController from "../../../../frontend/controllers/application_
|
|
5
5
|
*/
|
6
6
|
export default class extends ApplicationController {
|
7
7
|
static targets = ["tab", "content", "select"]
|
8
|
-
static values = { persist: Boolean }
|
8
|
+
static values = { persist: Boolean, key: String }
|
9
9
|
|
10
10
|
static keyBindings = [
|
11
11
|
{
|
@@ -23,9 +23,6 @@ export default class extends ApplicationController {
|
|
23
23
|
connect() {
|
24
24
|
super.connect()
|
25
25
|
|
26
|
-
const ourUrl = new URL(window.location.href)
|
27
|
-
this.keyBase = ourUrl.pathname.substring(1, ourUrl.pathname.length).replace(/\//, "_") + "_tabs_" + this.context.scope.element.id
|
28
|
-
|
29
26
|
let firstErrorIndex
|
30
27
|
this.tabTargets.forEach((tab, index) => {
|
31
28
|
let hasErrors = this.contentTargets[index].querySelectorAll(".is-invalid")
|
@@ -37,7 +34,13 @@ export default class extends ApplicationController {
|
|
37
34
|
}
|
38
35
|
})
|
39
36
|
|
40
|
-
|
37
|
+
if (this.keyValue) {
|
38
|
+
this.getUserData(this.keyValue).then((data) => {
|
39
|
+
this.open(firstErrorIndex || data?.tab_index || 0)
|
40
|
+
})
|
41
|
+
} else {
|
42
|
+
this.open(firstErrorIndex || 0)
|
43
|
+
}
|
41
44
|
}
|
42
45
|
|
43
46
|
select(event) {
|
@@ -51,7 +54,12 @@ export default class extends ApplicationController {
|
|
51
54
|
})
|
52
55
|
}
|
53
56
|
this.open(index)
|
54
|
-
|
57
|
+
|
58
|
+
if (this.keyValue) {
|
59
|
+
this.setUserData(this.keyValue, { tab_index: index }).then((data) => {
|
60
|
+
//console.log(data)
|
61
|
+
})
|
62
|
+
}
|
55
63
|
|
56
64
|
// Cancel the this event (dont show the browser context menu)
|
57
65
|
event.preventDefault()
|
@@ -75,49 +83,5 @@ export default class extends ApplicationController {
|
|
75
83
|
this.selectTarget.selectedIndex = index
|
76
84
|
}
|
77
85
|
|
78
|
-
storeValue(key, value) {
|
79
|
-
if (!this.persistValue) {
|
80
|
-
return
|
81
|
-
}
|
82
|
-
|
83
|
-
if (typeof Storage !== "undefined") {
|
84
|
-
sessionStorage.setItem(this.keyBase + "_" + key, value)
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
getValue(key) {
|
89
|
-
if (!this.persistValue) {
|
90
|
-
return
|
91
|
-
}
|
92
|
-
|
93
|
-
if (typeof Storage !== "undefined") {
|
94
|
-
return sessionStorage.getItem(this.keyBase + "_" + key)
|
95
|
-
}
|
96
|
-
}
|
97
|
-
|
98
86
|
disconnect() {}
|
99
|
-
|
100
|
-
tabToOpen() {
|
101
|
-
let urlValue = this.getUrlVar(this.context.scope.element.id + "Tab")
|
102
|
-
|
103
|
-
if (typeof urlValue !== "undefined") {
|
104
|
-
return urlValue
|
105
|
-
}
|
106
|
-
|
107
|
-
return this.getValue("openTab") || 0
|
108
|
-
}
|
109
|
-
|
110
|
-
getUrlVar(name) {
|
111
|
-
return this.getUrlVars()[name]
|
112
|
-
}
|
113
|
-
|
114
|
-
getUrlVars() {
|
115
|
-
let vars = {}
|
116
|
-
|
117
|
-
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
|
118
|
-
vars[key] = value
|
119
|
-
})
|
120
|
-
|
121
|
-
return vars
|
122
|
-
}
|
123
87
|
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Satis
|
2
|
+
class UserDataController < ApplicationController
|
3
|
+
def show
|
4
|
+
key = request.url.split('/user_data/').last
|
5
|
+
data = Satis.config.current_user.user_data.keyed(key)
|
6
|
+
|
7
|
+
if data.id.present?
|
8
|
+
render json: data.data, status: 200
|
9
|
+
else
|
10
|
+
render json: {}, status: 404
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
key = request.url.split('/user_data/').last
|
16
|
+
data = Satis.config.current_user.user_data.keyed(key)
|
17
|
+
|
18
|
+
data.data = user_data_update_params.as_json
|
19
|
+
data.save!
|
20
|
+
|
21
|
+
render json: data.data, status: 200
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def user_data_update_params
|
27
|
+
params.require(:user_datum)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
class CreateSatisUserData < ActiveRecord::Migration[6.1]
|
2
|
+
def change
|
3
|
+
create_table :satis_user_data, id: :uuid do |t|
|
4
|
+
t.string :key, null: false
|
5
|
+
t.jsonb :data, null: false, default: {}
|
6
|
+
t.belongs_to :user, null: false, foreign_key: true, type: :uuid
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
add_index :satis_user_data, :key, unique: true
|
11
|
+
add_index :satis_user_data, :data, using: :gin
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class ChangeSatisUserData < ActiveRecord::Migration[7.0]
|
2
|
+
disable_ddl_transaction!
|
3
|
+
def change
|
4
|
+
safety_assured { change_column :satis_user_data, :data, :jsonb, null: true, default: {} }
|
5
|
+
safety_assured { change_column :satis_user_data, :user_id, :uuid, null: true, foreign_key: true }
|
6
|
+
|
7
|
+
remove_index :satis_user_data, [:key]
|
8
|
+
add_index :satis_user_data, [:user_id, :key], unique: true, algorithm: :concurrently
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'satisfied'
|
2
|
+
|
3
|
+
module Satis::ActiveRecordHelpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
delegate :satisfied?, to: :class
|
8
|
+
end
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def satisfied(options = {})
|
12
|
+
@_satis_satisfied_options = options
|
13
|
+
include Satis::Satisfied
|
14
|
+
end
|
15
|
+
|
16
|
+
def satisfied?
|
17
|
+
included_modules.include?(Satis::Satisfied)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/satis/configuration.rb
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
module Satis
|
4
4
|
class Configuration
|
5
5
|
attr_accessor :submit_on_enter, :confirm_before_leave
|
6
|
-
attr_writer :default_help_text
|
6
|
+
attr_writer :default_help_text, :current_user
|
7
7
|
attr_writer :logger
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@logger = Logger.new(STDOUT)
|
11
11
|
@submit_on_enter = true
|
12
12
|
@confirm_before_leave = false
|
13
|
+
@current_user = -> {}
|
13
14
|
|
14
15
|
@default_help_text = lambda do |_template, _object, key, _additional_scope|
|
15
16
|
scope = help_scope(template, object, additional_scope)
|
@@ -57,5 +58,11 @@ module Satis
|
|
57
58
|
|
58
59
|
actions.map { |action| help_scope(template, object, additional_scope, action: action) }
|
59
60
|
end
|
61
|
+
|
62
|
+
def current_user
|
63
|
+
raise 'current_user should be a Proc' unless @current_user.is_a? Proc
|
64
|
+
|
65
|
+
instance_exec(&@current_user)
|
66
|
+
end
|
60
67
|
end
|
61
68
|
end
|
data/lib/satis/engine.rb
CHANGED
@@ -23,5 +23,13 @@ module Satis
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
initializer :append_migrations do |app|
|
28
|
+
unless app.root.to_s.match? root.to_s
|
29
|
+
config.paths['db/migrate'].expanded.each do |expanded_path|
|
30
|
+
app.config.paths['db/migrate'] << expanded_path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
26
34
|
end
|
27
35
|
end
|
data/lib/satis/menus/menu.rb
CHANGED
@@ -3,13 +3,13 @@
|
|
3
3
|
module Satis
|
4
4
|
module Menus
|
5
5
|
class Menu
|
6
|
-
attr_reader :items, :level
|
7
|
-
|
6
|
+
attr_reader :items, :level, :event
|
8
7
|
def initialize(*args, **kwargs)
|
9
8
|
@options = args.extract_options!
|
10
9
|
@items = []
|
11
10
|
@scope = Array.wrap(args.first)
|
12
11
|
@level = kwargs[:level] || 0
|
12
|
+
@event = kwargs[:event] || 'mouseover'
|
13
13
|
yield self if block_given?
|
14
14
|
end
|
15
15
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Satis
|
4
|
+
module Satisfied
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def satisfied_options
|
9
|
+
@_satis_satisfied_options || {}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
included do
|
14
|
+
has_many :user_data, class_name: 'Satis::UserData'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/satis/version.rb
CHANGED
data/lib/satis.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'satis/version'
|
2
2
|
require 'satis/engine'
|
3
3
|
require 'satis/configuration'
|
4
|
+
require 'satis/active_record_helpers'
|
4
5
|
|
5
6
|
require 'view_component'
|
6
7
|
require 'browser'
|
@@ -32,5 +33,16 @@ module Satis
|
|
32
33
|
def add_helper(name, component)
|
33
34
|
Satis::Helpers::Container.add_helper(name, component)
|
34
35
|
end
|
36
|
+
|
37
|
+
def add_component_helper(component_name, name, component)
|
38
|
+
klass = "Satis::#{component_name.to_s.classify}::Component".safe_constantize
|
39
|
+
return if klass.blank?
|
40
|
+
klass.add_helper name, component
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Include helpers
|
45
|
+
ActiveSupport.on_load(:active_record) do
|
46
|
+
include Satis::ActiveRecordHelpers
|
35
47
|
end
|
36
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: satis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.68
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom de Grunt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: browser
|
@@ -164,14 +164,19 @@ files:
|
|
164
164
|
- app/components/satis/tabs/component.scss
|
165
165
|
- app/components/satis/tabs/component_controller.js
|
166
166
|
- app/controllers/satis/application_controller.rb
|
167
|
+
- app/controllers/satis/user_data_controller.rb
|
167
168
|
- app/helpers/satis/application_helper.rb
|
168
169
|
- app/jobs/satis/application_job.rb
|
169
170
|
- app/mailers/satis/application_mailer.rb
|
170
171
|
- app/models/satis/application_record.rb
|
172
|
+
- app/models/satis/user_data.rb
|
171
173
|
- app/views/shared/_fields_for.html.slim
|
172
174
|
- config/routes.rb
|
175
|
+
- db/migrate/20220929142147_create_satis_user_data.rb
|
176
|
+
- db/migrate/20221212083110_change_satis_user_data.rb
|
173
177
|
- lib/satis.rb
|
174
178
|
- lib/satis/action_controller_helpers.rb
|
179
|
+
- lib/satis/active_record_helpers.rb
|
175
180
|
- lib/satis/configuration.rb
|
176
181
|
- lib/satis/engine.rb
|
177
182
|
- lib/satis/forms/builder.rb
|
@@ -184,6 +189,7 @@ files:
|
|
184
189
|
- lib/satis/menus/builder.rb
|
185
190
|
- lib/satis/menus/item.rb
|
186
191
|
- lib/satis/menus/menu.rb
|
192
|
+
- lib/satis/satisfied.rb
|
187
193
|
- lib/satis/version.rb
|
188
194
|
- lib/tasks/satis_tasks.rake
|
189
195
|
homepage: https://github.com/entdec/satis
|