mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
Merge branch 'feature-61730/Cis4_DashboardAnpassungen' into merge_C4_25999_61235_61730
This commit is contained in:
@@ -107,7 +107,7 @@ class DashboardLib
|
||||
$emptyoverride = new stdClass();
|
||||
$emptyoverride->dashboard_id = $dashboard->dashboard_id;
|
||||
$emptyoverride->uid = $uid;
|
||||
$emptyoverride->override = '{"' . self::USEROVERRIDE_SECTION . '": {"widgets":{}}}}';
|
||||
$emptyoverride->override = '{"' . self::USEROVERRIDE_SECTION . '": {"widgets":{}}, "custom": { "widgets" : {}}}';
|
||||
|
||||
return $emptyoverride;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,18 @@
|
||||
color: var(--fhc-link);
|
||||
}
|
||||
|
||||
@media (max-width: 576px){
|
||||
.widget-icon {
|
||||
max-height: 250px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.widget-icon-container{
|
||||
max-width: 250px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-tile-hover {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@@ -30,6 +42,23 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color:white;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.dashboard-section > .newGridRow{
|
||||
position:absolute;
|
||||
width:20px;
|
||||
height:20px;
|
||||
padding:0;
|
||||
bottom:0;
|
||||
left:50%;
|
||||
transform:translate(-50%, 50%);
|
||||
background-color:white;
|
||||
}
|
||||
|
||||
.newGridRow:hover {
|
||||
color:white;
|
||||
background-color:#6c757d;
|
||||
}
|
||||
|
||||
.empty-tile-hover:hover {
|
||||
|
||||
@@ -300,6 +300,7 @@ app.use(primevue.config.default, {
|
||||
tooltip: 8000
|
||||
}
|
||||
})
|
||||
app.directive('tooltip', primevue.tooltip);
|
||||
app.use(PluginsPhrasen);
|
||||
app.use(Theme);
|
||||
app.directive('contrast', contrast);
|
||||
|
||||
@@ -177,7 +177,13 @@ export default {
|
||||
});
|
||||
remove.forEach(wid => this.widgetRemove(name, wid));
|
||||
}
|
||||
this.sections = this.sections.sort((section1, section2) => section2.widgets.length - section1.widgets.length);
|
||||
this.sections = this.sections.sort((section1, section2) => {
|
||||
if(section1.name == 'custom')
|
||||
return 1;
|
||||
if (section2.name == 'custom')
|
||||
return -1;
|
||||
return section2.widgets.length - section1.widgets.length;
|
||||
});
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
},
|
||||
async beforeMount() {
|
||||
|
||||
@@ -41,6 +41,9 @@ export default {
|
||||
"item_data",
|
||||
"place",
|
||||
"setup",
|
||||
"dragstate",
|
||||
"resizeOverlay",
|
||||
"additionalRow"
|
||||
],
|
||||
computed: {
|
||||
maxHeight(){
|
||||
@@ -153,7 +156,8 @@ export default {
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="!hidden || editMode" :id="widgetID" class="dashboard-item card overflow-hidden h-100 position-relative" :class="arguments && arguments.className ? arguments.className : ''">
|
||||
<div v-else-if="!hidden || editMode" :id="widgetID" class="dashboard-item card overflow-hidden h-100 position-relative" :class="{'draggedItem':dragstate, 'dashboard-item-overlay':resizeOverlay, [arguments?.className]:arguments && arguments.className}">
|
||||
<div v-show="!dragstate" class="h-100 card border-0">
|
||||
<div v-if="widget" class="card-header d-flex ps-0 pe-2 align-items-center">
|
||||
<Transition>
|
||||
<span v-if="editMode && !isPinned" drag-action="move" class="col-auto mx-2 px-2 cursor-move"><i class="fa-solid fa-grip-vertical"></i></span>
|
||||
@@ -221,5 +225,6 @@ export default {
|
||||
</template>
|
||||
</div>
|
||||
</height-transition>
|
||||
</div>
|
||||
</div>`,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import BsConfirm from "../Bootstrap/Confirm.js";
|
||||
import SectionModal from "../Bootstrap/Alert.js";
|
||||
import DropGrid from '../Drop/Grid.js'
|
||||
import DashboardItem from "./Item.js";
|
||||
import CachedWidgetLoader from "../../composables/Dashboard/CachedWidgetLoader.js";
|
||||
@@ -41,6 +40,7 @@ export default {
|
||||
gridWidth: 1,
|
||||
gridHeight: null,
|
||||
draggedItem:null,
|
||||
additionalRow:false,
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
@@ -108,13 +108,13 @@ export default {
|
||||
},
|
||||
showSectionInformation(){
|
||||
if (this.name == "general"){
|
||||
SectionModal.popup(this.$p.t('dashboard', 'dashboardGeneralSectionDescription'));
|
||||
return this.$p.t('dashboard', 'dashboardGeneralSectionDescription');
|
||||
}
|
||||
else if(this.name == "custom"){
|
||||
SectionModal.popup(this.$p.t('dashboard', 'dashboardCustomSectionDescription'));
|
||||
return this.$p.t('dashboard', 'dashboardCustomSectionDescription');
|
||||
}
|
||||
else{
|
||||
SectionModal.popup(this.$p.t('dashboard', 'dashboardSectionDescription', [this.name]));
|
||||
return this.$p.t('dashboard', 'dashboardSectionDescription', [this.name]);
|
||||
}
|
||||
},
|
||||
handleConfigOpened() {
|
||||
@@ -209,18 +209,20 @@ export default {
|
||||
});
|
||||
},
|
||||
template: `
|
||||
<h4 v-if="editModeIsActive" class=" mb-0">
|
||||
<i @click="showSectionInformation(name)" class="fa-solid fa-circle-info section-info" ></i>
|
||||
<h4 v-if="editModeIsActive" class=" mb-2">
|
||||
<i v-tooltip="showSectionInformation(name)" class="fa-solid fa-circle-info section-info" ></i>
|
||||
{{sectionNameTranslation()}}:
|
||||
</h4>
|
||||
<div class="dashboard-section position-relative pb-3 border-bottom" ref="container" :style="getSectionStyle">
|
||||
<drop-grid v-model:cols="gridWidth" :items="items" :itemsSetup="computedWidgetsSetup" :active="editModeIsActive" :resize-limit="checkResizeLimit" :margin-for-extra-row=".01" @draggedItem="draggedItem=$event" @rearrange-items="updatePositions" @gridHeight="gridHeight=$event" >
|
||||
<button v-tooltip="$p.t('dashboard','addLine')" v-if="!additionalRow && editModeIsActive" @click="additionalRow=true" class="btn btn-outline-secondary rounded-circle newGridRow d-flex justify-content-center align-items-center">+</button>
|
||||
<drop-grid v-model:cols="gridWidth" v-model:additionalRow="additionalRow" :items="items" :itemsSetup="computedWidgetsSetup" :active="editModeIsActive" :resize-limit="checkResizeLimit" :margin-for-extra-row=".01" @draggedItem="draggedItem=$event" @rearrange-items="updatePositions" @gridHeight="gridHeight=$event" >
|
||||
<template #default="item">
|
||||
<div v-if="item.placeholder" class="empty-tile-hover" @click="$emit('widgetAdd', name, { widget: 1, config: {}, place: {[gridWidth]: {x:item.x,y:item.y,w:1,h:1}}, custom: 1 })"></div>
|
||||
<div v-else-if="item.blank || (item.widgetid && item.widgetid == draggedItem?.data.widgetid)" :class="{'dashboard-item-overlay':item.resizeOverlay}" class="dashboard-item card overflow-hidden h-100 position-relative draggedItem" ></div>
|
||||
<div v-if="item.placeholder" class="empty-tile-hover" @pointerdown="$emit('widgetAdd', name, { widget: 1, config: {}, place: {[gridWidth]: {x:item.x,y:item.y,w:1,h:1}}, custom: 1 })"></div>
|
||||
<dashboard-item
|
||||
v-else
|
||||
:id="item.widget"
|
||||
:dragstate="item.blank || (item.widgetid && item.widgetid == draggedItem?.data.widgetid)"
|
||||
:resizeOverlay="item.resizeOverlay"
|
||||
:widgetID="item.id"
|
||||
:width="item.w"
|
||||
:height="item.h"
|
||||
|
||||
@@ -36,11 +36,11 @@ export default {
|
||||
<bs-modal ref="modal" class="fade" :dialog-class="{'modal-fullscreen-sm-down': 1, 'modal-xl': widgets && widgets.length > 0}" @hiddenBsModal="close">
|
||||
<template v-slot:title>Create new widget</template>
|
||||
<template v-slot:default>
|
||||
<div v-if="widgets" class="row">
|
||||
<div v-if="widgets" class="row g-2">
|
||||
<div v-if="!widgets.length">
|
||||
No Widgets available
|
||||
</div>
|
||||
<div v-for="widget in widgets" :key="widget.widget_id" class="col-sm-6 col-md-4 col-lg-3 col-xl-2">
|
||||
<div v-for="widget in widgets" :key="widget.widget_id" class="widget-icon-container col-sm-6 col-md-4 col-lg-3 col-xl-2">
|
||||
<widget-icon @select="pick" :widget="widget" ></widget-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ export default {
|
||||
emits:["select"],
|
||||
template: /*html */`
|
||||
<div class="card h-100" @click="$emit('select',widget.widget_id);">
|
||||
<img class="card-img-top" :src="path(widget.setup.icon)" :alt="'pictogram for ' + (widget.setup.name || widget.widget_kurzbz)">
|
||||
<img class="card-img-top widget-icon" :src="path(widget.setup.icon)" :alt="'pictogram for ' + (widget.setup.name || widget.widget_kurzbz)">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ widget.setup.name || widget.widget_kurzbz }}</h5>
|
||||
<p class="card-text">{{ widget.beschreibung }}</p>
|
||||
|
||||
@@ -26,6 +26,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
additionalRow:{
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"rearrangeItems",
|
||||
@@ -48,7 +52,6 @@ export default {
|
||||
draggedOffset: [0,0],
|
||||
draggedItem: null,
|
||||
draggedNode: null,
|
||||
additionalRow: null,
|
||||
reorderedItems:[],
|
||||
clonedWidget:null,
|
||||
}
|
||||
@@ -60,6 +63,14 @@ export default {
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
additionalRowComputed: {
|
||||
get() {
|
||||
return this.additionalRow;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('update:additionalRow', value);
|
||||
}
|
||||
},
|
||||
items_hashmap() {
|
||||
let items = {};
|
||||
this.items.forEach(item => {
|
||||
@@ -117,10 +128,19 @@ export default {
|
||||
return [...this.placedItems, ...this.items_placeholders];
|
||||
},
|
||||
rows() {
|
||||
if ((this.mode == MODE_MOVE || this.mode == MODE_RESIZE) && this.dragGrid){
|
||||
return this.dragGrid.h;
|
||||
if (this.additionalRowComputed) {
|
||||
return this.grid ? (this.grid.h+1) : 1;
|
||||
}
|
||||
return this.grid ? this.grid.h : 1;
|
||||
/* if ((this.mode == MODE_MOVE || this.mode == MODE_RESIZE) && this.dragGrid){
|
||||
return this.dragGrid.h;
|
||||
}
|
||||
if (this.mode == MODE_IDLE) {
|
||||
if (this.additionalRowComputed) {
|
||||
return this.grid ? (this.grid.h+1) : 1;
|
||||
}
|
||||
}
|
||||
return this.grid ? this.grid.h : 1; */
|
||||
},
|
||||
gridStyle() {
|
||||
const addH = this.active ? this.marginForExtraRow : 0;
|
||||
@@ -347,17 +367,12 @@ export default {
|
||||
});
|
||||
},
|
||||
mouseLeave() {
|
||||
if (this.mode == MODE_IDLE) {
|
||||
/* if (this.mode == MODE_IDLE) {
|
||||
this.x = -1;
|
||||
this.y = -1;
|
||||
if (this.additionalRow !== null) {
|
||||
let gridHeight = this.grid.getMaxY() + 1;
|
||||
if(this.grid.h>gridHeight){
|
||||
this.grid.h = gridHeight;
|
||||
}
|
||||
this.additionalRow = null;
|
||||
}
|
||||
}
|
||||
this.additionalRowComputed = false;
|
||||
|
||||
} */
|
||||
},
|
||||
updateCursor(evt) {
|
||||
if (!this.active) {
|
||||
@@ -380,18 +395,6 @@ export default {
|
||||
if (this.x == gridX && this.y == gridY)
|
||||
return false;
|
||||
|
||||
if (this.mode == MODE_IDLE) {
|
||||
if (this.additionalRow === null && this.y == this.rows-1 && gridY == this.rows) {
|
||||
this.additionalRow = this.grid.h;
|
||||
this.grid.h += 1;
|
||||
} else if (this.additionalRow !== null && gridY != this.rows - 1) {
|
||||
let gridHeight = this.grid.getMaxY() + 1;
|
||||
if(this.grid.h > gridHeight){
|
||||
this.grid.h = gridHeight;
|
||||
}
|
||||
this.additionalRow = null;
|
||||
}
|
||||
}
|
||||
this.x = gridX;
|
||||
this.y = gridY;
|
||||
|
||||
@@ -405,6 +408,7 @@ export default {
|
||||
}
|
||||
},
|
||||
startMove(evt, item) {
|
||||
|
||||
if (!this.active)
|
||||
return;
|
||||
|
||||
@@ -413,14 +417,15 @@ export default {
|
||||
this.grid.h += 1;
|
||||
this.draggedItem = item;
|
||||
this.$emit('draggedItem',item);
|
||||
this.draggedNode = evt.target;
|
||||
|
||||
this.draggedNode = evt.target.closest(".drop-grid-item");
|
||||
//clones the widget for the drag Image
|
||||
let clone = evt.target.cloneNode(true);
|
||||
let clone = evt.target.closest(".drop-grid-item")?.cloneNode(true);
|
||||
|
||||
clone.style.zIndex = 5;
|
||||
clone.classList.add("widgetClone");
|
||||
this.$refs.container.appendChild(clone);
|
||||
this.clonedWidget = clone;
|
||||
|
||||
this.draggedOffset = [item.x - this.x, item.y - this.y];
|
||||
this._dragStart(evt, item);
|
||||
},
|
||||
@@ -480,6 +485,7 @@ export default {
|
||||
}
|
||||
},
|
||||
dragCancel() {
|
||||
this.additionalRowComputed = false;
|
||||
this.toggleDraggedItemOverlay(false);
|
||||
this.mode = MODE_IDLE;
|
||||
this.positionUpdates = null;
|
||||
@@ -498,9 +504,10 @@ export default {
|
||||
Array.from(document.getElementsByClassName("denied-dragging-animation"))?.forEach(ele => {
|
||||
ele.classList.remove("denied-dragging-animation");
|
||||
})
|
||||
|
||||
let widgetClones = document.getElementsByClassName("widgetClone");
|
||||
for(let widget of widgetClones){
|
||||
this.$refs.container.removeChild(widget);
|
||||
for (let i=0; i <widgetClones.length; i++){
|
||||
this.$refs.container.removeChild(widgetClones[i]);
|
||||
}
|
||||
|
||||
if (!this.active || this.x < 0 || this.y < 0 || this.x >= this.cols)
|
||||
@@ -528,6 +535,7 @@ export default {
|
||||
return updated;
|
||||
},
|
||||
emptyTileClicked() {
|
||||
this.additionalRowComputed = false;
|
||||
this.$emit('newItem', this.x, this.y);
|
||||
},
|
||||
updateCursorOnMouseMove(evt){
|
||||
@@ -614,7 +622,7 @@ export default {
|
||||
<TransitionGroup tag="div">
|
||||
<grid-item
|
||||
ref="gridItems"
|
||||
v-for="(item,index) in ((mode != 1 || mode != 2) && active ? placedItems_withPlaceholders : placedItems)"
|
||||
v-for="(item,index) in ((mode != 1 && mode != 2) && active ? placedItems_withPlaceholders : placedItems)"
|
||||
:key="item.data.id"
|
||||
:item="item"
|
||||
@start-move="startMove"
|
||||
@@ -623,8 +631,8 @@ export default {
|
||||
@start-resize="startResize"
|
||||
@dragging="dragging"
|
||||
@end-drag="dragCancel"
|
||||
@drop-drag="dragEnd"
|
||||
@touchEvent="updateCursorOnMouseMove"
|
||||
@touch-end="dragEnd();mouseUp();"
|
||||
@touch-start="updateCursorOnMouseMove($event); mouseDown();"
|
||||
class="position-absolute"
|
||||
:active="active"
|
||||
:style="{
|
||||
|
||||
@@ -17,7 +17,8 @@ export default {
|
||||
"endDrag",
|
||||
"dropDrag",
|
||||
"item",
|
||||
"touchEvent"
|
||||
"touchStart",
|
||||
"touchEnd",
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
@@ -54,16 +55,16 @@ export default {
|
||||
},
|
||||
touchDragEnd(evt) {
|
||||
if (!this.dragging)
|
||||
//return evt.preventDefault();
|
||||
return;
|
||||
return;
|
||||
this.dragging = false;
|
||||
this.$emit('dropDrag', evt);
|
||||
this.$emit('touchEnd', evt);
|
||||
},
|
||||
touchStart(event){
|
||||
this.$emit('touchEvent', event);
|
||||
this.$emit('touchStart', event);
|
||||
this.registerDragAction(event);
|
||||
this.tryDragStart(event, this.item);
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
template: `
|
||||
<div class="drop-grid-item"
|
||||
@@ -73,7 +74,7 @@ export default {
|
||||
@touchend="touchDragEnd"
|
||||
@dragstart="tryDragStart($event, item)"
|
||||
@drag="$emit('dragging',$event)"
|
||||
@touchmove="$emit('dragging',$event)"
|
||||
@touchmove.prevent="$emit('dragging',$event)"
|
||||
@dragend="$emit('endDrag', $event)"
|
||||
:draggable="active && !item.placeholder && dragAction != ''">
|
||||
<slot v-bind="item"></slot>
|
||||
|
||||
@@ -74,6 +74,8 @@ require_once('dbupdate_3.4/55968_index_anrechnung.php');
|
||||
require_once('dbupdate_3.4/25999_locale_update.php');
|
||||
require_once('dbupdate_3.4/55289_pep_fine_tuning.php');
|
||||
require_once('dbupdate_3.4/55614_perm_verwaltetoe.php');
|
||||
require_once('dbupdate_3.4/61730_Dashboard_Anpassungen.php');
|
||||
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
$result = @$db->db_query("SELECT preset_id FROM dashboard.tbl_dashboard_preset WHERE preset ? 'widgets'");
|
||||
$result_num_rows = $db->db_num_rows($result);
|
||||
$errorList = array();
|
||||
for($i = 0; $i < $result_num_rows; $i++)
|
||||
{
|
||||
$row = $db->db_fetch_object($result, $i);
|
||||
|
||||
$qry = "
|
||||
UPDATE dashboard.tbl_dashboard_preset
|
||||
SET preset =
|
||||
COALESCE(
|
||||
(SELECT jsonb_object_agg(keys,values) FROM (
|
||||
SELECT key AS keys,jsonb_build_object('widgets',to_jsonb(value)) AS values
|
||||
FROM jsonb_each(preset->'widgets')
|
||||
) AS subquery
|
||||
),preset)
|
||||
WHERE preset_id = ".$row->preset_id;
|
||||
|
||||
$db->db_query($qry);
|
||||
if (!$db->db_query($qry))
|
||||
array_push($errorList,'<br><strong>dashboard.tbl_dashboard_preset: ' . $db->db_last_error() . '</strong><br>') ;
|
||||
|
||||
}
|
||||
|
||||
$result = @$db->db_query("SELECT override_id FROM dashboard.tbl_dashboard_benutzer_override WHERE override ? 'widgets'");
|
||||
$result_num_rows = $db->db_num_rows($result);
|
||||
for($i = 0; $i < $result_num_rows; $i++)
|
||||
{
|
||||
$row = $db->db_fetch_object($result, $i);
|
||||
|
||||
$qry = "
|
||||
UPDATE dashboard.tbl_dashboard_benutzer_override
|
||||
SET override =
|
||||
COALESCE(
|
||||
(SELECT jsonb_object_agg(keys,values) FROM (
|
||||
SELECT key AS keys,jsonb_build_object('widgets',to_jsonb(value)) AS values
|
||||
FROM jsonb_each(override->'widgets')
|
||||
) AS subquery
|
||||
),override)
|
||||
WHERE override_id = ".$row->override_id;
|
||||
|
||||
$db->db_query($qry);
|
||||
if (!$db->db_query($qry))
|
||||
array_push($errorList,'<br><strong>dashboard.tbl_dashboard_benutzer_override: ' . $db->db_last_error() . '</strong><br>') ;
|
||||
|
||||
}
|
||||
|
||||
if(empty($errorList)){
|
||||
echo '<br>successfully updated dashboard.tbl_dashboard_preset and dashboard.tbl_dashboard_benutzer_override';
|
||||
}
|
||||
else{
|
||||
foreach($errorList as $error){
|
||||
echo $error;
|
||||
}
|
||||
}
|
||||
@@ -40581,6 +40581,26 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'dashboard',
|
||||
'phrase' => 'addLine',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Weitere Zeile hinzufügen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Add another line',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'dashboard',
|
||||
|
||||
Reference in New Issue
Block a user