diff --git a/api/cueSearch/tests/test_elasticSearch_indexing.py b/api/cueSearch/tests/test_elasticSearch_indexing.py index 56923678..d79e02e1 100644 --- a/api/cueSearch/tests/test_elasticSearch_indexing.py +++ b/api/cueSearch/tests/test_elasticSearch_indexing.py @@ -455,115 +455,116 @@ def testFindNonGlobalDimensionSuggestionResult(client, mocker): ################################ Delete all indexes ############## -# @pytest.mark.django_db(transaction=True) -# def testFindNonGlobalDimensionResultData(client, mocker): -# """Method to test non global dimension index""" -# ESIndexingUtils.deleteAllIndex() - -# connection = mixer.blend("dataset.connection") -# testDataset = mixer.blend( -# "dataset.dataset", -# name="orders", -# id=1, -# dimensions='["Brand", "Color", "State"]', -# metrics='["Orders", "OrderAmount", "OrderQuantity"]', -# granularity="day", -# timestampColumn="TestDate", -# sql="Select * from testTable", -# ) -# mockResponse = mocker.patch( -# "cueSearch.elasticSearch.elastic_search_indexing.ESIndexingUtils.runAllIndexDimension", -# new=mock.MagicMock(autospec=True, return_value=True), -# ) -# mockResponse.start() -# path = reverse("createDataset") -# data = { -# "name": "demo_dataset", -# "sql": "SELECT * from TEST_TABLE", -# "connectionId": connection.id, -# "metrics": ["Amount", "Quantity"], -# "dimensions": ["Category", "Region"], -# "timestamp": "CreatedAt", -# "granularity": "day", -# "isNonRollup": False, -# } -# response = client.post(path, data=data, content_type="application/json") - -# # create dimension for testing -# dataset = Dataset.objects.get(id=1) -# mockResponse.start() -# path = reverse("globalDimensionCreate") -# gd_data = { -# "name": "test", -# "dimensionalValues": [ -# { -# "datasetId": dataset.id, -# "dataset": "Returns", -# "dimension": "WarehouseCode", -# } -# ], -# } -# response = client.post(path, gd_data, content_type="application/json") -# assert response.data["success"] == True -# assert response.status_code == 200 - -# globalDimsId = GlobalDimensionServices.getGlobalDimensions() -# globalDimensionId = globalDimsId.data[0]["values"][0]["id"] - -# # Publishing global dimension by id -# path = reverse("pubGlobalDimension") -# payload = {"id": globalDimensionId, "published": True} -# response = client.post(path, payload) -# mockResponse.stop() -# listToIndex = [ -# {"dataset": "Test data", "datasetId": 1, "dimension": "Brand"}, -# {"dataset": "Test data", "datasetId": 1, "dimension": "WarehouseCode"}, -# ] -# res = {"success": True, "data": listToIndex} - -# mockResponse = mocker.patch( -# "cueSearch.services.globalDimension.GlobalDimensionServices.nonGlobalDimensionForIndexing", -# new=mock.MagicMock(autospec=True, return_value=res), -# ) -# mockResponse.start() -# ESIndexingUtils.indexNonGlobalDimensionsData() -# mockResponse.stop() - -# expectedResults = [ -# { -# "value": "TestData", -# "dimension": "Brand", -# "globalDimensionName": "Test data_Brand", -# "user_entity_identifier": "Test data_Brand", -# "id": "Brand_TestData_1", -# "dataset": "Test data", -# "datasetId": testDataset.id, -# "type": "DATASETDIMENSION", -# }, -# { -# "value": "TestData", -# "dimension": "WarehouseCode", -# "globalDimensionName": "Test data_WarehouseCode", -# "user_entity_identifier": "Test data_WarehouseCode", -# "id": "WarehouseCode_TestData_1", -# "dataset": "Test data", -# "datasetId": testDataset.id, -# "type": "DATASETDIMENSION", -# }, -# ] -# query = "TestData" -# result = ESQueryingUtils.findNonGlobalDimensionResults(query=query) -# count = 0 -# while not result: -# count += 1 -# result = ESQueryingUtils.findNonGlobalDimensionResults(query=query) - -# if count == 10: -# result = [] -# return result - -# assert result == expectedResults -# ################################ Delete all indexes ############## +@pytest.mark.django_db(transaction=True) +def testFindNonGlobalDimensionResultData(client, mocker): + """Method to test non global dimension index""" + ESIndexingUtils.deleteAllIndex() + + connection = mixer.blend("dataset.connection") + testDataset = mixer.blend( + "dataset.dataset", + name="orders", + id=1, + dimensions='["Brand", "Color", "State"]', + metrics='["Orders", "OrderAmount", "OrderQuantity"]', + granularity="day", + timestampColumn="TestDate", + sql="Select * from testTable", + ) + mockResponse = mocker.patch( + "cueSearch.elasticSearch.elastic_search_indexing.ESIndexingUtils.runAllIndexDimension", + new=mock.MagicMock(autospec=True, return_value=True), + ) + mockResponse.start() + path = reverse("createDataset") + data = { + "name": "demo_dataset", + "sql": "SELECT * from TEST_TABLE", + "connectionId": connection.id, + "metrics": ["Amount", "Quantity"], + "dimensions": ["Category", "Region"], + "timestamp": "CreatedAt", + "granularity": "day", + "isNonRollup": False, + } + response = client.post(path, data=data, content_type="application/json") + + # create dimension for testing + dataset = Dataset.objects.get(id=1) + mockResponse.start() + path = reverse("globalDimensionCreate") + gd_data = { + "name": "test", + "dimensionalValues": [ + { + "datasetId": dataset.id, + "dataset": "Returns", + "dimension": "WarehouseCode", + } + ], + } + response = client.post(path, gd_data, content_type="application/json") + assert response.data["success"] == True + assert response.status_code == 200 + + globalDimsId = GlobalDimensionServices.getGlobalDimensions() + globalDimensionId = globalDimsId.data[0]["values"][0]["id"] + + # Publishing global dimension by id + path = reverse("pubGlobalDimension") + payload = {"id": globalDimensionId, "published": True} + response = client.post(path, payload) + mockResponse.stop() + listToIndex = [ + {"dataset": "Test data", "datasetId": 1, "dimension": "Brand"}, + {"dataset": "Test data", "datasetId": 1, "dimension": "WarehouseCode"}, + ] + res = {"success": True, "data": listToIndex} + + mockResponse = mocker.patch( + "cueSearch.services.globalDimension.GlobalDimensionServices.nonGlobalDimensionForIndexing", + new=mock.MagicMock(autospec=True, return_value=res), + ) + mockResponse.start() + ESIndexingUtils.indexNonGlobalDimensionsData() + mockResponse.stop() + + expectedResults = [ + { + "value": "TestData", + "dimension": "Brand", + "globalDimensionName": "Test data_Brand", + "user_entity_identifier": "Test data_Brand", + "id": "Brand_TestData_1", + "dataset": "Test data", + "datasetId": testDataset.id, + "type": "DATASETDIMENSION", + }, + { + "value": "TestData", + "dimension": "WarehouseCode", + "globalDimensionName": "Test data_WarehouseCode", + "user_entity_identifier": "Test data_WarehouseCode", + "id": "WarehouseCode_TestData_1", + "dataset": "Test data", + "datasetId": testDataset.id, + "type": "DATASETDIMENSION", + }, + ] + query = "TestData" + result = ESQueryingUtils.findNonGlobalDimensionResults(query=query) + count = 0 + while not result: + count += 1 + result = ESQueryingUtils.findNonGlobalDimensionResults(query=query) + + if count == 10: + result = [] + return result + + assert result == expectedResults + + ################################ Delete all indexes ############## def testRunAllIndexing(client, mocker): diff --git a/api/dataset/services/datasets.py b/api/dataset/services/datasets.py index fcca3f93..0496260d 100644 --- a/api/dataset/services/datasets.py +++ b/api/dataset/services/datasets.py @@ -129,7 +129,6 @@ def getDatasetData(params: dict): res = ApiResponse("Error in fetching data") try: dataset = Dataset.objects.get(id=params["datasetId"]) - # params["sql"] = params["sql"] + "some went wrong" dataDf = Data.fetchDatasetDataframe(dataset, params["sql"]) if isinstance(dataDf, str): res.update(False, "Error occured while fetching data", dataDf) diff --git a/ui/src/components/Search/Card/CardSnippet/style.module.scss b/ui/src/components/Search/Card/CardSnippet/style.module.scss index ba3fad4e..4b839a49 100644 --- a/ui/src/components/Search/Card/CardSnippet/style.module.scss +++ b/ui/src/components/Search/Card/CardSnippet/style.module.scss @@ -72,7 +72,7 @@ margin-bottom: 5px; border-radius: 10px; background: white; - height: 154px; + height: auto; padding: 10px; .chartSnippet { @@ -81,7 +81,7 @@ margin: 0; background: #aaaaaa; border-radius: 5px; - height: 134px; + height: 100%; /*border: 1px solid #aaaaaa;*/ overflow: hidden; background: white; diff --git a/ui/src/components/Search/Card/DataDisplay/Chart/index.js b/ui/src/components/Search/Card/DataDisplay/Chart/index.js index 269d4c1d..d8f4804b 100644 --- a/ui/src/components/Search/Card/DataDisplay/Chart/index.js +++ b/ui/src/components/Search/Card/DataDisplay/Chart/index.js @@ -12,6 +12,7 @@ import { G2, Guide, } from "bizcharts"; +import ErrorDisplayCard from "../../Error/ErrorDisplay"; const { Html } = Guide; track(false); @@ -37,6 +38,7 @@ class ChartCard extends React.Component { render() { const cardData = this.props.cardData; + const errorSqlMessage = this.props.errorMessage const showPercentageButton = cardData && cardData.rowsTotal; let data = []; let chartMetaData = {}; @@ -126,17 +128,25 @@ class ChartCard extends React.Component { /> {geomElements} - ) : ( -
-
- -

