django-smartbase-admin 0.2.91__py3-none-any.whl → 0.2.93__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 (41) hide show
  1. django_smartbase_admin/actions/admin_action_list.py +0 -6
  2. django_smartbase_admin/admin/admin_base.py +1 -0
  3. django_smartbase_admin/admin/widgets.py +70 -0
  4. django_smartbase_admin/engine/admin_base_view.py +4 -1
  5. django_smartbase_admin/engine/filter_widgets.py +182 -1
  6. django_smartbase_admin/locale/sk/LC_MESSAGES/django.mo +0 -0
  7. django_smartbase_admin/locale/sk/LC_MESSAGES/django.po +241 -28
  8. django_smartbase_admin/services/views.py +2 -2
  9. django_smartbase_admin/static/sb_admin/build/webpack.common.js +9 -8
  10. django_smartbase_admin/static/sb_admin/dist/main.js +1 -1
  11. django_smartbase_admin/static/sb_admin/dist/main_style.css +1 -1
  12. django_smartbase_admin/static/sb_admin/dist/table.js +1 -1
  13. django_smartbase_admin/static/sb_admin/dist/tree_widget.js +1 -0
  14. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.css +1 -0
  15. django_smartbase_admin/static/sb_admin/dist/tree_widget_style.js +0 -0
  16. django_smartbase_admin/static/sb_admin/fancytree/jquery.fancytree-all-deps.min.js +2 -0
  17. django_smartbase_admin/static/sb_admin/src/css/_base.css +4 -0
  18. django_smartbase_admin/static/sb_admin/src/css/_inlines.css +3 -3
  19. django_smartbase_admin/static/sb_admin/src/css/_tabulator.css +6 -0
  20. django_smartbase_admin/static/sb_admin/src/css/components/_toggle.css +2 -1
  21. django_smartbase_admin/static/sb_admin/src/css/tree_widget.css +405 -0
  22. django_smartbase_admin/static/sb_admin/src/js/datepicker.js +1 -0
  23. django_smartbase_admin/static/sb_admin/src/js/table.js +18 -2
  24. django_smartbase_admin/static/sb_admin/src/js/table_modules/filter_module.js +3 -1
  25. django_smartbase_admin/static/sb_admin/src/js/table_modules/selection_module.js +20 -2
  26. django_smartbase_admin/static/sb_admin/src/js/table_modules/table_params_module.js +6 -0
  27. django_smartbase_admin/static/sb_admin/src/js/tree_widget.js +376 -0
  28. django_smartbase_admin/templates/sb_admin/actions/tree_list.html +63 -0
  29. django_smartbase_admin/templates/sb_admin/components/columns.html +1 -1
  30. django_smartbase_admin/templates/sb_admin/filter_widgets/advanced_filters/tree_select_filter.html +2 -0
  31. django_smartbase_admin/templates/sb_admin/filter_widgets/tree_select_filter.html +16 -0
  32. django_smartbase_admin/templates/sb_admin/sb_admin_base_no_sidebar.html +7 -5
  33. django_smartbase_admin/templates/sb_admin/sb_admin_js_trans.html +1 -0
  34. django_smartbase_admin/templates/sb_admin/widgets/filer_file.html +1 -1
  35. django_smartbase_admin/templates/sb_admin/widgets/tree_base.html +54 -0
  36. django_smartbase_admin/templates/sb_admin/widgets/tree_select.html +24 -0
  37. django_smartbase_admin/templates/sb_admin/widgets/tree_select_inline.html +12 -0
  38. {django_smartbase_admin-0.2.91.dist-info → django_smartbase_admin-0.2.93.dist-info}/METADATA +1 -1
  39. {django_smartbase_admin-0.2.91.dist-info → django_smartbase_admin-0.2.93.dist-info}/RECORD +41 -29
  40. {django_smartbase_admin-0.2.91.dist-info → django_smartbase_admin-0.2.93.dist-info}/LICENSE.md +0 -0
  41. {django_smartbase_admin-0.2.91.dist-info → django_smartbase_admin-0.2.93.dist-info}/WHEEL +0 -0
