Add parent widget drag handle (#7792)
* Add parent widget drag handle * Update parent.php * Update css.php
This commit is contained in:
+85
-45
@@ -310,7 +310,7 @@ div.hud_chart {
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
/* dashboard settings */
|
||||
/* Dashboard Settings */
|
||||
<?php
|
||||
foreach ($widgets as $row) {
|
||||
$widget_id = 'id_'.md5(preg_replace('/[^-A-Fa-f0-9]/', '', $row['dashboard_widget_uuid']));
|
||||
@@ -484,7 +484,7 @@ foreach ($widgets as $row) {
|
||||
}
|
||||
?>
|
||||
|
||||
/* Screen smaller than 575px? 1 columns */
|
||||
/* Screen smaller than 575px? 1 column */
|
||||
@media (max-width: 575px) {
|
||||
.widgets { grid-template-columns: repeat(1, minmax(100px, 1fr)); }
|
||||
.col-num { grid-column: span 1; }
|
||||
@@ -558,6 +558,7 @@ foreach ($widgets as $row) {
|
||||
|
||||
<script>
|
||||
|
||||
// Widget details expand button
|
||||
document.addEventListener('click', function(event) {
|
||||
let hud_content = event.target.closest('.hud_content');
|
||||
let hud_expander = event.target.closest('.hud_expander');
|
||||
@@ -589,7 +590,7 @@ function toggle_grid_row_span(widget_id) {
|
||||
let first_toggle = false;
|
||||
|
||||
function toggle_grid_row_span_all() {
|
||||
const widgets = document.querySelectorAll('div.widget, div.child_widget');
|
||||
const widgets = document.querySelectorAll('div.widget');
|
||||
|
||||
widgets.forEach(widget => {
|
||||
if (widget.classList.contains('details_disabled')) {
|
||||
@@ -613,14 +614,15 @@ function toggle_grid_row_span_all() {
|
||||
first_toggle = true;
|
||||
}
|
||||
|
||||
// Automatically update parent widget height and row span based on content and window size
|
||||
function update_parent_height() {
|
||||
const parent_widgets = document.querySelectorAll('.parent_widget');
|
||||
const parent_widgets = document.querySelectorAll('.parent_widget > .hud_box > .hud_content');
|
||||
|
||||
parent_widgets.forEach(parent_widget => {
|
||||
if (!parent_widget.dataset.originalHeight) {
|
||||
parent_widget.dataset.originalHeight = parseFloat(window.getComputedStyle(parent_widget).height.replace('px', ''));
|
||||
}
|
||||
const widget = parent_widget.closest('.widget');
|
||||
const widget = parent_widget.closest('.parent_widget');
|
||||
const row_gap = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--grid-gap').replace('px', ''));
|
||||
const row_height = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--row-height').replace('px', ''));
|
||||
const original_row_span = parseInt(window.getComputedStyle(widget).getPropertyValue('--row-span').replace('span ', ''));
|
||||
@@ -647,7 +649,7 @@ window.addEventListener('resize', update_parent_height);
|
||||
|
||||
<?php
|
||||
|
||||
//include the dashboards
|
||||
//include the widgets
|
||||
echo "<div class='widgets' id='widgets' style='padding: 0 5px;'>\n";
|
||||
$x = 0;
|
||||
foreach ($widgets as $row) {
|
||||
@@ -707,7 +709,10 @@ window.addEventListener('resize', update_parent_height);
|
||||
$widget_path_name = $widget_path_array[1];
|
||||
$path_array = glob(dirname(__DIR__, 2).'/*/'.$application_name.'/resources/dashboard/'.$widget_path_name.'.php');
|
||||
|
||||
echo "<div class='widget details_".$widget_details_state."' id='".$widget_id."' ".($widget_path == 'dashboard/parent' ? "data-is-parent='true'" : null)." draggable='false'>\n";
|
||||
// Widget class
|
||||
$widget_class = ($widget_path == 'dashboard/parent' ? 'parent_widget' : 'widget');
|
||||
|
||||
echo "<div class='".$widget_class." details_".$widget_details_state." draggable' id='".$widget_id."' draggable='false'>\n";
|
||||
if (file_exists($path_array[0])) {
|
||||
include $path_array[0];
|
||||
}
|
||||
@@ -730,22 +735,26 @@ window.addEventListener('resize', update_parent_height);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
div.widget.editable {
|
||||
cursor: move;
|
||||
.editable {
|
||||
position: relative;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.hud_box.editable {
|
||||
transition: 0.2s;
|
||||
border: 1px dashed rgba(0,0,0,0.4);
|
||||
border: 1px dashed rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.hud_box.editable:hover {
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,0.2);
|
||||
border: 1px dashed rgba(0,0,0,0.4);
|
||||
transform: scale(1.03, 1.03);
|
||||
border: 1px dashed rgba(0,0,0,0.3);
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.widget > .hud_box.editable:hover {
|
||||
transform: scale(1.03, 1.03);
|
||||
}
|
||||
|
||||
.hud_box .hud_box.editable:hover {
|
||||
box-shadow: none;
|
||||
transform: none;
|
||||
@@ -760,57 +769,63 @@ window.addEventListener('resize', update_parent_height);
|
||||
<?php unset($br); ?>
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.widget_edit_actions {
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: #ffffff75;
|
||||
backdrop-filter: blur(5px);
|
||||
border-bottom-left-radius: 5px;
|
||||
overflow: hidden;
|
||||
color: #000000aa;
|
||||
}
|
||||
|
||||
.widget_edit_actions i {
|
||||
padding: 8px 12px;
|
||||
background: #00000020;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const widgets = document.getElementById('widgets');
|
||||
let sortable;
|
||||
|
||||
//make widgets draggable
|
||||
function edit_mode(state) {
|
||||
|
||||
if (state == 'on') {
|
||||
$('span#expand_contract, #btn_edit, #btn_add').hide();
|
||||
$('.hud_box').addClass('editable');
|
||||
$('#btn_back, #btn_save').show();
|
||||
$('div.widget').attr('draggable',true).addClass('editable');
|
||||
$('div.widget, div.parent_widget').attr('draggable',true).addClass('editable');
|
||||
$('div.child_widget').attr('draggable',true).addClass('editable');
|
||||
|
||||
function update_widget_order() {
|
||||
let widget_ids_list = [];
|
||||
let order = 10;
|
||||
// Widget edit actions
|
||||
document.querySelectorAll('.parent_widget > .hud_box').forEach(widget => {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'widget_edit_actions';
|
||||
|
||||
widgets.querySelectorAll(':scope > div.widget[id]').forEach(widget => {
|
||||
const widget_id = widget.id;
|
||||
// Drag handle
|
||||
const grip_icon = document.createElement('i');
|
||||
grip_icon.className = 'fa-solid fa-grip-lines';
|
||||
|
||||
//add the widgets to the list
|
||||
widget_ids_list.push(`${widget_id}|null|${order}`);
|
||||
order += 10;
|
||||
|
||||
//add the nested widgets to the list
|
||||
const nested_container = widget.querySelector('.parent_widget');
|
||||
if (nested_container) {
|
||||
nested_container.querySelectorAll(':scope > div.child_widget[id]').forEach(nested => {
|
||||
const child_id = nested.id;
|
||||
widget_ids_list.push(`${child_id}|${widget_id}|${order}`);
|
||||
order += 10;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('widget_order').value = widget_ids_list;
|
||||
}
|
||||
container.appendChild(grip_icon);
|
||||
widget.prepend(container);
|
||||
});
|
||||
|
||||
// Make widgets draggable
|
||||
sortable = Sortable.create(widgets, {
|
||||
group: {
|
||||
name: 'shared',
|
||||
pull: function(to, from, dragEl) {
|
||||
return !dragEl.hasAttribute('data-is-parent');
|
||||
return !dragEl.classList.contains('parent_widget');
|
||||
},
|
||||
put: true,
|
||||
},
|
||||
animation: 150,
|
||||
draggable: '.widget',
|
||||
draggable: '.draggable',
|
||||
preventOnFilter: true,
|
||||
ghostClass: 'ghost',
|
||||
onSort: update_widget_order,
|
||||
@@ -831,7 +846,7 @@ window.addEventListener('resize', update_parent_height);
|
||||
},
|
||||
});
|
||||
|
||||
document.querySelectorAll('.parent_widget').forEach(function(container) {
|
||||
document.querySelectorAll('.parent_widget > .hud_box > .hud_content').forEach(function(container) {
|
||||
Sortable.create(container, {
|
||||
group: {
|
||||
name: 'shared',
|
||||
@@ -839,7 +854,7 @@ window.addEventListener('resize', update_parent_height);
|
||||
return true;
|
||||
},
|
||||
put: function(to, from, dragEl) {
|
||||
return !dragEl.hasAttribute('data-is-parent');
|
||||
return !dragEl.classList.contains('parent_widget');
|
||||
},
|
||||
},
|
||||
animation: 150,
|
||||
@@ -870,18 +885,43 @@ window.addEventListener('resize', update_parent_height);
|
||||
});
|
||||
});
|
||||
|
||||
function update_widget_order() {
|
||||
let widget_ids_list = [];
|
||||
let order = 10;
|
||||
|
||||
widgets.querySelectorAll(':scope > div.widget[id]').forEach(widget => {
|
||||
const widget_id = widget.id;
|
||||
|
||||
//add the widgets to the list
|
||||
widget_ids_list.push(`${widget_id}|null|${order}`);
|
||||
order += 10;
|
||||
|
||||
//add the nested widgets to the list
|
||||
const nested_container = widget.querySelector('.parent_widget > .hud_box > .hud_content');
|
||||
if (nested_container) {
|
||||
nested_container.querySelectorAll(':scope > div.child_widget[id]').forEach(nested => {
|
||||
const child_id = nested.id;
|
||||
widget_ids_list.push(`${child_id}|${widget_id}|${order}`);
|
||||
order += 10;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('widget_order').value = widget_ids_list;
|
||||
}
|
||||
}
|
||||
else { // off
|
||||
|
||||
$('div.widget').attr('draggable',false).removeClass('editable');
|
||||
$('div.child_widget').attr('draggable',false).removeClass('editable');
|
||||
$('div.widget, div.parent_widget, div.child_widget').attr('draggable',false).removeClass('editable');
|
||||
$('.hud_box').removeClass('editable');
|
||||
$('#btn_back, #btn_save').hide();
|
||||
$('span#expand_contract, #btn_edit, #btn_add').show();
|
||||
|
||||
document.querySelectorAll('.widget_edit_actions').forEach(element => element.remove());
|
||||
|
||||
sortable.option('disabled', true);
|
||||
document.querySelectorAll('.parent_widget').forEach(el => {
|
||||
const nested_sortable = Sortable.get(el);
|
||||
document.querySelectorAll('.parent_widget > .hud_box > .hud_content').forEach(element => {
|
||||
const nested_sortable = Sortable.get(element);
|
||||
|
||||
if (nested_sortable) {
|
||||
nested_sortable.option('disabled', true);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
<style>
|
||||
|
||||
div.parent_widget {
|
||||
.parent_widget > .hud_box > .hud_content {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
@@ -124,9 +124,9 @@ foreach ($child_widgets as $row) {
|
||||
|
||||
<?php
|
||||
|
||||
//include the dashboards
|
||||
//include the widgets
|
||||
echo "<div class='hud_box'>\n";
|
||||
echo " <div class='hud_content parent_widget'>\n";
|
||||
echo " <div class='hud_content'>\n";
|
||||
|
||||
$x = 0;
|
||||
foreach ($child_widgets as $row) {
|
||||
|
||||
@@ -3004,7 +3004,8 @@ else { //default: white
|
||||
border: 1px solid <?=$dashboard_border_color_hover?>;
|
||||
}
|
||||
|
||||
div.widget div.hud_box:first-of-type {
|
||||
div.widget div.hud_box:first-of-type,
|
||||
div.parent_widget div.hud_box:first-of-type {
|
||||
<?php
|
||||
echo "background: ".($dashboard_background_color[0] ?? '#ffffff').";\n";
|
||||
if (!empty($dashboard_background_color) && is_array($dashboard_background_color) && sizeof($dashboard_background_color) > 1) {
|
||||
|
||||
Reference in New Issue
Block a user