diff --git a/package-lock.json b/package-lock.json index 05e4b87..b2f0a22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,14 @@ "name": "log", "version": "0.1.0", "dependencies": { - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/react-fontawesome": "^0.2.2", - "@mui/icons-material": "^5.15.20", - "@mui/material": "^5.15.20", + "@material-ui/icons": "^4.11.3", + "@mui/icons-material": "^5.17.1", + "@mui/material": "^5.17.1", "@mui/styles": "^5.16.4", "@mui/x-charts": "^7.6.2", "@mui/x-data-grid": "^7.6.2", @@ -26,6 +27,7 @@ "ajv-keywords": "^3.5.2", "axios": "^1.6.7", "chart.js": "^4.4.9", + "file-saver": "^2.0.5", "mdb-react-ui-kit": "^7.1.0", "moment": "^2.30.1", "react": "^18.2.0", @@ -3764,6 +3766,29 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "license": "MIT" }, + "node_modules/@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.4.4" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0", + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/core-downloads-tracker": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz", @@ -9931,6 +9956,12 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", diff --git a/package.json b/package.json index f079127..d2aa7c0 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,14 @@ "version": "0.1.0", "private": true, "dependencies": { - "@emotion/react": "^11.11.3", - "@emotion/styled": "^11.11.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-solid-svg-icons": "^6.7.2", "@fortawesome/react-fontawesome": "^0.2.2", - "@mui/icons-material": "^5.15.20", - "@mui/material": "^5.15.20", + "@material-ui/icons": "^4.11.3", + "@mui/icons-material": "^5.17.1", + "@mui/material": "^5.17.1", "@mui/styles": "^5.16.4", "@mui/x-charts": "^7.6.2", "@mui/x-data-grid": "^7.6.2", @@ -21,6 +22,7 @@ "ajv-keywords": "^3.5.2", "axios": "^1.6.7", "chart.js": "^4.4.9", + "file-saver": "^2.0.5", "mdb-react-ui-kit": "^7.1.0", "moment": "^2.30.1", "react": "^18.2.0", diff --git a/src/APIRequestService/APIServices.js b/src/APIRequestService/APIServices.js index 8984e81..79d8ad7 100644 --- a/src/APIRequestService/APIServices.js +++ b/src/APIRequestService/APIServices.js @@ -1,117 +1,160 @@ +// import axios from 'axios'; + +// // Use the same environment variable name consistently +// const BASE_URL = process.env.REACT_APP_API_BASE_URL; +// console.log('API Base URL:', BASE_URL); +// // Enhanced token service +// export const getToken = () => { +// // Check multiple possible storage locations +// return localStorage.getItem('token') || +// sessionStorage.getItem('token') || +// document.cookie.split('; ').find(row => row.startsWith('token='))?.split('=')[1]; +// }; + +// const apiClient = axios.create({ +// baseURL: BASE_URL, +// headers: { +// 'Content-Type': 'application/json', +// }, +// }); + +// // Enhanced request interceptor +// apiClient.interceptors.request.use( +// (config) => { +// const token = getToken(); +// if (token) { +// config.headers['Authorization'] = `Bearer ${token}`; +// // Add debug logging +// console.debug('[API] Request with token:', { +// url: config.url, +// headers: config.headers +// }); +// } else { +// console.warn('[API] No token available for request:', config.url); +// } +// return config; +// }, +// (error) => { +// console.error('[API] Request interceptor error:', error); +// return Promise.reject(error); +// } +// ); + +// // Enhanced response interceptor +// apiClient.interceptors.response.use( +// (response) => { +// console.debug('[API] Successful response:', { +// url: response.config.url, +// status: response.status, +// data: response.data +// }); +// return response; +// }, +// (error) => { +// const originalRequest = error.config; + +// // Debug logging +// console.error('[API] Error response:', { +// url: originalRequest.url, +// status: error.response?.status, +// data: error.response?.data +// }); + +// // Handle 401 specifically +// if (error.response?.status === 401 && !originalRequest._retry) { +// originalRequest._retry = true; +// console.warn('[API] Attempting token refresh...'); +// // Add your token refresh logic here if needed +// } + +// return Promise.reject(error); +// } +// ); + +// // API methods +// const apiService = { +// get: (url, params, options = {}) => +// apiClient.get(url, { ...options, params }).catch(handleError), + +// post: (url, body = {}, options = {}) => +// apiClient.post(url, body, options).catch(handleError), + +// put: (url, body = {}, options = {}) => +// apiClient.put(url, body, options).catch(handleError), + +// delete: (url, options = {}) => +// apiClient.delete(url, options).catch(handleError), + +// // Add patch if needed +// patch: (url, body = {}, options = {}) => +// apiClient.patch(url, body, options).catch(handleError) +// }; + +// // Enhanced error handler +// const handleError = (error) => { +// // Your existing error handling logic +// // ... +// }; + +// // Specific API endpoints +// export const getSubmenuItems = async (id) => { +// try { +// const response = await apiService.get(`/api1/submenu1/${id}`); +// return response.data; +// } catch (error) { +// console.error('Error fetching submenu items:', error); +// throw error; // Re-throw for component-level handling +// } +// }; + +// // Export the configured service +// export default apiService; + import axios from 'axios'; - import { getToken } from '../../src/utils/tokenService'; -const BASE_URL = process.env.REACT_APP_API_BASE_URL; +const BASE_URL = process.env.REACT_APP_API_BASE_URL ; -const apiClient = axios.create({ +const apiService = axios.create({ baseURL: BASE_URL, - headers: { - 'Content-Type': 'application/json', - }, + timeout: 30000, }); -// Add a request interceptor to include Authorization header -apiClient.interceptors.request.use( + +// Request interceptor for auth token +apiService.interceptors.request.use( (config) => { - const token = getToken(); + const token = localStorage.getItem('authToken'); if (token) { - console.log("token: ",token); - config.headers['Authorization'] = `Bearer ${token}`; + config.headers.Authorization = `Bearer ${token}`; } return config; }, - (error) => Promise.reject(error) + (error) => { + return Promise.reject(error); + } ); -// Generic error handler function -const handleError = (error) => { - let errorMessage = 'An unknown error occurred'; - console.error('Error Details:', error); - - if (error.response) { - // HTTP errors - switch (error.response.status) { - case 401: - errorMessage = 'Unauthorized - Please login again.'; - break; - case 403: - errorMessage = 'Forbidden - Access denied.'; - break; - case 404: - errorMessage = 'Service not found.'; - break; - case 408: - errorMessage = 'Request timed out.'; - break; - case 500: - errorMessage = 'Internal server error.'; - break; - default: - errorMessage = `Unexpected error: ${error.response.statusText || 'Server Error'}`; +// Response interceptor +apiService.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + localStorage.removeItem('authToken'); + window.location.href = '/login'; } - } else if (error.request) { - // No response received - errorMessage = 'No response from server. Please check your connection.'; - } else { - // Other errors - errorMessage = error.message || 'An unexpected error occurred.'; + return Promise.reject(error); } +); - return Promise.reject(errorMessage); // Return error message as rejected promise +// Add downloadFile method +apiService.downloadFile = async (url, data) => { + try { + const response = await apiService.post(url, data, { + responseType: 'blob', + }); + return response.data; + } catch (error) { + throw error; + } }; -// Define the reusable methods -// const apiService = { -// get: (url, params) => -// apiClient -// .get(url, { params: params || {} }) -// .catch(handleError), // Attach error handler -// post: (url, body = {}) => -// apiClient -// .post(url, body) -// .catch(handleError), // Attach error handler -// put: (url, body = {}) => -// apiClient -// .put(url, body) -// .catch(handleError), // Attach error handler -// delete: (url) => -// apiClient -// .delete(url) -// .catch(handleError), // Attach error handler -// }; - -const apiService = { - get: (url, params) => - apiClient - .get(url, { params: params || {} }) - .catch(handleError), // Attach error handler - - post: (url, body = {}, options = {}) => - apiClient - .post(url, body, options) // Pass options such as headers - .catch(handleError), // Attach error handler - - put: (url, body = {}, options = {}) => - apiClient - .put(url, body, options) // Pass options such as headers - .catch(handleError), // Attach error handler - - delete: (url, options = {}) => - apiClient - .delete(url, options) // Pass options such as headers - .catch(handleError), // Attach error handler -}; -// Add at the bottom of APIService.js - -export const getSubmenuItems = async (id) => { - const response = await apiService.get(`/api1/submenu1/${id}`); - return response.data; -}; -export const addSubmenuItem = async (menuId, submenuData) => { - const response = await apiService.post(`/api1/menu/${menuId}/submenu`, submenuData); - return response.data; -}; -export const updateMenuItem = (id, formData) => apiService.put(`/api1/submenu1/${id}`, formData); -export const deleteMenuItem = (id) => apiService.delete(`/api1/menu/${id}`); - - -export default apiService; +export default apiService; \ No newline at end of file diff --git a/src/ApiServices/AddReportSQLBuilderAPI.js b/src/ApiServices/AddReportSQLBuilderAPI.js new file mode 100644 index 0000000..7f402ac --- /dev/null +++ b/src/ApiServices/AddReportSQLBuilderAPI.js @@ -0,0 +1,22 @@ +import axios from 'axios'; + +export const addSQLReport = async (formData) => { + try { + const token = localStorage.getItem('authToken'); + const response = await axios.post( + `${process.env.REACT_APP_API_BASE_URL}/Rpt_builder2/Rpt_builder2`, + formData, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + } + ); + return response.data; + } catch (error) { + console.error('Error adding SQL report:', error); + throw error; + } +}; + diff --git a/src/ApiServices/DeleteReportSQLAPI.js b/src/ApiServices/DeleteReportSQLAPI.js new file mode 100644 index 0000000..437b0bd --- /dev/null +++ b/src/ApiServices/DeleteReportSQLAPI.js @@ -0,0 +1,17 @@ +import apiService from '../APIRequestService/APIServices'; + + +export const deleteReportSQL = async (id) => { + if (!id) { + throw new Error("ID is required for deletion."); + } + const BASE_URL = `${process.env.REACT_APP_API_BASE_URL}/Rpt_builder2/Rpt_builder2/${id}`; + try { + const response = await apiService.delete(BASE_URL); + console.log("Delete response:", response.data); + return response.data; + } catch (error) { + console.error("Error in API call:", error.response || error.message); + throw error; + } +}; diff --git a/src/ApiServices/ReportBuilderService.js b/src/ApiServices/ReportBuilderService.js new file mode 100644 index 0000000..2ba1efe --- /dev/null +++ b/src/ApiServices/ReportBuilderService.js @@ -0,0 +1,134 @@ +import apiService from '../APIRequestService/APIServices'; + +const API_BASE_URL = 'api'; + +const ReportBuilderService = { + getById: (id) => apiService.get(`${API_BASE_URL}/edit-report/${id}`), + + buildReport: (id) => { + const params = { id }; + return apiService.get(`${API_BASE_URL}/build_report`, params); + }, + + getAll: (moduleId, page = 0, size = 1000) => { + const params = { page, size, moduleId }; + return apiService.get(`${API_BASE_URL}/report-builder-by-id`, params); + }, + + create: (fbHeader, moduleId) => { + const params = { moduleId }; + return apiService.post(`${API_BASE_URL}/report-builder`, fbHeader, { params }); + }, + + createservicereport: (fbHeader, moduleId) => { + const params = { moduleId }; + return apiService.post(`${API_BASE_URL}/report-builder_service`, fbHeader, { params }); + }, + + createQuery: (reportId) => { + const params = { reportId }; + return apiService.post(`${API_BASE_URL}/add-master-query`, {}, { params }); + }, + + update: (id, functionRegister) => { + return apiService.put(`${API_BASE_URL}/add-master-query/${id}`, functionRegister); + }, + + updateservicereport: (id, functionRegister) => { + return apiService.put(`${API_BASE_URL}/updatereport/${id}`, functionRegister); + }, + + getMasterQuery: (id) => apiService.get(`${API_BASE_URL}/master-query/${id}`), + + getMasterData: (query) => { + const params = { sql_query: query }; + return apiService.get(`${API_BASE_URL}/master-query-data`, params); + }, + + report2: (serviceName) => apiService.post(`${API_BASE_URL}/add-report`, serviceName), + + saveq: (data) => apiService.post('FndQuery/query', data), + + getall: () => apiService.get('FndQuery/query'), + + getreportdata: (apiName) => { + const url = `${API_BASE_URL}/${apiName}`; + return apiService.get(url); + }, + + getDatabase: () => apiService.get('SqlworkbenchSqlcont/sql'), + + getTableListn: (val) => apiService.get(`Table_list/${val}`), // table list + + getcolListn: (val, val1) => apiService.get(`Table_list/${val}/${val1}`), // column list + + getColumnList: (tableSchema, tables) => { + const params = { str: tables.join(',') }; + return apiService.get(`${API_BASE_URL}/AllTable_list/${tableSchema}`, { params }); + }, + + getAllColumnsFromAllTables: (tableNames) => { + // If tableNames is an array, join it with commas + const tables = Array.isArray(tableNames) ? tableNames.join(',') : tableNames; + return apiService.get(`Alias_Table_list/${tables}`); + }, + + getcollist: (table) => apiService.get(`fndMenu/loadcolumn/${table}`), + + createdb: (data) => apiService.post('SqlworkbenchSqlcont/sql', data), + + updateSqlModel: (id, sqlModel) => apiService.put(`SqlworkbenchSqlcont/sql/${id}`, sqlModel), + + getSqlModelById: (id) => apiService.get(`SqlworkbenchSqlcont/sql/${id}`), + + deleteSqlModel: (id) => apiService.delete(`SqlworkbenchSqlcont/sql/${id}`), + + getallentity: () => apiService.get(`${API_BASE_URL}/report-builder`), + + saveData: (data) => apiService.post('Rpt_builder/Rpt_builder', data), + + getDetails: () => apiService.get('Rpt_builder/Rpt_builder'), + + getDetailsById: (id) => apiService.get(`Rpt_builder/Rpt_builder/${id}`), + + deleteById: (id) => apiService.delete(`Rpt_builder/Rpt_builder/${id}`), + + updateData: (data, id) => apiService.put(`Rpt_builder/Rpt_builder/${id}`, data), + + saverbData: (data) => apiService.post('Rpt_builder2/Rpt_builder2', data), + + getrbDetails: () => apiService.get('Rpt_builder2/Rpt_builder2'), + + getrbDetailsById: (id) => apiService.get(`Rpt_builder2/Rpt_builder2/${id}`), + + deletrbById: (id) => apiService.delete(`Rpt_builder2/Rpt_builder2/${id}`), + + updaterbData: (data, id) => apiService.put(`Rpt_builder2/Rpt_builder2/${id}`, data), + + updaterbLineData: (data, id) => apiService.put(`Rpt_builder2_lines/update/${id}`, data), + + getrbLineDetailsById: (id) => apiService.get(`Rpt_builder2_lines/Rpt_builder2_lines/${id}`), + + getStdParamById: (id) => apiService.get(`Rpt_builder2/html/build_report2/${id}`), + + getcolumnDetailsByurl: (url) => apiService.get(`Rpt_builder2_lines/geturlkeybyurl?url=${url}`), + + getAllDetailsByurl: (url) => apiService.get(`Rpt_builder2_lines/fetch_data_url?url=${url}`), + + downloadFile: async (format, dataList, name) => { + const url = `${API_BASE_URL}/rbbuilder/fileconverter/downloadFile/${format}`; + try { + const fileData = await apiService.post(url, dataList, { responseType: 'blob' }); + const blob = new Blob([fileData], { type: 'application/octet-stream' }); + const fileName = name ? `${name}.${format}` : `download.${format}`; + const link = document.createElement('a'); + link.href = window.URL.createObjectURL(blob); + link.download = fileName; + link.click(); + } catch (error) { + console.error('Error downloading file:', error); + } + }, +}; + +export default ReportBuilderService; diff --git a/src/ApiServices/ReportRunnerAPI.js b/src/ApiServices/ReportRunnerAPI.js new file mode 100644 index 0000000..7c78b32 --- /dev/null +++ b/src/ApiServices/ReportRunnerAPI.js @@ -0,0 +1,49 @@ +import apiService from '../APIRequestService/APIServices'; +import { saveAs } from 'file-saver'; + +// Function to run a specific report +export const runReport = async (reportId) => { + try { + const response = await apiService.get(`Rpt_builder2/Rpt_builder2/${reportId}`); + return response.data; + } catch (error) { + console.error("Error running report:", error); + throw error; + } +}; + +// Function to fetch all reports +export const fetchAllReportsApi = async () => { + try { + const response = await apiService.get('Rpt_builder2/Rpt_builder2'); + return response.data; + } catch (error) { + console.error("Error fetching reports:", error); + throw error; + } +}; + +// Function to fetch standard parameters +export const fetchStandardParameters = async (url) => { + try { + const response = await apiService.get(`Rpt_builder2_lines/fetch_data_url?url=${encodeURIComponent(url)}`); + return response.data; + } catch (error) { + console.error("Error fetching parameters:", error); + throw error; + } +}; + +// File download function +export const downloadFile = async (format, dataList, name) => { + try { + const blob = await apiService.downloadFile( + `rbbuilder/fileconverter/downloadFile/${format}`, + dataList + ); + saveAs(blob, `${name}.${format}`); + } catch (error) { + console.error('Error downloading file:', error); + throw error; + } +}; \ No newline at end of file diff --git a/src/ApiServices/ReportSQLBuilderAPI.js b/src/ApiServices/ReportSQLBuilderAPI.js new file mode 100644 index 0000000..8a9b02f --- /dev/null +++ b/src/ApiServices/ReportSQLBuilderAPI.js @@ -0,0 +1,21 @@ +// src/api/ReportSqlBuilderApi.js + +import apiService from '../APIRequestService/APIServices';// Assuming apiService is in the same directory + + + +const BASE_URL = `${process.env.REACT_APP_API_BASE_URL}/Rpt_builder2/Rpt_builder2`; +console.log("BASE_URL:", BASE_URL); // Log the base URL for debugging +const ReportSqlBuilderApi = { + fetchUserDetails: async () => { + try { + const response = await apiService.get(BASE_URL); + return response.data; // Return only the data part of the response + } catch (error) { + throw error; // Let the error be handled by the calling component + } + }, +}; + +export default ReportSqlBuilderApi; + diff --git a/src/ApiServices/SQLWorksheetAPI.js b/src/ApiServices/SQLWorksheetAPI.js new file mode 100644 index 0000000..e69de29 diff --git a/src/ApiServices/SystemparameterApi.js b/src/ApiServices/SystemparameterApi.js new file mode 100644 index 0000000..ac6b192 --- /dev/null +++ b/src/ApiServices/SystemparameterApi.js @@ -0,0 +1,23 @@ +import apiService from '../APIRequestService/APIService'; + +export const getSysParameter = async (id) => { + try { + const response = await apiService.get(`/sysparam/getSysParams/${id}`); + return response.data; // Return only the data part of the response + } catch (error) { + throw error; // Let the error be handled by the calling component + } + } + +export const addSysParameter = async (formdata) => { + try { + const response = await apiService.put(`/sysparam/updateSysParams/${1}`,formdata); + console.log("add response data ",response.data) + return response.data; // Return only the data part of the response + } catch (error) { + throw error; // Let the error be handled by the calling component + } + } + + + diff --git a/src/ApiServices/UpdateReportSQLBuilderAPI.js b/src/ApiServices/UpdateReportSQLBuilderAPI.js new file mode 100644 index 0000000..c99c482 --- /dev/null +++ b/src/ApiServices/UpdateReportSQLBuilderAPI.js @@ -0,0 +1,16 @@ +import apiService from '../APIRequestService/APIServices'; + + + + +export const UpdateReportSQLBuilder = async (id,formData) => { + const BASE_URL = `${process.env.REACT_APP_API_BASE_URL}/Rpt_builder2/Rpt_builder2/${id}`; + try { + const response = await apiService.put(BASE_URL, formData); + console.log("update response: ",response.data); + + return response.data; // Return only the data part of the response + } catch (error) { + throw error; // Let the error be handled by the calling component + } + } \ No newline at end of file diff --git a/src/ApiServices/reportBaseUrlAddAPI.js b/src/ApiServices/reportBaseUrlAddAPI.js new file mode 100644 index 0000000..8b9ee76 --- /dev/null +++ b/src/ApiServices/reportBaseUrlAddAPI.js @@ -0,0 +1,24 @@ +// reportBaseUrlAddAPI.js +import apiService from '../APIRequestService/APIServices'; + +// Function to handle the Add API request +export const addReport = async (formData) => { + try { + const response = await apiService.post('/Rpt_builder2/Rpt_builder2', formData); + + console.log("add Report response: ",response) + return response; // Return the response to handle success in the component + } catch (error) { + throw error; // Re-throw error to handle it in the calling component + } +}; + +// Function to fetch keys from URL +export const getKeysFromUrl = async (url) => { + try { + const response = await apiService.get(`/api/report-builder/columns`, { url }); + return response; // Return the response for further processing + } catch (error) { + throw error; // Re-throw error to handle it in the calling component + } +}; diff --git a/src/ApiServices/reportBaseUrlAllAPI.js b/src/ApiServices/reportBaseUrlAllAPI.js new file mode 100644 index 0000000..ca4348d --- /dev/null +++ b/src/ApiServices/reportBaseUrlAllAPI.js @@ -0,0 +1,35 @@ +import axios from 'axios'; + +// Create axios instance +const apiService = axios.create({ + baseURL: process.env.REACT_APP_API_BASE_URL, +}); + +// Add request interceptor to inject the token +apiService.interceptors.request.use( + (config) => { + const token = localStorage.getItem('authToken'); + if (token) { + config.headers.Authorization = `Bearer ${token}`; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +// Add response interceptor to handle 401 errors +apiService.interceptors.response.use( + (response) => response, + (error) => { + if (error.response?.status === 401) { + // Handle token expiration (e.g., redirect to login) + localStorage.removeItem('authToken'); + window.location.href = '/login'; + } + return Promise.reject(error); + } +); + +export default apiService; \ No newline at end of file diff --git a/src/ApiServices/reportBaseUrlDeleteAPI.js b/src/ApiServices/reportBaseUrlDeleteAPI.js new file mode 100644 index 0000000..a1b9336 --- /dev/null +++ b/src/ApiServices/reportBaseUrlDeleteAPI.js @@ -0,0 +1,12 @@ +import apiService from '../APIRequestService/APIServices'; + + +export const deleteReport = async (reportId) => { + try { + const response = await apiService.delete(`/Rpt_builder2/Rpt_builder2/${reportId}`); + console.log(response.data); + return response; + } catch (error) { + throw error; + } +}; \ No newline at end of file diff --git a/src/ApiServices/reportBaseUrlEditAPI.js b/src/ApiServices/reportBaseUrlEditAPI.js new file mode 100644 index 0000000..916d385 --- /dev/null +++ b/src/ApiServices/reportBaseUrlEditAPI.js @@ -0,0 +1,16 @@ +import apiService from '../APIRequestService/APIServices'; + +const editReport = async (id, payload) => { + try { + const response = await apiService.put(`Rpt_builder2_lines/update/${id}`, payload); + console.log("Edit api report base url ", response.data) + return response.data; + } catch (error) { + console.error("Error in editReport:", error); + throw error; + } +}; + +export default { + editReport, +}; diff --git a/src/App.js b/src/App.js index e78ddce..3374976 100644 --- a/src/App.js +++ b/src/App.js @@ -37,6 +37,8 @@ import DashboardNewAdd from "./components/dashboardnew/dashboardadd/dashboardbui import DashboardNewEdit from "./components/dashboardnew/editdashboard/editformdashboard"; import EditNewDash from "./components/dashboardnew/editdashboard/editdashboard"; import SubMenuMaintenance from "./components/Dashboard/sub menu/submenumaintanence"; +import ReportRunnerAll from "./components/Dashboard/reports/reportrunnerall"; +import ReportBuilderSQL from "./components/Dashboard/reports/reportbuildersql"; const theme = createTheme({ palette: { primary: { @@ -65,22 +67,22 @@ const App = () => { draggable pauseOnHover /> - + - } /> - + } /> + {/* Main dashboard route */} - }> + }> } /> - + {/* Setup section with all maintenance routes */} }> Select a setup option from the menu} /> } /> } /> } /> - } /> - + } /> + } /> } /> } /> @@ -90,23 +92,25 @@ const App = () => { {/* Additional components */} } /> } /> - + - } /> - } /> - } /> - } /> - } /> - } /> - - } /> - } /> - } /> + }/> + }/> + }/> + }/> + }/> + }/> + } /> + } /> + {/* } /> */} + } /> + } /> - {/* buildercomponents */} + + } /> diff --git a/src/components/Dashboard/TokenRegistery/tokenregistryapi.js b/src/components/Dashboard/TokenRegistery/tokenregistryapi.js index 425a4b7..639aac7 100644 --- a/src/components/Dashboard/TokenRegistery/tokenregistryapi.js +++ b/src/components/Dashboard/TokenRegistery/tokenregistryapi.js @@ -4,7 +4,7 @@ import { getToken } from '../../../utils/tokenService'; // Create axios instance with base configuration const apiClient = axios.create({ - baseURL: process.env.REACT_APP_API_URL || 'http://157.66.191.31:33730/back/', + baseURL: process.env.REACT_APP_API_URL , }); // Add request interceptor to inject token diff --git a/src/components/Dashboard/dashboard.js b/src/components/Dashboard/dashboard.js index be58b1c..e75dd61 100644 --- a/src/components/Dashboard/dashboard.js +++ b/src/components/Dashboard/dashboard.js @@ -50,7 +50,7 @@ import ApiRegistery from "./ApiRegistery/ApiRegistery"; import TokenRegistery from "./TokenRegistery/TokenRegistery"; import HomePage from "./HomePage"; import Setup from "./Setup"; -import Report from "./reports/Report"; +// import Report from "./reports/Report"; import SequenceGenerator from "./document sequence/sequencegenerator"; import About from "./dropdown/about"; import Profile from "./dropdown/profile"; @@ -61,7 +61,9 @@ import DashboardNewEdit from "../dashboardnew/editdashboard/editformdashboard"; import EditNewDash from "../dashboardnew/editdashboard/editdashboard"; import DashboardRunner from "../dashboardnew/dashboardrunner/dashboardrunner"; import SubMenuMaintenance from "./sub menu/submenumaintanence"; - +import ReportRunnerAll from "./reports/reportrunnerall"; +import Report from "./reports/Report"; +import ReportBuilderSQL from "./reports/reportbuildersql"; const Dashboard = () => { const navigate = useNavigate(); @@ -585,7 +587,8 @@ const Dashboard = () => { } /> } /> - } /> + } /> + } /> } /> } /> }/> diff --git a/src/components/Dashboard/reports/Report.js b/src/components/Dashboard/reports/Report.js index e7de5ff..93de237 100644 --- a/src/components/Dashboard/reports/Report.js +++ b/src/components/Dashboard/reports/Report.js @@ -1,32 +1,50 @@ import React, { useState, useEffect } from "react"; - -const Card = ({ report }) => { - return ( -
-