@@ -0,0 +1,376 @@
1
+ const loadValue = function ($inputEl, treeWidgetData, treeInstance) {
2
+ let value = $inputEl.val()
3
+ if (value !== undefined) {
4
+ treeInstance.selectAll(false)
5
+ }
6
+
7
+ let selectedKeys = [value]
8
+ if (treeWidgetData.filter === true) {
9
+ let selectedData = []
10
+ selectedKeys = []
11
+ try {
12
+ selectedData = JSON.parse(value)
13
+ } catch(e) {
14
+ selectedData = []
15
+ }
16
+ finally {
17
+ selectedData.forEach(function (item) {
18
+ selectedKeys.push(item.value)
19
+ })
20
+ }
21
+ } else if (treeWidgetData.multiselect === 2) {
22
+ try {
23
+ selectedKeys = JSON.parse(value)
24
+ } catch (e) {
25
+ selectedKeys = []
26
+ }
27
+ }
28
+ selectedKeys.forEach(function (key) {
29
+ let selectedNode = treeInstance.getNodeByKey(key)
30
+ if (selectedNode) {
31
+ selectedNode.getParentList().forEach(function (node) {
32
+ // Expand all parents of selected node
33
+ node.setExpanded(true)
34
+ })
35
+ selectedNode.setSelected(true)
36
+ }
37
+ })
38
+ }
39
+
40
+
41
+ 'use strict'
42
+ {
43
+ $(function () {
44
+ const initTree = function ($treeEl) {
45
+ if ($treeEl.hasClass('fancytree-container')) {
46
+ return
47
+ }
48
+ $treeEl.on('change', (e) => {
49
+ const changeTarget = e.target.dataset['changeTarget']
50
+ if(changeTarget) {
51
+ const changeTargetEl = document.querySelector(changeTarget)
52
+ if(changeTargetEl) {
53
+ changeTargetEl.value = e.target.value
54
+ }
55
+ }
56
+ })
57
+ let filterData = {}
58
+ const filterByTableData = (treeInstance) => {
59
+ if(!filterData["isFiltered"]) {
60
+ treeInstance.filterNodes((node) => {
61
+ node.setExpanded(false)
62
+ return true
63
+ }, { autoExpand: false })
64
+ return
65
+ }
66
+
67
+ const tableData = {}
68
+ filterData['data'].forEach(item => tableData[item.path] = item)
69
+
70
+ treeInstance.filterNodes((node) => {
71
+ if(tableData[node.key]) {
72
+ return true
73
+ }
74
+ }, { autoExpand: true })
75
+ }
76
+
77
+ const $treeDataEl = $('#' + $treeEl.data('tree-data-id'))
78
+ const $treeAdditionalColumnsDataEl = $('#' + $treeEl.data('tree-additional-columns-id'))
79
+ const $treeStringsDataEl = $('#' + $treeEl.data('tree-strings-id'))
80
+ let treeWidgetData = {}
81
+ let additionalColumns = []
82
+ let treeStrings = {loading: "Loading...", loadError: "Load error!", moreData: "More...", noData: "No data."}
83
+ try {
84
+ treeWidgetData = JSON.parse($treeDataEl.text()) || {}
85
+ additionalColumns = JSON.parse($treeAdditionalColumnsDataEl.text()) || []
86
+ treeStrings = JSON.parse($treeStringsDataEl.text())
87
+ } catch (e) {
88
+ console.error(e)
89
+ }
90
+ const $inputEl = $('#' + treeWidgetData.input_id)
91
+ const $searchEl = $('#' + treeWidgetData.input_id + '_search')
92
+ const $matchesEl = $('#' + treeWidgetData.input_id + '_matches')
93
+ const $label = $('#' + treeWidgetData.input_id + '_label')
94
+ const tableConfig = {
95
+ indentation: 32,
96
+ nodeColumnIdx: 0,
97
+ }
98
+ if (treeWidgetData.checkbox) {
99
+ tableConfig.checkboxColumnIdx = 0
100
+ tableConfig.nodeColumnIdx = 1
101
+ }
102
+ let extensions = ["table", "gridnav", "filter"]
103
+ if (treeWidgetData.reorder_url) {
104
+ extensions.push("dnd5")
105
+ }
106
+ $treeEl.fancytree({
107
+ source: {
108
+ url: treeWidgetData.data_url,
109
+ },
110
+ extensions: extensions,
111
+ checkbox: treeWidgetData.checkbox,
112
+ selectMode: treeWidgetData.multiselect,
113
+ dnd5: {
114
+ preventVoidMoves: true,
115
+ preventRecursion: true,
116
+ autoExpandMS: 400,
117
+ dropMarkerParent: '.tree-list-view',
118
+ dropMarkerOffsetX: -8,
119
+ dropMarkerInsertOffsetX: 0,
120
+ dragStart: function () {
121
+ return true
122
+ },
123
+ dragEnter: function () {
124
+ return true
125
+ },
126
+ dragDrop: function (node, data) {
127
+ data.otherNode.moveTo(node, data.hitMode)
128
+ },
129
+ },
130
+ filter: {
131
+ autoApply: true, // Re-apply last filter if lazy data is loaded
132
+ autoExpand: true, // Expand all branches that contain matches while filtered
133
+ counter: false, // Show a badge with number of matching child nodes near parent icons
134
+ fuzzy: true, // Match single characters in order, e.g. 'fb' will match 'FooBar'
135
+ hideExpandedCounter: true, // Hide counter badge if parent is expanded
136
+ hideExpanders: true, // Hide expanders if all child nodes are hidden by filter
137
+ highlight: true, // Highlight matches by wrapping inside <mark> tags
138
+ leavesOnly: false, // Match end nodes only
139
+ nodata: true, // Display a 'no data' status node if result is empty
140
+ mode: "hide" // Grayout unmatched nodes (pass "hide" to remove unmatched node instead)
141
+ },
142
+ table: tableConfig,
143
+ gridnav: {
144
+ autofocusInput: false,
145
+ handleCursorKeys: true,
146
+ },
147
+ strings: treeStrings,
148
+ postProcess: function (event, data) {
149
+ setTimeout(function () {
150
+ loadValue($inputEl, treeWidgetData, data.tree)
151
+ }, 1)
152
+ },
153
+ select: function (event, data) {
154
+ if($inputEl.length > 0) {
155
+ let value = null
156
+ if (treeWidgetData.filter) {
157
+ value = data.tree.getSelectedNodes().map(function (node) {
158
+ return {'value': node.key, 'label': node.title}
159
+ })
160
+ $inputEl.val(JSON.stringify(value))
161
+ } else {
162
+ value = data.tree.getSelectedNodes().map(function (node) {
163
+ return node.key
164
+ }).join(", ")
165
+ if (treeWidgetData.multiselect === 2) {
166
+ value = JSON.stringify(data.tree.getSelectedNodes().map(function (node) {
167
+ return node.key
168
+ }))
169
+ }
170
+ let label = data.tree.getSelectedNodes().map(function (node) {
171
+ return node.title
172
+ }).join(", ")
173
+ $label.text(label)
174
+ $inputEl.val(value)
175
+ }
176
+ $inputEl[0].dispatchEvent(new CustomEvent('SBAutocompleteChange'))
177
+ $inputEl[0].dispatchEvent(new Event('change', {bubbles: true}))
178
+ return
179
+ }
180
+
181
+ if(treeWidgetData.filter_by_table_data && data.originalEvent) {
182
+ const selectedKeys = data.tree.getSelectedNodes().map(function (node) {
183
+ return node.data.id
184
+ })
185
+ document.body.dispatchEvent(new CustomEvent("treeRowSelected", {detail: {data: selectedKeys}}))
186
+ }
187
+ },
188
+ enhanceTitle: function(event, data) {
189
+ const reorderActive = treeWidgetData.reorder_url
190
+ const nodeRendered = data.node.rendered
191
+ const filteringActive = data.node.tree.enableFilter
192
+ const detailUrlPresent = treeWidgetData.detail_url
193
+ const validVisibleNode = data.node.span && data.node.span.classList.contains("fancytree-node") && !data.node.tr.classList.contains("fancytree-hide")
194
+ if (detailUrlPresent && (!nodeRendered || filteringActive) && !reorderActive && validVisibleNode) {
195
+ const title = data.node.span.querySelector('.fancytree-title')
196
+ const titleLink = document.createElement('a')
197
+ const url = treeWidgetData.detail_url.replace(-1, data.node.data.id)
198
+ titleLink.innerHTML = title.innerHTML
199
+ titleLink.classList.add('link')
200
+ titleLink.href = url
201
+ title.innerHTML = ''
202
+ title.append(titleLink)
203
+ title.addEventListener('mousedown', function (e) {
204
+ e.preventDefault()
205
+ e.stopPropagation()
206
+ }, true)
207
+ }
208
+ },
209
+ renderNode: function (event, data) {
210
+ const reorderActive = treeWidgetData.reorder_url
211
+ const nodeRendered = data.node.rendered
212
+ const validVisibleNode = data.node.span && data.node.span.classList.contains("fancytree-node") && !data.node.tr.classList.contains("fancytree-hide")
213
+ if (nodeRendered && !reorderActive) {
214
+ return
215
+ }
216
+ let isLastSib = data.node && data.node.tr && data.node.tr.classList.contains('fancytree-lastsib')
217
+ isLastSib = isLastSib === undefined ? false : isLastSib
218
+ if (data.node.parent) {
219
+ data.node.treeLevel = data.node.parent.treeLevel + 1
220
+ data.node.treeAdditionalLevel = [{
221
+ level: data.node.treeLevel,
222
+ lastSib: isLastSib
223
+ }, ...data.node.parent.treeAdditionalLevel]
224
+ } else {
225
+ data.node.treeLevel = 0
226
+ data.node.treeAdditionalLevel = []
227
+ }
228
+ data.node.rendered = true
229
+ if (validVisibleNode) {
230
+ const expander = data.node.span.querySelector('.fancytree-expander')
231
+ const level = data.node.treeLevel
232
+ const additionalLevel = data.node.treeAdditionalLevel
233
+ expander.innerHTML = ""
234
+ expander.className = 'fancytree-expander'
235
+ expander.classList.add('level-' + level)
236
+ if (data.node.parent.expanded) {
237
+ expander.classList.add('expanded-parent')
238
+ }
239
+ additionalLevel.forEach((item, i) => {
240
+ if (i !== 0 && item.lastSib) {
241
+ return
242
+ }
243
+ const expanderAdditional = document.createElement('span')
244
+ expanderAdditional.classList.add('expander-additional')
245
+ if (i === 0) {
246
+ expanderAdditional.classList.add('expander-additional-last')
247
+ }
248
+ expanderAdditional.style.left = -(50 + 100 * i) + '%'
249
+ expander.append(expanderAdditional)
250
+ })
251
+ const expanderBorder = document.createElement('span')
252
+ expanderBorder.classList.add('expander-border')
253
+ expander.append(expanderBorder)
254
+ expander.append(document.createElement('div'))
255
+ }
256
+ },
257
+ renderColumns: function (event, data) {
258
+ const $tdList = $(data.node.tr).find(">td")
259
+ additionalColumns.forEach(function (column, index) {
260
+ let value = data.node.data[column.key]
261
+ if (column.hide_zero && value === 0) {
262
+ value = ""
263
+ }
264
+ $tdList.eq(1 + tableConfig.nodeColumnIdx + index).html(value)
265
+ })
266
+ },
267
+ init: function (event, data) {
268
+ if(treeWidgetData.filter_by_table_data) {
269
+ filterByTableData(data.tree)
270
+ }
271
+ }
272
+ })
273
+
274
+ const clearSearchInput = function () {
275
+ $searchEl.val("")
276
+ $matchesEl.text("")
277
+ treeInstance.visit(function (node) {
278
+ node.rendered = false
279
+ })
280
+ treeInstance.clearFilter()
281
+ }
282
+
283
+ const treeInstance = $.ui.fancytree.getTree('#' + treeWidgetData.input_id + '_tree')
284
+ $inputEl.on('SBTableFilterFormLoad', () => {
285
+ loadValue($inputEl, treeWidgetData, treeInstance)
286
+ })
287
+ $inputEl.on('clear', () => {
288
+ treeInstance.getSelectedNodes().map(node => {
289
+ node.setSelected(false)
290
+ })
291
+ })
292
+ $searchEl.on("keyup", function (e) {
293
+ let match = $(this).val()
294
+ let n = treeInstance.filterNodes(match)
295
+
296
+ if (e && e.which === $.ui.keyCode.ESCAPE || $.trim(match) === "") {
297
+ clearSearchInput()
298
+ return
299
+ }
300
+ $matchesEl.text("(" + n + " matches)")
301
+ }).trigger("focus")
302
+
303
+ $searchEl.on('search', function (e) {
304
+ // handle clear event of search input only if clicked on X
305
+ if (e.target.value) {
306
+ return
307
+ }
308
+ clearSearchInput()
309
+ })
310
+
311
+ treeInstance.saveTreeOrder = function () {
312
+ const order = JSON.stringify(treeInstance.toDict())
313
+ fetch(treeWidgetData.reorder_url, {
314
+ method: 'POST',
315
+ headers: {
316
+ "X-CSRFToken": window.csrf_token,
317
+ },
318
+ body: order
319
+ }).then(response => response.json())
320
+ .then(res => {
321
+ document.getElementById("notification-messages").innerHTML = res.messages
322
+ window.htmx.process(document.getElementById("notification-messages"))
323
+ })
324
+ }
325
+
326
+ if(treeWidgetData.filter_by_table_data) {
327
+ document.body.addEventListener('tableDataProcessed', (e) => {
328
+ filterData = e.detail
329
+ if(treeInstance.getRootNode().getChildren()[0]["statusNodeType"] === "loading") {
330
+ return
331
+ }
332
+ filterByTableData(treeInstance)
333
+ })
334
+
335
+ document.body.addEventListener('treeDeselectAllRows', () => {
336
+ treeInstance.selectAll(false)
337
+ })
338
+ document.body.addEventListener('treeSelectAllRows', () => {
339
+ treeInstance.selectAll(true)
340
+ })
341
+ }
342
+ }
343
+
344
+ const initAllTrees = function () {
345
+ $('.js-tree-widget').each(function (index, element) {
346
+ const $treeEl = $(element)
347
+ if ($treeEl.hasClass('fancytree-container')) {
348
+ return
349
+ }
350
+ const $dropdownMenu = $treeEl.closest('.dropdown-menu')
351
+ if ($dropdownMenu.length > 0) {
352
+ const initTreeOnShow = function () {
353
+ initTree($treeEl)
354
+ $dropdownMenu.prev().off('show.bs.dropdown', initTreeOnShow)
355
+ }
356
+ $dropdownMenu.prev().on('show.bs.dropdown', initTreeOnShow)
357
+ return
358
+ }
359
+ initTree($treeEl)
360
+ })
361
+ }
362
+ initAllTrees()
363
+
364
+ document.addEventListener('formset:added', () => {
365
+ initAllTrees()
366
+ })
367
+
368
+ const queryBuilderEl$ = $(".query-builder-advanced")
369
+ queryBuilderEl$.on("afterCreateRuleInput.queryBuilder", function () {
370
+ setTimeout(() => {
371
+ //next tick
372
+ initAllTrees()
373
+ }, 0)
374
+ })
375
+ })
376
+ }
@@ -0,0 +1,63 @@
1
+ {% extends "sb_admin/actions/list.html" %}
2
+ {% load static sb_admin_tags i18n %}
3
+
4
+ {% block extrahead %}
5
+ {{ block.super }}
6
+ <style>
7
+ #table-columns-dropdown-wrapper {
8
+ display: none;
9
+ }
10
+ </style>
11
+ {% endblock %}
12
+
13
+ {% block tabulator_card %}
14
+ {% with enable_table_filter=request.reorder_active|yesno:',True' %}
15
+ {% if enable_table_filter %}
16
+ {{ block.super }}
17
+ {% else %}
18
+ <div class="overflow-hidden pb-8 relative tree-list-view">
19
+ {{ block.super }}
20
+ </div>
21
+ {% endif %}
22
+ {% endwith %}
23
+ {% endblock %}
24
+
25
+ {% block tabulator_custom_header %}
26
+ {% if not request.reorder_active %}
27
+ {% include content_context.tabulator_header_template_name %}
28
+ {% endif %}
29
+ {% endblock %}
30
+ {% block tabulator_body %}
31
+ {% with view_id|add:'_tree' as tree_id %}
32
+ <div class="overflow-auto w-full relative">
33
+ {% include "sb_admin/widgets/tree_base.html" with tree_main_column_name=list_title tree_reorder_url=content_context.tabulator_definition.treeReorderUrl tree_additional_columns=additional_columns tree_component_id=tree_id tree_data_url=tree_json_url tree_detail_url=content_context.tabulator_definition.tableDetailUrl hide_tree_search=True filter_by_table_data=enable_table_filter tree_show_checkbox=enable_table_filter tree_multiselect=enable_table_filter search_wrapper_classes="py-16 md:p-16" %}
34
+ </div>
35
+ {% endwith %}
36
+ {% if not request.reorder_active %}
37
+ <div class="hidden">
38
+ {{ block.super }}
39
+ </div>
40
+ {% endif %}
41
+ {% endblock %}
42
+ {% block tabulator_custom_footer %}
43
+ {% endblock %}
44
+
45
+ {% block actions %}
46
+ {% with view_id|add:'_tree' as tree_id %}
47
+ {% if request.request_data.action == 'action_enter_reorder' %}
48
+ <li class="max-sm:hidden">
49
+ <button onclick="$.ui.fancytree.getTree('#' + '{{ tree_id }}' + '_tree').saveTreeOrder()"
50
+ class="btn btn-empty">
51
+ {% trans 'Save Order' %}
52
+ </button>
53
+ </li>
54
+ {% endif %}
55
+ {% endwith %}
56
+ {{ block.super }}
57
+ {% endblock %}
58
+
59
+ {% block additional_js %}
60
+ {% if not request.reorder_active %}
61
+ {{ block.super }}
62
+ {% endif %}
63
+ {% endblock %}
@@ -1,6 +1,6 @@
1
1
  {% load i18n %}
