avo 2.17.1.pre.2.customauthorizationclients → 2.17.1.pre.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of avo might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile.lock +6 -5
- data/app/components/avo/button_component.rb +2 -2
- data/app/components/avo/fields/common/single_file_viewer_component.html.erb +3 -3
- data/app/components/avo/fields/date_field/edit_component.html.erb +2 -0
- data/app/components/avo/fields/date_field/index_component.html.erb +1 -0
- data/app/components/avo/fields/date_field/show_component.html.erb +1 -0
- data/app/components/avo/fields/date_time_field/edit_component.html.erb +2 -0
- data/app/components/avo/fields/date_time_field/index_component.html.erb +1 -0
- data/app/components/avo/fields/date_time_field/show_component.html.erb +1 -0
- data/app/components/avo/fields/time_field/edit_component.html.erb +40 -0
- data/app/components/avo/fields/time_field/edit_component.rb +4 -0
- data/app/components/avo/fields/time_field/index_component.html.erb +15 -0
- data/app/components/avo/fields/time_field/index_component.rb +4 -0
- data/app/components/avo/fields/time_field/show_component.html.erb +15 -0
- data/app/components/avo/fields/time_field/show_component.rb +4 -0
- data/app/components/avo/index/resource_controls_component.html.erb +2 -2
- data/app/components/avo/panel_component.html.erb +2 -4
- data/app/components/avo/panel_component.rb +2 -4
- data/app/components/avo/sidebar_profile_component.html.erb +4 -1
- data/app/components/avo/tab_switcher_component.html.erb +1 -1
- data/app/components/avo/tab_switcher_component.rb +2 -0
- data/app/components/avo/views/resource_edit_component.html.erb +10 -12
- data/app/components/avo/views/resource_show_component.html.erb +21 -25
- data/app/controllers/avo/application_controller.rb +17 -9
- data/app/controllers/avo/associations_controller.rb +1 -1
- data/app/helpers/avo/application_helper.rb +4 -0
- data/app/javascript/js/controllers/fields/date_field_controller.js +61 -21
- data/app/javascript/js/controllers/search_controller.js +3 -0
- data/avo.gemspec +1 -1
- data/db/factories.rb +1 -0
- data/lib/avo/concerns/handles_field_args.rb +4 -0
- data/lib/avo/configuration.rb +0 -2
- data/lib/avo/fields/base_field.rb +5 -1
- data/lib/avo/fields/date_field.rb +2 -0
- data/lib/avo/fields/time_field.rb +55 -0
- data/lib/avo/services/authorization_service.rb +62 -43
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +0 -4
- data/lib/generators/avo/templates/initializer/avo.tt +0 -1
- data/lib/generators/avo/templates/locales/avo.nb.yml +1 -1
- data/lib/generators/avo/templates/locales/avo.nn.yml +7 -7
- data/public/avo-assets/avo.base.css +12 -6
- data/public/avo-assets/avo.base.js +64 -64
- data/public/avo-assets/avo.base.js.map +2 -2
- metadata +12 -6
- data/lib/avo/services/authorization_clients/pundit_client.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e373d0b7b292a05ed70462e7a20e78a2f7c559a94f7aca774cd68165e18d2c70
|
4
|
+
data.tar.gz: 545d0fb57feac7577871bceeb107eec82a22d3f8ea0fe50370e93083b4fa4667
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7854ba8a53232541ed1ae751099ccf40a339bc25ab85f6cd2e3fa28b7d958f7e480e4d53acea0110acd7167e710e3fdfef91104d567a796b832360c2ce699a46
|
7
|
+
data.tar.gz: d00ec57468d98d63e4e594d93e1eb3bce3bc4734eb65951805124511d2e45eabab646b4b9f16e6d0f458c76732e7cf64d00bfa828154ea92173483bcad174afe
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
avo (2.17.1.pre.
|
4
|
+
avo (2.17.1.pre.3)
|
5
5
|
active_link_to
|
6
6
|
addressable
|
7
7
|
breadcrumbs_on_rails
|
@@ -17,7 +17,7 @@ PATH
|
|
17
17
|
pundit
|
18
18
|
rails (>= 6.0)
|
19
19
|
turbo-rails
|
20
|
-
view_component
|
20
|
+
view_component
|
21
21
|
zeitwerk
|
22
22
|
|
23
23
|
GEM
|
@@ -265,7 +265,7 @@ GEM
|
|
265
265
|
net-protocol
|
266
266
|
timeout
|
267
267
|
nio4r (2.5.8)
|
268
|
-
nokogiri (1.13.
|
268
|
+
nokogiri (1.13.9)
|
269
269
|
mini_portile2 (~> 2.8.0)
|
270
270
|
racc (~> 1.4)
|
271
271
|
orm_adapter (0.5.0)
|
@@ -413,8 +413,9 @@ GEM
|
|
413
413
|
tzinfo (2.0.5)
|
414
414
|
concurrent-ruby (~> 1.0)
|
415
415
|
unicode-display_width (2.2.0)
|
416
|
-
view_component (2.
|
416
|
+
view_component (2.74.1)
|
417
417
|
activesupport (>= 5.0.0, < 8.0)
|
418
|
+
concurrent-ruby (~> 1.0)
|
418
419
|
method_source (~> 1.0)
|
419
420
|
warden (1.2.9)
|
420
421
|
rack (>= 2.0.9)
|
@@ -437,7 +438,7 @@ GEM
|
|
437
438
|
websocket-extensions (0.1.5)
|
438
439
|
xpath (3.2.0)
|
439
440
|
nokogiri (~> 1.8)
|
440
|
-
zeitwerk (2.6.
|
441
|
+
zeitwerk (2.6.1)
|
441
442
|
|
442
443
|
PLATFORMS
|
443
444
|
ruby
|
@@ -88,8 +88,8 @@ class Avo::ButtonComponent < ViewComponent::Base
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def output_button
|
91
|
-
if
|
92
|
-
button_to
|
91
|
+
if args.dig(:method).present? || args.dig(:data, :turbo_method).present?
|
92
|
+
button_to args[:url], **args do
|
93
93
|
full_content
|
94
94
|
end
|
95
95
|
else
|
@@ -36,15 +36,15 @@
|
|
36
36
|
<% if @resource.authorization.authorize_action(:delete_attachments?, raise_exception: false) %>
|
37
37
|
<%= a_link destroy_path,
|
38
38
|
icon: 'heroicons/outline/trash',
|
39
|
-
method: :delete,
|
40
39
|
color: :red,
|
41
40
|
compact: true,
|
42
41
|
size: :xs,
|
43
42
|
class: 'text-center',
|
44
43
|
title: t('avo.delete_file', item: file.filename),
|
45
44
|
data: {
|
46
|
-
|
47
|
-
|
45
|
+
turbo_method: :delete,
|
46
|
+
turbo_frame: 'destroy_attachment_form',
|
47
|
+
turbo_confirm: t('avo.are_you_sure'),
|
48
48
|
tippy: :tooltip
|
49
49
|
} %>
|
50
50
|
<% end %>
|
@@ -7,6 +7,8 @@
|
|
7
7
|
date_field_picker_format_value: @field.picker_format,
|
8
8
|
date_field_first_day_of_week_value: @field.first_day_of_week,
|
9
9
|
date_field_disable_mobile_value: @field.disable_mobile,
|
10
|
+
date_field_field_type_value: "date",
|
11
|
+
date_field_picker_options_value: @field.picker_options,
|
10
12
|
} do %>
|
11
13
|
<%= datetime_field "fake_#{@field.id}", "fake",
|
12
14
|
value: @field.edit_formatted_value,
|
@@ -8,6 +8,8 @@
|
|
8
8
|
date_field_disable_mobile_value: @field.disable_mobile,
|
9
9
|
date_field_time24_hr_value: @field.time_24hr,
|
10
10
|
date_field_timezone_value: @field.timezone,
|
11
|
+
date_field_field_type_value: "dateTime",
|
12
|
+
date_field_picker_options_value: @field.picker_options,
|
11
13
|
} do %>
|
12
14
|
<%= datetime_field "fake_#{@field.id}", "fake",
|
13
15
|
value: @field.edit_formatted_value,
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%= field_wrapper **field_wrapper_args do %>
|
2
|
+
<%= content_tag :div, data: {
|
3
|
+
controller: "date-field",
|
4
|
+
date_field_view_value: @view,
|
5
|
+
date_field_enable_time_value: true,
|
6
|
+
date_field_picker_format_value: @field.picker_format,
|
7
|
+
date_field_disable_mobile_value: @field.disable_mobile,
|
8
|
+
date_field_time24_hr_value: @field.time_24hr,
|
9
|
+
date_field_no_calendar_value: true,
|
10
|
+
date_field_timezone_value: @field.timezone,
|
11
|
+
date_field_relative_value: @field.relative,
|
12
|
+
date_field_field_type_value: "time",
|
13
|
+
date_field_picker_options_value: @field.picker_options,
|
14
|
+
} do %>
|
15
|
+
<%= datetime_field "fake_#{@field.id}", "fake",
|
16
|
+
value: @field.edit_formatted_value,
|
17
|
+
class: classes("w-full"),
|
18
|
+
data: {
|
19
|
+
'date-field-target': 'fakeInput',
|
20
|
+
placeholder: @field.placeholder,
|
21
|
+
**@field.get_html(:data, view: view, element: :input)
|
22
|
+
},
|
23
|
+
disabled: @field.is_readonly?,
|
24
|
+
placeholder: @field.placeholder,
|
25
|
+
style: @field.get_html(:style, view: view, element: :input)
|
26
|
+
%>
|
27
|
+
<%= @form.text_field @field.id,
|
28
|
+
value: @field.edit_formatted_value,
|
29
|
+
class: classes("w-full hidden"),
|
30
|
+
data: {
|
31
|
+
'date-field-target': 'input',
|
32
|
+
placeholder: @field.placeholder,
|
33
|
+
**@field.get_html(:data, view: view, element: :input)
|
34
|
+
},
|
35
|
+
disabled: @field.is_readonly?,
|
36
|
+
placeholder: @field.placeholder,
|
37
|
+
style: @field.get_html(:style, view: view, element: :input)
|
38
|
+
%>
|
39
|
+
<% end %>
|
40
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= index_field_wrapper **field_wrapper_args do %>
|
2
|
+
<%= content_tag :div, data: {
|
3
|
+
controller: "date-field",
|
4
|
+
date_field_view_value: @view,
|
5
|
+
date_field_enable_time_value: true,
|
6
|
+
date_field_format_value: @field.format,
|
7
|
+
date_field_timezone_value: @field.timezone,
|
8
|
+
date_field_picker_format_value: @field.picker_format,
|
9
|
+
date_field_no_calendar_value: true,
|
10
|
+
date_field_relative_value: @field.relative,
|
11
|
+
date_field_field_type_value: "time",
|
12
|
+
} do %>
|
13
|
+
<%= @field.formatted_value %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= field_wrapper **field_wrapper_args do %>
|
2
|
+
<%= content_tag :div, data: {
|
3
|
+
controller: "date-field",
|
4
|
+
date_field_view_value: @view,
|
5
|
+
date_field_enable_time_value: true,
|
6
|
+
date_field_format_value: @field.format,
|
7
|
+
date_field_timezone_value: @field.timezone,
|
8
|
+
date_field_picker_format_value: @field.picker_format,
|
9
|
+
date_field_no_calendar_value: true,
|
10
|
+
date_field_relative_value: @field.relative,
|
11
|
+
date_field_field_type_value: "time",
|
12
|
+
} do %>
|
13
|
+
<%= @field.formatted_value %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
@@ -42,7 +42,7 @@
|
|
42
42
|
type: :submit,
|
43
43
|
data: {
|
44
44
|
target: 'control:detach',
|
45
|
-
|
45
|
+
turbo_confirm: t('avo.are_you_sure_detach_item', item: singular_resource_name),
|
46
46
|
control: :detach,
|
47
47
|
'resource-id': @resource.model.id,
|
48
48
|
'tippy': 'tooltip',
|
@@ -66,7 +66,7 @@
|
|
66
66
|
type: :submit,
|
67
67
|
data: {
|
68
68
|
target: 'control:destroy',
|
69
|
-
|
69
|
+
turbo_confirm: t('avo.are_you_sure', item: singular_resource_name),
|
70
70
|
control: :destroy,
|
71
71
|
'resource-id': @resource.model.id,
|
72
72
|
'tippy': 'tooltip',
|
@@ -25,10 +25,8 @@
|
|
25
25
|
<% end %>
|
26
26
|
<% if body? %>
|
27
27
|
<div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:gap-4 w-full">
|
28
|
-
<div class="flex-1 overflow-auto <% if sidebar? %> w-2/3 <% end %>">
|
29
|
-
|
30
|
-
<%= body %>
|
31
|
-
</div>
|
28
|
+
<div class="relative flex-1 overflow-auto <%= white_panel_classes %> <%= @body_classes %> <% if sidebar? %> w-2/3 <% end %>">
|
29
|
+
<%= body %>
|
32
30
|
</div>
|
33
31
|
<% if sidebar? %>
|
34
32
|
<div class="w-full sm:w-1/3 flex-shrink-0 h-full <%= white_panel_classes %>">
|
@@ -5,6 +5,8 @@ class Avo::PanelComponent < ViewComponent::Base
|
|
5
5
|
attr_reader :name
|
6
6
|
attr_reader :classes
|
7
7
|
|
8
|
+
delegate :white_panel_classes, to: :helpers
|
9
|
+
|
8
10
|
renders_one :tools
|
9
11
|
renders_one :body
|
10
12
|
renders_one :sidebar
|
@@ -26,10 +28,6 @@ class Avo::PanelComponent < ViewComponent::Base
|
|
26
28
|
|
27
29
|
private
|
28
30
|
|
29
|
-
def white_panel_classes
|
30
|
-
"bg-white rounded shadow"
|
31
|
-
end
|
32
|
-
|
33
31
|
def data_attributes
|
34
32
|
@data.merge({"panel-index": @index})
|
35
33
|
end
|
@@ -37,8 +37,11 @@
|
|
37
37
|
<%# Example link below %>
|
38
38
|
<%#= render Avo::ProfileItemComponent.new label: 'Profile', path: '/profile', icon: 'user-circle' %>
|
39
39
|
<%= button_to helpers.main_app.send(destroy_user_session_path),
|
40
|
-
method: :delete,
|
41
40
|
form: { "data-turbo" => "false" },
|
41
|
+
method: :delete,
|
42
|
+
data: {
|
43
|
+
confirm: t('avo.are_you_sure')
|
44
|
+
},
|
42
45
|
class: "flex-1 flex items-center justify-center bg-white text-left cursor-pointer text-red-600 font-semibold hover:bg-red-100 block px-4 py-1 w-full py-3 text-center rounded w-full",
|
43
46
|
form_class: 'flex-1' do %>
|
44
47
|
<%= helpers.svg 'logout', class: 'h-4 mr-1' %> <%= t('avo.sign_out') %>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
</div>
|
21
21
|
</div>
|
22
22
|
<% else %>
|
23
|
-
<div class="flex flex-wrap gap-2
|
23
|
+
<div class="flex flex-wrap gap-2 p-2 <%= white_panel_classes %>" data-target="tab-switcher" data-style="pills">
|
24
24
|
<% visible_items.each do |tab| %>
|
25
25
|
<%= a_link tab_path(tab),
|
26
26
|
color: selected?(tab) ? :primary : :gray,
|
@@ -11,6 +11,8 @@ class Avo::TabSwitcherComponent < Avo::BaseComponent
|
|
11
11
|
attr_reader :view
|
12
12
|
attr_reader :style
|
13
13
|
|
14
|
+
delegate :white_panel_classes, to: :helpers
|
15
|
+
|
14
16
|
def initialize(resource:, group:, current_tab:, active_tab_name:, view:, style:)
|
15
17
|
@active_tab_name = active_tab_name
|
16
18
|
@resource = resource
|
@@ -25,18 +25,16 @@
|
|
25
25
|
<% end %>
|
26
26
|
<% if can_see_the_destroy_button? %>
|
27
27
|
<%= a_link destroy_path,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
'resource-id': @resource.model.id,
|
39
|
-
} do %>
|
28
|
+
style: :text,
|
29
|
+
color: :red,
|
30
|
+
icon: 'trash',
|
31
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
32
|
+
data: {
|
33
|
+
turbo_confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
34
|
+
turbo_method: :delete,
|
35
|
+
control: :destroy,
|
36
|
+
'resource-id': @resource.model.id,
|
37
|
+
} do %>
|
40
38
|
<%= t('avo.delete').capitalize %>
|
41
39
|
<% end %>
|
42
40
|
<% end %>
|
@@ -21,17 +21,15 @@
|
|
21
21
|
<% end %>
|
22
22
|
<% elsif control.delete_button? %>
|
23
23
|
<% if can_see_the_destroy_button? %>
|
24
|
-
<%=
|
25
|
-
method: :delete,
|
26
|
-
local: true,
|
24
|
+
<%= a_link helpers.resource_path(model: @resource.model, resource: @resource),
|
27
25
|
style: :text,
|
28
|
-
loading: true,
|
29
|
-
confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
30
26
|
color: :red,
|
31
27
|
icon: 'trash',
|
32
28
|
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
33
29
|
title: control.title,
|
34
30
|
data: {
|
31
|
+
turbo_confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
32
|
+
turbo_method: :delete,
|
35
33
|
control: :destroy,
|
36
34
|
tippy: control.title ? :tooltip : nil,
|
37
35
|
'resource-id': @resource.model.id,
|
@@ -84,13 +82,13 @@
|
|
84
82
|
<% elsif control.detach_button? %>
|
85
83
|
<% if @reflection.present? && @resource.model.present? && can_detach? %>
|
86
84
|
<%= a_button url: detach_path,
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
85
|
+
icon: 'detach',
|
86
|
+
method: :delete,
|
87
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
88
|
+
style: :text,
|
89
|
+
data: {
|
90
|
+
confirm: "Are you sure you want to detach this #{title}."
|
91
|
+
} do %>
|
94
92
|
<%= control.label %>
|
95
93
|
<% end %>
|
96
94
|
<% end %>
|
@@ -126,19 +124,17 @@
|
|
126
124
|
<%= t('avo.go_back') %>
|
127
125
|
<% end %>
|
128
126
|
<% if can_see_the_destroy_button? %>
|
129
|
-
<%=
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
'resource-id': @resource.model.id,
|
141
|
-
} do %>
|
127
|
+
<%= a_link destroy_path,
|
128
|
+
style: :text,
|
129
|
+
color: :red,
|
130
|
+
icon: 'trash',
|
131
|
+
form_class: 'flex flex-col sm:flex-row sm:inline-flex',
|
132
|
+
data: {
|
133
|
+
turbo_confirm: t('avo.are_you_sure', item: @resource.model.model_name.name.downcase),
|
134
|
+
turbo_method: :delete,
|
135
|
+
control: :destroy,
|
136
|
+
'resource-id': @resource.model.id,
|
137
|
+
} do %>
|
142
138
|
<%= t('avo.delete').capitalize %>
|
143
139
|
<% end %>
|
144
140
|
<% end %>
|
@@ -1,5 +1,11 @@
|
|
1
1
|
module Avo
|
2
2
|
class ApplicationController < ::ActionController::Base
|
3
|
+
if defined?(Pundit::Authorization)
|
4
|
+
include Pundit::Authorization
|
5
|
+
else
|
6
|
+
include Pundit
|
7
|
+
end
|
8
|
+
|
3
9
|
include Pagy::Backend
|
4
10
|
include Avo::ApplicationHelper
|
5
11
|
include Avo::UrlHelpers
|
@@ -18,7 +24,7 @@ module Avo
|
|
18
24
|
before_action :set_view
|
19
25
|
before_action :set_sidebar_open
|
20
26
|
|
21
|
-
rescue_from
|
27
|
+
rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
|
22
28
|
rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
|
23
29
|
|
24
30
|
helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path, :turbo_frame_request?, :resource_view_path
|
@@ -251,16 +257,18 @@ module Avo
|
|
251
257
|
instance_eval(&Avo.configuration.authenticate)
|
252
258
|
end
|
253
259
|
|
254
|
-
def render_unauthorized(
|
255
|
-
|
260
|
+
def render_unauthorized(exception)
|
261
|
+
if !exception.is_a? Pundit::NotDefinedError
|
262
|
+
flash.now[:notice] = t "avo.not_authorized"
|
256
263
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
264
|
+
redirect_url = if request.referrer.blank? || (request.referrer == request.url)
|
265
|
+
root_url
|
266
|
+
else
|
267
|
+
request.referrer
|
268
|
+
end
|
262
269
|
|
263
|
-
|
270
|
+
redirect_to(redirect_url)
|
271
|
+
end
|
264
272
|
end
|
265
273
|
|
266
274
|
def set_authorization
|
@@ -157,7 +157,7 @@ module Avo
|
|
157
157
|
private
|
158
158
|
|
159
159
|
def set_related_authorization
|
160
|
-
@
|
160
|
+
@authorization = if related_resource
|
161
161
|
related_resource.authorization(user: _current_user)
|
162
162
|
else
|
163
163
|
Services::AuthorizationService.new _current_user
|
@@ -7,6 +7,9 @@ function universalTimestamp(timestampStr) {
|
|
7
7
|
return new Date(new Date(timestampStr).getTime() + (new Date(timestampStr).getTimezoneOffset() * 60 * 1000))
|
8
8
|
}
|
9
9
|
|
10
|
+
const RAW_DATE_FORMAT = 'y/LL/dd'
|
11
|
+
const RAW_TIME_FORMAT = 'TT'
|
12
|
+
|
10
13
|
export default class extends Controller {
|
11
14
|
static targets = ['input', 'fakeInput']
|
12
15
|
|
@@ -19,6 +22,10 @@ export default class extends Controller {
|
|
19
22
|
firstDayOfWeek: Number,
|
20
23
|
time24Hr: Boolean,
|
21
24
|
disableMobile: Boolean,
|
25
|
+
noCalendar: Boolean,
|
26
|
+
relative: Boolean,
|
27
|
+
fieldType: { type: String, default: 'dateTime' },
|
28
|
+
pickerOptions: { type: Object, default: {} },
|
22
29
|
}
|
23
30
|
|
24
31
|
flatpickrInstance;
|
@@ -90,8 +97,8 @@ export default class extends Controller {
|
|
90
97
|
initShow() {
|
91
98
|
let value = this.parsedValue
|
92
99
|
|
93
|
-
// Set the zone only if the type of field is date time.
|
94
|
-
if (this.enableTimeValue) {
|
100
|
+
// Set the zone only if the type of field is date time or relative time.
|
101
|
+
if (this.enableTimeValue && this.relativeValue) {
|
95
102
|
value = value.setZone(this.displayTimezone)
|
96
103
|
}
|
97
104
|
|
@@ -109,6 +116,8 @@ export default class extends Controller {
|
|
109
116
|
},
|
110
117
|
altInput: true,
|
111
118
|
onChange: this.onChange.bind(this),
|
119
|
+
noCalendar: false,
|
120
|
+
...this.pickerOptionsValue,
|
112
121
|
}
|
113
122
|
|
114
123
|
// Set the format of the displayed input field.
|
@@ -124,24 +133,45 @@ export default class extends Controller {
|
|
124
133
|
options.enableTime = this.enableTimeValue
|
125
134
|
options.enableSeconds = this.enableTimeValue
|
126
135
|
|
127
|
-
//
|
128
|
-
|
129
|
-
options.defaultDate = this.parsedValue.setZone(this.displayTimezone).toISO()
|
136
|
+
// Hide calendar and only keep time picker.
|
137
|
+
options.noCalendar = this.noCalendarValue
|
130
138
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
139
|
+
if (this.initialValue) {
|
140
|
+
// Enable timezone display
|
141
|
+
if (this.enableTimeValue && this.relativeValue) {
|
142
|
+
options.defaultDate = this.parsedValue.setZone(this.displayTimezone).toISO()
|
143
|
+
|
144
|
+
options.dateFormat = 'Y-m-d H:i:S'
|
145
|
+
} else {
|
146
|
+
// Because the browser treats the date like a timestamp and updates it at 00:00 hour, when on a western timezone the date will be converted with one day offset.
|
147
|
+
// Ex: 2022-01-30 will render as 2022-01-29 on an American timezone
|
148
|
+
options.defaultDate = universalTimestamp(this.initialValue)
|
149
|
+
}
|
136
150
|
}
|
137
151
|
|
138
152
|
this.flatpickrInstance = flatpickr(this.fakeInputTarget, options)
|
139
153
|
|
140
|
-
if
|
141
|
-
|
142
|
-
|
143
|
-
this.updateRealInput(universalTimestamp(this.initialValue))
|
154
|
+
// Don't try to parse the value if the input is empty.
|
155
|
+
if (!this.initialValue) {
|
156
|
+
return
|
144
157
|
}
|
158
|
+
|
159
|
+
let value
|
160
|
+
switch (this.fieldTypeValue) {
|
161
|
+
case 'time':
|
162
|
+
// For time values, we should maintain the real value and format it to a time-friendly format.
|
163
|
+
value = this.parsedValue.setZone(this.displayTimezone, { keepLocalTime: true }).toFormat(RAW_TIME_FORMAT)
|
164
|
+
break
|
165
|
+
case 'date':
|
166
|
+
value = DateTime.fromJSDate(universalTimestamp(this.initialValue)).toFormat(RAW_DATE_FORMAT)
|
167
|
+
break
|
168
|
+
default:
|
169
|
+
case 'dateTime':
|
170
|
+
value = this.parsedValue.setZone(this.displayTimezone).toISO()
|
171
|
+
break
|
172
|
+
}
|
173
|
+
|
174
|
+
this.updateRealInput(value)
|
145
175
|
}
|
146
176
|
|
147
177
|
onChange(selectedDates) {
|
@@ -152,24 +182,34 @@ export default class extends Controller {
|
|
152
182
|
return
|
153
183
|
}
|
154
184
|
|
155
|
-
let time
|
156
185
|
let args = {}
|
157
186
|
|
158
|
-
|
187
|
+
// For values that involve time we should keep the local time.
|
188
|
+
if (this.timezoneValue || !this.relativeValue) {
|
159
189
|
args = { keepLocalTime: true }
|
160
190
|
} else {
|
161
191
|
args = { keepLocalTime: false }
|
162
192
|
}
|
163
193
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
194
|
+
let value
|
195
|
+
switch (this.fieldTypeValue) {
|
196
|
+
case 'time':
|
197
|
+
// For time values, we should maintain the real value and format it to a time-friendly format.
|
198
|
+
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', args).toFormat(RAW_TIME_FORMAT)
|
199
|
+
break
|
200
|
+
case 'date':
|
201
|
+
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', { keepLocalTime: true }).toFormat(RAW_DATE_FORMAT)
|
202
|
+
break
|
203
|
+
default:
|
204
|
+
case 'dateTime':
|
205
|
+
value = DateTime.fromISO(selectedDates[0].toISOString()).setZone('UTC', args).toISO()
|
206
|
+
break
|
168
207
|
}
|
169
208
|
|
170
|
-
this.updateRealInput(
|
209
|
+
this.updateRealInput(value)
|
171
210
|
}
|
172
211
|
|
212
|
+
// Value should be a string
|
173
213
|
updateRealInput(value) {
|
174
214
|
this.inputTarget.value = value
|
175
215
|
}
|
@@ -73,6 +73,9 @@ export default class extends Controller {
|
|
73
73
|
Mousetrap.bind(['command+k', 'ctrl+k'], () => this.showSearchPanel())
|
74
74
|
}
|
75
75
|
|
76
|
+
// This line fixes a bug where the search box would be duplicated on back navigation.
|
77
|
+
this.autocompleteTarget.innerHTML = ''
|
78
|
+
|
76
79
|
autocomplete({
|
77
80
|
container: this.autocompleteTarget,
|
78
81
|
placeholder: this.translationKeys.placeholder,
|