GWM : filter data and structured response
This commit is contained in:
parent
065e62b750
commit
9afc6fcca1
3432
filter_files/divorces.json
Normal file
3432
filter_files/divorces.json
Normal file
File diff suppressed because it is too large
Load Diff
339
main.go
339
main.go
@ -69,7 +69,7 @@ func removeNamespace(xmlBytes []byte) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to fetch XML from an API and convert it to JSON
|
// Function to fetch XML from an API and convert it to JSON
|
||||||
func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]map[string]interface{}, error) {
|
func fetchAndConvertXMLToJSON(apiURL string, outputDir string, fileName string, tableName string, id string) ([]map[string]interface{}, error) {
|
||||||
// Call the API and get the XML response
|
// Call the API and get the XML response
|
||||||
resp, err := http.Get(apiURL)
|
resp, err := http.Get(apiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,21 +110,19 @@ func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save the JSON data to a file if required
|
// Save the JSON data to a file if required
|
||||||
|
|
||||||
// Ensure the folder exists
|
// Ensure the folder exists
|
||||||
outputDir := "kpi_files"
|
|
||||||
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
if err := os.MkdirAll(outputDir, os.ModePerm); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the file with a timestamped filename
|
// Save the file
|
||||||
fileName := fmt.Sprintf("%s/%s.json", outputDir, kpiName)
|
file := fmt.Sprintf("%s/%s.json", outputDir, fileName)
|
||||||
if err := ioutil.WriteFile(fileName, jsonData, 0644); err != nil {
|
if err := ioutil.WriteFile(file, jsonData, 0644); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the charts record
|
// Find the charts record
|
||||||
record, err := app.Dao().FindRecordById("charts", chartId)
|
record, err := app.Dao().FindRecordById(tableName, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// return c.JSON(500, map[string]interface{}{"code": 500,"message": "Error finding user.",})
|
// return c.JSON(500, map[string]interface{}{"code": 500,"message": "Error finding user.",})
|
||||||
}
|
}
|
||||||
@ -137,9 +135,10 @@ func fetchAndConvertXMLToJSON(apiURL string, kpiName string, chartId string) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to read JSON data from a file
|
// Function to read JSON data from a file
|
||||||
func readJSONFromFile(kpiName string) ([]map[string]interface{}, error) {
|
// Function to read JSON data from a file
|
||||||
// Construct the file path
|
func readJSONFromFile(folderName, kpiName string) ([]map[string]interface{}, error) {
|
||||||
filePath := fmt.Sprintf("kpi_files/%s.json", kpiName)
|
// Construct the file path dynamically using the folder name
|
||||||
|
filePath := fmt.Sprintf("%s/%s.json", folderName, kpiName)
|
||||||
|
|
||||||
// Read and return the JSON content from the file
|
// Read and return the JSON content from the file
|
||||||
fileContent, err := ioutil.ReadFile(filePath)
|
fileContent, err := ioutil.ReadFile(filePath)
|
||||||
@ -211,6 +210,60 @@ func generateFilters(responseRaw []map[string]interface{}, filterKeys []string)
|
|||||||
return filters, nil
|
return filters, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to fetch filter data of dataset
|
||||||
|
func fetchfilterJSON(dataset string) ([]FilterGroup, error) {
|
||||||
|
|
||||||
|
// Define struct for the result
|
||||||
|
var dataSetFilter struct {
|
||||||
|
Id string `db:"id" json:"id"`
|
||||||
|
FullDataUrl string `db:"full_data_url" json:"full_data_url"`
|
||||||
|
FilterKeys string `db:"filter_keys" json:"filter_keys"`
|
||||||
|
FileStatus bool `db:"file_status" json:"file_status"`
|
||||||
|
DataSet string `db:"dataset" json:"dataset"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query to get one row from the data_set_filter table
|
||||||
|
err := app.DB().
|
||||||
|
Select("id", "full_data_url", "filter_keys", "file_status", "dataset").
|
||||||
|
From("data_set_filter").
|
||||||
|
Where(dbx.HashExp{"dataset": dataset}).
|
||||||
|
One(&dataSetFilter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to fetch data_set_filter data: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch and convert XML to JSON if file is not saved
|
||||||
|
if !dataSetFilter.FileStatus { // Check if FileStatus is false
|
||||||
|
_, err := fetchAndConvertXMLToJSON(dataSetFilter.FullDataUrl, "filter_files", dataSetFilter.DataSet, "data_set_filter", dataSetFilter.Id)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to process URL '%s': %v", dataSetFilter.FullDataUrl, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the JSON data from the file
|
||||||
|
response, err := readJSONFromFile("filter_files", dataSetFilter.DataSet)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to read JSON for dataset '%s': %v", dataSetFilter.DataSet, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the filter keys
|
||||||
|
filterKeys := strings.Split(dataSetFilter.FilterKeys, ",")
|
||||||
|
|
||||||
|
// Generate filters
|
||||||
|
filters, err := generateFilters(response, filterKeys)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to generate filters: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the filters directly
|
||||||
|
return filters, nil
|
||||||
|
}
|
||||||
|
|
||||||
var app *pocketbase.PocketBase
|
var app *pocketbase.PocketBase
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -388,49 +441,49 @@ func main() {
|
|||||||
|
|
||||||
return c.HTML(http.StatusOK, `
|
return c.HTML(http.StatusOK, `
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
background-color: #f0f8ff;
|
background-color: #f0f8ff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.message-container {
|
.message-container {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #e0f7fa;
|
background-color: #e0f7fa;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
.message-container h1 {
|
.message-container h1 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #00796b;
|
color: #00796b;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.message-container p {
|
.message-container p {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #004d40;
|
color: #004d40;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 50px;
|
font-size: 50px;
|
||||||
color: #00796b;
|
color: #00796b;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<i>✔</i>
|
<i>✔</i>
|
||||||
<h1>User Approved Successfully</h1>
|
<h1>User Approved Successfully</h1>
|
||||||
<p>The user has been approved, and the approval email has been sent.</p>
|
<p>The user has been approved, and the approval email has been sent.</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -460,50 +513,50 @@ func main() {
|
|||||||
// Check if the email is already verified
|
// Check if the email is already verified
|
||||||
if record.GetBool("reviewed") {
|
if record.GetBool("reviewed") {
|
||||||
return c.HTML(http.StatusOK, `
|
return c.HTML(http.StatusOK, `
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
background-color: #f0f8ff;
|
background-color: #f0f8ff;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.message-container {
|
.message-container {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: #ffe0e0;
|
background-color: #ffe0e0;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
.message-container h1 {
|
.message-container h1 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #b71c1c;
|
color: #b71c1c;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.message-container p {
|
.message-container p {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #880e4f;
|
color: #880e4f;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 50px;
|
font-size: 50px;
|
||||||
color: #b71c1c;
|
color: #b71c1c;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<div class="icon">✖</div>
|
<div class="icon">✖</div>
|
||||||
<h1>Your Already Reviewed</h1>
|
<h1>Your Already Reviewed</h1>
|
||||||
<p>You have already been reviewed. No further action is required.</p>
|
<p>You have already been reviewed. No further action is required.</p>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the status is already "Denied" to avoid duplicate email
|
// Check if the status is already "Denied" to avoid duplicate email
|
||||||
@ -630,32 +683,32 @@ func main() {
|
|||||||
|
|
||||||
// Email body in HTML format
|
// Email body in HTML format
|
||||||
body := fmt.Sprintf(`
|
body := fmt.Sprintf(`
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<p>Dear %s,</p>
|
<p>Dear %s,</p>
|
||||||
<p> You have received new feedback from a user through the mobile application.</p>
|
<p> You have received new feedback from a user through the mobile application.</p>
|
||||||
<p><b>User Details:</b></p>
|
<p><b>User Details:</b></p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Name</b> %s</li>
|
<li><b>Name</b> %s</li>
|
||||||
<li><b>Date of Submission:</b> %s</li>
|
<li><b>Date of Submission:</b> %s</li>
|
||||||
<li><b>Time of Submission:</b> %s</li>
|
<li><b>Time of Submission:</b> %s</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p><b>Feedback:</b></p>
|
<p><b>Feedback:</b></p>
|
||||||
<pre>
|
<pre>
|
||||||
1. How was your experience with us today? Rating: %s
|
1. How was your experience with us today? Rating: %s
|
||||||
2. How did we perform in key areas?
|
2. How did we perform in key areas?
|
||||||
1. Ease of Use: %s
|
1. Ease of Use: %s
|
||||||
2. Quality: %s
|
2. Quality: %s
|
||||||
3. Design: %s
|
3. Design: %s
|
||||||
4. Redundancy: %s
|
4. Redundancy: %s
|
||||||
3. Additional Feedback:
|
3. Additional Feedback:
|
||||||
1. %s
|
1. %s
|
||||||
</pre>
|
</pre>
|
||||||
<p>Thank you,</p>
|
<p>Thank you,</p>
|
||||||
<p>The FCSC App Team</p>
|
<p>The FCSC App Team</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback)
|
`, adminName, userName, formattedDate, formattedDateTime, emojiRating, easeOfUse, quality, design, redundancy, additionalFeedback)
|
||||||
|
|
||||||
// Define the target type (e.g., "smtp")
|
// Define the target type (e.g., "smtp")
|
||||||
targetType := "feedback_receive_mail"
|
targetType := "feedback_receive_mail"
|
||||||
@ -829,6 +882,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var aggregatedResponse []map[string]interface{}
|
var aggregatedResponse []map[string]interface{}
|
||||||
|
|
||||||
|
filterData, err := fetchfilterJSON(dataset)
|
||||||
|
|
||||||
for _, record := range records {
|
for _, record := range records {
|
||||||
// Extract the URL for each record
|
// Extract the URL for each record
|
||||||
apiURL := record.GetString("url")
|
apiURL := record.GetString("url")
|
||||||
@ -842,7 +898,7 @@ func main() {
|
|||||||
saveToFile := record.GetBool("file_status")
|
saveToFile := record.GetBool("file_status")
|
||||||
chartId := record.GetString("id")
|
chartId := record.GetString("id")
|
||||||
if !saveToFile { // Check if saveToFile is false
|
if !saveToFile { // Check if saveToFile is false
|
||||||
_, err := fetchAndConvertXMLToJSON(apiURL, kpi, chartId)
|
_, err := fetchAndConvertXMLToJSON(apiURL, "kpi_files", kpi, "charts", chartId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to process URL '%s': %v", apiURL, err)
|
log.Printf("Failed to process URL '%s': %v", apiURL, err)
|
||||||
continue // Skip this record and proceed with others
|
continue // Skip this record and proceed with others
|
||||||
@ -850,30 +906,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the JSON data from the file
|
// Read the JSON data from the file
|
||||||
response, err := readJSONFromFile(kpi)
|
response, err := readJSONFromFile("kpi_files", kpi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to read JSON for KPI '%s': %v", kpi, err)
|
log.Printf("Failed to read JSON for KPI '%s': %v", kpi, err)
|
||||||
continue // Skip this record and proceed with others
|
continue // Skip this record and proceed with others
|
||||||
}
|
}
|
||||||
|
|
||||||
var filters []FilterGroup
|
|
||||||
filterKeysRaw := record.GetString("filter")
|
|
||||||
if record.GetBool("is_chart") {
|
|
||||||
|
|
||||||
// Split the filter keys if they come as a comma-separated string
|
|
||||||
filterKeys := strings.Split(filterKeysRaw, ",")
|
|
||||||
|
|
||||||
// Generate filters
|
|
||||||
var err error
|
|
||||||
filters, err = generateFilters(response, filterKeys)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Assign an empty filter slice
|
|
||||||
filters = []FilterGroup{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare the structure with URL and its response
|
// Prepare the structure with URL and its response
|
||||||
recordResult := map[string]interface{}{
|
recordResult := map[string]interface{}{
|
||||||
"url": apiURL,
|
"url": apiURL,
|
||||||
@ -884,7 +922,6 @@ func main() {
|
|||||||
"is_chart": record.GetString("is_chart"),
|
"is_chart": record.GetString("is_chart"),
|
||||||
"chart_type": record.GetString("chart_type"),
|
"chart_type": record.GetString("chart_type"),
|
||||||
"response": response,
|
"response": response,
|
||||||
"filters": filters,
|
|
||||||
"group_by": record.GetString("group_by"),
|
"group_by": record.GetString("group_by"),
|
||||||
"chart_heading": record.GetString("chart_heading"),
|
"chart_heading": record.GetString("chart_heading"),
|
||||||
}
|
}
|
||||||
@ -894,11 +931,17 @@ func main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the response structure
|
||||||
|
response := map[string]interface{}{
|
||||||
|
"filter_data": filterData,
|
||||||
|
"data": aggregatedResponse,
|
||||||
|
}
|
||||||
|
|
||||||
if len(aggregatedResponse) == 0 {
|
if len(aggregatedResponse) == 0 {
|
||||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "No data could be fetched from the provided URLs"})
|
return c.JSON(http.StatusInternalServerError, map[string]string{"error": "No data could be fetched from the provided URLs"})
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, aggregatedResponse)
|
return c.JSON(http.StatusOK, response)
|
||||||
})
|
})
|
||||||
|
|
||||||
e.Router.GET("/api/getHomePageData", func(c echo.Context) error {
|
e.Router.GET("/api/getHomePageData", func(c echo.Context) error {
|
||||||
@ -907,13 +950,14 @@ func main() {
|
|||||||
mainTopics := []struct {
|
mainTopics := []struct {
|
||||||
MainTopic string `db:"main_topic" json:"main_topic"`
|
MainTopic string `db:"main_topic" json:"main_topic"`
|
||||||
MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"`
|
MainTopicListOrder string `db:"main_topic_list_order" json:"main_topic_list_order"`
|
||||||
|
ColorPattern string `db:"color_pattern" json:"color_pattern"`
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
// Execute the query
|
// Execute the query
|
||||||
err := app.DB().
|
err := app.DB().
|
||||||
Select("main_topic", "main_topic_list_order").
|
Select("main_topic", "main_topic_list_order", "color_pattern").
|
||||||
From("home_screen").
|
From("home_screen").
|
||||||
GroupBy("main_topic").
|
GroupBy("main_topic", "color_pattern").
|
||||||
OrderBy("main_topic_list_order ASC").
|
OrderBy("main_topic_list_order ASC").
|
||||||
All(&mainTopics)
|
All(&mainTopics)
|
||||||
|
|
||||||
@ -987,6 +1031,7 @@ func main() {
|
|||||||
result = append(result, map[string]interface{}{
|
result = append(result, map[string]interface{}{
|
||||||
"main_topic": mainTopic.MainTopic,
|
"main_topic": mainTopic.MainTopic,
|
||||||
"main_topic_list_order": mainTopic.MainTopicListOrder,
|
"main_topic_list_order": mainTopic.MainTopicListOrder,
|
||||||
|
"color_pattern": mainTopic.ColorPattern,
|
||||||
"sub_topics": result2,
|
"sub_topics": result2,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
pb_data/data.db
BIN
pb_data/data.db
Binary file not shown.
BIN
pb_data/data.db-shm
Normal file
BIN
pb_data/data.db-shm
Normal file
Binary file not shown.
BIN
pb_data/data.db-wal
Normal file
BIN
pb_data/data.db-wal
Normal file
Binary file not shown.
BIN
pb_data/logs.db
BIN
pb_data/logs.db
Binary file not shown.
BIN
pb_data/logs.db-shm
Normal file
BIN
pb_data/logs.db-shm
Normal file
Binary file not shown.
BIN
pb_data/logs.db-wal
Normal file
BIN
pb_data/logs.db-wal
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user