{report.reportName}

-

{report.description}

-

- Active: {report.active ? "Yes" : "No"} -

-

Is SQL: {report.isSql ? "Yes" : "No"}

-
- ); -}; - -// Define the API base URL using the environment variable -const api = process.env.REACT_APP_API_BASE_URL; +import { useNavigate } from "react-router-dom"; +import { toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { + Container, + Grid, + Card, + CardHeader, + CardContent, + Typography, + CircularProgress, + Alert, + Paper, + Button, + Avatar, + Chip, + Box, + IconButton, + Divider +} from '@mui/material'; +import { + AddCircleOutline, + Storage as Database, + Link as LinkIcon, + CheckCircle, + Cancel, + MoreVert, + AccessTime +} from '@mui/icons-material'; const Report = () => { const [reports, setReports] = useState([]); const [loading, setLoading] = useState(true); + const [error, setError] = useState(""); + const navigate = useNavigate(); + const api = process.env.REACT_APP_API_BASE_URL; + console.log("API Base URL:", api); useEffect(() => { const fetchData = async () => { const token = localStorage.getItem("authToken"); if (!token) { - console.error("No auth token found. Redirecting to login."); - // You can redirect to the login page here if needed + setError("No auth token found. Please login."); + toast.error("Authentication required"); + navigate("/login"); return; } @@ -38,37 +56,276 @@ const Report = () => { }); if (!response.ok) { - throw new Error("Failed to fetch data"); + throw new Error(response.status === 401 ? "Session expired" : "Failed to fetch data"); } const data = await response.json(); setReports(data); - setLoading(false); } catch (error) { console.error("Error fetching data:", error); + setError(error.message); + if (error.message === "Session expired") { + toast.error("Session expired. Please login again."); + navigate("/login"); + } + } finally { setLoading(false); } }; fetchData(); - }, []); + }, [api, navigate]); + + const goToAddSQLReport = () => { + navigate("/dashboard/user-report"); + }; + + const goToAddURLReport = () => { + navigate("/admin/reportbuild2all"); + }; + + const handleCardClick = (report) => { + if (report.isSql) { + navigate(`/admin/report-runner1/${report.id}`, { + state: { reportId: report.id, reportData: report } + }); + } else { + navigate(`/admin/report-runner2/${report.id}`, { + state: { reportId: report.id, reportData: report } + }); + } + }; return ( -
-
-

