django-smartbase-admin 0.2.54__py3-none-any.whl → 1.0.42__py3-none-any.whl

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.
Files changed (184) hide show
  1. django_smartbase_admin/actions/admin_action_list.py +79 -38
  2. django_smartbase_admin/actions/advanced_filters.py +24 -1
  3. django_smartbase_admin/admin/admin_base.py +402 -97
  4. django_smartbase_admin/admin/site.py +93 -35
  5. django_smartbase_admin/admin/widgets.py +636 -26
  6. django_smartbase_admin/apps.py +2 -0
  7. django_smartbase_admin/engine/actions.py +34 -16
  8. django_smartbase_admin/engine/admin_base_view.py +252 -115
  9. django_smartbase_admin/engine/configuration.py +186 -4
  10. django_smartbase_admin/engine/const.py +6 -0
  11. django_smartbase_admin/engine/dashboard.py +49 -24
  12. django_smartbase_admin/engine/fake_inline.py +15 -11
  13. django_smartbase_admin/engine/field.py +42 -12
  14. django_smartbase_admin/engine/field_formatter.py +38 -14
  15. django_smartbase_admin/engine/filter_widgets.py +348 -24
  16. django_smartbase_admin/engine/menu_item.py +8 -5
  17. django_smartbase_admin/engine/modal_view.py +12 -7
  18. django_smartbase_admin/engine/request.py +2 -0
  19. django_smartbase_admin/integration/__init__.py +0 -0
  20. django_smartbase_admin/integration/django_cms.py +43 -0
  21. django_smartbase_admin/locale/sk/LC_MESSAGES/django.mo +0 -0
  22. django_smartbase_admin/locale/sk/LC_MESSAGES/django.po +268 -37
  23. django_smartbase_admin/migrations/0005_sbadminuserconfiguration.py +26 -0
  24. django_smartbase_admin/migrations/0006_alter_sbadminuserconfiguration_color_scheme.py +18 -0
  25. django_smartbase_admin/models.py +22 -0
  26. django_smartbase_admin/monkeypatch/admin_readonly_field_monkeypatch.py +96 -0
  27. django_smartbase_admin/monkeypatch/fake_inline_monkeypatch.py +1 -1
  28. django_smartbase_admin/querysets.py +3 -0
  29. django_smartbase_admin/services/configuration.py +30 -0
  30. django_smartbase_admin/services/thread_local.py +6 -19
  31. django_smartbase_admin/services/views.py +80 -13
  32. django_smartbase_admin/services/xlsx_export.py +6 -0
  33. django_smartbase_admin/static/sb_admin/build/tailwind.config.js +1 -0
  34. django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/colors.js +4 -0
  35. django_smartbase_admin/static/sb_admin/build/tailwind_config_partials/spacing.js +1 -0
  36. django_smartbase_admin/static/sb_admin/build/webpack.common.js +11 -8
  37. django_smartbase_admin/static/sb_admin/css/ckeditor/ckeditor_content_dark.css +208 -0
  38. django_smartbase_admin/static/sb_admin/css/coloris/coloris.min.css +1 -0
  39. django_smartbase_admin/static/sb_admin/dist/calendar.js +1 -0
  40. django_smartbase_admin/static/sb_admin/dist/calendar_style.css +1 -0
  41. django_smartbase_admin/static/sb_admin/dist/calendar_style.js +0 -0
  42. django_smartbase_admin/static/sb_admin/dist/chart.js +1 -1
  43. django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
  44. django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
  45. django_smartbase_admin/static/sb_admin/dist/table.js +1 -1
  46. django_smartbase_admin/static/sb_admin/dist/tree_widget.js +1 -0
  47. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.css +1 -0
  48. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.js +0 -0
  49. django_smartbase_admin/static/sb_admin/fancytree/jquery.fancytree-all-deps.min.js +1 -0
  50. django_smartbase_admin/static/sb_admin/images/file_types/file-csv.svg +11 -0
  51. django_smartbase_admin/static/sb_admin/images/file_types/file-doc.svg +11 -0
  52. django_smartbase_admin/static/sb_admin/images/file_types/file-docx.svg +11 -0
  53. django_smartbase_admin/static/sb_admin/images/file_types/file-other.svg +13 -0
  54. django_smartbase_admin/static/sb_admin/images/file_types/file-pdf.svg +11 -0
  55. django_smartbase_admin/static/sb_admin/images/file_types/file-ppt.svg +11 -0
  56. django_smartbase_admin/static/sb_admin/images/file_types/file-xls.svg +11 -0
  57. django_smartbase_admin/static/sb_admin/images/file_types/file-xlsx.svg +11 -0
  58. django_smartbase_admin/static/sb_admin/images/file_types/file-zip.svg +18 -0
  59. django_smartbase_admin/static/sb_admin/images/flags/de-at.png +0 -0
  60. django_smartbase_admin/static/sb_admin/images/flags/de-ch.png +0 -0
  61. django_smartbase_admin/static/sb_admin/images/logo_light.svg +21 -0
  62. django_smartbase_admin/static/sb_admin/js/coloris/coloris.min.js +6 -0
  63. django_smartbase_admin/static/sb_admin/js/fullcalendar.min.js +14804 -0
  64. django_smartbase_admin/static/sb_admin/js/sbadmin_prepopulated_fields_init.js +25 -0
  65. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Bolt-one.svg +3 -0
  66. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Calendar.svg +3 -0
  67. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Caution.svg +3 -0
  68. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Electric-drill.svg +3 -0
  69. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Fire-extinguisher.svg +3 -0
  70. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Gas.svg +3 -0
  71. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Lightning-fill.svg +3 -0
  72. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Moon.svg +3 -0
  73. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Phone-telephone.svg +3 -0
  74. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Printer.svg +3 -0
  75. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Pull.svg +3 -0
  76. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Sun-one.svg +3 -0
  77. django_smartbase_admin/static/sb_admin/sprites/sb_admin/Time.svg +3 -0
  78. django_smartbase_admin/static/sb_admin/src/css/_base.css +5 -1
  79. django_smartbase_admin/static/sb_admin/src/css/_colors.css +257 -82
  80. django_smartbase_admin/static/sb_admin/src/css/_components.css +61 -13
  81. django_smartbase_admin/static/sb_admin/src/css/_datepicker.css +8 -1
  82. django_smartbase_admin/static/sb_admin/src/css/_filer.css +60 -0
  83. django_smartbase_admin/static/sb_admin/src/css/_inlines.css +51 -10
  84. django_smartbase_admin/static/sb_admin/src/css/_tabulator.css +8 -2
  85. django_smartbase_admin/static/sb_admin/src/css/calendar.css +162 -0
  86. django_smartbase_admin/static/sb_admin/src/css/components/_button.css +41 -1
  87. django_smartbase_admin/static/sb_admin/src/css/components/_dropdown.css +31 -7
  88. django_smartbase_admin/static/sb_admin/src/css/components/_input.css +62 -20
  89. django_smartbase_admin/static/sb_admin/src/css/components/_modal.css +1 -1
  90. django_smartbase_admin/static/sb_admin/src/css/components/_query-builder.css +21 -2
  91. django_smartbase_admin/static/sb_admin/src/css/components/_toggle.css +12 -1
  92. django_smartbase_admin/static/sb_admin/src/css/components/_tooltip.css +8 -22
  93. django_smartbase_admin/static/sb_admin/src/css/style.css +17 -0
  94. django_smartbase_admin/static/sb_admin/src/css/tree_widget.css +411 -0
  95. django_smartbase_admin/static/sb_admin/src/js/autocomplete.js +69 -11
  96. django_smartbase_admin/static/sb_admin/src/js/calendar.js +56 -0
  97. django_smartbase_admin/static/sb_admin/src/js/chart.js +8 -22
  98. django_smartbase_admin/static/sb_admin/src/js/choices.js +18 -8
  99. django_smartbase_admin/static/sb_admin/src/js/datepicker.js +97 -336
  100. django_smartbase_admin/static/sb_admin/src/js/datepicker_plugins.js +357 -0
  101. django_smartbase_admin/static/sb_admin/src/js/main.js +306 -31
  102. django_smartbase_admin/static/sb_admin/src/js/multiselect.js +50 -41
  103. django_smartbase_admin/static/sb_admin/src/js/radio.js +31 -0
  104. django_smartbase_admin/static/sb_admin/src/js/range.js +3 -2
  105. django_smartbase_admin/static/sb_admin/src/js/table.js +34 -5
  106. django_smartbase_admin/static/sb_admin/src/js/table_modules/advanced_filter_module.js +43 -20
  107. django_smartbase_admin/static/sb_admin/src/js/table_modules/data_edit_module.js +8 -10
  108. django_smartbase_admin/static/sb_admin/src/js/table_modules/detail_view_module.js +50 -1
  109. django_smartbase_admin/static/sb_admin/src/js/table_modules/filter_module.js +10 -3
  110. django_smartbase_admin/static/sb_admin/src/js/table_modules/header_tabs_module.js +11 -11
  111. django_smartbase_admin/static/sb_admin/src/js/table_modules/selection_module.js +28 -8
  112. django_smartbase_admin/static/sb_admin/src/js/table_modules/table_params_module.js +6 -0
  113. django_smartbase_admin/static/sb_admin/src/js/table_modules/views_module.js +6 -0
  114. django_smartbase_admin/static/sb_admin/src/js/tree_widget.js +406 -0
  115. django_smartbase_admin/static/sb_admin/src/js/utils.js +56 -21
  116. django_smartbase_admin/templates/sb_admin/actions/change_form.html +176 -116
  117. django_smartbase_admin/templates/sb_admin/actions/dashboard.html +2 -2
  118. django_smartbase_admin/templates/sb_admin/actions/list.html +79 -39
  119. django_smartbase_admin/templates/sb_admin/actions/partials/action_link.html +14 -0
  120. django_smartbase_admin/templates/sb_admin/actions/partials/tabulator_header_v2.html +2 -2
  121. django_smartbase_admin/templates/sb_admin/actions/tree_list.html +63 -0
  122. django_smartbase_admin/templates/sb_admin/authentification/login_base.html +5 -1
  123. django_smartbase_admin/templates/sb_admin/components/columns.html +1 -1
  124. django_smartbase_admin/templates/sb_admin/components/filters.html +1 -0
  125. django_smartbase_admin/templates/sb_admin/components/filters_v2.html +99 -85
  126. django_smartbase_admin/templates/sb_admin/dashboard/calendar_widget.html +69 -0
  127. django_smartbase_admin/templates/sb_admin/dashboard/chart_widget.html +21 -2
  128. django_smartbase_admin/templates/sb_admin/dashboard/list_widget.html +6 -0
  129. django_smartbase_admin/templates/sb_admin/dashboard/widget_base.html +1 -1
  130. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/date_field.html +18 -8
  131. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/multiple_choice_field.html +1 -1
  132. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/tree_select_filter.html +2 -0
  133. django_smartbase_admin/templates/sb_admin/filter_widgets/boolean_field.html +1 -14
  134. django_smartbase_admin/templates/sb_admin/filter_widgets/date_field.html +18 -4
  135. django_smartbase_admin/templates/sb_admin/filter_widgets/multiple_choice_field.html +14 -0
  136. django_smartbase_admin/templates/sb_admin/filter_widgets/partials/clear.html +12 -6
  137. django_smartbase_admin/templates/sb_admin/filter_widgets/radio_choice_field.html +5 -3
  138. django_smartbase_admin/templates/sb_admin/filter_widgets/tree_select_filter.html +16 -0
  139. django_smartbase_admin/templates/sb_admin/includes/change_form_title.html +3 -1
  140. django_smartbase_admin/templates/sb_admin/includes/inline_fieldset.html +48 -39
  141. django_smartbase_admin/templates/sb_admin/includes/notifications.html +2 -1
  142. django_smartbase_admin/templates/sb_admin/includes/readonly_boolean_field.html +9 -0
  143. django_smartbase_admin/templates/sb_admin/includes/readonly_field.html +12 -0
  144. django_smartbase_admin/templates/sb_admin/includes/table_inline_delete_button.html +4 -5
  145. django_smartbase_admin/templates/sb_admin/inlines/stacked_inline.html +68 -40
  146. django_smartbase_admin/templates/sb_admin/inlines/table_inline.html +76 -34
  147. django_smartbase_admin/templates/sb_admin/integrations/filer/folder_list.html +18 -0
  148. django_smartbase_admin/templates/sb_admin/navigation.html +166 -158
  149. django_smartbase_admin/templates/sb_admin/partials/modal/modal_content.html +2 -6
  150. django_smartbase_admin/templates/sb_admin/sb_admin_base.html +49 -4
  151. django_smartbase_admin/templates/sb_admin/sb_admin_base_no_sidebar.html +27 -11
  152. django_smartbase_admin/templates/sb_admin/sb_admin_js_trans.html +3 -0
  153. django_smartbase_admin/templates/sb_admin/sprites/sb_admin.svg +1 -1
  154. django_smartbase_admin/templates/sb_admin/tailwind_whitelist.html +6 -3
  155. django_smartbase_admin/templates/sb_admin/widgets/array.html +0 -1
  156. django_smartbase_admin/templates/sb_admin/widgets/attributes.html +68 -0
  157. django_smartbase_admin/templates/sb_admin/widgets/autocomplete.html +13 -2
  158. django_smartbase_admin/templates/sb_admin/widgets/{checkbox_select.html → checkbox_dropdown.html} +2 -2
  159. django_smartbase_admin/templates/sb_admin/widgets/clearable_file_input.html +2 -2
  160. django_smartbase_admin/templates/sb_admin/widgets/color_field.html +30 -0
  161. django_smartbase_admin/templates/sb_admin/widgets/date.html +8 -1
  162. django_smartbase_admin/templates/sb_admin/widgets/filer_file.html +84 -0
  163. django_smartbase_admin/templates/sb_admin/widgets/includes/related_item_buttons.html +38 -0
  164. django_smartbase_admin/templates/sb_admin/widgets/multiwidget.html +1 -1
  165. django_smartbase_admin/templates/sb_admin/widgets/radio.html +3 -2
  166. django_smartbase_admin/templates/sb_admin/widgets/radio_dropdown.html +30 -0
  167. django_smartbase_admin/templates/sb_admin/widgets/read_only_password_hash.html +3 -0
  168. django_smartbase_admin/templates/sb_admin/widgets/time.html +8 -1
  169. django_smartbase_admin/templates/sb_admin/widgets/toggle.html +1 -1
  170. django_smartbase_admin/templates/sb_admin/widgets/tree_base.html +59 -0
  171. django_smartbase_admin/templates/sb_admin/widgets/tree_select.html +24 -0
  172. django_smartbase_admin/templates/sb_admin/widgets/tree_select_inline.html +12 -0
  173. django_smartbase_admin/templatetags/sb_admin_tags.py +115 -4
  174. django_smartbase_admin/utils.py +22 -3
  175. django_smartbase_admin/views/dashboard_view.py +6 -0
  176. django_smartbase_admin/views/global_filter_view.py +8 -2
  177. django_smartbase_admin/views/translations_view.py +12 -5
  178. django_smartbase_admin/views/user_config_view.py +52 -0
  179. django_smartbase_admin-1.0.42.dist-info/METADATA +166 -0
  180. {django_smartbase_admin-0.2.54.dist-info → django_smartbase_admin-1.0.42.dist-info}/RECORD +182 -118
  181. {django_smartbase_admin-0.2.54.dist-info → django_smartbase_admin-1.0.42.dist-info}/WHEEL +1 -1
  182. django_smartbase_admin/templates/sb_admin/integrations/sorting/change_list.html +0 -401
  183. django_smartbase_admin-0.2.54.dist-info/METADATA +0 -25
  184. {django_smartbase_admin-0.2.54.dist-info → django_smartbase_admin-1.0.42.dist-info}/LICENSE.md +0 -0
