From 9a7e791a55b1ad9a8537cc64fcfda74ca73859f3 Mon Sep 17 00:00:00 2001 From: psankhe28 Date: Tue, 29 Aug 2023 22:48:54 +0530 Subject: [PATCH] Logs and Monitoring sevrices code --- .../broadcast-transformer/index.tsx | 318 ++++++++++++++++ .../broadcast-transformer/style.css | 25 ++ src/pages/monitoring/dummy.json | 33 -- src/pages/monitoring/inbound/index.tsx | 321 ++++++++++++++++ src/pages/monitoring/inbound/style.css | 25 ++ src/pages/monitoring/kafka/index.tsx | 21 - .../logs/broadcast-transformer/index.tsx | 359 ++++++++++++++++++ .../logs/broadcast-transformer/style.css | 53 +++ src/pages/monitoring/logs/inbound/index.tsx | 359 ++++++++++++++++++ src/pages/monitoring/logs/inbound/style.css | 53 +++ .../monitoring/logs/orchestrator/index.tsx | 358 +++++++++++++++++ .../monitoring/logs/orchestrator/style.css | 53 +++ src/pages/monitoring/logs/outbound/index.tsx | 358 +++++++++++++++++ src/pages/monitoring/logs/outbound/style.css | 53 +++ .../monitoring/logs/transformer/index.tsx | 358 +++++++++++++++++ .../monitoring/logs/transformer/style.css | 53 +++ src/pages/monitoring/logs/uci-api/index.tsx | 356 +++++++++++++++++ src/pages/monitoring/logs/uci-api/style.css | 53 +++ src/pages/monitoring/orchestrator/index.tsx | 318 ++++++++++++++++ src/pages/monitoring/orchestrator/style.css | 26 ++ src/pages/monitoring/outbound/index.tsx | 315 +++++++++++++++ src/pages/monitoring/outbound/style.css | 25 ++ src/pages/monitoring/overview/card.tsx | 40 ++ src/pages/monitoring/overview/index.tsx | 245 ++++++++---- src/pages/monitoring/overview/style.css | 4 + src/pages/monitoring/transformer/index.tsx | 316 +++++++++++++++ src/pages/monitoring/transformer/style.css | 25 ++ src/pages/monitoring/uci-api/index.tsx | 318 ++++++++++++++++ src/pages/monitoring/uci-api/style.css | 25 ++ 29 files changed, 4732 insertions(+), 134 deletions(-) create mode 100644 src/pages/monitoring/broadcast-transformer/index.tsx create mode 100644 src/pages/monitoring/broadcast-transformer/style.css delete mode 100644 src/pages/monitoring/dummy.json create mode 100644 src/pages/monitoring/inbound/index.tsx create mode 100644 src/pages/monitoring/inbound/style.css delete mode 100644 src/pages/monitoring/kafka/index.tsx create mode 100644 src/pages/monitoring/logs/broadcast-transformer/index.tsx create mode 100644 src/pages/monitoring/logs/broadcast-transformer/style.css create mode 100644 src/pages/monitoring/logs/inbound/index.tsx create mode 100644 src/pages/monitoring/logs/inbound/style.css create mode 100644 src/pages/monitoring/logs/orchestrator/index.tsx create mode 100644 src/pages/monitoring/logs/orchestrator/style.css create mode 100644 src/pages/monitoring/logs/outbound/index.tsx create mode 100644 src/pages/monitoring/logs/outbound/style.css create mode 100644 src/pages/monitoring/logs/transformer/index.tsx create mode 100644 src/pages/monitoring/logs/transformer/style.css create mode 100644 src/pages/monitoring/logs/uci-api/index.tsx create mode 100644 src/pages/monitoring/logs/uci-api/style.css create mode 100644 src/pages/monitoring/orchestrator/index.tsx create mode 100644 src/pages/monitoring/orchestrator/style.css create mode 100644 src/pages/monitoring/outbound/index.tsx create mode 100644 src/pages/monitoring/outbound/style.css create mode 100644 src/pages/monitoring/overview/card.tsx create mode 100644 src/pages/monitoring/transformer/index.tsx create mode 100644 src/pages/monitoring/transformer/style.css create mode 100644 src/pages/monitoring/uci-api/index.tsx create mode 100644 src/pages/monitoring/uci-api/style.css diff --git a/src/pages/monitoring/broadcast-transformer/index.tsx b/src/pages/monitoring/broadcast-transformer/index.tsx new file mode 100644 index 0000000..925c2e4 --- /dev/null +++ b/src/pages/monitoring/broadcast-transformer/index.tsx @@ -0,0 +1,318 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +// import { formatDate, reverseFormatDate } from "../../../utils/functions"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface BroadcastTransformerProps extends React.HTMLAttributes { + theme: string; +} + +export const BroadcastTransformer: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [BroadcastTransformerData, setBroadcastTransformerData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setBroadcastTransformerData(res["Broadcast Transformer".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setBroadcastTransformerData(res["Broadcast Transformer".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(BroadcastTransformerData), + datasets: [ + { + label: "Broadcast Transformer", + data: Object.values(BroadcastTransformerData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(BroadcastTransformerData), + datasets: [ + { + label: "Broadcast Transformer", + data: Object.values(BroadcastTransformerData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(BroadcastTransformerData), + datasets: [ + { + label: "Broadcast Transformer", + data: Object.values(BroadcastTransformerData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + setDropdown(false); + setFinal(selected); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default BroadcastTransformer; diff --git a/src/pages/monitoring/broadcast-transformer/style.css b/src/pages/monitoring/broadcast-transformer/style.css new file mode 100644 index 0000000..dc6b6c1 --- /dev/null +++ b/src/pages/monitoring/broadcast-transformer/style.css @@ -0,0 +1,25 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.dark-dropdown { + color: black ; +} \ No newline at end of file diff --git a/src/pages/monitoring/dummy.json b/src/pages/monitoring/dummy.json deleted file mode 100644 index 9b4ad95..0000000 --- a/src/pages/monitoring/dummy.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "Kafka Topics": { - "broadcast-transformer": "7", - "com.odk.transformer": "17", - "generic-transformer": "0", - "notification-outbound": "35", - "outbound": "17", - "inbound-processed": "24", - "process-outbound": "52", - "telemetry": "14", - "outbound-processed": "0" - }, - "UCI API": { - "ResolveUser": 1 - }, - "Inbound": { - "Data inserted in Cassandra": 1, - "Kafka topic push": 1 - }, - "Orchestrator": { - "Topic consumed from Kafka": 5, - "Notification pushed to Kafka": 5 - }, - "Broadcast Transformer": { - "Broadcast Processed": 5, - "Kafka Push to outbound": 5 - }, - "Outbound": { - "Saved data in cache": 5, - "Notification inserted in Cassandra": 5 - } - } - \ No newline at end of file diff --git a/src/pages/monitoring/inbound/index.tsx b/src/pages/monitoring/inbound/index.tsx new file mode 100644 index 0000000..6b7a6c4 --- /dev/null +++ b/src/pages/monitoring/inbound/index.tsx @@ -0,0 +1,321 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +// import { formatDate, reverseFormatDate } from "../../../utils/functions"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface InboundProps extends React.HTMLAttributes { + theme: string; +} + +export const Inbound: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [InboundData, setInboundData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + console.log(file) + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setInboundData(res["Inbound".trim()] || {}); + console.log(res) + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + console.log(final) + + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setInboundData(res["Inbound".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(InboundData), + datasets: [ + { + label: "Inbound", + data: Object.values(InboundData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(InboundData), + datasets: [ + { + label: "Inbound", + data: Object.values(InboundData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(InboundData), + datasets: [ + { + label: "Inbound", + data: Object.values(InboundData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + setFinal(selected); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default Inbound; diff --git a/src/pages/monitoring/inbound/style.css b/src/pages/monitoring/inbound/style.css new file mode 100644 index 0000000..dc6b6c1 --- /dev/null +++ b/src/pages/monitoring/inbound/style.css @@ -0,0 +1,25 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.dark-dropdown { + color: black ; +} \ No newline at end of file diff --git a/src/pages/monitoring/kafka/index.tsx b/src/pages/monitoring/kafka/index.tsx deleted file mode 100644 index 557c9e7..0000000 --- a/src/pages/monitoring/kafka/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import {BarChart} from "../../../components"; -import jsonData from '../dummy.json'; - -const kafkaTopicsData = jsonData["Kafka Topics"]; - -const data = { - labels: Object.keys(kafkaTopicsData), - datasets: [ - { - label: "Kafka Topics", - data: Object.values(kafkaTopicsData).map(Number), - backgroundColor: "rgba(75, 192, 192, 0.6)", - }, - ], -}; - -const Kafka = () => { - return ; -}; - -export default Kafka; \ No newline at end of file diff --git a/src/pages/monitoring/logs/broadcast-transformer/index.tsx b/src/pages/monitoring/logs/broadcast-transformer/index.tsx new file mode 100644 index 0000000..fdfd673 --- /dev/null +++ b/src/pages/monitoring/logs/broadcast-transformer/index.tsx @@ -0,0 +1,359 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface BroadcastTransformerLogsProps extends React.HTMLAttributes { + theme: string; +} + +export const BroadcastTransformerLogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("broadcast-transformer", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton,date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("broadcast-transformer", date); + } else { + response = await downloadErrLogData("broadcast-transformer", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "broadcast_transformer"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date,maxLines,searchText]); + + + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton,date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default BroadcastTransformerLogs; diff --git a/src/pages/monitoring/logs/broadcast-transformer/style.css b/src/pages/monitoring/logs/broadcast-transformer/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/broadcast-transformer/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/logs/inbound/index.tsx b/src/pages/monitoring/logs/inbound/index.tsx new file mode 100644 index 0000000..e0b77e6 --- /dev/null +++ b/src/pages/monitoring/logs/inbound/index.tsx @@ -0,0 +1,359 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface InboundLogsProps extends React.HTMLAttributes { + theme: string; +} + +export const InboundLogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("inbound", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton,date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("inbound", date); + } else { + response = await downloadErrLogData("inbound", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "inbound"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date,maxLines,searchText]); + + + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton,date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default InboundLogs; diff --git a/src/pages/monitoring/logs/inbound/style.css b/src/pages/monitoring/logs/inbound/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/inbound/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/logs/orchestrator/index.tsx b/src/pages/monitoring/logs/orchestrator/index.tsx new file mode 100644 index 0000000..d99bc33 --- /dev/null +++ b/src/pages/monitoring/logs/orchestrator/index.tsx @@ -0,0 +1,358 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface OrchestratorLogsProps extends React.HTMLAttributes { + theme: string; +} + +export const OrchestratorLogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("orchestrator", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton,date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("orchestrator", date); + } else { + response = await downloadErrLogData("orchestrator", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "orchestrator"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date,maxLines,searchText]); + + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton,date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default OrchestratorLogs; diff --git a/src/pages/monitoring/logs/orchestrator/style.css b/src/pages/monitoring/logs/orchestrator/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/orchestrator/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/logs/outbound/index.tsx b/src/pages/monitoring/logs/outbound/index.tsx new file mode 100644 index 0000000..b094424 --- /dev/null +++ b/src/pages/monitoring/logs/outbound/index.tsx @@ -0,0 +1,358 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface OutboundLogsProps extends React.HTMLAttributes { + theme: string; +} + +export const OutboundLogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("outbound", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton,date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("outbound", date); + } else { + response = await downloadErrLogData("outbound", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "outbound"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date,maxLines,searchText]); + + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton,date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default OutboundLogs; diff --git a/src/pages/monitoring/logs/outbound/style.css b/src/pages/monitoring/logs/outbound/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/outbound/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/logs/transformer/index.tsx b/src/pages/monitoring/logs/transformer/index.tsx new file mode 100644 index 0000000..532e1b0 --- /dev/null +++ b/src/pages/monitoring/logs/transformer/index.tsx @@ -0,0 +1,358 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface TransformerLogsProps extends React.HTMLAttributes { + theme: string; +} + +export const TransformerLogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("transformer", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton,date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("transformer", date); + } else { + response = await downloadErrLogData("transformer", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "transformer"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date,maxLines,searchText]); + + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton,date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default TransformerLogs; diff --git a/src/pages/monitoring/logs/transformer/style.css b/src/pages/monitoring/logs/transformer/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/transformer/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/logs/uci-api/index.tsx b/src/pages/monitoring/logs/uci-api/index.tsx new file mode 100644 index 0000000..03cc1dd --- /dev/null +++ b/src/pages/monitoring/logs/uci-api/index.tsx @@ -0,0 +1,356 @@ +import React, { useEffect, useState } from "react"; +import { + MDBBtn, + MDBBtnGroup, + MDBCol, + MDBContainer, + MDBRow, +} from "mdb-react-ui-kit"; +import "./style.css"; +import Ansi from "ansi-to-react"; +import { useStore } from "../../../../store"; +import toast from "react-hot-toast"; +import { getFilesData } from "../../../../api/getFiles"; +import { downloadLogData } from "../../../../api/downloadLog"; +import { downloadErrLogData } from "../../../../api/downloadErrLog"; +import { fetchServiceData } from "../../../../api/fetchService"; +import DatePicker from "react-datepicker"; +import { MDBIcon } from "mdb-react-ui-kit"; + +interface DropdownItem { + value: number; +} + +interface UCIAPIlogsProps extends React.HTMLAttributes { + theme: string; +} + +export const UCIAPIlogs: React.FC = ({ theme }) => { + const store: any = useStore(); + const [searchText, setSearchText] = useState(0); + const [filterText, setFilterText] = useState(""); + const [filter, setFilter] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + DropdownItem[] + >([]); + const [showDropdown, setShowDropdown] = useState(false); + const [messageLines, setMessageLines] = useState([]); + const [searchPerformed, setSearchPerformed] = useState(false); + const [activeButton, setActiveButton] = useState("normal"); + const [flag, setFlag] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const maxLines = process.env.REACT_APP_MAX_LINES + ? parseInt(process.env.REACT_APP_MAX_LINES) + : 5000; + + const [logdate, setLogDate] = useState(new Date()); + const [date, setDate] = useState(); + + function formatDateTo_dd_mm_yyyy(inputDate) { + const date = new Date(inputDate); + + const day = String(date.getDate()).padStart(2, "0"); + const month = String(date.getMonth() + 1).padStart(2, "0"); + const year = date.getFullYear(); + + return `${day}_${month}_${year}`; + } + + const handleDateChange = (date: Date | null) => { + setLogDate(date); + let d = formatDateTo_dd_mm_yyyy(date); + setDate(d); + }; + + const fetchMessageData = async () => { + setFlag(false); + setIsLoading(true); + try { + let logData = ""; + let responseType = activeButton === "normal" ? "logs" : "error"; + const response = await fetchServiceData("uci-apis", searchText, date); + logData = response.data.result[responseType]; + const lines = logData.split("\n"); + setMessageLines(lines); + setFlag(true); + } catch (error) { + console.error("Error reading the file:", error); + } + setIsLoading(false); + }; + + const handleSearchInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSearchText(Number(value)); + + const data = [10, 100, 1000, 5000]; + const uniqueData = Array.from(new Set(data)); + + const suggestions: DropdownItem[] = uniqueData.map((val) => ({ + value: val, + })); + + setAutocompleteSuggestions(suggestions.filter((item) => item.value)); + setShowDropdown(true); + }; + + const handleFilterInputChange = ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setFilterText(value); + setFilter(true); + }; + + const handleSearchSubmit = (event: React.FormEvent) => { + event.preventDefault(); + setSearchPerformed(true); + setShowDropdown(false); + fetchMessageData(); + }; + + const handleFilterSubmit = (event: React.FormEvent) => { + event.preventDefault(); + fetchMessageData(); + }; + + const handleDropdownItemClick = (value: number) => { + setSearchText(value); + setShowDropdown(false); + }; + + const handleClick = (buttonName) => { + setActiveButton(buttonName); + fetchMessageData(); + }; + + const handleDownload = async (activeButton, date) => { + let response; + if (activeButton === "normal") { + response = await downloadLogData("uci-apis", date); + } else { + response = await downloadErrLogData("uci-apis", date); + } + const responseData = response.data; + console.log(responseData); + + const blob = new Blob([responseData], { type: "text/plain" }); + + const url = URL.createObjectURL(blob); + + const tempAnchor = document.createElement("a"); + tempAnchor.href = url; + const serviceName = "uci_api"; + const filename = `${serviceName}_${date}.txt`; + tempAnchor.download = filename; + document.body.appendChild(tempAnchor); + tempAnchor.click(); + + document.body.removeChild(tempAnchor); + + URL.revokeObjectURL(url); + }; + + useEffect(() => { + store?.startLoading(); + getFilesData() + .then((res) => { + store?.stopLoading(); + }) + .catch((err) => { + store?.stopLoading(); + toast.error(err.message); + }); + + if (activeButton) { + fetchMessageData(); + } + + if (maxLines <= searchText) { + handleDownload(activeButton, date); + } + }, [activeButton, date, maxLines, searchText]); + return ( + + + + + + + +
+ + + Search + +
+ {showDropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleDropdownItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+ +
+ + + Filter + +
+
+
+ {flag && searchPerformed && ( + + handleClick("normal")} + style={{ + backgroundColor: + activeButton === "normal" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Normal Logs + + handleClick("err")} + style={{ + backgroundColor: activeButton === "err" ? "#007BFF" : "#B0C4DE", + borderColor: "#007BFF", + }} + > + Error + + + )} + {flag && searchPerformed && !isLoading && messageLines.length === 0 && ( +

+ No data available for selected date +

+ )} + + {!searchPerformed && ( +

Please select a date

+ )} + {searchPerformed && ( + + handleDownload(activeButton, date)} + style={{ + backgroundColor: "#007BFF", + borderColor: "#007BFF", + }} + > + Download + + + )} + {searchPerformed && maxLines > searchText && ( +
+ {searchPerformed && ( +
+ {!filter && + activeButton === "normal" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "normal" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} + {!filter && + activeButton === "err" && + messageLines.slice(0, searchText).map((line, index) => ( +

+ {line} +

+ ))} + {filter && + activeButton === "err" && + messageLines + .slice(0, searchText) + .filter((line) => line.includes(filterText)) + .map((line, index) => ( +

+ {line} +

+ ))} +
+ )} +
+ )} + {searchPerformed && maxLines <= searchText && ( +
+

+ Too large to display! +

+
+ )} +
+ ); +}; + +export default UCIAPIlogs; diff --git a/src/pages/monitoring/logs/uci-api/style.css b/src/pages/monitoring/logs/uci-api/style.css new file mode 100644 index 0000000..e730bd9 --- /dev/null +++ b/src/pages/monitoring/logs/uci-api/style.css @@ -0,0 +1,53 @@ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + min-width: 10%; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.highlight { + background-color: yellow; +} + +.date-picker-container { + z-index: 9999 !important; + position: relative; +} + +.date-picker { + padding: 5px; + width: 120px; + cursor: pointer; +} + +.light-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: #333; +} + +.dark-icon { + position: absolute; + top: 50%; + left:-20px; + transform: translateY(-50%); + font-size: 18px; + color: white; +} diff --git a/src/pages/monitoring/orchestrator/index.tsx b/src/pages/monitoring/orchestrator/index.tsx new file mode 100644 index 0000000..cea6e02 --- /dev/null +++ b/src/pages/monitoring/orchestrator/index.tsx @@ -0,0 +1,318 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +// import { formatDate, reverseFormatDate } from "../../../utils/functions"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface OrchestratorProps extends React.HTMLAttributes { + theme: string; +} + +export const Orchestrator: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [OrchestratorData, setOrchestratorData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setOrchestratorData(res["Orchestrator".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setOrchestratorData(res["Orchestrator".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(OrchestratorData), + datasets: [ + { + label: "Orchestrator", + data: Object.values(OrchestratorData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(OrchestratorData), + datasets: [ + { + label: "Orchestrator", + data: Object.values(OrchestratorData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(OrchestratorData), + datasets: [ + { + label: "Orchestrator", + data: Object.values(OrchestratorData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + setDropdown(false); + setFinal(selected); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default Orchestrator; diff --git a/src/pages/monitoring/orchestrator/style.css b/src/pages/monitoring/orchestrator/style.css new file mode 100644 index 0000000..7b4f6f8 --- /dev/null +++ b/src/pages/monitoring/orchestrator/style.css @@ -0,0 +1,26 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.dark-dropdown { + color: black ; +} + diff --git a/src/pages/monitoring/outbound/index.tsx b/src/pages/monitoring/outbound/index.tsx new file mode 100644 index 0000000..158a038 --- /dev/null +++ b/src/pages/monitoring/outbound/index.tsx @@ -0,0 +1,315 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface OutboundProps extends React.HTMLAttributes { + theme: string; +} + +export const Outbound: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [OutboundData, setOutboundData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setOutboundData(res["Outbound".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setOutboundData(res["Outbound".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(OutboundData), + datasets: [ + { + label: "Outbound", + data: Object.values(OutboundData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(OutboundData), + datasets: [ + { + label: "Outbound", + data: Object.values(OutboundData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(OutboundData), + datasets: [ + { + label: "Outbound", + data: Object.values(OutboundData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + setFinal(selected); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default Outbound; diff --git a/src/pages/monitoring/outbound/style.css b/src/pages/monitoring/outbound/style.css new file mode 100644 index 0000000..dc6b6c1 --- /dev/null +++ b/src/pages/monitoring/outbound/style.css @@ -0,0 +1,25 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.dark-dropdown { + color: black ; +} \ No newline at end of file diff --git a/src/pages/monitoring/overview/card.tsx b/src/pages/monitoring/overview/card.tsx new file mode 100644 index 0000000..954e857 --- /dev/null +++ b/src/pages/monitoring/overview/card.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import { + MDBCard, + MDBCardBody, + MDBCol, + MDBRow, +} from "mdb-react-ui-kit"; +import { formatNumberWithCommas } from "../../../utils/functions"; + +const OverviewComponent = ({ theme, jsonData }) => { + const data = jsonData; + + const renderDataCards = (data: { [key: string]: number }) => { + return Object.entries(data).map(([key, value]) => ( + + + +
{formatNumberWithCommas(value)}
+