Reports

-
- {loading ? ( -

Loading...

- ) : ( -
- {reports.map((report) => ( - - ))} -
+ + {/* Header Section */} + + + All Reports + + + + + + + + {/* Loading State */} + {loading && ( + + + )} -
+ + {/* Error State */} + {error && !loading && ( + + {error} + + )} + + {/* Reports Grid */} + {!loading && reports.length > 0 && ( + + {reports.map((report) => ( + + handleCardClick(report)} + > + {/* Card Header with Gradient */} + + + + {report.isSql ? : } + + + {report.isSql ? "SQL Report" : "URL Report"} + + + + {/* Status Chip */} + : } + sx={{ + backgroundColor: report.active ? 'rgba(40, 167, 69, 0.1)' : 'rgba(220, 53, 69, 0.1)', + color: report.active ? '#28a745' : '#dc3545', + px: 1, + py: 0.5 + }} + /> + + + {/* Card Content */} + + + {report.reportName} + + + {report.description || "No description available"} + + + + {/* Card Footer */} + + + + + + Updated: {new Date(report.updatedAt).toLocaleDateString()} + + + { + e.stopPropagation(); + // Add menu functionality here + }} + > + + + + + + + ))} + + )} + + {/* Empty State */} + {!loading && reports.length === 0 && !error && ( + + + No reports available + + + Create your first report by clicking one of the "Add Report" buttons + + + + + + + )} + ); }; -export default Report; +export default Report; \ No newline at end of file diff --git a/src/components/Dashboard/reports/reportbuildersql.js b/src/components/Dashboard/reports/reportbuildersql.js index 1e7bc9a..05b046f 100644 --- a/src/components/Dashboard/reports/reportbuildersql.js +++ b/src/components/Dashboard/reports/reportbuildersql.js @@ -1,64 +1,72 @@ import React, { useState, useEffect } from "react"; -import { - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - Paper, +import { useNavigate } from "react-router-dom"; +import { toast } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import { + Box, Button, - TextField, + Card, + CardContent, + CardHeader, + Checkbox, + Chip, Dialog, DialogActions, DialogContent, DialogTitle, - MenuItem, - Select, - IconButton, - Typography, - Box, - CircularProgress, - Pagination, - Chip, + Divider, FormControlLabel, - Checkbox, - InputAdornment, - Tooltip, - Divider + Grid, + IconButton, + Menu, + MenuItem, + Pagination, + Paper, + Select, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TextField, + Typography, } from "@mui/material"; -import { - Add as AddIcon, - Edit as EditIcon, - Delete as DeleteIcon, - Settings as SettingsIcon, - ArrowBack as ArrowBackIcon, - Search as SearchIcon, - Close as CloseIcon, - PlayArrow as PlayArrowIcon, - ViewColumn as ViewColumnIcon, - List as ListIcon, - MoreVert as MoreVertIcon +import { + Add, + ArrowBack, + CheckCircle, + Close, + Delete, + Edit, + MoreVert, + PlayArrow, + Search, + Settings, + ViewList, } from "@mui/icons-material"; -import { useNavigate } from "react-router-dom"; -import { toast } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import ReportSqlBuilderApi from "APIServices/ReportSQLBuilderAPI"; -import { addSQLReport } from "APIServices/AddReportSQLBuilderAPI"; -import { UpdateReportSQLBuilder } from "APIServices/UpdateReportSQLBuilderAPI"; -import { deleteReportSQL } from "APIServices/DeleteReportSQLAPI"; -import ConfirmModal from "../../common/ConfirmModal"; -import ReportBuilderService from "../../../APIServices/ReportBuilderService"; +import ReportSqlBuilderApi from "./../../../ApiServices/ReportSQLBuilderAPI"; +import { addSQLReport } from "./../../../ApiServices/AddReportSQLBuilderAPI"; +import { UpdateReportSQLBuilder } from "./../../../ApiServices/UpdateReportSQLBuilderAPI"; +import { deleteReportSQL } from "./../../../ApiServices/DeleteReportSQLAPI"; +import ReportBuilderService from "../../../ApiServices/ReportBuilderService"; -function UserDetailsView() { +const ReportBuilderSQL = () => { const [userDetails, setUserDetails] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [loading, setLoading] = useState(true); - const [recordsPerPage, setRecordsPerPage] = useState(10); + const [rowsPerPage, setRowsPerPage] = useState(10); const [currentPage, setCurrentPage] = useState(1); const navigate = useNavigate(); - const [showModal, setShowModal] = useState(false); - const [showAddModal, setShowAddModal] = useState(false); + const [visibleColumns, setVisibleColumns] = useState({ + reportName: true, + description: true, + action: true, + status: true, + }); + const [editDialogOpen, setEditDialogOpen] = useState(false); + const [addDialogOpen, setAddDialogOpen] = useState(false); const [selectedReport, setSelectedReport] = useState(null); const [editData, setEditData] = useState({ reportName: "", @@ -72,9 +80,9 @@ function UserDetailsView() { isSql: true, Rpt_builder2_lines: [{ model: "" }], }); - const [showConfirmModal, setShowConfirmModal] = useState(false); - const [deleteItem, setDeleteItem] = useState({ index: null, id: null }); - const [showReportConfigModal, setShowReportConfigModal] = useState(false); + const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false); + const [itemToDelete, setItemToDelete] = useState({ id: null, name: "" }); + const [reportConfigOpen, setReportConfigOpen] = useState(false); const [reportConfigData, setReportConfigData] = useState({ conn_name: "", date_param_req: "", @@ -82,19 +90,21 @@ function UserDetailsView() { adhoc_param_html: "", column_str: "", sql_str: "", - id: null + id: null, }); const [databaseConnections, setDatabaseConnections] = useState([]); + const [columnsMenuAnchor, setColumnsMenuAnchor] = useState(null); + const [rowsMenuAnchor, setRowsMenuAnchor] = useState(null); const fetchUserDetails = async () => { try { setLoading(true); const data = await ReportSqlBuilderApi.fetchUserDetails(); setUserDetails(data); - toast.success('Data fetched successfully!'); + toast.success("Data fetched successfully!"); } catch (error) { - console.error('Error fetching user details:', error); - toast.error('Failed to fetch user details.'); + console.error("Error fetching user details:", error); + toast.error("Failed to fetch user details."); } finally { setLoading(false); } @@ -104,127 +114,107 @@ function UserDetailsView() { fetchUserDetails(); }, []); - const handlePlayClick = () => { - if (selectedReport) { - goToRunner(selectedReport); - } else { - toast.error("No report selected to run."); - } - }; - - const handleRecordsPerPageChange = (event) => { - setRecordsPerPage(parseInt(event.target.value, 10)); + const handleSearch = (e) => { + setSearchQuery(e.target.value); setCurrentPage(1); }; - const handleInputChange = (event) => { - const { name, value, checked, type } = event.target; - const inputValue = type === "checkbox" ? checked : value; + const filteredData = userDetails.filter((item) => + item.reportName?.toLowerCase().includes(searchQuery.toLowerCase()) + ); - if (showModal) { - setEditData((prev) => ({ ...prev, [name]: inputValue })); - } else if (showAddModal) { - setNewData((prev) => ({ ...prev, [name]: inputValue })); - } + const totalPages = Math.ceil(filteredData.length / rowsPerPage); + const paginatedData = filteredData.slice( + (currentPage - 1) * rowsPerPage, + currentPage * rowsPerPage + ); + + const handleEdit = (report) => { + setEditData(report); + setEditDialogOpen(true); }; - const handleSubmit = async () => { + const handleEditSubmit = async () => { try { const updatedReport = await UpdateReportSQLBuilder(editData.id, editData); - toast.success("Report Updated successfully.."); - const updatedDetails = userDetails.map((detail) => - detail.id === editData.id ? { ...detail, ...editData } : detail + setUserDetails( + userDetails.map((detail) => + detail.id === editData.id ? { ...detail, ...editData } : detail + ) ); - setUserDetails(updatedDetails); - setShowModal(false); + setEditDialogOpen(false); + toast.success("Report updated successfully"); } catch (error) { - console.error("Error updating the report: ", error); + console.error("Error updating report:", error); toast.error("Failed to update report"); } }; - const filteredUsers = userDetails.filter( - (item) => - item.reportName && - item.reportName.toLowerCase().includes(searchQuery.toLowerCase()) - ); - - const slicedUsers = filteredUsers.slice( - (currentPage - 1) * recordsPerPage, - currentPage * recordsPerPage - ); - - const totalPages = Math.ceil(filteredUsers.length / recordsPerPage); - - const handlePageChange = (event, page) => { - setCurrentPage(page); - }; - - const handleGoTo = (data) => { - const hasReportData = data.rpt_builder2_lines?.some(line => line.model && line.model.trim() !== ""); - if (hasReportData) { - fetchReportConfiguration(data.id, data); - } else { - navigate("/admin/reportquery", { state: { id: data.id, reportData: data } }); + const handleAddSubmit = async () => { + try { + const addedReport = await addSQLReport(newData); + setUserDetails([...userDetails, addedReport]); + setAddDialogOpen(false); + setNewData({ + reportName: "", + description: "", + active: false, + isSql: true, + Rpt_builder2_lines: [{ model: "" }], + }); + toast.success("Report added successfully"); + } catch (error) { + console.error("Error adding report:", error); + toast.error("Failed to add report"); } }; - const handleRowClick = (report) => { - fetchReportConfiguration(report.id, report); + const handleDelete = async () => { + try { + await deleteReportSQL(itemToDelete.id); + setUserDetails(userDetails.filter((item) => item.id !== itemToDelete.id)); + setDeleteConfirmOpen(false); + toast.success("Report deleted successfully"); + } catch (error) { + console.error("Error deleting report:", error); + toast.error("Failed to delete report"); + } }; const fetchDatabaseConnections = async () => { try { - setLoading(true); const response = await ReportBuilderService.getDatabase(); - if (response && response.data) { - setDatabaseConnections(response.data); - } else { - setDatabaseConnections([]); - } + setDatabaseConnections(response?.data || []); } catch (error) { - console.error("Error fetching database connections: ", error); + console.error("Error fetching database connections:", error); toast.error("Failed to load database connections"); - setDatabaseConnections([]); - } finally { - setLoading(false); } }; - const fetchReportConfiguration = async (reportId, report) => { + const handleRowClick = async (report) => { try { setLoading(true); - const response = await ReportBuilderService.getrbLineDetailsById(report.rpt_builder2_lines[0].id); await fetchDatabaseConnections(); - if (response && response.data) { - let configData = {}; + const response = await ReportBuilderService.getrbLineDetailsById( + report.rpt_builder2_lines[0].id + ); + + let configData = {}; + if (report.Rpt_builder2_lines?.length > 0) { try { - if (report.Rpt_builder2_lines && report.Rpt_builder2_lines.length > 0) { - const modelData = JSON.parse(report.Rpt_builder2_lines[0].model); - configData = { - conn_name: modelData.conn_name || "", - date_param_req: modelData.date_param_req || "", - std_param_html: modelData.std_param_html || "", - adhoc_param_html: modelData.adhoc_param_html || "", - column_str: modelData.column_str || "", - sql_str: modelData.sql_str || "", - id: report.rpt_builder2_lines[0].id - }; - } else { - configData = { - conn_name: "", - date_param_req: "", - std_param_html: "", - adhoc_param_html: "", - column_str: "", - sql_str: "", - id: report.rpt_builder2_lines[0].id - }; - } + const modelData = JSON.parse(report.Rpt_builder2_lines[0].model); + configData = { + conn_name: modelData.conn_name || "", + date_param_req: modelData.date_param_req || "", + std_param_html: modelData.std_param_html || "", + adhoc_param_html: modelData.adhoc_param_html || "", + column_str: modelData.column_str || "", + sql_str: modelData.sql_str || "", + id: report.rpt_builder2_lines[0].id, + }; } catch (error) { - console.error("Error parsing report configuration: ", error); - toast.error("Failed to parse report configuration"); + console.error("Error parsing report config:", error); configData = { conn_name: "", date_param_req: "", @@ -232,34 +222,21 @@ function UserDetailsView() { adhoc_param_html: "", column_str: "", sql_str: "", - id: report.rpt_builder2_lines[0].id + id: report.rpt_builder2_lines[0].id, }; } - setReportConfigData(configData); - setShowReportConfigModal(true); - } else { - toast.error("No configuration data found for this report"); } + + setReportConfigData(configData); + setReportConfigOpen(true); } catch (error) { - console.error("Error fetching report configuration: ", error); + console.error("Error fetching report config:", error); toast.error("Failed to load report configuration"); } finally { setLoading(false); } }; - const handleReportConfigClose = () => { - setShowReportConfigModal(false); - }; - - const handleReportConfigChange = (e) => { - const { name, value } = e.target; - setReportConfigData(prev => ({ - ...prev, - [name]: value - })); - }; - const handleReportConfigUpdate = async () => { try { setLoading(true); @@ -276,271 +253,289 @@ function UserDetailsView() { header_id: reportConfigData.id, model: JSON.stringify(reportData), }; - - const response = await ReportBuilderService.updaterbLineData(saveReportData, reportConfigData.id); - toast.success("Report configuration updated successfully"); - setShowReportConfigModal(false); + + await ReportBuilderService.updaterbLineData( + saveReportData, + reportConfigData.id + ); + setReportConfigOpen(false); + toast.success("Report configuration updated"); fetchUserDetails(); } catch (error) { - console.error("Error updating report configuration: ", error); + console.error("Error updating report config:", error); toast.error("Failed to update report configuration"); } finally { setLoading(false); } }; - const handleDelete = async () => { - const { id } = deleteItem; - if (!id) { - toast.error("Invalid ID. Deletion failed."); - return; - } - - try { - const deletedReport = await deleteReportSQL(id); - toast.success("Report deleted successfully"); - setUserDetails(userDetails.filter(item => item.id !== id)); - } catch (error) { - console.error("Error in deleting report:", error); - toast.error("Failed to delete report"); - } - }; - - const confirmDelete = (e, index, id, reportName) => { - e.stopPropagation(); - setDeleteItem({ index, id, reportName }); - setShowConfirmModal(true); - }; - - const handleEdit = (detail) => { - setEditData(detail); - setShowModal(true); - }; - - const handleClose = () => { - setShowModal(false); - }; - - const handleAddClose = () => { - setShowAddModal(false); - }; - - const handleAddSubmit = async () => { - try { - const addedReport = await addSQLReport(newData); - setUserDetails((prevUserDetails) => [...prevUserDetails, addedReport]); - setNewData({ - reportName: "", - description: "", - active: false, - isSql: true - }); - setShowAddModal(false); - toast.success("User report added successfully!"); - } catch (error) { - toast.error("Failed to add the user report. Please try again."); - console.error("Error adding user report: ", error); - } - }; - const goToRunner = (report) => { - if (!report || typeof report.isSql === "undefined") { - console.error("Invalid report object:", report); - return; - } + if (!report || typeof report.isSql === "undefined") return; + navigate( + report.isSql + ? `/admin/report-runner/${report.id}` + : `/admin/report-runner2/${report.id}` + ); + }; - if (report.isSql) { - navigate(`/admin/report-runner/${report.id}`); - } else { - navigate(`/admin/report-runner2/${report.id}`); - } + const toggleColumn = (column) => { + setVisibleColumns((prev) => ({ + ...prev, + [column]: !prev[column], + })); }; return ( - - - - Report Builder (SQL) - - - - - - + + + + + + + Report Builder (SQL) + + + + + + + + + + + - - setSearchQuery(e.target.value)} - InputProps={{ - startAdornment: ( - - - - ), - endAdornment: searchQuery && ( - - setSearchQuery("")}> - - - - ), - }} - sx={{ width: '50%' }} - /> - + + + + + + ), + }} + /> + + + + + setColumnsMenuAnchor(null)} + > + {Object.keys(visibleColumns).map((column) => ( + toggleColumn(column)}> + + } + label={column.charAt(0).toUpperCase() + column.slice(1)} + /> + + ))} + - {loading ? ( - - - - ) : ( - <> - + + setRowsMenuAnchor(null)} + > + {[5, 10, 20, 50].map((num) => ( + { + setRowsPerPage(num); + setRowsMenuAnchor(null); + }} + > + {num} + {rowsPerPage === num && ( + + )} + + ))} + + + + + + - - Go To - Report Name - Description - Status - Actions + + Go To + {visibleColumns.reportName && Report Name} + {visibleColumns.description && Description} + {visibleColumns.status && Status} + {visibleColumns.action && Actions} - {slicedUsers.length === 0 ? ( + {paginatedData.length === 0 ? ( - No records found. + No records found ) : ( - slicedUsers.filter((detail) => detail.isSql).map((detail, index) => ( - handleRowClick(detail)} - sx={{ cursor: 'pointer' }} - > - - { - e.stopPropagation(); - handleGoTo(detail); - }} - > - - - - {detail.reportName} - {detail.description || "No description available"} - - - - - { - e.stopPropagation(); - handleEdit(detail); - }} - > - - - { - e.stopPropagation(); - confirmDelete(e, index, detail.id, detail.reportName); - }} - > - - - - - )) + paginatedData + .filter((detail) => detail.isSql) + .map((detail) => ( + handleRowClick(detail)} + sx={{ cursor: "pointer" }} + > + + { + e.stopPropagation(); + handleRowClick(detail); + }} + > + + + + {visibleColumns.reportName && ( + {detail.reportName} + )} + {visibleColumns.description && ( + + {detail.description || "No description available"} + + )} + {visibleColumns.status && ( + + + + )} + {visibleColumns.action && ( + + { + e.stopPropagation(); + handleEdit(detail); + }} + > + + + { + e.stopPropagation(); + setItemToDelete({ + id: detail.id, + name: detail.reportName, + }); + setDeleteConfirmOpen(true); + }} + > + + + + )} + + )) )}
- - - - Rows per page: - - - + + + Showing {(currentPage - 1) * rowsPerPage + 1} to{" "} + {Math.min(currentPage * rowsPerPage, filteredData.length)} of{" "} + {filteredData.length} entries + setCurrentPage(page)} color="primary" - showFirstButton - showLastButton /> - - - )} + +
+
{/* Edit Dialog */} - - Edit User Detail + setEditDialogOpen(false)}> + + Edit Report + setEditDialogOpen(false)} + > + + + - + + setEditData({ ...editData, reportName: e.target.value }) + } + sx={{ mb: 2 }} /> + setEditData({ ...editData, description: e.target.value }) + } + sx={{ mb: 2 }} /> + setEditData({ ...editData, active: e.target.checked }) + } /> } label="Active" @@ -548,40 +543,51 @@ function UserDetailsView() { - - + + {/* Add Dialog */} - - Add New User Detail + setAddDialogOpen(false)}> + + Add New Report + setAddDialogOpen(false)} + > + + + - + + setNewData({ ...newData, reportName: e.target.value }) + } + sx={{ mb: 2 }} /> + setNewData({ ...newData, description: e.target.value }) + } + sx={{ mb: 2 }} /> + setNewData({ ...newData, active: e.target.checked }) + } /> } label="Active" @@ -589,113 +595,179 @@ function UserDetailsView() { - - + + - {/* Confirmation Dialog */} - setShowConfirmModal(false)} - onConfirm={handleDelete} - title="Confirm Deletion" - message={`Are you sure you want to delete "${deleteItem.reportName || 'this report'}"? This action cannot be undone.`} - confirmText="Delete" - cancelText="Cancel" - /> + {/* Delete Confirmation Dialog */} + setDeleteConfirmOpen(false)} + > + Confirm Deletion + + + Are you sure you want to delete "{itemToDelete.name}"? This action + cannot be undone. + + + + + + + {/* Report Configuration Dialog */} - - Report Configuration + setReportConfigOpen(false)} + maxWidth="md" + fullWidth + > + + Report Configuration + setReportConfigOpen(false)} + > + + + - - - - - - + + + + + setReportConfigData({ + ...reportConfigData, + conn_name: e.target.value, + }) + } + sx={{ mb: 2 }} + > + Select Database Connection + {databaseConnections.map((db) => ( + + {db.name} + + ))} + + + + + setReportConfigData({ + ...reportConfigData, + date_param_req: e.target.value, + }) + } + sx={{ mb: 2 }} + > + Select Option + Yes + No + + + + + setReportConfigData({ + ...reportConfigData, + sql_str: e.target.value, + }) + } + sx={{ mb: 2 }} + InputProps={{ + style: { fontFamily: "monospace" }, + }} /> - + + setReportConfigData({ + ...reportConfigData, + column_str: e.target.value, + }) + } + sx={{ mb: 2 }} /> - - - - - + + + + + setReportConfigData({ + ...reportConfigData, + std_param_html: e.target.value, + }) + } + sx={{ mb: 2 }} + /> + + + + setReportConfigData({ + ...reportConfigData, + adhoc_param_html: e.target.value, + }) + } + sx={{ mb: 2 }} + /> + + - - +
); -} +}; -export default UserDetailsView; \ No newline at end of file +export default ReportBuilderSQL; \ No newline at end of file diff --git a/src/components/Dashboard/reports/reportrunnerall.js b/src/components/Dashboard/reports/reportrunnerall.js index 12bafe3..25111b8 100644 --- a/src/components/Dashboard/reports/reportrunnerall.js +++ b/src/components/Dashboard/reports/reportrunnerall.js @@ -2,15 +2,45 @@ import React, { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; -import { fetchAllReportsApi } from '../../../APIServices/ReportRunnerAPI'; +import { fetchAllReportsApi } from '../../../ApiServices/ReportRunnerAPI'; +import { + Container, + Grid, + Card, + CardHeader, + CardContent, + CardActions, + Typography, + Button, + CircularProgress, + Alert, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Avatar, + IconButton, + Chip, + Divider, + Paper +} from '@mui/material'; +import { + AddCircleOutline, + Link, + Storage as Database, + MoreVert, + AccessTime, + Delete, + CheckCircle, + Cancel +} from '@mui/icons-material'; const ReportRunnerAll = () => { const [gridData, setGridData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(""); const [rowSelected, setRowSelected] = useState(null); - const [modalDelete, setModalDelete] = useState(false); - const [reports, setReports] = useState([]); + const [openDeleteDialog, setOpenDeleteDialog] = useState(false); const navigate = useNavigate(); @@ -23,16 +53,12 @@ const ReportRunnerAll = () => { try { const data = await fetchAllReportsApi(); console.log("Fetched all reports:", data); - setGridData(data); - setReports(data); - - if (data.length === 0) { - setError("No data available"); - } + if (data.length === 0) setError("No data available"); } catch (error) { console.error("Error while fetching reports:", error); setError("Error fetching data."); + toast.error("Failed to load reports"); } finally { setIsLoading(false); } @@ -42,170 +68,196 @@ const ReportRunnerAll = () => { const goToAdd2 = () => navigate("/admin/reportbuild2all"); const goToRunner = (report) => { - console.log("at time of navigating reportID: ",report.id, " report: ",report); if (report.isSql) { - navigate(`/admin/report-runner1/${report.id}`,{ state: { reportId: report.id, reportData: report}}); + navigate(`/admin/report-runner1/${report.id}`, { + state: { reportId: report.id, reportData: report } + }); } else { - navigate(`/admin/report-runner2/${report.id}`,{ state: { reportId: report.id, reportData: report}}); + navigate(`/admin/report-runner2/${report.id}`, { + state: { reportId: report.id, reportData: report } + }); } }; const handleDelete = async (id) => { - setModalDelete(false); + setOpenDeleteDialog(false); try { - const response = await fetch(`/api/report-builder/${id}`, { method: "DELETE" }); + const response = await fetch(`/api/report-builder/${id}`, { + method: "DELETE" + }); if (response.ok) { - toast.success("Deleted successfully"); + toast.success("Report deleted successfully"); fetchAllReports(); } else { - toast.error("Error deleting data."); + throw new Error("Failed to delete"); } } catch (err) { console.error(err); - toast.error("Error deleting data."); + toast.error("Error deleting report"); } }; const openDeleteModal = (row) => { setRowSelected(row); - setModalDelete(true); + setOpenDeleteDialog(true); }; return ( -
+ {/* Header */} -
-

All Reports

+ + + + All Reports +
- - + +
-
+ - {/* Loading Spinner */} + {/* Loading state */} {isLoading && ( -
-
- Loading... -
+ + + + )} + + {/* Error state */} + {error && !isLoading && ( + + {error} + )} {/* Report Cards */} {!isLoading && gridData.length > 0 && ( -
+ {gridData.map((report, index) => ( -
-
+ goToRunner(report)} - style={{ cursor: 'pointer' }} > {/* Card Header */} -
-
-
- -
- - {report.isSql == null ? "N/A" : report.isSql ? "SQL Report" : "URL Report"} - -
- - {report.active ? "Active" : "Inactive"} - -
+ + {report.isSql ? : } + + } + action={ + : } + sx={{ ml: 1 }} + /> + } + title={ + + {report.isSql ? "SQL Report" : "URL Report"} + + } + sx={{ + bgcolor: report.isSql ? 'primary.50' : 'secondary.50', + borderBottom: '1px solid', + borderColor: 'divider' + }} + /> - {/* Card Body */} -
-
+ {/* Card Content */} + + {report.reportName} -
-

+ + {report.description || "No description available"} -

-
+ + {/* Card Footer */} -
-
- - - Updated: {new Date(report.updatedAt).toLocaleDateString()} - - -
-
-
-
+ + + + + Updated: {new Date(report.updatedAt).toLocaleDateString()} + + { + e.stopPropagation(); + openDeleteModal(report); + }} + > + + + + +
))} -
+ )} - {/* Error */} - {error &&
{error}
} - - {/* Delete Modal */} - {modalDelete && ( -
-
-
-
-
Delete Confirmation
- -
-
-

Are you sure you want to delete the report?

-
{rowSelected?.reportName}
-
-
- - -
-
-
-
- )} -
+ {/* Delete Dialog */} + setOpenDeleteDialog(false)} + > + Delete Confirmation + + + Are you sure you want to delete the report? + + + {rowSelected?.reportName} + + + + + + + + ); };