@@ -24,31 +24,16 @@ class SBAdminChart {
24
24
  }
25
25
 
26
26
  initChart() {
27
+ this.options.formId = this.options.formId || `${this.options.widgetId}-filter-form`
27
28
  const ctx = document.getElementById(`${this.options.widgetId}-chart`)
28
29
  this.chart = new Chart(ctx, {
29
30
  type: this.options.chartType,
30
31
  data: {},
31
- options: {
32
- scales: {
33
- x: {
34
- ticks: {
35
- font: {
36
- weight: 600,
37
- }
38
- }
39
- },
40
- y: {
41
- ticks: {
42
- font: {
43
- weight: 600,
44
- }
45
- }
46
- }
47
- }
48
- }
32
+ options: this.options.chartOptions || {},
33
+ plugins: this.options.chartPlugins || []
49
34
  })
50
35
  this.refreshData()
51
- document.addEventListener("SBAdminReloadTableData", () => {
36
+ document.addEventListener(window.sb_admin_const.TABLE_RELOAD_DATA_EVENT_NAME, () => {
52
37
  this.refreshData()
53
38
  })
54
39
  }
@@ -63,7 +48,7 @@ class SBAdminChart {
63
48
  }
64
49
 
65
50
  refreshData() {
66
- const filterForm = document.querySelector(`#${this.options.widgetId}-filter-form`)
51
+ const filterForm = document.getElementById(this.options.formId)
67
52
  const filterData = new FormData(filterForm).entries()
68
53
  const filterDataNotEmpty = {}
69
54
  for (const [key, value] of filterData) {
@@ -81,7 +66,7 @@ class SBAdminChart {
81
66
  .then(res => {
82
67
  this.chart.data.labels = res.data.main.labels
83
68
  this.chart.data.datasets = this.processDatasets(res.data.main.datasets)
84
- if (this.chart.data.labels.length > 1) {
69
+ if (this.chart.data.labels.length >= 1) {
85
70
  this.chart.canvas.classList.remove('!hidden')
86
71
  } else {
87
72
  this.chart.canvas.classList.add('!hidden')
@@ -112,11 +97,12 @@ class SBAdminChart {
112
97
  }
113
98
  })
114
99
  }
100
+ this.chart.canvas.dispatchEvent(new CustomEvent('chartDataLoaded'))
115
101
  })
116
102
  }
117
103
 
118
104
  initFilters() {
119
- filterInputValueChangeListener(`[form="${this.options.widgetId}-filter-form"]`, (event) => {
105
+ filterInputValueChangeListener(`[form="${this.options.formId}"]`, (event) => {
120
106
  this.refreshData()
121
107
  filterInputValueChangedUtil(event.target)
122
108
  })
@@ -49,16 +49,29 @@ export const choicesJSOptions = (choiceInput) => ({
49
49
  })
50
50
 
51
51
 
52
+ const getChoiceValueForInput = (currentValue) => {
53
+ let value = {
54
+ 'value': currentValue.value,
55
+ 'label': currentValue.label,
56
+ }
57
+ if(currentValue.customProperties?.create){
58
+ value['create'] = true
59
+ }
60
+ return value
61
+ }
62
+
52
63
  export const choicesJSListeners = {
64
+ 'selectItem': (item, inputEl) => {
65
+ if (!item) return
66
+ const choiceValue = [getChoiceValueForInput(item)]
67
+ inputEl.value = JSON.stringify(choiceValue)
68
+ },
53
69
  'addItem': (choicesJS, inputEl) => {
54
70
  const choiceValue = []
55
71
  let choicesJSValue = choicesJS.getValue()
56
72
  choicesJSValue = Array.isArray(choicesJSValue) ? choicesJSValue : [choicesJSValue]
57
73
  choicesJSValue.forEach(function (currentValue) {
58
- choiceValue.push({
59
- 'value': currentValue.value,
60
- 'label': currentValue.label,
61
- })
74
+ choiceValue.push(getChoiceValueForInput(currentValue))
62
75
  })
63
76
  inputEl.value = JSON.stringify(choiceValue)
64
77
  },
@@ -68,10 +81,7 @@ export const choicesJSListeners = {
68
81
  if (choicesJSValue !== undefined) {
69
82
  choicesJSValue = Array.isArray(choicesJSValue) ? choicesJSValue : [choicesJSValue]
70
83
  choicesJSValue.forEach(function (currentValue) {
71
- choiceValue.push({
72
- 'value': currentValue.value,
73
- 'label': currentValue.label,
74
- })
84
+ choiceValue.push(getChoiceValueForInput(currentValue))
75
85
  })
76
86
  }
77
87
  inputEl.value = JSON.stringify(choiceValue)
@@ -1,357 +1,133 @@
1
1
  import flatpickr from "flatpickr"
2
- import {monthToStr} from "flatpickr/dist/esm/utils/formatting"
3
2
  import {createIcon} from "./utils"
4
- // eslint-disable-next-line no-unused-vars
5
- const monthYearViewsPlugin = (fp) => {
6
- const customViewsWrapper = document.createElement('div')
7
- customViewsWrapper.classList.add('flatpickr-custom-views-wrapper')
3
+ import {
4
+ createRadioInput,
5
+ customActionsPlugin,
6
+ monthYearViewsPlugin
7
+ } from "./datepicker_plugins"
8
8
 
9
- const customMonthsView = document.createElement('div')
10
- customMonthsView.classList.add('flatpickr-custom-months-view', 'hidden')
11
9
 
12
- const customYearsView = document.createElement('div')
13
- customYearsView.classList.add('flatpickr-custom-years-view', 'hidden')
14
-
15
- customViewsWrapper.append(customMonthsView)
16
- customViewsWrapper.append(customYearsView)
17
-
18
- const yearElHeight = 48
19
- const yearScrollToElement = 106
20
-
21
- let currentYearEl = null
22
-
23
- const changeActiveView = (view) => {
24
- switch (view) {
25
- case 'months':
26
- customMonthsView.classList.remove('hidden')
27
- customYearsView.classList.add('hidden')
28
- break
29
- case 'years':
30
- customMonthsView.classList.add('hidden')
31
- customYearsView.classList.remove('hidden')
32
- currentYearEl.parentNode.scrollTop = yearElHeight * yearScrollToElement
33
- break
34
- default:
35
- customMonthsView.classList.add('hidden')
36
- customYearsView.classList.add('hidden')
37
- }
38
- }
39
-
40
- const selectMonth = (e) => {
41
- fp.changeMonth(parseInt(e.target.dataset.month), false)
42
- buildMonths()
43
- buildYears()
44
- changeActiveView()
45
- }
46
-
47
- const selectYear = (e) => {
48
- fp.changeYear(parseInt(e.target.dataset.year), false)
49
- buildMonths()
50
- buildYears()
51
- changeActiveView("months")
52
- }
53
-
54
- const yearInRange = (year, selectedYears) => {
55
- if (selectedYears[0] && selectedYears[1]) {
56
- return selectedYears[0] <= year && year <= selectedYears[1]
57
- }
58
- return selectedYears[0] === year
59
- }
60
-
61
- const monthInRange = (monthIndex, selectedMonths, selectedYears) => {
62
- //range
63
- if (selectedYears[0] && selectedYears[1]) {
64
- if (selectedYears[0] === selectedYears[1]) {
65
- if (selectedYears[0] === fp.currentYear) {
66
- return selectedMonths[0] <= monthIndex && monthIndex <= selectedMonths[1]
67
- }
68
- return false
69
- }
70
- if (selectedYears[0] === fp.currentYear && monthIndex >= selectedMonths[0]) {
71
- return true
72
- }
73
- if (selectedYears[0] < fp.currentYear && fp.currentYear < selectedYears[1]) {
74
- return true
75
- }
76
- if (selectedYears[1] === fp.currentYear && monthIndex <= selectedMonths[1]) {
77
- return true
78
- }
79
- return false
10
+ export default class Datepicker {
11
+ constructor(target) {
12
+ target = target || document
13
+ let documentLocale = document.documentElement.lang || 'default'
14
+ documentLocale = documentLocale.split('-')[0]
15
+ if (documentLocale === 'en') {
16
+ documentLocale = 'default'
80
17
  }
81
-
82
- //single value
83
- if (selectedYears[0] && !selectedYears[1]) {
84
- if (selectedYears[0] === fp.currentYear && monthIndex === selectedMonths[0]) {
85
- return true
86
- }
18
+ flatpickr.localize(this.getLocale(documentLocale))
19
+ this.initWidgets(target)
20
+ if(target === document) {
21
+ document.addEventListener('formset:added', (e) => {
22
+ this.initWidgets(e.target)
23
+ })
87
24
  }
88
-
89
- return false
90
25
  }
91
26
 
92
- const buildBackButton = (backToView) => {
93
- const back = document.createElement('div')
94
- back.classList.add('flatpickr-back')
95
- back.textContent = "Back"
96
- fp._bind(back, 'click', (e) => {
97
- e.preventDefault()
98
- e.stopPropagation()
99
- changeActiveView(backToView)
100
- })
101
- return back
27
+ getLocale(locale) {
28
+ // eslint-disable-next-line no-undef
29
+ const l = require(`flatpickr/dist/l10n/${locale}.js`)
30
+ return l.default[locale]
102
31
  }
103
32
 
104
- const buildMonths = () => {
105
- customMonthsView.innerHTML = ''
106
- const monthsHeader = fp.monthNav.cloneNode(true)
107
- const yearEl = monthsHeader.querySelector('.flatpickr-current-month')
108
- yearEl.innerHTML = fp.currentYear
109
- fp._bind(yearEl, 'click', () => {
110
- changeActiveView('years')
111
- })
112
-
113
- const prevYear = monthsHeader.querySelector('.flatpickr-prev-month')
114
- const nextYear = monthsHeader.querySelector('.flatpickr-next-month')
115
-
116
- prevYear.replaceChildren(createIcon('Left-small'))
117
- nextYear.replaceChildren(createIcon('Right-small'))
118
-
119
- fp._bind(prevYear, 'click', (e) => {
120
- e.preventDefault()
121
- e.stopPropagation()
122
- fp.changeYear(fp.currentYear - 1)
123
- buildMonths()
124
- buildYears()
125
- })
126
- fp._bind(nextYear, 'click', (e) => {
127
- e.preventDefault()
128
- e.stopPropagation()
129
- fp.changeYear(fp.currentYear + 1)
130
- buildMonths()
131
- buildYears()
132
- })
133
-
134
-
135
- const monthsContent = fp.innerContainer.cloneNode(true)
136
- monthsContent.querySelector('.flatpickr-weekdays').remove()
137
- const monthsContainer = monthsContent.querySelector('.dayContainer')
138
- monthsContainer.innerHTML = ''
139
-
140
- const selectedMonths = fp.selectedDates.map(date => {
141
- return date.getMonth()
142
- })
143
- const selectedYears = fp.selectedDates.map(date => {
144
- return date.getFullYear()
145
- })
146
-
147
- for (let i = 0; i < 12; i++) {
148
- const month = document.createElement('span')
149
- month.classList.add('flatpickr-day', 'flatpickr-month')
150
- if (i === fp.now.getMonth() && fp.currentYear === fp.now.getFullYear()) {
151
- month.classList.add('today')
152
- }
153
-
154
- if (monthInRange(i, selectedMonths, selectedYears)) {
155
- month.classList.add('selected')
156
- }
157
-
158
- month.textContent = monthToStr(i, fp.shorthand, fp.l10n)
159
- month.dataset.month = i.toString()
160
- month.addEventListener("click", selectMonth)
161
- monthsContainer.appendChild(month)
33
+ initFlatPickr(datePickerEl, options={}, optionsOverride={}) {
34
+ let sbadminDatepickerData = {}
35
+ if(datePickerEl.dataset.sbadminDatepicker) {
36
+ sbadminDatepickerData = JSON.parse(datePickerEl.dataset.sbadminDatepicker)
162
37
  }
163
38
 
164
- customMonthsView.append(monthsHeader)
165
- customMonthsView.append(monthsContent)
166
- customMonthsView.append(buildBackButton())
167
- }
168
-
169
- const buildYears = () => {
170
- customYearsView.innerHTML = ''
171
- const yearsHeader = fp.monthNav.cloneNode(true)
172
- const yearEl = yearsHeader.querySelector('.flatpickr-current-month')
173
- yearEl.innerHTML = fp.currentYear
174
-
175
- yearsHeader.querySelector('.flatpickr-prev-month').remove()
176
- yearsHeader.querySelector('.flatpickr-next-month').remove()
177
-
178
-
179
- const yearsContent = fp.innerContainer.cloneNode(true)
180
- yearsContent.querySelector('.flatpickr-weekdays').remove()
181
- yearsContent.querySelector('.flatpickr-days').classList.add('h-full', '-mr-8')
182
-
183
- const yearsContainer = yearsContent.querySelector('.dayContainer')
184
- yearsContainer.classList.add('overflow-auto', 'custom-scrollbar')
185
- yearsContainer.innerHTML = ''
186
-
187
- const currentYear = fp.now.getFullYear()
188
- const selectedYears = fp.selectedDates.map(date => {
189
- return date.getFullYear()
190
- })
39
+ flatpickr(datePickerEl, {
40
+ onReady: (selectedDates, dateStr, instance) => {
41
+ instance.nextMonthNav?.replaceChildren(createIcon('Right-small'))
42
+ instance.prevMonthNav?.replaceChildren(createIcon('Left-small'))
191
43
 
192
- for (let i = currentYear - 100; i <= currentYear + 100; i++) {
193
- const year = document.createElement('span')
194
- year.classList.add('flatpickr-day', 'flatpickr-year')
44
+ const isInTable = datePickerEl.closest('[data-filter-input-name]')
195
45
 
196
- if (i === fp.now.getFullYear()) {
197
- year.classList.add('today')
198
- currentYearEl = year
199
- }
200
-
201
- if (yearInRange(i, selectedYears)) {
202
- year.classList.add('selected')
203
- }
204
-
205
- year.textContent = i.toString()
206
- year.dataset.year = i.toString()
207
- year.addEventListener("click", selectYear)
208
- yearsContainer.appendChild(year)
209
- }
46
+ // real input element should be present only in filters
47
+ const realInput = document.getElementById(datePickerEl.dataset.sbadminDatepickerRealInputId)
48
+ const mainInput = realInput || datePickerEl
49
+ mainInput.addEventListener('clear', () => {
50
+ instance.clear()
51
+ })
210
52
 
211
- customYearsView.append(yearsHeader)
212
- customYearsView.append(yearsContent)
213
- customYearsView.append(buildBackButton("months"))
214
- }
215
53
 
216
- const replaceOriginalMonths = () => {
217
- const currentMonth = fp.monthNav.querySelector('.flatpickr-current-month')
218
- currentMonth.innerHTML = ''
219
- currentMonth.textContent = `${monthToStr(fp.currentMonth, fp.shorthand, fp.l10n)} ${fp.currentYear}`
220
- return currentMonth
221
- }
222
-
223
- const build = () => {
224
- fp.monthNav.parentNode.insertBefore(customViewsWrapper, fp.monthNav)
54
+ if(!isInTable){
55
+ this.createClear(instance)
56
+ }
225
57
 
226
- fp._bind(replaceOriginalMonths(), "click", (e) => {
227
- e.preventDefault()
228
- e.stopPropagation()
229
- changeActiveView('months')
58
+ if(isInTable && realInput) {
59
+ // set initial value from real input to flatpickr
60
+ realInput.addEventListener('SBTableFilterFormLoad', () => {
61
+ if(!datePickerEl.value) {
62
+ instance.setDate(realInput.value, false, instance.config.dateFormat)
63
+ }
64
+ })
65
+ return
66
+ }
67
+ if(realInput) {
68
+ // advanced filters
69
+ instance.setDate(realInput.value, false, instance.config.dateFormat)
70
+ }
71
+ },
72
+ onClose: function(selectedDates, dateStr, instance) {
73
+ // fix single day range
74
+ if(instance.config.mode === "range" && selectedDates.length === 1){
75
+ instance.setDate([selectedDates[0],selectedDates[0]], true)
76
+ }
77
+ },
78
+ onChange: function(selectedDates, dateStr) {
79
+ const realInput = document.getElementById(datePickerEl.dataset.sbadminDatepickerRealInputId)
80
+ if(realInput) {
81
+ realInput.value = dateStr
82
+ realInput.removeAttribute('data-label')
83
+ realInput.dispatchEvent(new Event('change'))
84
+ }
85
+ },
86
+ ...options,
87
+ ...sbadminDatepickerData.flatpickrOptions,
88
+ ...optionsOverride
230
89
  })
231
-
232
- buildMonths()
233
- buildYears()
234
- }
235
-
236
- return {
237
- onReady: build,
238
- onChange: [
239
- replaceOriginalMonths,
240
- buildMonths,
241
- buildYears,
242
- ],
243
- onMonthChange: replaceOriginalMonths,
244
- onYearChange: replaceOriginalMonths
245
- }
246
- }
247
-
248
- // eslint-disable-next-line no-unused-vars
249
- const customActionsPlugin = (fp) => {
250
-
251
- const dateFormat = 'd/m/Y'
252
- const createRadioInput = (id, name, value, label, checked) => {
253
- const inputWrapperEl = document.createElement('label')
254
- inputWrapperEl.classList.add('relative', 'block', 'px-12', 'py-8')
255
- inputWrapperEl.setAttribute('for', id)
256
- const labelEl = document.createElement('label')
257
- labelEl.innerText = label
258
- labelEl.setAttribute('for', id)
259
- const inputEl = document.createElement('input')
260
- inputEl.id = id
261
- inputEl.name = name
262
- inputEl.value = value
263
- inputEl.type = 'radio'
264
- inputEl.classList.add('radio')
265
- inputEl.checked = checked
266
- inputWrapperEl.append(inputEl)
267
- inputWrapperEl.append(labelEl)
268
- return inputWrapperEl
269
- }
270
-
271
- const dateTimeReviver = (key, value) => {
272
- if (key === 'value') {
273
- const newValue = []
274
- value.forEach((val) => {
275
- newValue.push(new Date(val))
276
- })
277
- return newValue
278
- }
279
- return value
280
90
  }
281
91
 
282
- const createShortcuts = () => {
283
- const baseId = fp.element.id
284
- const baseValue = fp.element.value
92
+ initShortcutsDropdown(datePickerEl) {
93
+ const realInput = document.getElementById(datePickerEl.dataset.sbadminDatepickerRealInputId)
94
+ const baseId = realInput.id
95
+ const baseValue = realInput.value
285
96
  const el = document.createElement('div')
286
- const shortcuts = JSON.parse(fp.element.dataset.sbadminDatepicker, dateTimeReviver).shortcuts
287
- el.classList.add('flatpickr-shortcuts')
97
+ const shortcuts = JSON.parse(datePickerEl.dataset.sbadminDatepickerShortcuts)
98
+ el.classList.add('flatpickr-shortcuts', 'dropdown-menu')
288
99
  el.addEventListener('change', (e) => {
289
- const value = e.target.value
290
- fp.setDate(shortcuts[value].value, true, dateFormat)
100
+ realInput.value = e.target.value
101
+ datePickerEl.value = e.target.nextElementSibling.innerText
291
102
  })
292
103
 
293
104
  shortcuts.forEach((shortcut, idx) => {
294
- const fromDateFormatted = fp.formatDate(shortcut.value[0], fp.config.dateFormat)
295
- const toDateFormatted = fp.formatDate(shortcut.value[1], fp.config.dateFormat)
296
- let shortcutValueStr
297
- if (fromDateFormatted === toDateFormatted) {
298
- shortcutValueStr = fromDateFormatted
299
- } else {
300
- shortcutValueStr = fromDateFormatted + fp.config.locale.rangeSeparator + toDateFormatted
105
+ const checked = JSON.stringify(shortcut.value) === baseValue
106
+ if(checked) {
107
+ datePickerEl.value = shortcut.label
301
108
  }
302
109
  el.append(createRadioInput(
303
110
  `${baseId}_range${idx}`,
304
111
  `${baseId}_shortcut`,
305
- idx,
112
+ JSON.stringify(shortcut.value),
306
113
  shortcut.label,
307
- baseValue === shortcutValueStr
114
+ checked,
115
+ idx
308
116
  ))
309
117
  })
310
- fp.calendarContainer.prepend(el)
311
- }
312
-
313
-
314
- return {
315
- onReady: createShortcuts,
316
- }
317
- }
318
-
319
-
320
- export default class Datepicker {
321
- constructor() {
322
- let documentLocale = document.documentElement.lang || 'default'
323
- if (documentLocale === 'en') {
324
- documentLocale = 'default'
325
- }
326
- flatpickr.localize(this.getLocale(documentLocale))
327
- this.initWidgets()
328
-
329
- document.addEventListener('formset:added', () => {
330
- this.initWidgets()
331
- })
332
- }
333
-
334
- getLocale(locale) {
335
- // eslint-disable-next-line no-undef
336
- const l = require(`flatpickr/dist/l10n/${locale}.js`)
337
- return l.default[locale]
118
+ datePickerEl.parentElement.append(el)
119
+ datePickerEl.readOnly = true
120
+ datePickerEl.dataset['bsToggle'] = "dropdown"
121
+ new window.bootstrap5.Dropdown(datePickerEl)
338
122
  }
339
123
 
340
124
  initWidgets(parentEl=null) {
341
125
  const datePickerSelector = {
342
126
  '.js-datepicker': {
343
- dateFormat: "d.m.Y",
344
- allowInput: true,
345
- plugins: [
346
- monthYearViewsPlugin,
347
- ]
348
- },
349
- '.js-datepicker-not-inline': {
350
- mode: "range",
351
127
  allowInput: true,
352
128
  plugins: [
353
129
  monthYearViewsPlugin,
354
- ]
130
+ ],
355
131
  },
356
132
  '.js-datepicker-range': {
357
133
  inline: true,
@@ -360,14 +136,14 @@ export default class Datepicker {
360
136
  plugins: [
361
137
  monthYearViewsPlugin,
362
138
  customActionsPlugin
363
- ]
139
+ ],
364
140
  },
365
141
  '.js-timepicker': {
366
142
  enableTime: true,
367
143
  noCalendar: true,
368
144
  dateFormat: "H:i",
369
145
  allowInput: true,
370
- time_24hr: true
146
+ time_24hr: true,
371
147
  },
372
148
  '.js-datetimepicker': {
373
149
  enableTime: true,
@@ -376,7 +152,7 @@ export default class Datepicker {
376
152
  time_24hr: true,
377
153
  plugins: [
378
154
  monthYearViewsPlugin,
379
- ]
155
+ ],
380
156
  }
381
157
  }
382
158
  if(!parentEl) {
@@ -384,26 +160,11 @@ export default class Datepicker {
384
160
  }
385
161
 
386
162
  Object.keys(datePickerSelector).forEach(selector => {
387
- parentEl.querySelectorAll(selector).forEach(datePickerEl => {
388
- let sbadminDatepickerData = {}
389
- if(datePickerEl.dataset.sbadminDatepicker) {
390
- sbadminDatepickerData = JSON.parse(datePickerEl.dataset.sbadminDatepicker)
163
+ parentEl.querySelectorAll(`${selector}:not([type="hidden"])`).forEach(datePickerEl => {
164
+ if(datePickerEl.closest('.djn-empty-form')){
165
+ return
391
166
  }
392
- flatpickr(datePickerEl, {
393
- onReady: (selectedDates, dateStr, instance) => {
394
- const isInTable = datePickerEl.closest('[data-filter-input-name]')
395
- if(!isInTable) {
396
- this.createClear(instance)
397
- }
398
- instance.nextMonthNav?.replaceChildren(createIcon('Right-small'))
399
- instance.prevMonthNav?.replaceChildren(createIcon('Left-small'))
400
- datePickerEl.addEventListener('clear', () => {
401
- instance.clear()
402
- })
403
- },
404
- ...datePickerSelector[selector],
405
- ...sbadminDatepickerData.flatpickrOptions
406
- })
167
+ this.initFlatPickr(datePickerEl, datePickerSelector[selector])
407
168
  })
408
169
  })
409
170
  }