No Data

+ ) : errorSqlMessage ? : + + ( +
+
+ +

No Data

+
-
- ); + ); + return (
diff --git a/ui/src/components/Search/Card/DataDisplay/Table/index.js b/ui/src/components/Search/Card/DataDisplay/Table/index.js index 2c3352bc..be74fe39 100644 --- a/ui/src/components/Search/Card/DataDisplay/Table/index.js +++ b/ui/src/components/Search/Card/DataDisplay/Table/index.js @@ -1,13 +1,15 @@ import React, { useState, useEffect, useRef } from "react"; -import { message, Select, Table } from "antd"; +import { message, Select, Table, Button } from "antd"; import _ from "lodash"; import { calculateColumnsWidth } from "components/Utils/columnWidthHelper"; import Loader from "components/Utils/Loader"; import style from "./style.module.scss"; +import ErrorDisplayCard from "../../Error/ErrorDisplay.js" export default function TableCard(props) { const tableData = props.cardData; const loadingTableData = props.loadingData; + const errorSqlMessage = props.errorMessage const columns = !_.isEmpty(tableData) && Object.keys(tableData[0]).map((col) => { @@ -25,17 +27,28 @@ export default function TableCard(props) { }; const dataTable = ( - - ); + errorSqlMessage ? ( +
+ < ErrorDisplayCard + loadingData={loadingTableData} + errorMessage={errorSqlMessage} + + /> +
+ ) + : + +
+ ); return (
{loadingTableData ? ( diff --git a/ui/src/components/Search/Card/DataDisplay/index.js b/ui/src/components/Search/Card/DataDisplay/index.js index f3413b86..01ef79cf 100644 --- a/ui/src/components/Search/Card/DataDisplay/index.js +++ b/ui/src/components/Search/Card/DataDisplay/index.js @@ -1,14 +1,17 @@ import React, { useState, useEffect, useRef, useContext } from "react"; import searchResultService from "services/main/searchResult"; import { GlobalContext } from "layouts/GlobalContext"; +import { message } from "antd"; import TableCard from "./Table"; import Chart from "./Chart"; +import ErrorDisplayCard from "../Error/ErrorDisplay"; export default function DataDisplay({ params, isSnippet }) { const { searchCardData, addSearchCardData } = useContext(GlobalContext); const [cardData, setCardData] = useState(); const [loadingData, setLoadingData] = useState(false); + const [errorMessage, setErrorMessage] = useState(null) useEffect(() => { if (searchCardData[JSON.stringify(params)]) { @@ -25,25 +28,34 @@ export default function DataDisplay({ params, isSnippet }) { setCardData(response.data); addSearchCardData([JSON.stringify(params)], response.data); } + if (!response.success) { + setCardData(null) + setErrorMessage(response["data"]) + } setLoadingData(false); }; - return (
- {params.renderType == "table" ? ( - - ) : ( - - )} + + { + params.renderType == "table" ? ( + + ) : ( + + ) + }
); } diff --git a/ui/src/components/Search/Card/Error/ErrorDisplay.js b/ui/src/components/Search/Card/Error/ErrorDisplay.js new file mode 100644 index 00000000..7df3cdf1 --- /dev/null +++ b/ui/src/components/Search/Card/Error/ErrorDisplay.js @@ -0,0 +1,33 @@ +import React, { useState, useEffect, useRef } from "react"; +import _ from "lodash"; +import Loader from "components/Utils/Loader"; +import style from "./style.module.scss"; + +export default function ErrorDisplayCard(props) { + const errorSqlMessage = props.errorMessage + const loadingData = props.loadingData + + const dataTable = ( + +
+
+

No Data

+

{errorSqlMessage}

+
+ +
+ ); + return ( +
+ {loadingData ? ( +
+ +
+ ) : ( + dataTable + )} +
+ ); +} diff --git a/ui/src/components/Search/Card/Error/style.module.scss b/ui/src/components/Search/Card/Error/style.module.scss new file mode 100644 index 00000000..2a0a18af --- /dev/null +++ b/ui/src/components/Search/Card/Error/style.module.scss @@ -0,0 +1,30 @@ + +// html { +// scroll-behaviour: smooth; +// } + +.antdTable { + height: 100%; + border: none; + overflow: auto; + td{ + padding: 2px !important; + } + } + + .loadingDiv { + /*width: 100%;*/ + align-items: center; + justify-content: center; + display: flex; + /*height: 100%;*/ + text-align: center; + } + .errorMessageStyle{ + position: initial; + overflow: scroll; + word-wrap: break-word; + height: 150px; + width: auto; + } + \ No newline at end of file diff --git a/ui/src/components/Search/SearchResult/style.module.scss b/ui/src/components/Search/SearchResult/style.module.scss index 011691be..d2a89506 100644 --- a/ui/src/components/Search/SearchResult/style.module.scss +++ b/ui/src/components/Search/SearchResult/style.module.scss @@ -3,7 +3,7 @@ .searchResultsWrapper { /*background: white;*/ - +height: fit-content; } .cardPanelWrapper {