2
2
 
3
- <div class="inline-flex relative js-select-all-wrapper">
3
+ <div id="table-columns-dropdown-wrapper" class="inline-flex relative js-select-all-wrapper">
4
4
  <button
5
5
  data-bs-toggle="dropdown"
6
6
  aria-expanded="false"
@@ -0,0 +1,2 @@
1
+ {% include 'sb_admin/filter_widgets/tree_select_filter.html' %}
2
+
@@ -0,0 +1,16 @@
1
+ {% load sb_admin_tags %}
2
+
3
+ <div class="dropdown-menu max-h-none w-248">
4
+ <div class="px-12 pt-8 border-b border-dark-200">
5
+ {% with tree_widget_id=filter_widget.view_id|add:"-"|add:filter_widget.input_id|add:"_tree" %}
6
+ <div class="relative -mx-12">
7
+ <input form="{{ filter_widget.view_id }}-filter-form" type="hidden"
8
+ id="{{ filter_widget.input_id }}" name="{{ filter_widget.input_name }}"
9
+ {% if not all_filters_visible %}disabled{% endif %}{% if filter_widget.get_default_value %} value="{{ filter_widget.get_default_value|get_json }}"{% endif %}>
10
+ {% include "sb_admin/widgets/tree_base.html" with tree_additional_columns=filter_widget.additional_columns tree_strings=filter_widget.tree_strings tree_filter=True tree_value=filter_widget.get_default_value tree_multiselect=filter_widget.multiselect tree_component_id=filter_widget.input_id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True search_wrapper_classes="pb-8 px-12" table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" %}
11
+ </div>
12
+ {% endwith %}
13
+ </div>
14
+ {% include "sb_admin/filter_widgets/partials/clear.html" %}
15
+ </div>
16
+
@@ -25,6 +25,10 @@
25
25
  {% block style_init %}{% endblock %}
26
26
 
27
27
  <script>window.csrf_token = "{{ csrf_token }}"</script>
28
+
29
+ {% block jquery %}
30
+ <script src="{% static 'sb_admin/js/jquery-3.7.1.min.js' %}"></script>
31
+ {% endblock %}
28
32
  {% block js_init %}
29
33
  <script>
30
34
  {% if const %}
@@ -35,12 +39,10 @@
35
39
  }