{key}

+
+
+
+ )); + }; + + return ( +
+ + {Object.entries(data).map(([category, categoryData]) => ( + + {categoryData && + renderDataCards(categoryData as { [key: string]: number })} + + ))} + +
+ ); +}; + +export default OverviewComponent; diff --git a/src/pages/monitoring/overview/index.tsx b/src/pages/monitoring/overview/index.tsx index 8496b6b..6e8a3ba 100644 --- a/src/pages/monitoring/overview/index.tsx +++ b/src/pages/monitoring/overview/index.tsx @@ -1,103 +1,188 @@ -import { MDBCard, MDBCardBody, MDBCol, MDBRow, MDBBtn } from "mdb-react-ui-kit"; +import { + MDBCard, + MDBCardBody, + MDBCol, + MDBRow, + MDBBtn, + MDBSwitch, +} from "mdb-react-ui-kit"; import "./style.css"; +import { useEffect, useState } from "react"; +import { triggerRealtimeDataRes } from "../../../api/triggerRealtime"; +import { stopRealtime } from "../../../api/stopRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { fetchOverviewData } from "../../../api/fetchOverview"; +import { + convertToShortDate, + formatDate, + reverseFormatDate, +} from "../../../utils/functions"; +import OverviewComponent from "./card"; interface OverviewHeaderProps extends React.HTMLAttributes { - children?: React.ReactNode; theme: string; } -export const Overview: React.FC = ({ - children, - theme, - ...rest -}) => { - const handleFilterInputChange = ( + +interface AutocompleteItem { + value: string; +} + +export const Overview: React.FC = ({ theme }) => { + const [isRealtimeEnabled, setIsRealtimeEnabled] = useState(false); + const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + AutocompleteItem[] + >([]); + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + const [flag, setFlag] = useState(false); + const [OverviewData, setOverviewData] = useState({}); + + const handleSearchInputChange = async ( event: React.ChangeEvent ) => { const { value } = event.target; + setSelected(value); + setFlag(false); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestions( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); }; - const handleFilterSubmit = (event: React.FormEvent) => { + const handleSearchSubmit = async ( + event: React.FormEvent + ) => { event.preventDefault(); + setDropdown(false); + setFlag(true); + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + const apiEndpoint = fetchOverviewData(file); + let res; + + try { + const response = await apiEndpoint; + res = response.data.result; + + const parsedData = JSON.parse(res); + + setOverviewData(parsedData); + } catch (error) { + console.error("Error toggling:", error); + } + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + + const handleToggleChange = async () => { + setIsRealtimeEnabled(!isRealtimeEnabled); + const apiEndpoint = isRealtimeEnabled + ? triggerRealtimeDataRes() + : stopRealtime(); + + try { + const response = await apiEndpoint; + console.log("Toggle API Response:", response); + } catch (error) { + console.error("Error toggling:", error); + } }; + async function fetchData() { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchOverviewData(file); + let res; + const response = await apiEndpoint; + res = response.data.result; + + const parsedData = JSON.parse(res); + + setOverviewData(parsedData); + } + } + + useEffect(() => { + fetchData(); + console.log(!selected || localStorage.getItem("file") == null) + }, []); + return (
-
- - - Filter - -
-
-
- - - - -
80
-

