22import {
33 PropType , defineComponent , nextTick , ref , watch ,
44} from ' vue' ;
5- import * as d3 from ' d3' ;
65import UVdatApi from ' ../../api/UVDATApi' ;
76import { FeatureGraphData , VectorFeatureTableGraph } from ' ../../types' ;
7+ import { renderVectorFeatureGraph } from ' ./vectorFeatureGraphUtils' ;
88
99export default defineComponent ({
1010 name: ' FeatureGraph' ,
@@ -17,91 +17,48 @@ export default defineComponent({
1717 type: Number as PropType <number >,
1818 required: true ,
1919 },
20+ mapLayerId: {
21+ type: Number ,
22+ required: true ,
23+ },
2024 },
2125 setup(props ) {
2226 const graphContainer = ref <SVGSVGElement | null >(null );
2327 const graphDialogContainer = ref <SVGSVGElement | null >(null );
2428 const graphData = ref <FeatureGraphData | null >(null );
2529 const dialogVisible = ref (false );
26-
27- // Render graph using D3
28- const renderGraph = (data : FeatureGraphData , container = ' graphContainer' ) => {
29- const localContainer = container === ' graphContainer' ? graphContainer : graphDialogContainer ;
30- if (! localContainer .value || ! data ) return ;
31-
32- const svg = d3 .select (localContainer .value );
33- svg .selectAll (' *' ).remove (); // Clear any existing content in the SVG
34-
35- const margin = {
36- top: 20 , right: container === ' graphContainer' ? 0 : 20 , bottom: 40 , left: 40 ,
37- };
38-
39- // Set the maximum width to 250px
40- const width = localContainer .value ?.clientWidth || 250 - margin .left - margin .right ;
41- const height = 400 - margin .top - margin .bottom ;
42-
43- const x = d3 .scaleLinear ().range ([0 , width ]);
44- const y = d3 .scaleLinear ().range ([height , 0 ]);
45-
46- const line = d3 .line ()
47- .x ((d : [number , number ]) => x (d [0 ]))
48- .y ((d : [number , number ]) => y (d [1 ]));
49-
50- let dataForGraph: { data: [number , number ][], filterVal? : string } | undefined ;
51-
52- // Check for default data or apply filter if necessary
53- if (data .graphs [props .vectorFeatureId ]) {
54- dataForGraph = data .graphs [props .vectorFeatureId ];
55- }
56-
57- if (! dataForGraph ) {
58- return ; // Return if no data is available
59- }
60-
61- // Set the domain for the axes, ensuring we handle empty arrays correctly
62- const xExtent = d3 .extent (dataForGraph .data .map ((item ) => item [0 ]));
63- const yExtent = d3 .extent (dataForGraph .data .map ((item ) => item [1 ]));
64-
65- // Fallback to zero if data is empty
66- x .domain (xExtent [0 ] !== undefined ? xExtent : [0 , 1 ]);
67- y .domain (yExtent [0 ] !== undefined ? yExtent : [0 , 1 ]);
68-
69- // Create the graph container
70- const g = svg .append (' g' )
71- .attr (' transform' , ` translate(${margin .left },${margin .top }) ` );
72-
73- // Add the line path to the graph
74- svg .append (' path' )
75- .attr (' fill' , ' none' )
76- .attr (' stroke' , ' steelblue' )
77- .attr (' stroke-width' , 1.5 )
78- .attr (' d' , line (dataForGraph .data .sort ((a , b ) => a [0 ] - b [0 ])))
79- .attr (' transform' , ` translate(${margin .left },${margin .top }) ` );
80-
81- // Add the X-axis
82- g .append (' g' )
83- .attr (' class' , ' x axis' )
84- .attr (' transform' , ` translate(0,${height }) ` )
85- .call (d3 .axisBottom (x ).ticks (5 ));
86-
87- // Add the Y-axis
88- g .append (' g' )
89- .attr (' class' , ' y axis' )
90- .call (d3 .axisLeft (y ));
91- };
30+ const noGraphData = ref (false );
9231
9332 // Fetch feature graph data when component is mounted or props change
9433 const fetchFeatureGraphData = async () => {
34+ noGraphData .value = false ;
9535 try {
9636 const data = await UVdatApi .getFeatureGraphData (
9737 props .graphInfo .type , // Use graphInfo.type (tableType) instead of mapLayerId
9838 props .vectorFeatureId ,
9939 props .graphInfo .xAxis ,
10040 props .graphInfo .yAxis ,
101- props .graphInfo .indexer ,
10241 );
42+ if (data .graphs && Object .keys (data .graphs ).length === 0 ) {
43+ noGraphData .value = true ;
44+ return ;
45+ }
10346 graphData .value = data ;
104- renderGraph (data );
47+ if (graphContainer .value ) {
48+ nextTick (() => {
49+ if (graphContainer .value ) {
50+ renderVectorFeatureGraph (
51+ data ,
52+ graphContainer .value ,
53+ {
54+ specificGraphKey: props .vectorFeatureId ,
55+ xAxisIsTime: props .graphInfo .xAxis === ' unix_time' ,
56+ xAxisVerticalLabels: true ,
57+ },
58+ );
59+ }
60+ });
61+ }
10562 } catch (error ) {
10663 // eslint-disable-next-line no-console
10764 console .error (' Error fetching feature graph data:' , error );
@@ -112,15 +69,27 @@ export default defineComponent({
11269 watch (
11370 () => [props .graphInfo , props .vectorFeatureId ],
11471 () => fetchFeatureGraphData (),
115- { immediate: true },
11672 );
73+ watch (graphContainer , () => {
74+ fetchFeatureGraphData ();
75+ });
11776
11877 // Open the dialog to display a larger graph
11978 const openDialog = () => {
12079 dialogVisible .value = true ;
12180 nextTick (() => {
122- if (graphData .value ) {
123- renderGraph (graphData .value , ' graphDialogContainer' );
81+ if (graphData .value && graphDialogContainer .value ) {
82+ renderVectorFeatureGraph (
83+ graphData .value ,
84+ graphDialogContainer .value ,
85+ {
86+ specificGraphKey: props .vectorFeatureId ,
87+ xAxisIsTime: props .graphInfo .xAxis === ' unix_time' ,
88+ showXYValuesOnHover: true ,
89+ xAxisLabel: props .graphInfo .xAxisLabel ,
90+ yAxisLabel: props .graphInfo .yAxisLabel ,
91+ },
92+ );
12493 }
12594 });
12695 };
@@ -131,29 +100,36 @@ export default defineComponent({
131100 graphData ,
132101 dialogVisible ,
133102 openDialog ,
103+ noGraphData ,
134104 };
135105 },
136106});
137107 </script >
138108
139109<template >
140110 <div >
141- <!-- Button to open dialog -->
142- <v-btn color =" primary" @click =" openDialog" >
143- View Larger Graph
144- </v-btn >
145-
146- <!-- Graph container -->
147- <svg ref =" graphContainer" width =" 100%" height =" 400" class =" selectedFeatureSVG" />
148-
149- <!-- Dialog for larger chart -->
111+ <div v-if =" noGraphData" >
112+ <v-alert type =" warning" >
113+ No Data to Graph
114+ </v-alert >
115+ </div >
116+ <div v-if =" graphData" >
117+ <v-btn color =" primary" size =" x-small" @click =" openDialog" >
118+ View Larger Graph
119+ </v-btn >
120+ </div >
121+ <svg ref =" graphContainer" width =" 100%" :height =" graphData ? 400 : 0" class =" selectedFeatureSVG" />
150122 <v-dialog v-model =" dialogVisible" max-width =" 800px" >
151123 <v-card >
152124 <v-card-title >
153- <span class =" headline" >Feature Graph</span >
125+ <v-row >
126+ <v-spacer />
127+ <span class =" headline" >{{ graphInfo.name }}</span >
128+ <v-spacer />
129+ </v-row >
154130 </v-card-title >
155131 <v-card-text >
156- <svg ref =" graphDialogContainer" width =" 100%" height =" 500 " />
132+ <svg ref =" graphDialogContainer" width =" 100%" height =" 400 " />
157133 </v-card-text >
158134 <v-card-actions >
159135 <v-btn @click =" dialogVisible = false" >
0 commit comments