36
40
  </script>
37
41
  {% endblock %}
38
- {% if content_context.is_jquery_required %}
39
- <script src="{% static 'sb_admin/js/jquery-3.7.1.min.js' %}"></script>
40
- {% endif %}
41
- {% block jquery %}
42
- {% endblock %}
43
42
  {% block tree_widget_static %}
43
+ <script src="{% static 'sb_admin/fancytree/jquery.fancytree-all-deps.min.js' %}"></script>
44
+ <script src="{% static 'sb_admin/dist/tree_widget.js' %}"></script>
45
+ <link rel="stylesheet" href="{% static 'sb_admin/dist/tree_widget_style.css' %}">
44
46
  {% endblock %}
45
47
  {% block extrahead %}{% endblock %}
46
48
  <style>@media (min-width: 1200px){.xl\:\!block {display: block !important;}}</style>
@@ -8,4 +8,5 @@
8
8
  window.sb_admin_translation_strings["reorder"] = '{% trans "Reorder" %}';
9
9
  window.sb_admin_translation_strings["page"] = '{% blocktrans %}<strong>${from} - ${to}</strong> of <strong>${total}</strong><span class="max-xs:hidden"> items</span>{% endblocktrans %}'
10
10
  window.sb_admin_translation_strings["page_empty"] = '{% blocktrans %}<strong>0</strong> items{% endblocktrans %}'