No. of Notifications sent

-
-
-
- - - -
65
-

- No. of Notifications received by users -

-
-
-
- - - -
50
-

No. of Notifications opened by users

-
-
-
-
- - - - -
80
-

No. of Notifications sent

-
-
-
- - - -
65
-

- No. of Notifications received by users -

-
-
+ +
+ + + Submit + +
+ {dropdown && autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + className={`${theme}-dropdown`} + > + {item.value} +
  • + ))} +
+ )} +
- - - -
50
-

No. of Notifications opened by users

-
-
+ + Toggle Realtime   +
+ {(selected || localStorage.getItem("file") != null || flag) && ( + + )} + {(!selected && localStorage.getItem("file") == null) && ( +

Please enter a date

+ )}
); }; diff --git a/src/pages/monitoring/overview/style.css b/src/pages/monitoring/overview/style.css index 9d5f368..d269be9 100644 --- a/src/pages/monitoring/overview/style.css +++ b/src/pages/monitoring/overview/style.css @@ -12,3 +12,7 @@ background-color: black; color: black; } + +.dark-dropdown { + color: black ; +} \ No newline at end of file diff --git a/src/pages/monitoring/transformer/index.tsx b/src/pages/monitoring/transformer/index.tsx new file mode 100644 index 0000000..96a5035 --- /dev/null +++ b/src/pages/monitoring/transformer/index.tsx @@ -0,0 +1,316 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +// import { formatDate, reverseFormatDate } from "../../../utils/functions"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface TransformerProps extends React.HTMLAttributes { + theme: string; +} + +export const Transformer: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [TransformerData, setTransformerData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setTransformerData(res["Transformer".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setTransformerData(res["Transformer".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(TransformerData), + datasets: [ + { + label: "Transformer", + data: Object.values(TransformerData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(TransformerData), + datasets: [ + { + label: "Transformer", + data: Object.values(TransformerData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(TransformerData), + datasets: [ + { + label: "Transformer", + data: Object.values(TransformerData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + setFinal(selected); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(false); + }; + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default Transformer; diff --git a/src/pages/monitoring/transformer/style.css b/src/pages/monitoring/transformer/style.css new file mode 100644 index 0000000..5859a92 --- /dev/null +++ b/src/pages/monitoring/transformer/style.css @@ -0,0 +1,25 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; + } + + .autocomplete-dropdown li { + cursor: pointer; + padding: 8px; + } + + .autocomplete-dropdown li:hover { + background-color: #f0f0f0; + } + + .dark-dropdown { + color: black ; + } \ No newline at end of file diff --git a/src/pages/monitoring/uci-api/index.tsx b/src/pages/monitoring/uci-api/index.tsx new file mode 100644 index 0000000..9807987 --- /dev/null +++ b/src/pages/monitoring/uci-api/index.tsx @@ -0,0 +1,318 @@ +import { + MDBBtn, + MDBCol, + MDBDropdown, + MDBDropdownItem, + MDBDropdownMenu, + MDBDropdownToggle, + MDBRow, +} from "mdb-react-ui-kit"; +import BarChart from "../../../components/visualisation/bar"; +import React, { useEffect, useState } from "react"; +import { useStore } from "../../../store"; +import { getBots } from "../../../api/getBots"; +import { toast } from "react-hot-toast"; +import "./style.css"; +import PieChart from "../../../components/visualisation/pie"; +import LineChart from "../../../components/visualisation/line"; +// import { formatDate, reverseFormatDate } from "../../../utils/functions"; +import { fetchRealtime } from "../../../api/fetchRealtimeData"; +import { getFilesData } from "../../../api/getFiles"; +import { convertToShortDate, formatDate, reverseFormatDate } from "../../../utils/functions"; + +interface AutocompleteItem { + value: string; +} + +interface UCIAPIProps extends React.HTMLAttributes { + theme: string; +} + +export const UCIAPI: React.FC = ({ theme }) => { + const [selectedChart, setSelectedChart] = useState("barchart"); + const [dropdownLabel, setDropdownLabel] = useState("Select Chart"); + const [searchText, setSearchText] = useState(""); + // const [autocompleteSuggestions, setAutocompleteSuggestions] = useState< + // AutocompleteItem[] + // >([]); + const [autocompleteSuggestionsFile, setAutocompleteSuggestionsFile] = + useState([]); + const [botList, setBotList] = useState([]); + const store: any = useStore(); + + const [selected, setSelected] = useState(""); + const [dropdown, setDropdown] = useState(true); + + const [uciApiData, setUciApiData] = useState([]); + + const [final, setFinal] = useState(""); + + const func = async () => { + if (localStorage.getItem("file")) { + const file = localStorage.getItem("file"); + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setUciApiData(res["uci-apis".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } else if (final !== "") { + + const file = reverseFormatDate(final); + localStorage.setItem("file", file); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const apiEndpoint = fetchRealtime(file); + try { + const response = await apiEndpoint; + const res = JSON.parse(response.data.result); + setUciApiData(res["uci-apis".trim()] || {}); + } catch (error) { + console.error("Error toggling:", error); + } + } + fetchBotData(); + }; + + useEffect(() => { + func(); + // fetchBotData(); + }, [final]); + + const dataBar = { + labels: Object.keys(uciApiData), + datasets: [ + { + label: "UCI APIS", + data: Object.values(uciApiData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const dataPie = { + labels: Object.keys(uciApiData), + datasets: [ + { + label: "UCI APIS", + data: Object.values(uciApiData).map(Number), + }, + ], + }; + + const dataLine = { + labels: Object.keys(uciApiData), + datasets: [ + { + label: "UCI APIS", + data: Object.values(uciApiData).map(Number), + backgroundColor: "rgba(75, 192, 192, 0.6)", + }, + ], + }; + + const handleChartChange = (value, label) => { + setSelectedChart(value); + setDropdownLabel(label); + }; + + let chartComponent; + if (selectedChart === "barchart") { + chartComponent = ; + } else if (selectedChart === "piechart") { + // chartComponent = ; + chartComponent = ; + } else if (selectedChart === "linechart") { + chartComponent = ; + } + + const fetchBotData = async () => { + store?.startLoading(); + const data = searchText.length > 0 ? { name: searchText } : {}; + try { + const res = await getBots(data); + store?.stopLoading(); + setBotList(res?.data?.result?.data.map((bot) => bot.name)); + } catch (err) { + store?.stopLoading(); + toast.error(err.message); + } + }; + + // const handleSearchInputChange = ( + // event: React.ChangeEvent + // ) => { + // const { value } = event.target; + // setSearchText(value); + + // const lowercasedValue = value.toLowerCase(); + // const suggestions: AutocompleteItem[] = botList.map((name) => ({ + // value: name, + // })); + + // setAutocompleteSuggestions( + // suggestions.filter((item) => + // item.value.toLowerCase().includes(lowercasedValue) + // ) + // ); + // }; + + // const handleSearchSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // }; + + const handleSearchSubmitFile = async ( + event: React.FormEvent + ) => { + event.preventDefault(); + + const shortDate = convertToShortDate(selected); + localStorage.setItem("shortDate", shortDate); + localStorage.setItem("data_time", selected); + + const file = reverseFormatDate(selected); + localStorage.setItem("file", file); + + func(); + }; + + const handleSearchInputChangeFile = async ( + event: React.ChangeEvent + ) => { + const { value } = event.target; + setSelected(value); + setFinal(selected); + + const lowercasedValue = value.toLowerCase(); + const apiEndpoint = getFilesData(); + let data = []; + + try { + const response = await apiEndpoint; + data = response.data.result; + } catch (error) { + console.error("Error toggling:", error); + } + + const suggestions: AutocompleteItem[] = data.map((name) => ({ + value: formatDate(name), + })); + + setAutocompleteSuggestionsFile( + suggestions.filter((item) => + item.value.toLowerCase().includes(lowercasedValue) + ) + ); + }; + + const handleAutocompleteItemClick = (value) => { + setSelected(value); + setDropdown(true); + }; + + return ( +
+ + + + + {dropdownLabel} + + + handleChartChange("barchart", "Bar Chart")} + style={{ cursor: "pointer" }} + > + Bar Chart + + handleChartChange("piechart", "Pie Chart")} + style={{ cursor: "pointer" }} + > + Pie Chart + + handleChartChange("linechart", "Line Chart")} + style={{ cursor: "pointer" }} + > + Line Chart + + + + + {/* +
+ + + Search + +
+ {autocompleteSuggestions.length > 0 && ( +
    + {autocompleteSuggestions.map((item) => ( +
  • setSearchText(item.value)}> + {item.value} +
  • + ))} +
+ )} +
*/} + +
+ + + Search + +
+ {dropdown && autocompleteSuggestionsFile.length > 0 && ( +
    + {autocompleteSuggestionsFile.map((item) => ( +
  • handleAutocompleteItemClick(item.value)} + > + {item.value} +
  • + ))} +
+ )} +
+
+ {chartComponent} +
+ ); +}; + +export default UCIAPI; diff --git a/src/pages/monitoring/uci-api/style.css b/src/pages/monitoring/uci-api/style.css new file mode 100644 index 0000000..2af15c3 --- /dev/null +++ b/src/pages/monitoring/uci-api/style.css @@ -0,0 +1,25 @@ +/* Add a higher z-index to the autocomplete dropdown */ +.autocomplete-dropdown { + position: absolute; + z-index: 100; + background-color: #fff; + border: 1px solid #ccc; + padding: 5px; + list-style: none; + max-height: 150px; + max-width: inherit; + overflow-y: auto; +} + +.autocomplete-dropdown li { + cursor: pointer; + padding: 8px; +} + +.autocomplete-dropdown li:hover { + background-color: #f0f0f0; +} + +.dark-dropdown { + color: black !important; +} \ No newline at end of file