2023-11-25 06:17:45 +00:00
< script setup lang = "ts" >
2023-11-26 06:02:16 +00:00
import { ref , onMounted , reactive , nextTick , shallowRef } from "vue" ;
2023-11-25 06:18:18 +00:00
import { Modal } from "bootstrap" ;
2023-11-25 06:17:45 +00:00
import { setActivePinia } from "pinia" ;
import pinia from "../store/index" ;
setActivePinia ( pinia ) ;
2023-11-25 06:18:18 +00:00
import "../../node_modules/gridstack/dist/gridstack.min.css" ;
2023-11-25 06:17:45 +00:00
import { GridStack } from "gridstack" ;
import { settingsStore as settings } from "../store/settingsStore.js" ;
2023-11-26 18:32:42 +00:00
import active _heard _stations from "./grid_active_heard_stations.vue" ;
2023-11-26 18:52:04 +00:00
import mini _heard _stations from "./grid_active_heard_stations_mini.vue" ;
2023-12-03 18:02:40 +00:00
import active _stats from "./grid_active_stats.vue" ;
import active _audio _level from "./grid_active_audio.vue" ;
2023-12-03 23:39:06 +00:00
import active _rig _control from "./grid_active_rig_control.vue" ;
import active _broadcats from "./grid_active_broadcasts.vue" ;
2023-12-03 18:02:40 +00:00
import s _meter from "./grid_s-meter.vue" ;
import dbfs _meter from "./grid_dbfs.vue" ;
2023-12-05 03:24:58 +00:00
import grid _activities from "./grid_activities.vue" ;
2023-11-25 06:17:45 +00:00
import { stateDispatcher } from "../js/eventHandler" ;
2023-11-26 06:02:16 +00:00
2023-11-25 06:17:45 +00:00
let count = ref ( 0 ) ;
let info = ref ( "" ) ;
let gridFloat = ref ( false ) ;
let color = ref ( "black" ) ;
let gridInfo = ref ( "" ) ;
let grid = null ; // DO NOT use ref(null) as proxies GS will break all logic when comparing structures... see https://github.com/gridstack/gridstack.js/issues/2115
let items = ref ( [ ] ) ;
2023-11-26 06:07:52 +00:00
class gridWidget {
2023-11-26 06:02:16 +00:00
component2 ;
size ;
text ;
constructor ( component , size , text ) {
this . component2 = component ;
this . size = size ;
this . text = text ;
}
}
const gridWidgets = [
2023-11-26 06:07:52 +00:00
new gridWidget (
active _heard _stations ,
{ x : 0 , y : 0 , w : 7 , h : 20 } ,
"Heard stations" ,
) ,
new gridWidget (
active _stats ,
2023-12-03 18:02:40 +00:00
{ x : 0 , y : 0 , w : 4 , h : 35 } ,
2023-11-26 06:07:52 +00:00
"Stats (waterfall, etc)" ,
) ,
2023-12-03 23:39:06 +00:00
new gridWidget ( active _audio _level , { x : 0 , y : 0 , w : 4 , h : 13 } , "Audio" ) ,
2023-11-26 06:07:52 +00:00
new gridWidget (
active _rig _control ,
{ x : 0 , y : 0 , w : 6 , h : 12 } ,
"Rig control" ,
) ,
2023-12-03 23:39:06 +00:00
new gridWidget ( active _broadcats , { x : 1 , y : 1 , w : 4 , h : 12 } , "Broadcats" ) ,
2023-11-26 18:52:04 +00:00
new gridWidget (
mini _heard _stations ,
2023-12-03 23:39:06 +00:00
{ x : 1 , y : 1 , w : 3 , h : 27 } ,
2023-11-26 18:52:04 +00:00
"Mini Heard stations" ,
) ,
2023-12-04 03:49:02 +00:00
new gridWidget ( s _meter , { x : 1 , y : 1 , w : 2 , h : 4 } , "S-Meter" ) ,
new gridWidget ( dbfs _meter , { x : 1 , y : 1 , w : 2 , h : 4 } , "Dbfs Meter" ) ,
2023-12-05 03:27:35 +00:00
new gridWidget ( grid _activities , { x : 1 , y : 1 , w : 3 , h : 27 } , "Activities" ) ,
2023-11-26 06:02:16 +00:00
] ;
2023-11-25 06:18:18 +00:00
onMounted ( ( ) => {
grid = GridStack . init ( {
// DO NOT user grid.value = GridStack.init(), see above
float : true ,
2023-11-26 06:02:16 +00:00
cellHeight : "10px" ,
minRow : 50 ,
margin : 5 ,
2023-12-05 03:24:58 +00:00
draggable : {
scroll : true ,
} ,
2023-12-03 18:02:40 +00:00
resizable : {
2023-12-04 03:49:02 +00:00
handles : "se,sw" ,
} ,
2023-11-25 06:18:18 +00:00
} ) ;
2023-11-25 06:17:45 +00:00
2023-11-25 06:18:18 +00:00
grid . on ( "dragstop" , function ( event , element ) {
const node = element . gridstackNode ;
info . value = ` you just dragged node # ${ node . id } to ${ node . x } , ${ node . y } – good job! ` ;
} ) ;
grid . on ( "change" , onChange ) ;
// gridFloat.value = grid.float();
} ) ;
function changeFloat ( ) {
gridFloat . value = ! gridFloat . value ;
grid . float ( gridFloat . value ) ;
}
function onChange ( event , changeItems ) {
updateInfo ( ) ;
// update item position
changeItems . forEach ( ( item ) => {
var widget = items . value . find ( ( w ) => w . id == item . id ) ;
if ( ! widget ) {
alert ( "Widget not found: " + item . id ) ;
return ;
}
widget . x = item . x ;
widget . y = item . y ;
widget . w = item . w ;
widget . h = item . h ;
} ) ;
}
function addNewWidget2 ( componentToAdd ) {
2023-11-26 06:07:52 +00:00
const node = items [ count . value ] || { ... componentToAdd . size } ;
2023-11-25 06:18:18 +00:00
node . id = "w_" + count . value ++ ;
2023-11-26 06:07:52 +00:00
node . component2 = shallowRef ( { ... componentToAdd . component2 } ) ;
2023-11-25 06:18:18 +00:00
items . value . push ( node ) ;
nextTick ( ( ) => {
grid . makeWidget ( node . id ) ;
updateInfo ( ) ;
} ) ;
}
function removeLastWidget ( ) {
if ( count . value == 0 ) return ;
var id = ` w_ ${ count . value - 1 } ` ;
var index = items . value . findIndex ( ( w ) => w . id == id ) ;
if ( index < 0 ) return ;
var removed = items . value [ index ] ;
remove ( removed ) ;
}
function remove ( widget ) {
var index = items . value . findIndex ( ( w ) => w . id == widget . id ) ;
items . value . splice ( index , 1 ) ;
const selector = ` # ${ widget . id } ` ;
grid . removeWidget ( selector , false ) ;
updateInfo ( ) ;
}
function updateInfo ( ) {
color . value =
grid . engine . nodes . length == items . value . length ? "black" : "red" ;
gridInfo . value = ` Grid engine: ${ grid . engine . nodes . length } , widgets: ${ items . value . length } ` ;
}
function showModal ( ) {
new Modal ( "#tileModal" , { } ) . show ( ) ;
}
function quickfill ( ) {
2023-11-26 06:02:16 +00:00
gridWidgets . forEach ( async ( gw ) => {
await addNewWidget2 ( gw ) ;
2023-11-26 06:07:52 +00:00
} ) ;
2023-11-25 06:18:18 +00:00
}
2023-11-25 06:17:45 +00:00
< / script >
< template >
2023-12-08 21:20:11 +00:00
< button class = "btn btn-secondary fixed-middle-right rounded-0 rounded-start-4 p-1 pt-4 pb-4" type = "button" data -bs -toggle = " offcanvas " data -bs -target = " # offcanvasGridItems " aria -controls = " offcanvasGridItems " > < i class = "bi bi-grip-vertical h1" > < / i > < / button >
2023-12-05 03:27:35 +00:00
< div class = "grid-container vh-100" >
< div class = "grid-stack" >
< div
v - for = "(w, indexs) in items"
class = "grid-stack-item"
: gs - x = "w.x"
: gs - y = "w.y"
: gs - w = "w.w"
: gs - h = "w.h"
: gs - id = "w.id"
: id = "w.id"
: key = "w.id"
: gs - auto - position = "true"
>
< div class = "grid-stack-item-content" >
< button
@ click = "remove(w)"
class = "btn-close grid-stack-floaty-btn"
> < / button >
< component :is ="w.component2" / >
< / div >
2023-11-25 06:17:45 +00:00
< / div >
< / div >
2023-11-25 06:18:18 +00:00
< / div >
2023-12-08 21:20:11 +00:00
< div class = "offcanvas offcanvas-end" data -bs -scroll = " true " data -bs -backdrop = " true " tabindex = "-1" id = "offcanvasGridItems" aria -labelledby = " offcanvasGridItemsLabel " >
< div class = "offcanvas-header" >
< h5 class = "offcanvas-title" id = "offcanvasGridItemsLabel" >
< button class = "btn btn-secondary" type = "button" @click ="quickfill" > Quickfill grid < / button >
< / h5 >
< button type = "button" class = "btn-close" data -bs -dismiss = " offcanvas " aria -label = " Close " > < / button >
< / div >
< div class = "offcanvas-body" >
< div class = "accordion" id = "accordionExample" >
<!-- Heard Stations -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingHeardStations" >
< button class = "accordion-button" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseHeardStations " aria -expanded = " true " aria -controls = " collapseHeardStations " >
< strong > Heard Stations < / strong >
< / button >
< / h2 >
< div id = "collapseHeardStations" class = "accordion-collapse collapse show" aria -labelledby = " headingHeardStations " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
< button type = "button" @click ="addNewWidget2(gridWidgets[0])" class = "btn btn-outline-secondary" data -bs -dismiss = " modal " > Heard station list < / button >
< / div >
< / div >
< / div >
<!-- Activities -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingActivities" >
< button class = "accordion-button collapsed" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseActivities " aria -expanded = " false " aria -controls = " collapseActivities " >
< strong > Activities < / strong >
< / button >
< / h2 >
< div id = "collapseActivities" class = "accordion-collapse collapse" aria -labelledby = " headingActivities " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
<!-- Content for Activities -- >
< / div >
< / div >
< / div >
<!-- Radio Control -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingRadioControl" >
< button class = "accordion-button collapsed" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseRadioControl " aria -expanded = " false " aria -controls = " collapseRadioControl " >
< strong > Radio Control < / strong >
< / button >
< / h2 >
< div id = "collapseRadioControl" class = "accordion-collapse collapse" aria -labelledby = " headingRadioControl " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
< button type = "button" @click ="addNewWidget2(gridWidgets[3])" class = "btn btn-outline-secondary" data -bs -dismiss = " modal " > Rig Control < / button >
< / div >
< / div >
< / div >
<!-- Audio Control -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingAudioControl" >
< button class = "accordion-button collapsed" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseAudioControl " aria -expanded = " false " aria -controls = " collapseAudioControl " >
< strong > Audio Control < / strong >
< / button >
< / h2 >
< div id = "collapseAudioControl" class = "accordion-collapse collapse" aria -labelledby = " headingAudioControl " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
< button type = "button" @click ="addNewWidget2(gridWidgets[2])" class = "btn btn-outline-secondary" data -bs -dismiss = " modal " > Audio < / button >
< / div >
< / div >
< / div >
<!-- Statistics -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingStatistics" >
< button class = "accordion-button collapsed" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseStatistics " aria -expanded = " false " aria -controls = " collapseStatistics " >
< strong > Statistics < / strong >
< / button >
< / h2 >
< div id = "collapseStatistics" class = "accordion-collapse collapse" aria -labelledby = " headingStatistics " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
< button type = "button" @click ="addNewWidget2(gridWidgets[1])" class = "btn btn-outline-secondary" data -bs -dismiss = " modal " > Stats ( waterfall , etc ) < / button >
2023-11-25 06:17:45 +00:00
< / div >
< / div >
< / div >
2023-12-08 21:20:11 +00:00
<!-- Broadcasts -- >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingBroadcasts" >
< button class = "accordion-button collapsed" type = "button" data -bs -toggle = " collapse " data -bs -target = " # collapseBroadcasts " aria -expanded = " false " aria -controls = " collapseBroadcasts " >
< strong > Broadcasts < / strong >
< / button >
< / h2 >
< div id = "collapseBroadcasts" class = "accordion-collapse collapse" aria -labelledby = " headingBroadcasts " data -bs -parent = " # accordionExample " >
< div class = "accordion-body" >
< button type = "button" @click ="addNewWidget2(gridWidgets[4])" class = "btn btn-outline-secondary" data -bs -dismiss = " modal " > Broadcasts < / button >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
2023-11-25 06:17:45 +00:00
< / template >
2023-12-08 21:20:11 +00:00
2023-11-25 06:17:45 +00:00
< style >
2023-12-08 21:20:11 +00:00
. fixed - middle - right {
position : fixed ; /* Fixed/sticky position */
top : 50 % ; /* Position at the middle of the viewport */
right : 0 px ; /* Place the button 20px from the right */
transform : translateY ( - 50 % ) ; /* Adjust for exact vertical centering */
z - index : 999 ; /* Ensure it's on top of other elements */
}
2023-11-25 06:17:45 +00:00
. grid - stack - item {
text - align : center ;
overflow : auto ;
z - index : 50 ;
}
2023-11-25 06:18:18 +00:00
. grid - stack - floaty - btn {
position : absolute ;
right : 0 px ;
z - index : 1000 ;
float : right ;
2023-11-26 18:32:42 +00:00
top : 6 px ;
2023-11-25 06:17:45 +00:00
}
2023-12-05 03:24:58 +00:00
. grid - container {
2023-12-05 03:27:35 +00:00
overflow - y : auto ;
}
2023-11-25 06:18:18 +00:00
< / style >