11
+ window.sb_admin_translation_strings["selected"] = '{% blocktrans %}${value} selected{% endblocktrans %}'
11
12
  </script>
@@ -39,7 +39,7 @@
39
39
  {% file_icon object %}
40
40
  {% endif %}
41
41
  {% else %}
42
- <img class="thumbnail_img hidden quiet" alt="{% trans 'no file selected' %}">
42
+ <img class="thumbnail_img hidden quiet" alt="{% trans 'No file selected' %}">
43
43
  {% endif %}
44
44
 
45
45
  <div>
@@ -0,0 +1,54 @@
1
+ {% load static sb_admin_tags i18n %}
2
+
3
+ {% if not hide_tree_search %}
4
+ <div class="border-b border-dark-200 {{ search_wrapper_classes }}">
5
+ <div class="js-tree-widget-search relative">
6
+ {% trans 'Search' as search_string %}
7
+ <input id="{{ tree_component_id }}_search" name="search" placeholder="{{ tree_filter_placeholder|default:search_string }}" autocomplete="off" class="input pl-36" type="search">
8
+ <div class="absolute pl-10 left-0 top-0 bottom-0 flex items-center gap-8 rounded-r">
9
+ <svg class="w-20 h-20">
10
+ <use xlink:href="#Search"></use>
11
+ </svg>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ {% endif %}
16
+ <div class="{{ table_wrapper_classes }}">
17
+ <table style="width: 100%;" id="{{ tree_component_id }}_tree" class="js-tree-widget fancytree-ext-table" data-tree-data-id="{{ tree_component_id }}_data" data-tree-additional-columns-id="{{ tree_component_id }}_additional_columns" data-tree-strings-id="{{ tree_component_id }}_tree_strings">
18
+ <thead>
19
+ <tr>
20
+ {% if tree_show_checkbox %}<th></th>{% endif %}
21
+ <th class="text-left">{{ tree_main_column_name }}<span id="{{ tree_component_id }}_matches" class="ml-4"></span></th>
22
+ {% for column in tree_additional_columns %}
23
+ <th>{{ column.title }}</th>
24
+ {% endfor %}
25
+ </tr>
26
+ </thead>
27
+ <tbody>
28
+ <tr>
29
+ {% if tree_show_checkbox %}<td class="alignCenter fancytree-checkbox-column"></td>{% endif %}
30
+ <td></td>
31
+ {% for column in tree_additional_columns %}
32
+ <td></td>
33
+ {% endfor %}
34
+ </tr>
35
+ </tbody>
36
+ </table>
37
+ </div>
38
+
39
+ <script id="{{ tree_component_id }}_data" type="application/json">
40
+ {
41
+ "filter": {% if tree_filter %}true{% else %}false{% endif %},
42
+ "input_id": "{{ tree_component_id }}",
43
+ "data_url": "{{ tree_data_url }}",
44
+ "checkbox": {% if tree_show_checkbox %}true{% else %}false{% endif %},
45
+ "multiselect": {% if tree_multiselect %}2{% else %}1{% endif %},
46
+ "detail_url":"{{ tree_detail_url }}",
47
+ "reorder_url":"{{ tree_reorder_url }}",
48
+ "filter_by_table_data": {% if filter_by_table_data %}true{% else %}false{% endif %}
49
+ }
50
+ </script>
51
+ <script id="{{ tree_component_id }}_additional_columns" type="application/json">{{ tree_additional_columns|get_json|safe }}</script>
52
+ <script id="{{ tree_component_id }}_tree_strings" type="application/json">
53
+ {{ tree_strings|get_json|safe }}
54
+ </script>
@@ -0,0 +1,24 @@
1
+ {% load sb_admin_tags %}
2
+
3
+ <div class="relative">
4
+ {% include 'sb_admin/widgets/includes/field_label.html' %}
5
+ <div id="{{ widget.attrs.id }}-wrapper" class="tree-widget-wrapper">
6
+ <input type="hidden" id="{{ widget.attrs.id }}" name="{{ widget.name }}"{% if widget.raw_value %} value="{{ widget.raw_value|get_json }}"{% endif %}>
7
+ <button
8
+ data-bs-toggle="dropdown"
9
+ aria-expanded="false"
10
+ data-bs-offset="[0, 8]"
11
+ class="btn px-10 font-normal w-full"
12
+ >
13
+ <span id="{{ widget.attrs.id }}_label">{% get_item widget.value_dict widget.raw_value widget.form_field.empty_label %}</span>
14
+ <svg class="ml-8">
15
+ <use xlink:href="#Down"></use>
16
+ </svg>
17
+ </button>
18
+ <div class="dropdown-menu max-h-none w-248">
19
+ <div class="py-8">
20
+ {% include "sb_admin/widgets/tree_base.html" with tree_additional_columns=widget.additional_columns tree_strings=widget.tree_strings tree_value=widget.raw_value tree_multiselect=filter_widget.multiselect tree_component_id=widget.attrs.id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" %}
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </div>
@@ -0,0 +1,12 @@
1
+ {% load sb_admin_tags %}
2
+
3
+ <div class="relative -mb-2">
4
+ <script>
5
+ document.currentScript.closest('.djn-table').querySelector('.djn-thead').classList.add('hidden');
6
+ </script>
7
+ <div id="{{ widget.attrs.id }}-wrapper" class="tree-widget-wrapper">
8
+ <input type="hidden" id="{{ widget.attrs.id }}" name="{{ widget.name }}"{% if widget.raw_value %}
9
+ value="{{ widget.raw_value|get_json }}"{% endif %}>
10
+ {% include "sb_admin/widgets/tree_base.html" with tree_main_column_name=filter_widget.form_field.label tree_strings=widget.tree_strings tree_additional_columns=widget.additional_columns tree_value=widget.raw_value tree_multiselect=filter_widget.multiselect tree_component_id=widget.attrs.id tree_data_url=filter_widget.to_json.autocomplete_url tree_show_checkbox=True table_wrapper_classes="max-h-432 overflow-auto custom-scrollbar" search_wrapper_classes="pb-16 px-16" %}
11
+ </div>
12
+ </div>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-smartbase-admin
3
- Version: 0.2.91
3
+ Version: 0.2.93
4
4
  Summary:
5
5
  Author: SmartBase
6
6
  Author-email: info@smartbase.sk