Chart disappeared on refresh

Hello
I need some help.
I am currently using ui template to display my chart and it works just fine. But when I refresh webpage it disappeared.
After Deploy


After Refresh

[
    {
        "id": "auto_inject_trigger_01",
        "type": "inject",
        "z": "4e40fbd2a88aea91",
        "name": "Daily Total ",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "900",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "triggerAutoDailyTotal",
        "payload": "",
        "payloadType": "date",
        "x": 250,
        "y": 620,
        "wires": [
            [
                "auto_func_set_date_sql_01"
            ]
        ]
    },
    {
        "id": "auto_func_set_date_sql_01",
        "type": "function",
        "z": "4e40fbd2a88aea91",
        "name": "Set Current UTC Date & SQL",
        "func": "const now = new Date();\n\nconst year = now.getUTCFullYear();\nconst month_0idx = now.getUTCMonth();\nconst day = now.getUTCDate();\n\nconst reportDateUTCObj = new Date(Date.UTC(year, month_0idx, day, 0, 0, 0, 0));\n\nconst dateForQuery = reportDateUTCObj.getUTCFullYear() + '-' +\n    (reportDateUTCObj.getUTCMonth() + 1).toString().padStart(2, '0') + '-' +\n    reportDateUTCObj.getUTCDate().toString().padStart(2, '0');\n\nconst startTimeSQL = `${dateForQuery} 00:00:00.000`;\nconst endTimeSQL = `${dateForQuery} 23:59:59.999`;\n\nmsg.payload = `\n    SELECT\n    [Time],\n    SUM(Total) AS Total \nFROM\n    dbo.batch\nWHERE\n    [Time] >= CONVERT(datetime, '${startTimeSQL}', 120)\n    AND [Time] <= CONVERT(datetime, '${endTimeSQL}', 120)\nGROUP BY\n    [Time]\nORDER BY\n    [Time] ASC;\n`;\n\nmsg.reportDateForUTCDay = reportDateUTCObj; \nconst displayDateForStatus = reportDateUTCObj.toLocaleDateString('en-GB', { timeZone: 'UTC' });\n\nnode.log(\"AutoDailyTotal: Querying for \" + displayDateForStatus + \" (UTC Day)\");\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 480,
        "y": 620,
        "wires": [
            [
                "auto_mssql_data_01"
            ]
        ]
    },
    {
        "id": "auto_mssql_data_01",
        "type": "MSSQL",
        "z": "4e40fbd2a88aea91",
        "mssqlCN": "8baf7e1e28030a6d",
        "name": "Get Current Day Data",
        "outField": "payload",
        "returnType": 0,
        "throwErrors": "1",
        "query": "",
        "modeOpt": "queryMode",
        "modeOptType": "query",
        "queryOpt": "payload",
        "queryOptType": "editor",
        "paramsOpt": "queryParams",
        "paramsOptType": "none",
        "rows": "",
        "rowsType": "msg",
        "parseMustache": true,
        "params": [],
        "x": 780,
        "y": 620,
        "wires": [
            [
                "auto_func_calculate_sum_01",
                "36f6f7e1b733d31b"
            ]
        ]
    },
    {
        "id": "auto_func_calculate_sum_01",
        "type": "function",
        "z": "4e40fbd2a88aea91",
        "name": "Calc Auto Daily Sum (7AM-7PM UTC)",
        "func": "const batchData = msg.payload;\nconst reportDateUTCObjInput = msg.reportDateForUTCDay;\n\nlet reportDateStringForDisplay = \"an unspecified UTC date\";\nlet reportDateUTCObj = null;\n\nif (reportDateUTCObjInput) {\n    reportDateUTCObj = new Date(reportDateUTCObjInput);\n    if (isNaN(reportDateUTCObj.getTime())) {\n        reportDateUTCObj = null;\n    } else {\n        reportDateStringForDisplay = reportDateUTCObj.toLocaleDateString('en-GB', { timeZone: 'UTC' });\n    }\n}\n\nif (!reportDateUTCObj) {\n    msg.payload = \"Today's Total (7AM-7PM UTC): Error - Date Invalid\";\n    node.warn(\"AutoDailySum Calc: Invalid date object received.\");\n    return msg;\n}\n\nif (!Array.isArray(batchData)) {\n    node.warn(\"AutoDailySum Calc: Input batchData is not an array for \" + reportDateStringForDisplay + \" (UTC).\");\n    msg.payload = \"Today's Total (7AM-7PM UTC) for \" + reportDateStringForDisplay + \": Error fetching data\";\n    return msg;\n}\n\nlet dailyTotalOutputSum = 0;\nlet dataFoundInTimeRange = false;\n\nbatchData.forEach((item, index) => {\n    if (!item || typeof item.Time === 'undefined' || item.Total === null || typeof item.Total === 'undefined') {\n        return;\n    }\n    const itemTime = new Date(item.Time);\n    if (isNaN(itemTime.getTime())) {\n        return;\n    }\n\n    // SQL already filters by day, but double-check for safety if needed (usually not with this setup)\n    // if (itemTime.getUTCFullYear() !== reportDateUTCObj.getUTCFullYear() || ... ) return;\n\n    const itemHourUTC = itemTime.getUTCHours();\n    const itemTotal = parseFloat(item.Total);\n\n    if (itemHourUTC >= 7 && itemHourUTC < 19) { // Sum for 07:00 UTC to 18:59 UTC\n        if (!isNaN(itemTotal)) {\n            dailyTotalOutputSum += itemTotal;\n            dataFoundInTimeRange = true;\n        }\n    }\n});\n\nlet dailyTotalString;\nif (batchData.length === 0 && !dataFoundInTimeRange) { // No data returned from SQL at all for the day\n    dailyTotalString = \"Current Output: No data\";\n} else if (!dataFoundInTimeRange) { // Data existed for the day, but none in the 7AM-7PM range\n    dailyTotalString = \"Current Output: 0\";\n} else {\n    dailyTotalString = \"Current Output: \" + dailyTotalOutputSum.toLocaleString();\n}\n\nmsg.payload = dailyTotalString;\nnode.log(\"AutoDailySum Calc: \" + msg.payload);\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1090,
        "y": 620,
        "wires": [
            [
                "78a071dec8d0aca5"
            ]
        ]
    },
    {
        "id": "78a071dec8d0aca5",
        "type": "ui-text",
        "z": "4e40fbd2a88aea91",
        "group": "1f528672fb91aed2",
        "order": 8,
        "width": 0,
        "height": 0,
        "name": "Output",
        "label": "",
        "format": "{{msg.payload}}",
        "layout": "row-center",
        "style": true,
        "font": "",
        "fontSize": "35",
        "color": "#000000",
        "wrapText": false,
        "className": "",
        "x": 1350,
        "y": 620,
        "wires": []
    },
    {
        "id": "36f6f7e1b733d31b",
        "type": "function",
        "z": "4e40fbd2a88aea91",
        "name": "Daily Hourly Chart Data",
        "func": "const rawData = msg.payload;\n\n// --- Logic for data preparation (same core logic as before) ---\nif (!Array.isArray(rawData)) {\n    node.status({ fill: \"red\", shape: \"ring\", text: \"Input data is not an array\" });\n    // Send empty data for the template to handle\n    msg.payload = { labels: [], datasets: [] };\n    msg.options = {\n        plugins: { title: { display: true, text: 'Hourly Output vs. Target (Data Error)' } }\n    };\n    return msg;\n}\n\nconst hourlyTotals = {};\nconst desiredHoursUTC = [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];\nconst xLabels = [\n    \"7AM-8AM\", \"8AM-9AM\", \"9AM-10AM\", \"10AM-11AM\",\n    \"11AM-12PM\", \"12PM-1PM\", \"1PM-2PM\", \"2PM-3PM\",\n    \"3PM-4PM\", \"4PM-5PM\", \"5PM-6PM\", \"6PM-7PM\"\n];\n\ndesiredHoursUTC.forEach(hour => {\n    hourlyTotals[hour] = 0;\n});\n\nlet dataFoundForChart = false;\nrawData.forEach(item => {\n    if (!item || typeof item.Time === 'undefined' || item.Total === null || typeof item.Total === 'undefined') {\n        return;\n    }\n    const itemTime = new Date(item.Time);\n    if (isNaN(itemTime.getTime())) {\n        return;\n    }\n    const itemHourUTC = itemTime.getUTCHours();\n    if (itemHourUTC >= 7 && itemHourUTC < 19) { // UTC 7:00 to 18:59\n        const itemTotal = parseFloat(item.Total);\n        if (!isNaN(itemTotal)) {\n            if (hourlyTotals.hasOwnProperty(itemHourUTC)) {\n                hourlyTotals[itemHourUTC] += itemTotal;\n                dataFoundForChart = true;\n            }\n        }\n    }\n});\n\nconst actualOutputValues = [];\ndesiredHoursUTC.forEach(hour => {\n    actualOutputValues.push(hourlyTotals[hour]);\n});\n\nconst committedHourlyTarget = flow.get(\"currentHourlyTarget\");\nlet targetOutputValues = new Array(xLabels.length).fill(null);\n\nif (committedHourlyTarget !== null && typeof committedHourlyTarget === 'number' && !isNaN(committedHourlyTarget)) {\n    targetOutputValues = new Array(xLabels.length).fill(committedHourlyTarget);\n}\n\nif (!dataFoundForChart && rawData.length > 0 && committedHourlyTarget === null) {\n    node.status({ fill: \"yellow\", shape: \"ring\", text: \"Actuals out of range, no target\" });\n} else if (!dataFoundForChart && committedHourlyTarget === null) {\n    node.status({ fill: \"yellow\", shape: \"ring\", text: \"No actuals data, no target\" });\n} else {\n    node.status({ fill: \"green\", shape: \"dot\", text: \"Combined chart data prepared\" });\n}\nmsg.payload = {\n    labels: xLabels,\n    datasets: [\n        {\n            label: \"Hourly Output\", // BAR chart\n            data: actualOutputValues,\n            type: 'bar',\n            backgroundColor: 'rgba(54, 162, 235, 0.5)', // Blue\n            borderColor: 'rgb(54, 162, 235)',\n            borderWidth: 1,\n            yAxisID: 'yBar'\n        },\n        {\n            label: \"Target Output\", // LINE chart\n            data: targetOutputValues,\n            type: 'line',\n            fill: false,\n            borderColor: 'rgb(255, 99, 132)', // Red\n            tension: 0.1,\n            yAxisID: 'yLine'\n        }\n    ]\n};\n\nmsg.options = { // Chart.js options\n    responsive: true,\n    maintainAspectRatio: false,\n    interaction: {\n        mode: 'index',\n        intersect: false,\n    },\n    stacked: false,\n    plugins: {\n        title: {\n            display: true,\n            text: 'Hourly Output vs. Target Output (7AM-7PM UTC)'\n        },\n        legend: {\n            position: 'top',\n        }\n    },\n    scales: {\n        x: {\n            display: true,\n            title: {\n                display: false,\n                text: 'Time Slot'\n            }\n        },\n        yBar: {\n            type: 'linear',\n            display: true,\n            position: 'left',\n            title: {\n                display: true,\n                text: 'Hourly Output'\n            },\n            beginAtZero: true\n        },\n        yLine: {\n            type: 'linear',\n            display: true,\n            position: 'right',\n            title: {\n                display: true,\n                text: 'Target Output'\n            },\n            grid: {\n                drawOnChartArea: false,\n            },\n            beginAtZero: true\n        }\n    }\n};\n\nreturn msg;\n/*\n// TEMPORARY TEST CODE FOR \"Daily Hourly Chart Data\" (36f6f7e1b733d31b)\nnode.warn(\"Sending TEST message from Output Chart Function\");\nmsg.payload = {\n    testProperty: \"This is a TEST payload from the server function for output chart\",\n    labels: [\"Test1\", \"Test2\"],\n    datasets: [{label: \"Test Data\", data: [1,2], type: 'line'}]\n};\nmsg.options = { testOption: \"Test option value\" };\nmsg.distinctMarker = \"FROM_OUTPUT_CHART_FUNCTION_36f6f7e1b733d31b\"; // Add a very unique marker\nreturn msg;\n*/",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1070,
        "y": 800,
        "wires": [
            [
                "47dc19ff18262555",
                "0d7f850d62581469"
            ]
        ]
    },
    {
        "id": "47dc19ff18262555",
        "type": "ui-template",
        "z": "4e40fbd2a88aea91",
        "group": "1f528672fb91aed2",
        "page": "",
        "ui": "",
        "name": "",
        "order": 1,
        "width": "12",
        "height": "12",
        "head": "",
        "format": "<script src=\"https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js\"></script>\n<div style=\"width: 100%; height: 100%; position: relative;\">\n    <canvas ref=\"chartCanvasElement\"></canvas>\n</div>\n\n<script>\n    let chartInstance = null;\n\n    const renderOrUpdateChart = (currentMsg) => {\n        console.log('Output Chart Template - renderOrUpdateChart CALLED with currentMsg:', JSON.parse(JSON.stringify(currentMsg || {note: \"currentMsg was null/undefined\"})));\n        this.$nextTick(() => {\n            if (!this.$refs.chartCanvasElement) {\n                console.warn('Output Chart Template: Canvas element not found.');\n                return;\n            }\n            const canvas = this.$refs.chartCanvasElement;\n            const ctx = canvas.getContext('2d');\n            if (!ctx) {\n                console.error('Output Chart Template: Failed to get 2D context.');\n                return;\n            }\n            if (chartInstance) {\n                chartInstance.destroy();\n                chartInstance = null;\n            }\n            if (typeof Chart === 'undefined') {\n                console.error('Output Chart Template: Chart.js not loaded!');\n                ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.font = \"16px Arial\"; ctx.fillStyle = \"red\"; ctx.textAlign = \"center\"; ctx.fillText(\"Chart.js not loaded.\", canvas.width / 2, canvas.height / 2);\n                return;\n            }\n\n            const hasMsg = !!currentMsg;\n            const hasPayload = !!(currentMsg && currentMsg.payload);\n            const hasDatasets = !!(currentMsg && currentMsg.payload && typeof currentMsg.payload.datasets !== 'undefined' && currentMsg.payload.datasets !== null && Array.isArray(currentMsg.payload.datasets));\n            const hasLabels = !!(currentMsg && currentMsg.payload && typeof currentMsg.payload.labels !== 'undefined' && currentMsg.payload.labels !== null && Array.isArray(currentMsg.payload.labels));\n            console.log(`Output Chart Template - DATA CHECK: hasMsg: ${hasMsg}, hasPayload: ${hasPayload}, hasDatasets: ${hasDatasets}, hasLabels: ${hasLabels}`);\n            if(hasPayload) {\n                console.log('Output Chart Template - currentMsg.payload content:', JSON.parse(JSON.stringify(currentMsg.payload)));\n            }\n\n            if (hasMsg && hasPayload && hasDatasets && hasLabels && currentMsg.payload.datasets.length > 0) {\n                console.log('Output Chart Template: Valid data found. Creating chart.');\n                // ... (rest of your chart creation logic using currentMsg.payload and currentMsg.options)\n                const chartData = { labels: currentMsg.payload.labels, datasets: currentMsg.payload.datasets };\n                const chartOptions = currentMsg.options || { responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: 'Chart' } } };\n                chartInstance = new Chart(ctx, { data: chartData, options: chartOptions });\n            } else {\n                console.log('Output Chart Template: No valid data to draw. Displaying \"Waiting for data...\"');\n                ctx.clearRect(0, 0, canvas.width, canvas.height);\n                ctx.font = \"16px Arial\"; ctx.fillStyle = \"grey\"; ctx.textAlign = \"center\";\n                ctx.fillText(\"Waiting for data...\", canvas.width / 2, canvas.height / 2);\n            }\n        });\n    };\n\n    console.log('Output Chart Template - Script evaluating. Initial this.msg:', JSON.parse(JSON.stringify(this.msg || {note: \"this.msg was null/undefined\"})));\n    \n    if (this.msg && this.msg.payload && this.msg.payload.datasets) { // Check if msg has data from resendOnRefresh\n        renderOrUpdateChart(this.msg);\n    } else {\n        // If no valid initial data (e.g. from resendOnRefresh), display \"Waiting\" and request it.\n        renderOrUpdateChart(null); \n        if (this.send) { // this.send is available in Dashboard 2.0 ui-template\n            console.log('Output Chart Template: Requesting initial data...');\n            this.send({topic: \"REQUEST_OUTPUT_CHART_DATA\", requestTime: Date.now()});\n        } else {\n            console.error('Output Chart Template: this.send is not available to request data.');\n        }\n    }\n</script>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 1280,
        "y": 800,
        "wires": [
            [
                "80b9dc6e0aa7906f"
            ]
        ]
    },
    {
        "id": "71f2f0954ec54534",
        "type": "link in",
        "z": "4e40fbd2a88aea91",
        "name": "Trigger output",
        "links": [
            "c91128631132c36f"
        ],
        "x": 285,
        "y": 680,
        "wires": [
            [
                "auto_func_set_date_sql_01"
            ]
        ]
    },
    {
        "id": "c91128631132c36f",
        "type": "link out",
        "z": "4e40fbd2a88aea91",
        "name": "Send Trigger for Output Chart Refresh",
        "mode": "link",
        "links": [
            "71f2f0954ec54534"
        ],
        "x": 1555,
        "y": 800,
        "wires": []
    },
    {
        "id": "80b9dc6e0aa7906f",
        "type": "switch",
        "z": "4e40fbd2a88aea91",
        "name": "",
        "property": "topic",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "REQUEST_OUTPUT_CHART_DATA",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 1430,
        "y": 800,
        "wires": [
            [
                "c91128631132c36f"
            ]
        ]
    },
    {
        "id": "0d7f850d62581469",
        "type": "debug",
        "z": "4e40fbd2a88aea91",
        "name": "debug 4",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1280,
        "y": 920,
        "wires": []
    },
    {
        "id": "8baf7e1e28030a6d",
        "type": "MSSQL-CN",
        "tdsVersion": "7_4",
        "name": "i4.0",
        "server": "10.183.175.8",
        "port": "1433",
        "encyption": true,
        "trustServerCertificate": true,
        "database": "i4.0",
        "useUTC": true,
        "connectTimeout": "15000",
        "requestTimeout": "15000",
        "cancelTimeout": "5000",
        "pool": "10",
        "parseJSON": false,
        "enableArithAbort": true,
        "readOnlyIntent": false
    },
    {
        "id": "1f528672fb91aed2",
        "type": "ui-group",
        "name": "Delta SA 03",
        "page": "8ad4c897bc98235a",
        "width": "6",
        "height": 1,
        "order": 3,
        "showTitle": false,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "8ad4c897bc98235a",
        "type": "ui-page",
        "name": "Main Page",
        "ui": "e37b297fa64e1312",
        "path": "/page3",
        "icon": "home",
        "layout": "grid",
        "theme": "8796486dd6098e1f",
        "breakpoints": [
            {
                "name": "Default",
                "px": "0",
                "cols": "3"
            },
            {
                "name": "Tablet",
                "px": "576",
                "cols": "6"
            },
            {
                "name": "Small Desktop",
                "px": "768",
                "cols": "9"
            },
            {
                "name": "Desktop",
                "px": "1024",
                "cols": "12"
            }
        ],
        "order": 1,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "e37b297fa64e1312",
        "type": "ui-base",
        "name": "My Dashboard",
        "path": "/dashboard",
        "appIcon": "",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control",
            "ui-text",
            "ui-text-input"
        ],
        "showPathInSidebar": false,
        "headerContent": "page",
        "navigationStyle": "default",
        "titleBarStyle": "fixed",
        "showReconnectNotification": true,
        "notificationDisplayTime": 1,
        "showDisconnectNotification": true,
        "allowInstall": true
    },
    {
        "id": "8796486dd6098e1f",
        "type": "ui-theme",
        "name": "Theme 2",
        "colors": {
            "surface": "#0f0f0f",
            "primary": "#050505",
            "bgPage": "#767474",
            "groupBg": "#d8d4d4",
            "groupOutline": "#ffffff"
        },
        "sizes": {
            "density": "default",
            "pagePadding": "12px",
            "groupGap": "4px",
            "groupBorderRadius": "4px",
            "widgetGap": "1px"
        }
    }
]

I did tried using the link in and link out but I don't know if I'm using it right.
Any advice would be appreciated.