From d91c64a50ea86cdba5f3a0213946759b20837cd1 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Mon, 27 Feb 2023 00:16:00 +0530 Subject: [PATCH 01/73] the dataset integration changes done which is not completely ready as join func need to discussed --- .../MysqlFormForConnection.jsx | 7 - .../DatasetIntegration.jsx | 120 ++++++++--- .../DatasetSelect/DatasetSelect.jsx | 192 ++++++++++-------- .../IntegrationDatasets/Join/Join.jsx | 73 +++++-- .../dataset_integration.module.css | 13 ++ 5 files changed, 261 insertions(+), 144 deletions(-) diff --git a/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx b/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx index bf0b4cc7a..649314b29 100644 --- a/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx +++ b/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx @@ -135,13 +135,6 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han port: "" } - // //clear input fields - // setConnectionData({ - // ...connectionData, ...dataForReset - // }) - - - var returnValues = GetErrorKey(err, ["database", "username", "password", "host", "port"]) var errorKeys = returnValues[0] var errorMessages = returnValues[1] diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 198f8bf65..6219102c1 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -8,8 +8,11 @@ import { useState } from 'react' import HTTPService from '../../../Services/HTTPService' import UrlConstant from '../../../Constants/UrlConstants' import Loader from '../../Loader/Loader' -import { Alert, Button, Collapse, IconButton } from '@mui/material' +import { Alert, Button, Collapse, IconButton, Snackbar } from '@mui/material' import CloseIcon from '@mui/icons-material/Close'; +import { CheckLg } from 'react-bootstrap-icons' +import { GetErrorHandlingRoute, GetErrorKey } from '../../../Utils/Common' +import { useHistory } from 'react-router-dom' const converter = require('json-2-csv') const fs = require('fs') @@ -37,6 +40,7 @@ const DatasetIntegration = () => { const [loader, setLoader] = useState(false) const [circleLoad, setCircleLoad] = useState(false) + const history = useHistory(); const handleChangeDatasetNameSelector = (event, i, source) => { console.log(event.target.value, i, source) @@ -45,17 +49,25 @@ const DatasetIntegration = () => { list_selected[i] = event.target.value console.log(list_selected, "list_selected") setListOfDatasetSelected([...list_selected]); - getFilesAssociatedForTheSelectedDatasets(source, list_selected) + let list_selected_file = [...listOfFilesSelected] + list_selected_file[i] = "" + setListOfFilesSelected([...list_selected_file]); + console.log(finalDataNeedToBeGenerated, "finalDataNeedToBeGenerated") + if (event.target.value) { + getFilesAssociatedForTheSelectedDatasets(source, list_selected) + } } else { let list_selected = [...listOfFilesSelected] list_selected[i] = event.target.value console.log(list_selected, "file_selected") setListOfFilesSelected([...list_selected]); - let newListForColumns = listOfFilesAvailableForSelect.filter((eachFile, index) => { - return list_selected.includes(eachFile.name) - }) + // let newListForColumns = listOfFilesAvailableForSelect.filter((eachFile, index) => { + // return list_selected.includes(eachFile.name) + // }) // setListOfDatsetFileAvailableForColumn([...newListForColumns]) - getFilesAssociatedForTheSelectedDatasets(source, list_selected) + if (event.target.value) { + getFilesAssociatedForTheSelectedDatasets(source, list_selected) + } } }; const handleChangeFileNameSelector = (event, i) => { @@ -96,10 +108,14 @@ const DatasetIntegration = () => { HTTPService(method, url, "", false, true, false).then((res) => { setLoader(false) setAllDatasetNameList([...res.data]) - }).catch((e) => { + }).catch((err) => { + // console.log(e.response) setAlertType("error") setMessage("Error occurred! Dataset could not fetched.") setLoader(false) + if (err?.response.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } }) } const getFilesAssociatedForTheSelectedDatasets = (source, list) => { @@ -140,34 +156,74 @@ const DatasetIntegration = () => { { ...res.data } ) } - }).catch((e) => { + }).catch((err) => { setOpen(true); setAlertType("error") - setMessage(e?.message ? e.message : "Some error occurred while generating!") + setMessage(err?.message ? err.message : "Some error occurred while generating!") let id = setTimeout(() => { setOpen(false); return clearTimeout(id) }, 2500) - // if (source == "dataset") { - // setListOfFilesAvailableForSelect([ - // { file_name: "name_of_the file1", file: "path_of_the_file1" }, - // { file_name: "name_of_the file2", file: "path_of_the_file2" }, - // { file_name: "name_of_the file3", file: "path_of_the_file3" }, - // { file_name: "name_of_the file4", file: "path_of_the_file4" }, - // { file_name: "name_of_the file5", file: "path_of_the_file5" }, - // { file_name: "name_of_the file6", file: "path_of_the_file6" }, - // { file_name: "name_of_the file7", file: "path_of_the_file7" }, - // { file_name: "name_of_the file8", file: "path_of_the_file8" }, - // ]) - // } else if (source == "file") { - // setListOfDatsetFileAvailableForColumn( - // { - // path_of_the_file1: ["id", "mobile_number"], - // path_of_the_file6: ["id", "phone_number"] - // } - // ) - // } setLoader(false) + + var returnValues = GetErrorKey(err, ["datasets", "files"]) + var errorKeys = returnValues[0] + var errorMessages = returnValues[1] + if (errorKeys.length > 0) { + for (var i = 0; i < errorKeys.length; i++) { + console.log(errorKeys[i]) + let id; + switch (errorKeys[i]) { + case "datasets": + setOpen(true); + setLoader(false) + setAlertType("error") + setMessage(errorMessages[i] ? errorMessages[i] : "Some error occurred while fetching files for selected dataset!") + id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + break; + case "files": setOpen(true); + setLoader(false) + setAlertType("error") + setMessage(errorMessages[i] ? errorMessages[i] : "Some error occurred while fetching files for selected dataset!") + id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + break; + default: + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setOpen(true); + setLoader(false) + setAlertType("error") + // setMessage(err?.res ? err.message : "Some error occurred while generating!") + let id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + } + + } + } + } + else { + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setOpen(true); + setLoader(false) + setAlertType("error") + setMessage("Some error occurred while generating!") + let id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + } + } }) } const deleteTable = (tableName, index) => { @@ -183,7 +239,7 @@ const DatasetIntegration = () => { console.log(list_selected, tableName.name, index) setListOfFilesSelected([...list_selected]); } - const generateData = (left_on, right_on) => { + const generateData = (left_on, right_on, joinType) => { setLoader(true) let url = UrlConstant.base_url + UrlConstant.joining_the_table console.log(finalDataNeedToBeGenerated, "finalDataNeedToBeGenerated") @@ -199,7 +255,7 @@ const DatasetIntegration = () => { "columns2": [ ...finalDataNeedToBeGenerated[secondFile] ], - "how": "left", + "how": joinType ? joinType : "left", "left_on": [left_on], "right_on": [right_on], } @@ -219,7 +275,7 @@ const DatasetIntegration = () => { setOpen(true); setLoader(false) setAlertType("error") - setMessage(err?.message ? err.message : "Some error occurred while generating!") + // setMessage(err?.res ? err.message : "Some error occurred while generating!") let id = setTimeout(() => { setOpen(false); return clearTimeout(id) @@ -287,7 +343,7 @@ const DatasetIntegration = () => { - + {listOfFilesSelected.length > 0 && } ) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index 919dfbcdb..f2ae0344b 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -12,6 +12,7 @@ import Typography from '@mui/material/Typography'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import DeleteIcon from '@mui/icons-material/Delete'; import { Checkbox, FormControlLabel } from '@mui/material'; +import { CheckLg } from 'react-bootstrap-icons'; const DatasetSelect = (props) => { const { setFinalDataNeedToBeGenerated, finalDataNeedToBeGenerated, deleteTable, listOfFilesSelected, handleChangeFileNameSelector, noOfFileSelector, listOfFilesAvailableForSelect, allDatasetNameList, listOfDatasetSelected, handleChangeDatasetNameSelector, noOfDatasetSelector, handleClickSelectDataset, listOfDatsetFileAvailableForColumn } = props const [selectAll, setSelectAll] = useState(false) @@ -54,113 +55,136 @@ const DatasetSelect = (props) => { return ( - - Select datasets + + + + Select datasets + + - - {/* handleClickSelectDataset("dataset")}>+ Add datasets */} - = allDatasetNameList.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn} onClick={() => handleClickSelectDataset("dataset")}>+ Add datasets + + + + Select files + = allDatasetNameList.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn} onClick={() => handleClickSelectDataset("dataset")}>+ Add datasets + + - - {noOfDatasetSelector.map((eachDatasetName, i) => { - return - - Dataset name - - - - })} + + + {noOfDatasetSelector.map((eachDatasetName, i) => { + return + + + Dataset name + + + + })} + + + {noOfDatasetSelector.map((eachFileName, i) => { + return + + + File name + + + + })} + - + {/* + + + + */} + {/* Select Files handleClickSelectDataset("file")}>+ Add files - {/* = listOfFilesAvailableForSelect.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn} onClick={() => handleClickSelectDataset("file")}>+ Add files */} + = listOfFilesAvailableForSelect.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn} onClick={() => handleClickSelectDataset("file")}>+ Add files - - - {noOfFileSelector.map((eachFileName, i) => { - return - - File name - - - - })} - + */} + {/* + + */} {/* {listOfDatsetFileAvailableForColumn.length > 0 && */} - + {listOfFilesSelected.length > 0 && - Select Columns + Select columns {Object.keys(listOfDatsetFileAvailableForColumn).map((eachDatasetFile, index) => { - return - } - aria-controls="panel1a-content" - id="panel1a-header" - > - {eachDatasetFile.split("/")[eachDatasetFile.split("/").length - 1]} - {/* + console.log(eachDatasetFile, "eachDatasetFile", listOfDatasetSelected, listOfFilesSelected) + if (listOfFilesSelected.includes(eachDatasetFile)) { + return + } + aria-controls="panel1a-content" + id="panel1a-header" + > + {eachDatasetFile.split("/")[eachDatasetFile.split("/").length - 1]} + {/* deleteTable(eachDatasetFile, index)} /> */} - - {/* + + {/* changeAllSelect(eachDatasetFile)} control={} label={"Select all"} /> */} - - {listOfDatsetFileAvailableForColumn[eachDatasetFile]?.length > 0 && listOfDatsetFileAvailableForColumn[eachDatasetFile]?.map((eachColumn, index) => { - return handleChangeColumns(e, eachDatasetFile, eachColumn)} />} label={eachColumn} /> - })} - - + + {listOfDatsetFileAvailableForColumn[eachDatasetFile]?.length > 0 && listOfDatsetFileAvailableForColumn[eachDatasetFile]?.map((eachColumn, index) => { + return handleChangeColumns(e, eachDatasetFile, eachColumn)} />} label={eachColumn} /> + })} + + + } })} - + } {/* } */} diff --git a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx index 584a3de50..a79969921 100644 --- a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx @@ -7,13 +7,14 @@ import Select from '@mui/material/Select'; import styles from "../dataset_integration.module.css" import DragHandleIcon from '@mui/icons-material/DragHandle'; import { Button, CircularProgress } from '@mui/material'; +import { Cpu } from 'react-bootstrap-icons'; const Join = (props) => { - const { circleLoad, listOfDatasetSelected, listOfDatsetFileAvailableForColumn, generateData, finalDataNeedToBeGenerated } = props + const { circleLoad, listOfDatasetSelected, listOfFilesSelected, listOfDatsetFileAvailableForColumn, generateData, finalDataNeedToBeGenerated } = props const [join, setJoin] = useState({}) const [joinVal1, setJoinVal1] = useState("") const [joinVal2, setJoinVal2] = useState("") const [age, setAge] = React.useState(''); - + const [joinType, setJoinType] = useState("") const [finalJoin, setFinalJoin] = useState({}) const handleChange = (event, source) => { console.log(event.target.value) @@ -56,10 +57,39 @@ const Join = (props) => { - + + + Primary dataset + + + + + - + Primary dataset - - Primary dataset colounm name + + Primary dataset column name { label="Primary dataset" > - None + Clear {Object.keys(listOfDatsetFileAvailableForColumn).map((eachFile, index) => { if (eachFile != joinVal1) { @@ -134,8 +165,8 @@ const Join = (props) => { - - Primary dataset colounm name + + Primary dataset column name handleChangeDatasetNameSelector(e, i, "file")} @@ -165,7 +165,7 @@ const DatasetSelect = (props) => { } aria-controls="panel1a-content" - id="panel1a-header" + id="summary_id_accordion" > {eachDatasetFile.split("/")[eachDatasetFile.split("/").length - 1]} {/* @@ -177,7 +177,7 @@ const DatasetSelect = (props) => { */} {listOfDatsetFileAvailableForColumn[eachDatasetFile]?.length > 0 && listOfDatsetFileAvailableForColumn[eachDatasetFile]?.map((eachColumn, index) => { - return handleChangeColumns(e, eachDatasetFile, eachColumn)} />} label={eachColumn} /> + return handleChangeColumns(e, eachDatasetFile, eachColumn)} />} label={eachColumn} /> })} diff --git a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx index a79969921..f851ed41f 100644 --- a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx @@ -59,10 +59,10 @@ const Join = (props) => { - Primary dataset + Join type handleChange(e, "val1")} label="Primary dataset" @@ -118,8 +118,8 @@ const Join = (props) => { Primary dataset column name handleChange(e, "val2")} label="Primary dataset" @@ -166,10 +166,10 @@ const Join = (props) => { - Primary dataset column name + Primary dataset column name @@ -150,9 +148,9 @@ const Join = (props) => { onChange={(e) => handleChange(e, "val2")} label="Primary dataset" > - + {/* Clear - + */} {Object.keys(listOfDatsetFileAvailableForColumn).map((eachFile, index) => { if (eachFile != joinVal1) { return {eachFile.split("/")[eachFile.split("/").length - 1]} @@ -174,11 +172,11 @@ const Join = (props) => { onChange={(e) => handleChangeJoin(e, "join2")} label="Primary dataset colounm name" > - + {/* Clear - + */} {finalDataNeedToBeGenerated[joinVal2]?.map((eachFile, index) => { - return {eachFile} + return {eachFile} })} From 2d163b76c147ab1bf7803342cbea3260b2cdb43a Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Thu, 2 Mar 2023 15:49:24 +0530 Subject: [PATCH 06/73] 1317 --- src/Components/Navbar/GuestUserNavbar.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Components/Navbar/GuestUserNavbar.js b/src/Components/Navbar/GuestUserNavbar.js index ad6b9604b..de3c64798 100644 --- a/src/Components/Navbar/GuestUserNavbar.js +++ b/src/Components/Navbar/GuestUserNavbar.js @@ -15,6 +15,7 @@ const GuestUserNavBar = (props) => { const [screenlabels, setscreenlabels] = useState(labels["en"]); const [isLoader, setIsLoader] = useState(false); const [phoneNumber, setPhoneNumber] = useState(null); + const [adminNotOnboarded, setAdminNotOnboarded] = useState(false); useEffect(() => { HTTPService( @@ -32,6 +33,10 @@ const GuestUserNavBar = (props) => { ) { setPhoneNumber(response.data.organization.phone_number); } + if(response.data.organization == null) { + setAdminNotOnboarded(true) + } + }) .catch((e) => { setIsLoader(false); @@ -154,6 +159,8 @@ const GuestUserNavBar = (props) => { */} + {adminNotOnboarded ? + <> {   {"Register"} - + : "" } + Date: Thu, 2 Mar 2023 16:00:18 +0530 Subject: [PATCH 07/73] no conflicts --- src/Components/Navbar/GuestUserNavbar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Navbar/GuestUserNavbar.js b/src/Components/Navbar/GuestUserNavbar.js index de3c64798..d3f20000f 100644 --- a/src/Components/Navbar/GuestUserNavbar.js +++ b/src/Components/Navbar/GuestUserNavbar.js @@ -159,7 +159,7 @@ const GuestUserNavBar = (props) => { */} - {adminNotOnboarded ? + {!adminNotOnboarded ? <> From edefef99551fe8114a43eb6e9db9e3f295a228d8 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 2 Mar 2023 16:24:36 +0530 Subject: [PATCH 08/73] implementing standardization --- package.json | 2 + public/index.html | 44 +- src/App.js | 3 +- src/Assets/CSS/common.css | 20 + src/Assets/Img/explore_dataset.svg | 1 + src/Assets/Img/login_datahub.svg | 1 + .../AccordionForUploadedFileDetails.jsx | 127 +++-- .../AdminDatasetConnection/AddDataset.jsx | 99 ++-- .../DataStandardizationInAddDataset.css | 20 + .../DataStandardizationInAddDataset.js | 69 +++ .../LiveApiConnection.jsx | 204 ++++--- .../LocalMachineUploadDataset.css | 6 + .../MysqlFormForConnection.jsx | 68 ++- .../PostgresFormForConnection.jsx | 55 +- .../ViewMetaDatasetDetails.jsx | 9 +- src/Components/CoSteward/AddCoSteward.jsx | 124 +++-- .../DatasetSelect/DatasetSelect.jsx | 4 +- .../GuestUser/GuestUserDatasetCard.js | 5 +- src/Components/GuestUser/GuestUserDatasets.js | 22 +- .../GuestUserMainPage/EachCardForDetails.jsx | 66 +++ .../GuestMainPageCarousel.jsx | 89 +++ .../LeftRightDescription.jsx | 65 +++ .../GuestUserMainPage/ViewDetail.jsx | 78 +++ .../guest_user_main_page.module.css | 80 +++ .../GuestUser/guestUserLegal.module.css | 30 +- src/Components/Navbar/GuestUserNavbar.js | 50 +- src/Components/Participants/EditCoSteward.js | 15 +- .../Participants/ParticipantsCards.js | 291 +++++++--- .../AddParticipantRegistrationform.js | 48 +- .../ParticipantRegistrationForm.js | 70 ++- src/Components/signup/DataStandardization.js | 337 ++++++++++++ src/Components/signup/OrgRightside.js | 33 +- src/Components/signup/dataStandardization.css | 14 + src/Constants/UrlConstants.js | 4 + src/Constants/labels.js | 4 + src/Utils/Common.js | 48 +- src/Views/Dataset/DataSetFilter.js | 100 ++-- .../Dataset/DatasetAdmin/DatasetAdmin.js | 54 +- src/Views/GuestUser/GuestUserHome.js | 2 +- src/Views/GuestUser/GuestUserMainHomePage.jsx | 124 +++++ src/Views/Login/Login.js | 36 +- .../ParticipantCoStewardManagement.jsx | 512 ++++++++++-------- src/Views/Participants/AddParticipants.js | 129 +++-- src/Views/Participants/EditParticipants.js | 255 +++++++-- .../ParticipantOrganisationSetting.js | 24 +- 45 files changed, 2556 insertions(+), 885 deletions(-) create mode 100644 src/Assets/Img/explore_dataset.svg create mode 100644 src/Assets/Img/login_datahub.svg create mode 100644 src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css create mode 100644 src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js create mode 100644 src/Components/GuestUser/GuestUserMainPage/EachCardForDetails.jsx create mode 100644 src/Components/GuestUser/GuestUserMainPage/GuestMainPageCarousel.jsx create mode 100644 src/Components/GuestUser/GuestUserMainPage/LeftRightDescription.jsx create mode 100644 src/Components/GuestUser/GuestUserMainPage/ViewDetail.jsx create mode 100644 src/Components/GuestUser/GuestUserMainPage/guest_user_main_page.module.css create mode 100644 src/Components/signup/DataStandardization.js create mode 100644 src/Components/signup/dataStandardization.css create mode 100644 src/Views/GuestUser/GuestUserMainHomePage.jsx diff --git a/package.json b/package.json index 45d82f4b8..4fbb31cbd 100755 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "react-scripts": "3.4.0", "react-select": "^5.3.2", "react-select-country-list": "^2.2.3", + "react-slick": "^0.29.0", "react-sortable-tree": "2.8.0", "react-sortable-tree-patch-react-17": "2.9.0", "react-toastify": "^8.0.2", @@ -62,6 +63,7 @@ "recharts": "^2.1.13", "redux": "^4.0.4", "redux-thunk": "^2.3.0", + "slick-carousel": "^1.8.1", "styled-components": "^5.3.5", "tooltip": "^1.6.1", "validator": "^13.7.0" diff --git a/public/index.html b/public/index.html index dc3083948..2ab8d8230 100755 --- a/public/index.html +++ b/public/index.html @@ -1,19 +1,21 @@ - - - - - - - - - DataHub - - - -
- - - - + + + \ No newline at end of file diff --git a/src/App.js b/src/App.js index 43e1d26b2..22015f2b2 100755 --- a/src/App.js +++ b/src/App.js @@ -24,6 +24,7 @@ import GuestUserContact from "./Views/GuestUser/GuestUserContact"; import AddParticipantRegistrationForm from "./Components/PatricipantRegistration/AddParticipantRegistrationform" import ViewMetaDatasetDetails from "./Components/AdminDatasetConnection/ViewMetaDatasetDetails"; import Viewdetails from "./Components/GuestUser/Viewdetails"; +import GuestUserMainHomePage from "./Views/GuestUser/GuestUserMainHomePage"; function App() { return ( @@ -42,7 +43,7 @@ function App() { - + diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 1eca73dc7..04d1a64bc 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1014,4 +1014,24 @@ button.disbalesubmitbtndept { .react-multi-email input { min-width: 500px !important; +} + +.carousel_in_guest_user_main_page .slick-current { + /* height: 300px !important; + width: 400px !important; */ + /* height: 300px; */ + +} + +.carousel_in_guest_user_main_page .slick-arrow { + height: 50px !important; + width: 50px !important; + background-color: rgba(228, 228, 228, 1) !important; + z-index: 10; + border-radius: 10px !important; + +} + +.back_btn_guest .MuiSvgIcon-root { + color: #3491EE !important; } \ No newline at end of file diff --git a/src/Assets/Img/explore_dataset.svg b/src/Assets/Img/explore_dataset.svg new file mode 100644 index 000000000..86082fc68 --- /dev/null +++ b/src/Assets/Img/explore_dataset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Assets/Img/login_datahub.svg b/src/Assets/Img/login_datahub.svg new file mode 100644 index 000000000..62997fec1 --- /dev/null +++ b/src/Assets/Img/login_datahub.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Components/AdminDatasetConnection/AccordionForUploadedFileDetails.jsx b/src/Components/AdminDatasetConnection/AccordionForUploadedFileDetails.jsx index e6fd02cdb..1d951cb23 100644 --- a/src/Components/AdminDatasetConnection/AccordionForUploadedFileDetails.jsx +++ b/src/Components/AdminDatasetConnection/AccordionForUploadedFileDetails.jsx @@ -1,51 +1,82 @@ -import { Avatar, Accordion, AccordionDetails, AccordionSummary, Divider, IconButton, ListItem, ListItemAvatar, ListItemText, Typography, Badge, LinearProgress } from '@mui/material' -import React from 'react' -import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -import DescriptionOutlinedIcon from '@mui/icons-material/DescriptionOutlined'; -import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; +import { + Avatar, + Accordion, + AccordionDetails, + AccordionSummary, + Divider, + IconButton, + ListItem, + ListItemAvatar, + ListItemText, + Typography, +} from "@mui/material"; +import React from "react"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import DescriptionOutlinedIcon from "@mui/icons-material/DescriptionOutlined"; +import DeleteOutlinedIcon from "@mui/icons-material/DeleteOutlined"; -const AccordionForUploadedFileDetails = ({ data, title, deleteFunc, source, datasetname, loader }) => { - console.log(data) - return ( - - } - aria-controls="panel1a-content" - id="panel1a-header" - > - - {title} +const AccordionForUploadedFileDetails = ({ + data, + title, + deleteFunc, + source, + datasetname, +}) => { + console.log(data); + return ( + + } + aria-controls="panel1a-content" + id="panel1a-header" + > + + {title} - {data?.length} - - - - - - - {/*
    */} - {data?.map((item) => { - console.log(data, item) - return - - - - - - - - deleteFunc(datasetname, source, item)} - color='warning' /> - - - - })} - {/*
*/} -
-
-
- ) -} + + {data?.length}{" "} + +
+ +
+ + + {/*
    */} + {data?.map((item) => { + return ( + + + + + + + + + deleteFunc(datasetname, source, item)} + color="warning" + /> + + + + ); + })} + {/*
*/} +
+
+
+ ); +}; -export default AccordionForUploadedFileDetails \ No newline at end of file +export default AccordionForUploadedFileDetails; diff --git a/src/Components/AdminDatasetConnection/AddDataset.jsx b/src/Components/AdminDatasetConnection/AddDataset.jsx index 4a190cd79..48f56cf48 100644 --- a/src/Components/AdminDatasetConnection/AddDataset.jsx +++ b/src/Components/AdminDatasetConnection/AddDataset.jsx @@ -32,9 +32,10 @@ import axios from "axios" import { Avatar, Checkbox, CircularProgress, FormControl, FormControlLabel, FormGroup, InputAdornment, InputLabel, ListItem, ListItemAvatar, ListItemText, MenuItem, Select, List, IconButton, Snackbar, Alert, Chip, Paper, Divider, Skeleton } from '@mui/material' import Success from '../Success/Success'; import CategorySelectorList from './CategorySelectorList'; +import DataStandardizationInAddDataset from './DataStandardizationInAddDataset.js'; //stepper steps label -const steps = ['Dataset name', 'Create or upload dataset', 'Create a metadata']; +const steps = ['Dataset name', 'Create or upload dataset', 'Data standardization', 'Create a metadata']; const AddDataset = (props) => { const { isDatasetEditModeOn, datasetId, isaccesstoken, setOnBoardedTrue, cancelAction, setTokenLocal, onBoardingPage } = props @@ -134,13 +135,14 @@ const AddDataset = (props) => { payload.append("file_name", filename) payload.append("dataset_name", datasetname) console.log("PAYLOAD CREATED", payload) - + let checkforAccess = isaccesstoken ? isaccesstoken : false; HTTPService( "DELETE", UrlConstant.base_url + UrlConstant.dataseteth, payload, true, - true + true, + checkforAccess ).then((response) => { console.log("RESPONSE", response) if (source == "file") { @@ -164,27 +166,44 @@ const AddDataset = (props) => { // setKey(Math.random()) }).catch((e) => { - console.log(e); - // var returnValues = GetErrorKey(e, payload.keys()); - // var errorKeys = returnValues[0]; - // var errorMessages = returnValues[1]; - // if (errorKeys.length > 0) { - // for (var i = 0; i < errorKeys.length; i++) { - // switch (errorKeys[i]) { - // case "dataset_name": - // setDatasetNameError(errorMessages[i]); - // break; - // case "datasets": - // setDataSetFileError(errorMessages[i]); - // break; - // default: - // history.push(GetErrorHandlingRoute(e)); - // break; - // } - // } - // } else { - // history.push(GetErrorHandlingRoute(e)); - // } + var returnValues = GetErrorKey(e, payload.keys()); + var errorKeys = returnValues[0]; + var errorMessages = returnValues[1]; + if (errorKeys.length > 0) { + for (var i = 0; i < errorKeys.length; i++) { + switch (errorKeys[i]) { + case "dataset_name": + // setDatasetNameError(errorMessages[i]); + setMessageForSnackBar("Dataset deletion failed") + setErrorOrSuccess("error") + handleClick() + break; + case "file_name": + // setDataSetFileError(errorMessages[i]); + setMessageForSnackBar("Dataset deletion failed") + setErrorOrSuccess("error") + handleClick() + break; + default: + if (e?.response?.status == 401) { + history.push(GetErrorHandlingRoute(e)); + } else { + setMessageForSnackBar("Dataset deletion failed") + setErrorOrSuccess("error") + handleClick() + } + break; + } + } + } else { + if (e?.response?.status == 401) { + history.push(GetErrorHandlingRoute(e)); + } else { + setMessageForSnackBar("Dataset deletion failed") + setErrorOrSuccess("error") + handleClick() + } + } }); } @@ -281,16 +300,23 @@ const AddDataset = (props) => { // setfileValid(errorMessages[i]); break; default: - setMessageForSnackBar("Dataset uploaded failed") - setErrorOrSuccess("error") - handleClick() - break; + if (e?.response?.status == 401) { + history.push(GetErrorHandlingRoute(e)); + } else { + setMessageForSnackBar("Dataset with this name already exist") + setErrorOrSuccess("error") + handleClick() + } } } } else { - setMessageForSnackBar("Dataset uploaded failed") - setErrorOrSuccess("error") - handleClick() + if (e?.response?.status == 401) { + history.push(GetErrorHandlingRoute(e)); + } else { + setMessageForSnackBar("Dataset with this name already exist") + setErrorOrSuccess("error") + handleClick() + } } //setfileValid(e.response.data.sample_dataset[0]); // history.push(GetErrorHandlingRoute(e)); @@ -1059,7 +1085,14 @@ const AddDataset = (props) => { : ""} - {activeStep == 2 ? + { + activeStep == 2 ? + + : + "" + } + + {activeStep == 3 ? { )} */} - {activeStep == 2 ? : : } diff --git a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css new file mode 100644 index 000000000..d2bc2dd34 --- /dev/null +++ b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css @@ -0,0 +1,20 @@ +.data_standardization_cloumn_container{ + display: flex; + justify-content: space-around; + padding-right: 200px; +} +.data_standardization_title{ + display: flex; + justify-content: space-around; + padding-right: 300px; + margin-top: 30px; +} +.data_standardization_title > span{ + font-weight: 700; + height: 50px; + font-size: 18px; +} +.uploaded_data_column_name_title{ + font-weight: 400; + font-size: 16px; +} \ No newline at end of file diff --git a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js new file mode 100644 index 000000000..c8b795f25 --- /dev/null +++ b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js @@ -0,0 +1,69 @@ +import React, { useState } from "react"; +import InputLabel from "@mui/material/InputLabel"; +import MenuItem from "@mui/material/MenuItem"; +import FormControl from "@mui/material/FormControl"; +import Select, { SelectChangeEvent } from "@mui/material/Select"; +import './DataStandardizationInAddDataset.css' + +const DataStandardizationInAddDataset = () => { + const [keysInUploadedDataset, setKeysInUploadedDataset] = useState([ + "user_name", + "user_phone_number", + "user_address", + ]); + const [standardColumnNames, setStandardColumnNames] = useState([ + { key: "farmer_name", description: "give farmer name" }, + { key: "farmer_name", description: "give farmer name" }, + { key: "farmer_name", description: "give farmer name" }, + ]); + + const handleChange = (e) => { + console.log("handle change clicked"); + // setAge(e.target.value); + }; + + return ( + <> +
+ + Uploaded Data Column Name + + + Standard Data Column Name + +
+ {keysInUploadedDataset?.map((keyNames, index) => { + return ( +
+

{keyNames}

+
+ + Select column/key + + +
+
+ ); + })} + + + ); +}; + +export default DataStandardizationInAddDataset; diff --git a/src/Components/AdminDatasetConnection/LiveApiConnection.jsx b/src/Components/AdminDatasetConnection/LiveApiConnection.jsx index 4329a805b..ded020b65 100644 --- a/src/Components/AdminDatasetConnection/LiveApiConnection.jsx +++ b/src/Components/AdminDatasetConnection/LiveApiConnection.jsx @@ -1,48 +1,67 @@ import React from "react"; import { useState, useEffect } from "react"; import { Row, Col, Button } from "react-bootstrap"; -import { TextField, InputAdornment, Snackbar, Alert, Chip, IconButton } from "@mui/material"; -import CloseIcon from '@mui/icons-material/Close'; -import HubOutlinedIcon from '@mui/icons-material/HubOutlined'; -import KeyOutlinedIcon from '@mui/icons-material/KeyOutlined'; -import Axios from 'axios'; -import { GetErrorHandlingRoute, getTokenLocal, validateInputField } from "../../Utils/Common"; +import { + TextField, + InputAdornment, + Snackbar, + Alert, + IconButton, +} from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import HubOutlinedIcon from "@mui/icons-material/HubOutlined"; +import KeyOutlinedIcon from "@mui/icons-material/KeyOutlined"; +import Axios from "axios"; +import { getTokenLocal } from "../../Utils/Common"; import Loader from "../Loader/Loader"; -import { BodyText } from "react-bootstrap-icons"; import UrlConstant from "../../Constants/UrlConstants"; import ConnectionProgressGif from "./ConnectionProgressGif"; -import { UserOutlined } from "@ant-design/icons"; -import Person2Icon from '@mui/icons-material/Person2'; -import RegexConstants from "../../Constants/RegexConstants"; +import Person2Icon from "@mui/icons-material/Person2"; export default function LiveApiConnection(props) { - const { isDatasetEditModeOn, LiveApiFileList, setLiveApiFileList, cancelForm, datasetname, deleteFunc, localUploaded, mysqlFileList, - setPostgresFileList, setMysqlFileList, postgresFileList, setAllFiles, handleMetadata, progress, setProgress, uploadFile, setFile, key, isaccesstoken } = props - const [apifield, setApifield] = useState("") - const [authkey, setAuthKey] = useState("") - const [isConnected, setIsConnected] = useState(false) - const [isExported, setIsExported] = useState(false) - const [loader, setLoader] = useState(true) - const [messageForSnackBar, setMessageForSnackBar] = useState("") - const [errorOrSuccess, setErrorOrSuccess] = useState("error") + const { + isDatasetEditModeOn, + LiveApiFileList, + setLiveApiFileList, + cancelForm, + datasetname, + deleteFunc, + localUploaded, + mysqlFileList, + setPostgresFileList, + setMysqlFileList, + postgresFileList, + setAllFiles, + handleMetadata, + progress, + setProgress, + uploadFile, + setFile, + key, + isaccesstoken, + } = props; + const [apifield, setApifield] = useState(""); + const [authkey, setAuthKey] = useState(""); + const [loader, setLoader] = useState(true); + const [messageForSnackBar, setMessageForSnackBar] = useState(""); + const [errorOrSuccess, setErrorOrSuccess] = useState("error"); const [open, setOpen] = React.useState(false); - const [fileName, setFileName] = useState("") + const [fileName, setFileName] = useState(""); //handling toast const handleClick = () => { setOpen(true); }; const handleClose = (event, reason) => { - if (reason === 'clickaway') { + if (reason === "clickaway") { return; } setOpen(false); }; useEffect(() => { - - setLoader(false) - }, []) + setLoader(false); + }, []); const action = ( { - - var method = "POST" - setLoader(true) - let bodyFormData = new FormData() - bodyFormData.append("dataset_name", datasetname) - bodyFormData.append("file_name", fileName) - bodyFormData.append("source", "live_api") - bodyFormData.append("api_key", authkey) - bodyFormData.append("url", apifield) + var method = "POST"; + setLoader(true); + let bodyFormData = new FormData(); + bodyFormData.append("dataset_name", datasetname); + bodyFormData.append("file_name", fileName); + bodyFormData.append("source", "live_api"); + bodyFormData.append("api_key", "Bearer " + authkey); + bodyFormData.append("url", apifield); let accesstoken = isaccesstoken || getTokenLocal(); - let url = "" + let url = ""; if (isDatasetEditModeOn) { - url = UrlConstant.base_url + UrlConstant.live_api + "?dataset_exists=True" + url = + UrlConstant.base_url + UrlConstant.live_api + "?dataset_exists=True"; } else { - url = UrlConstant.base_url + UrlConstant.live_api + url = UrlConstant.base_url + UrlConstant.live_api; } Axios({ method: method, @@ -82,35 +101,41 @@ export default function LiveApiConnection(props) { "Content-Type": "application/json", Authorization: "Bearer " + accesstoken, }, - }).then((response) => { - console.log(response) - setLoader(false) - setMessageForSnackBar("File exported successfully!") - setErrorOrSuccess("success") - handleClick() - setLiveApiFileList(response.data) - setIsConnected(true) - }).catch((error) => { - console.log(error) - setLoader(false) - setMessageForSnackBar("File export failed!") - setErrorOrSuccess("error") - handleClick() - setIsConnected(false) }) - } - + .then((response) => { + setLoader(false); + setMessageForSnackBar("File exported successfully!"); + setErrorOrSuccess("success"); + handleClick(); + setLiveApiFileList(response.data); + }) + .catch((error) => { + setLoader(false); + setMessageForSnackBar(error.response?.data?.message); + setErrorOrSuccess("error"); + handleClick(); + }); + }; return ( <> {loader ? : ""} - {messageForSnackBar} + + {messageForSnackBar} + @@ -118,7 +143,7 @@ export default function LiveApiConnection(props) { Please provide the Live API credentials - + ), }} - style={{ width: "80%", marginTop: "20px" }} id="api" + style={{ width: "80%", marginTop: "20px" }} + id="api" value={fileName} onChange={(e) => setFileName(e.target.value.trim())} - label="File name" name='file_name' variant="standard" + label="File name" + name="file_name" + variant="standard" /> ), }} - style={{ width: "80%", marginTop: "20px" }} id="api" + style={{ width: "80%", marginTop: "20px" }} + id="api" value={apifield} onChange={(e) => setApifield(e.target.value)} - label="API" name='host_address' variant="standard" + label="API" + name="host_address" + variant="standard" /> ), }} - style={{ width: "80%", marginTop: "20px" }} id="auth_key" + style={{ width: "80%", marginTop: "20px" }} + id="auth_key" value={authkey} - onChange={(e) => setAuthKey(e.target.value == "" ? `Bearer ${e.target.value}` : e.target.value)} - label="Authentication Key" name='host_address' variant="standard" /> - + onChange={(e) => setAuthKey(e.target.value)} + label="Authentication Key" + name="host_address" + variant="standard" + /> + + Fetch data{" "} + - - + mysqlFileList={mysqlFileList} + setMysqlFileList={setMysqlFileList} + postgresFileList={postgresFileList} + setPostgresFileList={setPostgresFileList} + setAllFiles={setAllFiles} + handleMetadata={handleMetadata} + progress={progress} + setProgress={setProgress} + uploadFile={uploadFile} + setFile={setFile} + key={key} + /> - - ) -} \ No newline at end of file + ); +} diff --git a/src/Components/AdminDatasetConnection/LocalMachineUploadDataset.css b/src/Components/AdminDatasetConnection/LocalMachineUploadDataset.css index c37b5bf78..6b308ecc5 100644 --- a/src/Components/AdminDatasetConnection/LocalMachineUploadDataset.css +++ b/src/Components/AdminDatasetConnection/LocalMachineUploadDataset.css @@ -254,4 +254,10 @@ .viewdetails_table table td { max-width: 100px; + word-break: break-all !important; +} +.mui_snackbar_in_live_api_classname > div :nth-child(2){ + max-width: 1300px !important; + overflow: scroll !important; + height: 35px !important; } \ No newline at end of file diff --git a/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx b/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx index 538808505..bf0b4cc7a 100644 --- a/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx +++ b/src/Components/AdminDatasetConnection/MysqlFormForConnection.jsx @@ -90,7 +90,7 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han //Connection establishment to the given database details const tryToConnect = () => { setLoader(true) - setSpinner(true) + // setSpinner(true) //building the body for request object let bodyData = { @@ -110,21 +110,21 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han true, checkforAcess).then((res) => { console.log(res) + setLoader(false) setDbData([...res.data]) setIsConnected(true) //if error occurs Alert will be shown as Snackbar setMessageForSnackBar("Connection establishment done!") setErrorOrSuccess("success") handleClick() - setLoader(false) - setSpinner(false) + // setSpinner(false) }).catch((err) => { //if any error occurs displaying the error toast console.log(err) setLoader(false) - setSpinner(false) + // setSpinner(false) //setting the cookies upon the successfull response with the validity of 1 hour or till the time metadata and dataset upload done let dataForReset = { @@ -155,17 +155,26 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han case "host": seteErrorHostMysql(errorMessages[i]); break; case "port": seteErrorPortMysql(errorMessages[i]); break; //if error occurs Alert will be shown as Snackbar - default: setMessageForSnackBar("Connection establishment failed!") - setErrorOrSuccess("error") - handleClick(); break; + default: + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar("Connection establishment failed!") + setErrorOrSuccess("error") + handleClick(); break; + } + } } } else { - //if error occurs Alert will be shown as Snackbar - setMessageForSnackBar("Connection establishment failed!") - setErrorOrSuccess("error") - handleClick() //toggling toast + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar("Connection establishment failed!") + setErrorOrSuccess("error") + handleClick(); + } setIsConnected(false) // move to table form } @@ -210,7 +219,7 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han setLoader(true) setSelectedTable(query); - let token = getTokenLocal(); + let token = isaccesstoken ? isaccesstoken : getTokenLocal(); Axios({ method: method, url: UrlConstant.base_url + UrlConstant.get_column_from_table_name, @@ -226,12 +235,16 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han generateColumns([...res.data]) setLoader(false) }).catch((err) => { + setLoader(false) console.log(err) //if error occurs Alert will be shown as Snackbar - setMessageForSnackBar("Columns fetching failed. Please try again!") //error message set - setErrorOrSuccess("error") //error type set - handleClick() //toggling toast - setLoader(false) + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar(`Columns fetching failed with status code ${err?.response?.status ? err?.response?.status : "NA"} :. Please try again!`) //error message set + setErrorOrSuccess("error") //error type set + handleClick() //toggling toast + } }) }; @@ -255,7 +268,8 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han newFormData.append("source", "mysql") newFormData.append("table_name", table_name) - let token = getTokenLocal(); + let token = isaccesstoken ? isaccesstoken : getTokenLocal(); + let url = "" if (isDatasetEditModeOn) { @@ -316,14 +330,24 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han break; default: - setMessageForSnackBar("Some error occurred during exporting!") - handleClick() + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar(`Some error occurred during exporting with status code ${err?.response?.status ? err?.response?.status : "NA"} :. Please try again!`) //error message set + setErrorOrSuccess("error") //error type set + handleClick() //toggling toast + } break; } } } else { - setMessageForSnackBar("Some error occurred during exporting!") - handleClick() + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar(`Some error occurred during exporting with status code ${err?.response?.status ? err?.response?.status : "NA"} :. Please try again!`) //error message set + setErrorOrSuccess("error") //error type set + handleClick() //toggling toast + } } @@ -445,7 +469,7 @@ const MysqlFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, han }, []) return ( <> - {loader && isConnected ? : ""} + {loader ? : ""} { console.log(err) //if error occurs Alert will be shown as Snackbar - setMessageForSnackBar("Columns fetching failed. Please try again!") //error message set - setErrorOrSuccess("error") //error type set - handleClick() //toggling toast + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar(`Columns fetching failed with status code ${err?.response?.status ? err?.response?.status : "NA"} :. Please try again!`) //error message set + setErrorOrSuccess("error") //error type set + handleClick() //toggling toast + } setLoader(false) }) }; @@ -258,7 +271,8 @@ const PostgresFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, newFormData.append("source", "postgresql") newFormData.append("table_name", table_name) - let token = getTokenLocal(); + let token = isaccesstoken ? isaccesstoken : getTokenLocal(); + let url = "" if (isDatasetEditModeOn) { url = UrlConstant.base_url + UrlConstant.send_columns_to_export + "?dataset_exists=True" @@ -318,14 +332,23 @@ const PostgresFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, break; default: - setMessageForSnackBar("Some error occurred during exporting!") - handleClick() + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar("Some error occurred during exporting!") + handleClick(); break; + } + break; } } } else { - setMessageForSnackBar("Some error occurred during exporting!") - handleClick() + if (err?.response?.status == 401) { + history.push(GetErrorHandlingRoute(err)); + } else { + setMessageForSnackBar("Some error occurred during exporting!") + handleClick() + } } // //if error occurs Alert will be shown as Snackbar // setMessageForSnackBar("File export failed!") @@ -445,7 +468,7 @@ const PostgresFormForConnection = ({ isDatasetEditModeOn, seteErrorDatasetName, }, []) return ( <> - {loader && isConnected ? : ""} + {loader ? : ""} {isFileDataLoaded && fileData.map(itm1 => { return (itm1?.content?.length > 0 && - {itm1?.file ? : ""} + {itm1?.file ? : ""} + {itm1?.source? : ""} - downloadAttachment(UrlConstant.base_url + downloadfile?.file ? downloadfile?.file : "", downloadfile?.file?.split("/")[5]) + downloadAttachment(UrlConstant.base_url + downloadfile?.file ? downloadfile?.file : "", downloadfile?.file?.split("/").pop()) } > - {downloadfile?.file?.split("/")[5]} + {downloadfile?.file?.split("/").pop()} {/*
*/} {/* m */}
@@ -429,7 +430,7 @@ export default function ViewMetaDatasetDetails(props) { {orgdetail.name} {orgdetail.org_email} - {orgdes ? parse(orgdes) : orgdes} + {/* {orgdes ? parse(orgdes) : orgdes} */} {orgdetail?.phone_number} {orgdetail?.address?.city} {orgdetail?.address?.country} diff --git a/src/Components/CoSteward/AddCoSteward.jsx b/src/Components/CoSteward/AddCoSteward.jsx index 320984f0a..6ff32d90d 100644 --- a/src/Components/CoSteward/AddCoSteward.jsx +++ b/src/Components/CoSteward/AddCoSteward.jsx @@ -11,9 +11,14 @@ import UrlConstants from "../../Constants/UrlConstants"; import validator from "validator"; import { useHistory } from "react-router-dom"; import RegexConstants from "../../Constants/RegexConstants"; -import { GetErrorHandlingRoute, GetErrorKey, mobileNumberMinimunLengthCheck,} from "../../Utils/Common"; +import { + GetErrorHandlingRoute, + GetErrorKey, + mobileNumberMinimunLengthCheck, + stringMinimumLengthCheck, +} from "../../Utils/Common"; import Loader from "../../Components/Loader/Loader"; -import CoStewardForm from "../CoSteward/CoStewardForm" +import CoStewardForm from "../CoSteward/CoStewardForm"; const useStyles = { btncolor: { @@ -48,13 +53,13 @@ export default function AddCoSteward(props) { const [isSuccess, setisSuccess] = useState(false); const [isLoader, setIsLoader] = useState(false); - const[firstNameErrorMessage, setFirstNameErrorMessage] = useState(null) - const[lastNameErrorMessage,setLastNameErrorMessage] = useState(null) - const[emailErrorMessage, setEmailErrorMessage] = useState(null) - const[phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null) - const[orgNameErrorMessage, setOrgNameErrorMessage] = useState(null) - const[orgEmailErrorMessage,setOrgEmailErrorMessage] = useState(null) - const[orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null) + const [firstNameErrorMessage, setFirstNameErrorMessage] = useState(null); + const [lastNameErrorMessage, setLastNameErrorMessage] = useState(null); + const [emailErrorMessage, setEmailErrorMessage] = useState(null); + const [phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null); + const [orgNameErrorMessage, setOrgNameErrorMessage] = useState(null); + const [orgEmailErrorMessage, setOrgEmailErrorMessage] = useState(null); + const [orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null); const isValidURL = (string) => { var res = string.match(RegexConstants.NEW_WEBSITE_REGEX); @@ -63,17 +68,16 @@ export default function AddCoSteward(props) { const isValidCapsUrl = (string) => { var res1 = string.match(RegexConstants.NEW_C_WEBSITE_REGEX); return res1 !== null; - } + }; const addNewCoSteward = () => { - - setFirstNameErrorMessage(null) - setLastNameErrorMessage(null) - setEmailErrorMessage(null) - setPhoneNumberErrorMessage(null) - setOrgNameErrorMessage(null) - setOrgEmailErrorMessage(null) - setOrgWebsiteErrorMessage(null) - setisorganisationemailerror(null) + setFirstNameErrorMessage(null); + setLastNameErrorMessage(null); + setEmailErrorMessage(null); + setPhoneNumberErrorMessage(null); + setOrgNameErrorMessage(null); + setOrgEmailErrorMessage(null); + setOrgWebsiteErrorMessage(null); + setisorganisationemailerror(null); var bodyFormData = new FormData(); bodyFormData.append("email", useremail.toLowerCase()); @@ -99,33 +103,48 @@ export default function AddCoSteward(props) { bodyFormData, false, true - ).then((response) => { + ) + .then((response) => { setIsLoader(false); setisSuccess(true); - console.log(response, "response of costeward added") + console.log(response, "response of costeward added"); }) .catch((e) => { setIsLoader(false); - console.log(e); - var returnValues = GetErrorKey(e, bodyFormData.keys()) - var errorKeys = returnValues[0] - var errorMessages = returnValues[1] - if (errorKeys.length > 0){ - for (var i=0; i 0) { + for (var i = 0; i < errorKeys.length; i++) { + switch (errorKeys[i]) { + case "first_name": + setFirstNameErrorMessage(errorMessages[i]); + break; + case "last_name": + setLastNameErrorMessage(errorMessages[i]); + break; + case "email": + setEmailErrorMessage(errorMessages[i]); + break; + case "phone_number": + setPhoneNumberErrorMessage(errorMessages[i]); + break; + case "name": + setOrgNameErrorMessage(errorMessages[i]); + break; + case "org_email": + setOrgEmailErrorMessage(errorMessages[i]); + break; + case "website": + setOrgWebsiteErrorMessage(errorMessages[i]); + break; + default: + history.push(GetErrorHandlingRoute(e)); + break; } } - } - else{ - history.push(GetErrorHandlingRoute(e)) + } else { + history.push(GetErrorHandlingRoute(e)); } }); }; @@ -141,7 +160,8 @@ export default function AddCoSteward(props) { btntext={"ok"} heading={"Co-Steward added successfully !"} imageText={"Added"} - msg={"You added a Co-Steward."}> + msg={"You added a Co-Steward."} + > ) : ( <> { + setlastname={(ref) => { setlastname(ref); }} useremail={useremail} @@ -197,9 +217,7 @@ export default function AddCoSteward(props) { isexisitinguseremail={isexisitinguseremail} first_heading={screenlabels.co_steward?.first_heading} second_heading={screenlabels.co_steward?.second_heading} - third_heading={ - screenlabels.co_steward?.third_heading - } + third_heading={screenlabels.co_steward?.third_heading} firstNameErrorMessage={firstNameErrorMessage} lastNameErrorMessage={lastNameErrorMessage} emailErrorMessage={emailErrorMessage} @@ -207,7 +225,7 @@ export default function AddCoSteward(props) { orgNameErrorMessage={orgNameErrorMessage} orgEmailErrorMessage={orgEmailErrorMessage} orgWebsiteErrorMessage={orgWebsiteErrorMessage} - > + >
@@ -219,22 +237,23 @@ export default function AddCoSteward(props) { websitelink && !iswebsitelinkrerror && organisationaddress && - pincode && + stringMinimumLengthCheck(pincode, 5) && firstname && useremail && - !isuseremailerror ? - ( + !isuseremailerror ? ( ) : ( )} @@ -246,7 +265,8 @@ export default function AddCoSteward(props) { @@ -256,4 +276,4 @@ export default function AddCoSteward(props) { ); -} \ No newline at end of file +} diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index 3cf6d6f88..919dfbcdb 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -149,9 +149,9 @@ const DatasetSelect = (props) => { deleteTable(eachDatasetFile, index)} /> */} - + {/* changeAllSelect(eachDatasetFile)} control={} label={"Select all"} /> - + */} {listOfDatsetFileAvailableForColumn[eachDatasetFile]?.length > 0 && listOfDatsetFileAvailableForColumn[eachDatasetFile]?.map((eachColumn, index) => { return handleChangeColumns(e, eachDatasetFile, eachColumn)} />} label={eachColumn} /> diff --git a/src/Components/GuestUser/GuestUserDatasetCard.js b/src/Components/GuestUser/GuestUserDatasetCard.js index 9a48a50b5..00140e914 100644 --- a/src/Components/GuestUser/GuestUserDatasetCard.js +++ b/src/Components/GuestUser/GuestUserDatasetCard.js @@ -36,7 +36,7 @@ const useStyles = { cardcolor: { border: "1px solid #E4E4E4", "box-shadow": "none", - cursor: "pointer", + // cursor: "pointer", height: "355px", "border-radius": "2px", width: "346px", @@ -45,7 +45,7 @@ const useStyles = { togglecardcolor: { "box-shadow": "0px 4px 20px rgba(216, 175, 40, 0.28)", border: "1px solid #ebd79c", - cursor: "pointer", + // cursor: "pointer", height: "355px", width: "346px", "margin-left": "20px", @@ -234,7 +234,6 @@ export default function GuestUserDatasetCard(props) { {/* {toTitleCase(`View details`)} */} View details - ) : ( <> diff --git a/src/Components/GuestUser/GuestUserDatasets.js b/src/Components/GuestUser/GuestUserDatasets.js index 9ff76e360..1f17ad140 100644 --- a/src/Components/GuestUser/GuestUserDatasets.js +++ b/src/Components/GuestUser/GuestUserDatasets.js @@ -25,7 +25,11 @@ import GuestUserDatasetListing from "./GuestUserDatasetListing"; import ViewDataSet from "../Datasets/viewDataSet"; import Axios from "axios"; import RegexConstants from "../../Constants/RegexConstants"; -export default function GuestUserDatasets() { +import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import styles from "./guestUserLegal.module.css"; + +export default function GuestUserDatasets(props) { + const { setIsExploreDatasetViewOn } = props const [isLoader, setIsLoader] = useState(false); const [isShowLoadMoreButton, setisShowLoadMoreButton] = useState(false); const [showLoadMoreAdmin, setShowLoadMoreAdmin] = useState(false); @@ -226,6 +230,8 @@ export default function GuestUserDatasets() { setSubcategoryFilterValue([]); break; } + // Reset dataset list to the original state if the category filter is empty + if (value.length === 0) getAllDataSets(); } else if (input_field === "Subcategories") { setSubcategoryFilterValue(value); } @@ -877,7 +883,7 @@ export default function GuestUserDatasets() { fromDateandToDate.push(new Date(fromdate.getTime() - (fromdate.getTimezoneOffset() * 60000)).toJSON()); // Adding 86400000 will add 1 more day in date (86400000 == 24hrs) fromDateandToDate.push(new Date(todate.getTime() - (todate.getTimezoneOffset() * 60000) + 86400000).toJSON()); - console.log('payload in date fillter api',fromDateandToDate, fromdate, todate) + console.log('payload in date fillter api', fromDateandToDate, fromdate, todate) setIsShowAll(false); @@ -970,6 +976,18 @@ export default function GuestUserDatasets() {
+ setIsExploreDatasetViewOn(false)} + className={styles.backButtonMainDiv + " back_btn_guest"} + sx={{ + display: "flex", + justifyContent: "left", + marginBottom: "20px", + }} + > + {" "} + {labels.en.common.back}{" "} +
{ + const { heading, no, address, icon, eachData, setIsViewDetails, setViewDetailData } = props + return ( + +
+
+ {/* */} + {eachData?.organization?.logo ? : + {eachData?.organization?.name?.charAt(0)}} +

{eachData?.organization.name}

+

+ + {eachData?.organization?.address?.country ? eachData.organization.address.country : "Bangalore, India"} + +

+ + + + + + {+eachData?.dataset_count > 9 ? eachData?.dataset_count : "0" + eachData?.dataset_count} + + + Datasets + + + + + + + + {+eachData?.users_count > 9 ? eachData?.users_count : "0" + eachData?.users_count} + + + Pariticipants + + + + + +
+
+
+
+ +
+ ) +} + +export default EachCardForDetails \ No newline at end of file diff --git a/src/Components/GuestUser/GuestUserMainPage/GuestMainPageCarousel.jsx b/src/Components/GuestUser/GuestUserMainPage/GuestMainPageCarousel.jsx new file mode 100644 index 000000000..cddd6473e --- /dev/null +++ b/src/Components/GuestUser/GuestUserMainPage/GuestMainPageCarousel.jsx @@ -0,0 +1,89 @@ +import React, { Component } from "react"; +import { Container, Row } from "react-bootstrap"; +import Slider from "react-slick"; +import EachCardForDetails from "./EachCardForDetails"; +import icon from "../../../Assets/Img/bellboy.gif" +import GuestUserDatasetCard from "../GuestUserDatasetCard"; +import styles from "./guest_user_main_page.module.css" +import { useHistory } from "react-router-dom"; + +export default function GuestMainPageCarousel(props) { + const { heading, costewardData, participant, datasets, setIsViewDetails, setViewDetailData } = props + // render(props) { + const history = useHistory() + const settings = { + className: "center", + centerMode: true, + infinite: true, + centerPadding: "60px", + slidesToShow: 3, + speed: 500, + autoplay: true, + autoplaySpeed: 5000 + }; + const datasetsetting = { + className: "center", + centerMode: true, + infinite: true, + centerPadding: "10px", + slidesToShow: 3, + speed: 500, + autoplay: true, + autoplaySpeed: 6000 + }; + let data = ["1", "@", "3", 4, 5, 6, 7, 8] + return ( + <> + + {/* */} + +

{"Co-Stewards"}

+ + {costewardData.map((each, i) => { + return
+ +
+ })} +
+

{"Datasets"}

+ + {datasets.map((dataset, i) => { + return
+ history.push("/home/viewdataset/" + dataset.id)} + margingtop={"supportcard supportcardmargintop20px"} + /> +
+ })} +
+ {/*
+ */} +

{"Participants"}

+ + {participant.map((each, i) => { + return
+ +
+ })} +
+ + + + {/*
*/} +
+ + ); + // } +} \ No newline at end of file diff --git a/src/Components/GuestUser/GuestUserMainPage/LeftRightDescription.jsx b/src/Components/GuestUser/GuestUserMainPage/LeftRightDescription.jsx new file mode 100644 index 000000000..885925712 --- /dev/null +++ b/src/Components/GuestUser/GuestUserMainPage/LeftRightDescription.jsx @@ -0,0 +1,65 @@ +import { Button } from '@mui/material' +import React from 'react' +import { Col, Container, Row } from 'react-bootstrap' +import { useHistory } from 'react-router-dom' +import data_transfer from "../../../Assets/Img/explore_dataset.svg" +import login_datahub from "../../../Assets/Img/login_datahub.svg" + + +import styles from "./guest_user_main_page.module.css" + +const LeftRightDescription = (props) => { + const { setIsExploreDatasetViewOn } = props + const history = useHistory() + function topFunction() { + document.body.scrollTop = 0; // For Safari + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera + } + return ( + + +
+ data_transfer + + +

+ Cutting-edge data management platform for curation, distribution, and administration of datasets with a state-of-the-art data hub and comprehensive data sets for research and analysis. +

+ + + + + +

+ Unlock valuable insights and informed decision-making! Register or login now to access our advanced data management platform with a state-of-the-art data hub and comprehensive datasets. +

+ + + + + + + data_transfer + + + + ) +} + +export default LeftRightDescription \ No newline at end of file diff --git a/src/Components/GuestUser/GuestUserMainPage/ViewDetail.jsx b/src/Components/GuestUser/GuestUserMainPage/ViewDetail.jsx new file mode 100644 index 000000000..f304b6e01 --- /dev/null +++ b/src/Components/GuestUser/GuestUserMainPage/ViewDetail.jsx @@ -0,0 +1,78 @@ +import React, { useState, useMemo } from 'react'; +import Row from 'react-bootstrap/Row' +import Col from 'react-bootstrap/Col' + +import countryList from "react-select-country-list"; +import { useHistory } from 'react-router-dom'; +import { Avatar, Tooltip } from '@mui/material'; +import { Zoom } from '@material-ui/core'; +import labels from '../../../Constants/labels'; +import { Container } from 'react-bootstrap'; +import parse from "html-react-parser"; +import UrlConstant from '../../../Constants/UrlConstants'; + +// import Select from 'react-select' +const useStyles = { + data: { float: "left", "margin-top": "5px" }, + left: { float: "left", "text-align": "left" }, + marginrowtop: { "margin-top": "40px" }, + headingbold: { fontWeight: "bold" }, + fourthhead: { float: 'left', 'margin-left': '700px', 'margin-top': '-27px' }, + Fourthhead: { float: 'right', 'margin-right': '383px', 'margin-top': '17px' } + +}; +export default function ViewDetail(props) { + const [screenlabels, setscreenlabels] = useState(labels['en']); + // const options = useMemo(() => countryList().getData(), []) + const history = useHistory(); + // console.log('props in view details', props) + + console.log('view details', props) + console.log(props) + return ( + + + + + + +
+ + + + {/* {props.coSteward ? screenlabels.viewCoSteward.first_heading : screenlabels.viewparticipants.first_heading} */} + + + + + {Object.keys(props.viewDetailData.organization).map((each, index) => { + if (each !== "address" && each != "" && each != "id" && each != "org_description") { + return +
{each ? each : ""}
+ {each == "logo" ? +
+ {console.log(UrlConstant.base_url_without_slash + props?.viewDetailData?.organization[each])} + {props?.viewDetailData?.organization[each] ? : "NA"} +
: +
+ {props?.viewDetailData?.organization[each] ? ` ${props?.viewDetailData?.organization[each]}` : "NA"} +
} + + } + })} + + + +
+ + ); +} diff --git a/src/Components/GuestUser/GuestUserMainPage/guest_user_main_page.module.css b/src/Components/GuestUser/GuestUserMainPage/guest_user_main_page.module.css new file mode 100644 index 000000000..39dd50897 --- /dev/null +++ b/src/Components/GuestUser/GuestUserMainPage/guest_user_main_page.module.css @@ -0,0 +1,80 @@ +.btncolor { + color: #ab8405 !important; + border-color: #ab8405 !important; + border-radius: 0; + text-transform: none; + font-weight: 400; + font-size: 14px; + visibility: hidden; + width: 80%; + margin-top: 30px !important; + outline: none !important; +} + +.explore_btn { + color: black !important; + border-color: black !important; + border-radius: 0; + text-transform: none; + font-weight: 400; + font-size: 14px; + visibility: visible; + width: 80%; + margin-top: 30px !important; + outline: none !important; +} + +.main_card:hover .btncolor { + visibility: visible !important; + color: #ab8405; +} + +.main_card { + width: 500px !important; +} + +.margintopbtm { + margin: 80px 0px 50px 0px; +} + +.explore_btn:hover { + background-color: #ab8405 !important; + color: white !important; + border-color: #ab8405 !important; +} + +.image { + height: 100%; + width: 100%; +} + +.imageCol { + padding: 70px; +} + +/* .image:hover .imageCol { + padding: 80px !important +} */ +.paragraph { + padding: 0px 50px; +} + +.desc_detail { + background: #636363; + /* fallback for old browsers */ + background: -webkit-linear-gradient(to right, #ab84057f, white); + background: -webkit-linear-gradient(to bottom, #ab84057f, white); + /* Chrome 10-25, Safari 5.1-6 */ + background: linear-gradient(to right, #ab84057f, white); + background: linear-gradient(to bottom, #ab84057f, white); +} + +.desc_detail_rev { + background: #636363; + /* fallback for old browsers */ + background: -webkit-linear-gradient(to right, white, #ab84057f); + background: -webkit-linear-gradient(to bottom, white, #ab84057f); + /* Chrome 10-25, Safari 5.1-6 */ + background: linear-gradient(to right, white, #ab84057f); + background: linear-gradient(to bottom, white, #ab84057f); +} \ No newline at end of file diff --git a/src/Components/GuestUser/guestUserLegal.module.css b/src/Components/GuestUser/guestUserLegal.module.css index b374dad8b..21f1da185 100644 --- a/src/Components/GuestUser/guestUserLegal.module.css +++ b/src/Components/GuestUser/guestUserLegal.module.css @@ -1,21 +1,23 @@ .backButtonMainDiv { - display: flex; - /* margin-left: 290px; */ - /* justify-content: space-between; */ - color: #3491ee; - align-items: center; - cursor: pointer; - } - .backArrowIcon { - width: 16px; - height: 16px; - margin-right: 14px; - cursor: pointer; - } + display: flex; + /* margin-left: 290px; */ + /* justify-content: space-between; */ + color: #3491ee !important; + align-items: center; + cursor: pointer; +} +.backArrowIcon { + width: 16px; + height: 16px; + margin-right: 14px; + cursor: pointer; + color: #3491ee !important; +} -.legalButton:hover{ + +.legalButton:hover { text-decoration: underline !important; } \ No newline at end of file diff --git a/src/Components/Navbar/GuestUserNavbar.js b/src/Components/Navbar/GuestUserNavbar.js index 4e2bf87a0..ad6b9604b 100644 --- a/src/Components/Navbar/GuestUserNavbar.js +++ b/src/Components/Navbar/GuestUserNavbar.js @@ -1,37 +1,21 @@ import React, { useState, useEffect } from "react"; -import { - Nav, - NavLink, - Bars, - NavMenu, - NavBtn, - NavBtnLink, -} from "./NavbarElements"; +import { Nav, NavLink, NavMenu, NavBtn, NavBtnLink } from "./NavbarElements"; import labels from "../../Constants/labels"; -import LocalStorageConstants from "../../Constants/LocalStorageConstants"; -import { Link, useHistory } from "react-router-dom"; +import { useHistory } from "react-router-dom"; import HTTPService from "../../Services/HTTPService"; -import { flushLocalstorage, getUserLocal } from "../../Utils/Common"; import UrlConstant from "../../Constants/UrlConstants"; -import Avatar from "@mui/material/Avatar"; import "./Navbar.css"; -import Button from "@mui/material/Button"; import Loader from "../Loader/Loader"; -import { GetErrorHandlingRoute } from "../../Utils/Common"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; import Farmstack from "../../Assets/Img/farmstack.jpg"; -import Toolbar from '@mui/material/Toolbar'; +import Toolbar from "@mui/material/Toolbar"; const GuestUserNavBar = (props) => { - const [profile, setprofile] = useState(null); const [screenlabels, setscreenlabels] = useState(labels["en"]); const [isLoader, setIsLoader] = useState(false); - const [linkClicked, setLinkClicked] = useState(false); const [phoneNumber, setPhoneNumber] = useState(null); - let history = useHistory(); - useEffect(() => { HTTPService( "GET", @@ -67,18 +51,17 @@ const GuestUserNavBar = (props) => { {/* */} - FarmStack + FarmStack - {/* */} - + {/* */} @@ -110,10 +93,9 @@ const GuestUserNavBar = (props) => { src={require("../../Assets/Img/call_icon.png")} alt="call" style={{ - width: "52px", - height: "52px", - "margin-left": "-50px", - "margin-top": "9px", + width: "42px", + height: "42px", + margin: "9px 0 9px 50px", }} />      diff --git a/src/Components/Participants/EditCoSteward.js b/src/Components/Participants/EditCoSteward.js index cc4ceb4f5..a984d1ca4 100644 --- a/src/Components/Participants/EditCoSteward.js +++ b/src/Components/Participants/EditCoSteward.js @@ -1,11 +1,12 @@ import React from "react"; import EditParticipants from "../../Views/Participants/EditParticipants"; -const EditCoSteward = ()=>{ - - return(<> - - ) -} +const EditCoSteward = () => { + return ( + <> + + + ); +}; -export default EditCoSteward; \ No newline at end of file +export default EditCoSteward; diff --git a/src/Components/Participants/ParticipantsCards.js b/src/Components/Participants/ParticipantsCards.js index 64b9758d1..c781d8878 100644 --- a/src/Components/Participants/ParticipantsCards.js +++ b/src/Components/Participants/ParticipantsCards.js @@ -1,81 +1,190 @@ -import * as React from 'react'; -import { styled } from '@mui/material/styles'; -import Card from '@mui/material/Card'; -import CardHeader from '@mui/material/CardHeader'; -import CardMedia from '@mui/material/CardMedia'; -import CardContent from '@mui/material/CardContent'; -import CardActions from '@mui/material/CardActions'; -import Collapse from '@mui/material/Collapse'; -import Avatar from '@mui/material/Avatar'; -import IconButton from '@mui/material/IconButton'; -import Typography from '@mui/material/Typography'; -import { red } from '@mui/material/colors'; -import Row from 'react-bootstrap/Row' -import Col from 'react-bootstrap/Col' +import * as React from "react"; +import { styled } from "@mui/material/styles"; +import Card from "@mui/material/Card"; +import CardHeader from "@mui/material/CardHeader"; +import CardMedia from "@mui/material/CardMedia"; +import CardContent from "@mui/material/CardContent"; +import CardActions from "@mui/material/CardActions"; +import Collapse from "@mui/material/Collapse"; +import Avatar from "@mui/material/Avatar"; +import IconButton from "@mui/material/IconButton"; +import Typography from "@mui/material/Typography"; +import { red } from "@mui/material/colors"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; import Button from "@mui/material/Button"; -import THEME_COLORS from '../../Constants/ColorConstants' -import UrlConstants from '../../Constants/UrlConstants' +import THEME_COLORS from "../../Constants/ColorConstants"; +import UrlConstants from "../../Constants/UrlConstants"; import { useHistory } from "react-router-dom"; -import { Tooltip, Zoom } from '@mui/material'; +import { Tooltip, Zoom } from "@mui/material"; const useStyles = { - btncolor: {color: THEME_COLORS.THEME_COLOR, "border-color": THEME_COLORS.THEME_COLOR, "border-radius": 0,"text-transform": "capitalize", "border-radius": "2px", "text-transform": "capitalize", "width": "116px", "height": "34px", "margin-left": "-25px", "font-weight": "400", "font-family": "Open Sans", 'font-style': 'normal', 'font-size': '14px'}, - btnPosition: {color: THEME_COLORS.THEME_COLOR, "border-color": THEME_COLORS.THEME_COLOR, "border-radius": 0,"text-transform": "capitalize", "border-radius": "2px", "text-transform": "capitalize", "width": "116px", "height": "34px", "margin-right": "-20px", "font-weight": "400", "font-family": "Open Sans", 'font-style': 'normal', 'font-size': '14px'}, - cardcolor:{border: "1px solid #E4E4E4","box-shadow": "none",cursor:"pointer",'min-height': "240px","width": "350px","border-radius": "2px"}, - togglecardcolor:{"box-shadow": "0px 4px 20px rgba(216, 175, 40, 0.28)", border: "1px solid #D8AF28",cursor:"pointer",'min-height': "240px","width": "350px"}, - marginrowtop: {"margin-top": "30px"}, - cardDataHeading:{'font-family': 'Open Sans', "font-weight": "600","font-size": "14px",color: "#3D4A52", "text-align": "left", 'padding-left': '10px' }, - cardData:{'font-family': 'Open Sans', "font-weight": "400","font-size": "14px",color: "#3D4A52", "text-align": "left", 'margin-top': '10px', 'padding-left': '0px'} + btncolor: { + color: THEME_COLORS.THEME_COLOR, + "border-color": THEME_COLORS.THEME_COLOR, + "border-radius": 0, + "text-transform": "capitalize", + "border-radius": "2px", + "text-transform": "capitalize", + width: "116px", + height: "34px", + "margin-left": "-25px", + "font-weight": "400", + "font-family": "Open Sans", + "font-style": "normal", + "font-size": "14px", + }, + btnPosition: { + color: THEME_COLORS.THEME_COLOR, + "border-color": THEME_COLORS.THEME_COLOR, + "border-radius": 0, + "text-transform": "capitalize", + "border-radius": "2px", + "text-transform": "capitalize", + width: "116px", + height: "34px", + "margin-right": "-20px", + "font-weight": "400", + "font-family": "Open Sans", + "font-style": "normal", + "font-size": "14px", + }, + cardcolor: { + border: "1px solid #E4E4E4", + "box-shadow": "none", + cursor: "pointer", + "min-height": "240px", + width: "350px", + "border-radius": "2px", + }, + togglecardcolor: { + "box-shadow": "0px 4px 20px rgba(216, 175, 40, 0.28)", + border: "1px solid #D8AF28", + cursor: "pointer", + "min-height": "240px", + width: "350px", + }, + marginrowtop: { "margin-top": "30px" }, + cardDataHeading: { + "font-family": "Open Sans", + "font-weight": "600", + "font-size": "14px", + color: "#3D4A52", + "text-align": "left", + "padding-left": "10px", + }, + cardData: { + "font-family": "Open Sans", + "font-weight": "400", + "font-size": "14px", + color: "#3D4A52", + "text-align": "left", + "margin-top": "10px", + "padding-left": "0px", + }, }; export default function ParticipantsCards(props) { const [isshowbutton, setisshowbutton] = React.useState(false); const history = useHistory(); - console.log('props in view details card ', props) return ( - - setisshowbutton(true)} onMouseLeave={()=>setisshowbutton(false)}> - -
- - : - {props.firstname.charAt(0)} - } - action={ - - + setisshowbutton(true)} + onMouseLeave={() => setisshowbutton(false)} + > + + > +
+ + ) : ( + + {props.firstname.charAt(0)} + + ) + } + action={} + title={props.mainheading} + subheader={props.subheading} + style={{ + "background-color": "#F4F4F4", + padding: "9px", + height: "84px", + "text-align": "left", + "font-family": "Open Sans", + "font-style": "normal", + "font-weight": 400, + "font-size": "14px", + "line-height": "19px", + color: "#3D4A52", + }} + />
-
+ - +
Dataset
- 9?props.dataset:"0"+props.dataset}> -
{props.dataset>9?props.dataset:"0"+props.dataset}
-
+ 9 ? props.dataset : "0" + props.dataset} + > +
+ {props.dataset > 9 ? props.dataset : "0" + props.dataset} +
+
- Connectors
- 9?props.connector:"0"+props.connector}> -
{props.connector>9?props.connector:"0"+props.connector}
-
+ Connectors +
+ 9 ? props.connector : "0" + props.connector + } + > +
+ {props.connector > 9 ? props.connector : "0" + props.connector} +
+
- Status
- -
{props.active}
-
- - + Status +
+ +
+ {props.active} +
+
{/* @@ -91,26 +200,50 @@ export default function ParticipantsCards(props) { */} - {isshowbutton? - - - - - - - :<>} + {isshowbutton ? ( + + + + + + + + + ) : ( + <> + )} ); -} \ No newline at end of file +} diff --git a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js index f2fd94e0e..1ff0c0347 100644 --- a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js +++ b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js @@ -1,22 +1,21 @@ import React, { useState, useEffect } from "react"; -import Navbar from "../../Components/Navbar/Navbar"; import ParticipantRegistrationForm from "./ParticipantRegistrationForm"; import Success from "../../Components/Success/Success"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; import Container from "react-bootstrap/Container"; import labels from "../../Constants/labels"; -// import Button from "@mui/material/Button"; import THEME_COLORS from "../../Constants/ColorConstants"; import HTTPService from "../../Services/HTTPService"; import UrlConstants from "../../Constants/UrlConstants"; import validator from "validator"; import { useHistory } from "react-router-dom"; import RegexConstants from "../../Constants/RegexConstants"; -import HandleSessionTimeout, { GetErrorHandlingRoute, GetErrorKey, mobileNumberMinimunLengthCheck, validateInputField } from "../../Utils/Common"; +import { GetErrorHandlingRoute, GetErrorKey, mobileNumberMinimunLengthCheck } from "../../Utils/Common"; import Loader from "../../Components/Loader/Loader"; import { Snackbar, Button, IconButton, Alert } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; + const useStyles = { btncolor: { color: "white", @@ -59,8 +58,13 @@ function AddParticipantsRegistrationform(props) { const[orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null) const [open, setOpen] = React.useState(false) const [messageForSnackBar, setMessageForSnackBar] = useState("") - const [messageForlogin, setMessageForLogin] = useState("") const [errorOrSuccess, setErrorOrSuccess] = useState("error") + const [selectCoSteward, setSelectCoSteward] = useState([]) + const [selectedCosteward, setSelectedCosteward] = useState([]) + + useEffect(() => { + getListOfCostewards() + }, []) const isValidURL = (string) => { var res = string.match(RegexConstants.NEW_WEBSITE_REGEX); @@ -94,7 +98,30 @@ function AddParticipantsRegistrationform(props) { ); - + const getListOfCostewards = () => { + setIsLoader(true); + HTTPService( + 'POST', + UrlConstants.base_url + UrlConstants.costewardlist_selfregister, + '', + false, + false, + ) + .then((response) => { + setIsLoader(false); + console.log(response) + setSelectCoSteward([...response.data]) + console.log("response of costewards", response.data); + }).catch((e) => { + setMessageForSnackBar("Get list of Co-Stewards failed!!!") + setIsLoader(false); + history.push(GetErrorHandlingRoute(e)); + }); +}; +const handlelistofCosteward = (e) => { + console.log(e.target.value) + setSelectedCosteward(e.target.value) +} const addNewParticipants = () => { setFirstNameErrorMessage(null) @@ -114,6 +141,8 @@ function AddParticipantsRegistrationform(props) { bodyFormData.append("name", organisationname); bodyFormData.append("phone_number", contactnumber); bodyFormData.append("website", websitelink); + bodyFormData.append("on_boarded_by", selectedCosteward) + bodyFormData.append( "address", JSON.stringify({ @@ -131,10 +160,10 @@ function AddParticipantsRegistrationform(props) { false ) .then((response) => { + console.log(response) setIsLoader(false); setisSuccess(true); setMessageForSnackBar("You are added as a Participant") - setMessageForLogin("Click OK to login as Participant") setErrorOrSuccess("success") handleClick() }) @@ -156,7 +185,7 @@ function AddParticipantsRegistrationform(props) { case "name": setOrgNameErrorMessage(errorMessages[i]); break; case "org_email": setOrgEmailErrorMessage(errorMessages[i]); break; case "website": setOrgWebsiteErrorMessage(errorMessages[i]); break; - default: history.push(GetErrorHandlingRoute(e)); break; + default: setMessageForSnackBar("Something went wrong"); break; } } } @@ -252,6 +281,11 @@ function AddParticipantsRegistrationform(props) { orgNameErrorMessage={orgNameErrorMessage} orgEmailErrorMessage={orgEmailErrorMessage} orgWebsiteErrorMessage={orgWebsiteErrorMessage} + selectCoSteward={selectCoSteward} + setSelectCoSteward={setSelectCoSteward} + getListOfCostewards={getListOfCostewards} + handlelistofCosteward={handlelistofCosteward} + selectedCosteward={selectedCosteward} > diff --git a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js index 47ef35d61..bedbb2563 100644 --- a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js +++ b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js @@ -4,19 +4,23 @@ import Col from 'react-bootstrap/Col' import THEME_COLORS from '../../Constants/ColorConstants' import labels from '../../Constants/labels'; import TextField from "@mui/material/TextField"; -import MenuItem from '@mui/material/MenuItem'; +import InputLabel from "@mui/material/InputLabel"; +import MenuItem from "@mui/material/MenuItem"; +import FormControl from "@mui/material/FormControl"; +import Select from "@mui/material/Select"; import countryList from "react-select-country-list"; import MuiPhoneNumber from "material-ui-phone-number"; -import { FormControlLabel } from '@mui/material'; -import Checkbox from "@mui/material/Checkbox"; import RegexConstants from '../../Constants/RegexConstants'; -import { handleAddressCharacters, handleNameFieldEntry, preventSpaceKey, validateInputField } from '../../Utils/Common'; -// import Select from 'react-select' +import { Stack } from '@mui/material'; +import Alert from "@mui/material/Alert"; +import { handleAddressCharacters, validateInputField } from '../../Utils/Common'; + const useStyles = { btncolor: {color: THEME_COLORS.THEME_COLOR, "border-color": THEME_COLORS.THEME_COLOR, "border-radius": 0}, marginrowtop: {"margin-top": "30px"}, marginrowtop50: {"margin-top": "50px"}, inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, + inputwidthcofield: {"margin-right" : "100px", width: "98%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, headingbold:{fontWeight: "bold"} }; @@ -37,7 +41,7 @@ export default function ParticipantRegistrationForm(props) { +
+ +
+ + {"Select Your Co-Steward"} + + + + + + + + If you do not select your Co-Steward, you will be the part of Steward network + + + + + + + + + {"Select Co-Steward"} + + + + + + ) } diff --git a/src/Components/signup/DataStandardization.js b/src/Components/signup/DataStandardization.js new file mode 100644 index 000000000..be46efd5d --- /dev/null +++ b/src/Components/signup/DataStandardization.js @@ -0,0 +1,337 @@ +import { TextField } from "@material-ui/core"; +import React, { useState } from "react"; +import "./dataStandardization.css"; +import AddIcon from "@mui/icons-material/Add"; +import ClearIcon from "@mui/icons-material/Clear"; +import { Button } from "@mui/material"; +import { Col, Row } from "react-bootstrap"; +import labels from "../../Constants/labels"; + +const DataStandardization = () => { + const [tableRow, setTableRow] = useState([1]); + const [dataPointCategoryNames, setDataPointCategoryNames] = useState([]); + const [columnNames, setColumnNames] = useState({}); + + // Funcitons + + const hanldeTableAdd = () => { + console.log("hanldeTableAdd click"); + console.log("columnNames in add table", columnNames); + let newTableRow = [...tableRow]; + newTableRow.push(1); + setTableRow(newTableRow); + console.log("tableRow", tableRow, newTableRow); + }; + + const handleTableDelete = (index) => { + let newTableRow = [...tableRow]; + newTableRow.splice(index, 1); + setTableRow(newTableRow); + let tmpDataPointCategoryNames = [...dataPointCategoryNames]; + tmpDataPointCategoryNames.splice(index, 1); + setDataPointCategoryNames(tmpDataPointCategoryNames); + let tmpColumnNames = { ...columnNames }; + tmpColumnNames[index] = [{}]; + setColumnNames(tmpColumnNames); + console.log("tableRow", tableRow, newTableRow); + }; + + const handleTableRowAdd = (index) => { + console.log("hanldeTable row Add click"); + let newTableRow = [...tableRow]; + newTableRow[index] = newTableRow[index] + 1; + setTableRow(newTableRow); + console.log("tableRow in handleTableRowAdd", tableRow, newTableRow); + }; + + const handleTableRowDelete = (index, keyIndex) => { + console.log("index to row", index, keyIndex); + let tmpColumnNames = columnNames; + if (tmpColumnNames[index]?.[keyIndex]) tmpColumnNames[index][keyIndex] = {}; + setColumnNames(tmpColumnNames); + let newTableRow = [...tableRow]; + newTableRow[index] = newTableRow[index] - 1; + setTableRow(newTableRow); + console.log("tableRow", tableRow, tmpColumnNames); + }; + + const handleDataPointCategoryNames = (value, index) => { + let tmpDataPointName = [...dataPointCategoryNames]; + console.log( + "tmpDataPointName[index] in handleDataPointCategoryNames", + tmpDataPointName[index] + ); + tmpDataPointName[index] = value; + console.log( + "tmpDataPointName[index] in handleDataPointCategoryNames", + tmpDataPointName[index] + ); + + // let tmpColumnNames = {} + // tmpDataPointName.forEach((item, index)=>{ + // console.log(item) + // tmpColumnNames[item] = [{}] + // }) + // setColumnNames(tmpColumnNames) + setDataPointCategoryNames(tmpDataPointName); + // setColumnNames({...columnNames}) + console.log("columnNames", columnNames); + console.log("dataPointCategoryNames", dataPointCategoryNames); + }; + + const handleColumnName = (value, tableKeyName, index) => { + console.log("handleColumnName called"); + + let newTmpColumnNames = { ...columnNames }; + dataPointCategoryNames.forEach((item, index) => { + console.log(item); + if (!newTmpColumnNames[index]) newTmpColumnNames[index] = [{}]; + }); + setColumnNames(newTmpColumnNames); + + let tmpColumnNames = newTmpColumnNames; + console.log( + "tmpColumnNames[tableKeyName]", + tmpColumnNames[tableKeyName], + tmpColumnNames, + tableKeyName + ); + if (!tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index]) + tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)].push({}); + + // console.log('tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)]',tmpColumnNames,dataPointCategoryNames.indexOf(tableKeyName),tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)],tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index]['columnName']) + + tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index][ + "columnName" + ] + ? (tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index][ + "columnName" + ] = value) + : (tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index] = { + ...tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][ + index + ], + columnName: value, + }); + setColumnNames(tmpColumnNames); + console.log( + "tmpColumnNames", + tmpColumnNames, + newTmpColumnNames, + columnNames + ); + }; + + const handleColumnDescription = (value, tableKeyName, index) => { + console.log("handleColumnDescription called"); + + let tmpColumnNames = { ...columnNames }; + console.log( + "tmpColumnNames[tableKeyName]", + tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)], + tmpColumnNames, + tableKeyName + ); + + if (!tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index]) + tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)].push({}); + + tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index][ + "columnDescription" + ] + ? (tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index][ + "columnDescription" + ] = value) + : (tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][index] = { + ...tmpColumnNames[dataPointCategoryNames.indexOf(tableKeyName)][ + index + ], + columnDescription: value, + }); + setColumnNames(tmpColumnNames); + console.log("tmpColumnNames", tmpColumnNames, columnNames); + }; + + const handleSubmit = () => { + console.log("submit click"); + }; + + const handleClear = () => { + setTableRow([1]); + setDataPointCategoryNames([]); + setColumnNames({}); + }; + + console.log( + "component re rendring", + columnNames, + columnNames[0]?.[0]?.columnName + ); + + return ( + <> +
+
+

Data Standardization

+
+
+ {tableRow.map((row, index) => { + console.log("row no in map", row, index); + + let tmpRowArray = new Array(row); + tmpRowArray.fill(1); + + return ( + <> +
+ + handleDataPointCategoryNames(e.target.value, index) + } + style={{ width: "850px" }} + // className="profilelastname" + // onChange={props.handleprofilelastname} + //inputRef={props.profilelastname} + // error={ + // props.ispropfilelastnameerror || props.lastNameErrorMessage + // } + // helperText={ + // props.ispropfilelastnameerror + // ? "Enter Valid last name" + // : props.lastNameErrorMessage + // } + // value={props.profilelastname} + /> + {index === 0 ? ( + + + + ) : ( + handleTableDelete(index)}> + + + )} + {tmpRowArray.map((childRow, keyIndex) => { + return ( + <> +
+ + handleColumnName( + e.target.value, + dataPointCategoryNames[index], + keyIndex + ) + } + id={`data_standardization_table_row${keyIndex}`} + className="data_standardization_table_row_class_name" + label="Column/Key Name" + variant="outlined" + style={{ width: "300px" }} + // className="profilelastname" + // onChange={props.handleprofilelastname} + //inputRef={props.profilelastname} + // error={ + // props.ispropfilelastnameerror || props.lastNameErrorMessage + // } + // helperText={ + // props.ispropfilelastnameerror + // ? "Enter Valid last name" + // : props.lastNameErrorMessage + // } + // value={props.profilelastname} + /> + + handleColumnDescription( + e.target.value, + dataPointCategoryNames[index], + keyIndex + ) + } + id={`data_standardization_table_row_description${keyIndex}`} + className="data_standardization_table_row_description_class_name" + label="Column/Key Description" + variant="outlined" + style={{ width: "500px" }} + // className="profilelastname" + // onChange={props.handleprofilelastname} + //inputRef={props.profilelastname} + // error={ + // props.ispropfilelastnameerror || props.lastNameErrorMessage + // } + // helperText={ + // props.ispropfilelastnameerror + // ? "Enter Valid last name" + // : props.lastNameErrorMessage + // } + // value={props.profilelastname} + /> + {keyIndex === 0 ? ( + handleTableRowAdd(index)}> + + + ) : ( + + handleTableRowDelete(index, keyIndex) + } + > + + + )} +
+ + ); + })} +
+ + ); + })} +
+ +
+ + + + + + + + + ); +}; + +export default DataStandardization; diff --git a/src/Components/signup/OrgRightside.js b/src/Components/signup/OrgRightside.js index 340ab3d70..1897dedf5 100644 --- a/src/Components/signup/OrgRightside.js +++ b/src/Components/signup/OrgRightside.js @@ -71,7 +71,7 @@ export default function OrgRightside(props) { HTTPService( "GET", UrlConstant.base_url + - ((isLoggedInUserParticipant() || isLoggedInUserCoSteward()) + (isLoggedInUserParticipant() || isLoggedInUserCoSteward() ? UrlConstant.participant : UrlConstant.org) + id + @@ -89,10 +89,25 @@ export default function OrgRightside(props) { props.setOrgName(response?.data?.organization?.name); props.setOrgMail(response?.data?.organization?.org_email); props.setOrgWebsite(response?.data?.organization?.website); - props.setOrgAddress(response?.data?.organization?.address?.address || JSON.parse(response?.data?.organization?.address)?.address); - props.setCountryValue(response?.data?.organization?.address?.country || JSON.parse(response?.data?.organization?.address)?.country) + props.setOrgAddress( + response?.data?.organization?.address?.address || + JSON.parse(response?.data?.organization?.address)?.address + ); + props.setCountryValue( + response?.data?.organization?.address?.country || + JSON.parse(response?.data?.organization?.address)?.country + ); + if ( + response?.data?.organization?.address?.country || + JSON.parse(response?.data?.organization?.address)?.country + ) { + props.setOrgcountrybtn(true); + } props.setValidOrgnumber(response?.data?.user?.phone_number); - props.setOrgPincode(response?.data?.organization?.address?.pincode || JSON.parse(response?.data?.organization?.address)?.pincode) + props.setOrgPincode( + response?.data?.organization?.address?.pincode || + JSON.parse(response?.data?.organization?.address)?.pincode + ); if ( response?.data?.organization?.name && @@ -113,7 +128,7 @@ export default function OrgRightside(props) { response?.data?.organization?.website && response?.data?.organization?.website.trim().length > 0 ) { - props.isOrgWebsiteerror(false); + props.setisOrgWebsiteerror(false); } if (response.data.organization.address) { @@ -805,7 +820,7 @@ export default function OrgRightside(props) { Next */} {props.orgName && - props.validOrgNumber.length > 8 && + props.validOrgNumber?.length == 15 && !props.isOrgnameerror && props.Orgemailbtn && !props.isOrgmailerror && @@ -814,11 +829,11 @@ export default function OrgRightside(props) { props.orgCity && !props.isOrgcityerror && props.Orgcountrybtn && - props.orgPincode.length >= 5 && + props.orgPincode?.length >= 5 && !props.ispincodeerror && Orgdesbtn && props.orgfile != null && - props.orgfile.size < 2097152 ? ( + props.orgfile?.size < 2097152 ? ( @@ -195,50 +196,57 @@ export default function DataSetFilter(props) { )} - - {props.showMemberFilters && ( - - - new -   {screenlabels.dataset.status} - - - )} - {props.showMemberFilters && - props.statusFilter && - props.statusFilter.map((status) => ( - - props.handleFilterChange( - status.index, - screenlabels.dataset.status - ) - } - /> - ))} - {props.showMemberFilters && ( - - - new -   {screenlabels.dataset.datasets} - - + {getRoleLocal() !== "datahub_co_steward" && ( + <> + {props.showMemberFilters && ( + + + new +   {screenlabels.dataset.status} + + + )} + {props.showMemberFilters && + props.statusFilter && + props.statusFilter.map((status) => ( + + props.handleFilterChange( + status.index, + screenlabels.dataset.status + ) + } + /> + ))} + {props.showMemberFilters && ( + + + new +   {screenlabels.dataset.datasets} + + + )} + {props.showMemberFilters && + props.enableStatusFilter.map((filter) => ( + + props.handleFilterChange( + filter.index, + screenlabels.dataset.enabled + ) + } + /> + ))} + )} - {props.showMemberFilters && - props.enableStatusFilter.map((filter) => ( - - props.handleFilterChange( - filter.index, - screenlabels.dataset.enabled - ) - } - /> - ))} + {/* new @@ -294,7 +302,7 @@ export default function DataSetFilter(props) { /> {props.categoryFilterValue.length && - props.subcategoryFilterValue.length ? ( + props.subcategoryFilterValue.length ? ( - - - - - setTab(1)} label="Co-Steward" value="1" /> - setTab(2)} label="Participant" value="2" /> - - - + style={useStyles.background} + > + {isLoader ? : ""} + {!isLoggedInUserCoSteward() ? ( + <> + + + + + + setTab(1)} + label="Co-Steward" + value="1" + /> + setTab(2)} + label="Participant" + value="2" + /> + + + {/* */} - - - - history.push("/datahub/participants/addcosteward") - }> - - {coStewardList.map((rowData, index) => ( - - - - ))} - - - - {isCoStewardShowLoadMoreButton ? ( - - - - ) : ( - <> - )} - - - - - - - - - - - history.push("/datahub/participants/add") - }> - - {participantList.map((rowData, index) => ( + - + + addevent={() => + history.push("/datahub/participants/addcosteward") + } + > - ))} - - - - {isShowLoadMoreButton ? ( - - + {coStewardList.map((rowData, index) => ( + + + + ))} + + + + {isCoStewardShowLoadMoreButton ? ( + + + + ) : ( + <> + )} + + + + + + + + + + history.push("/datahub/participants/add") + } + > - ) : ( - <> - )} - - - - - - : <> -
- -
- + {participantList.map((rowData, index) => ( + + + + ))} + + + + {isShowLoadMoreButton ? ( + + + + ) : ( + <> + )} + + + - - - - history.push("/datahub/participants/add") - }> - - {participantListCoSteward.map((rowData, index) => ( + + ) : ( + <> +
+ +
+ + + + - + style={useStyles.marginrowtop10px} + > + history.push("/datahub/participants/add")} + > - ))} - - - - {isShowLoadMoreButton ? ( - - - - ) : ( - <> - )} - - - - - - } - + {participantListCoSteward.map((rowData, index) => ( + + + + ))} + + + + {isShowLoadMoreButton ? ( + + + + ) : ( + <> + )} + + + + )} - ) - } + ); +} diff --git a/src/Views/Participants/AddParticipants.js b/src/Views/Participants/AddParticipants.js index c0bb34681..d84774428 100644 --- a/src/Views/Participants/AddParticipants.js +++ b/src/Views/Participants/AddParticipants.js @@ -13,7 +13,14 @@ import UrlConstants from "../../Constants/UrlConstants"; import validator from "validator"; import { useHistory } from "react-router-dom"; import RegexConstants from "../../Constants/RegexConstants"; -import HandleSessionTimeout, { GetErrorHandlingRoute, GetErrorKey, isLoggedInUserCoSteward, mobileNumberMinimunLengthCheck, validateInputField, getUserLocal } from "../../Utils/Common"; +import { + GetErrorHandlingRoute, + GetErrorKey, + isLoggedInUserCoSteward, + mobileNumberMinimunLengthCheck, + getUserLocal, + stringMinimumLengthCheck, +} from "../../Utils/Common"; import Loader from "../../Components/Loader/Loader"; const useStyles = { btncolor: { @@ -51,15 +58,14 @@ function AddParticipants(props) { const [isSuccess, setisSuccess] = useState(false); const [isLoader, setIsLoader] = useState(false); - const[firstNameErrorMessage, setFirstNameErrorMessage] = useState(null) - const[lastNameErrorMessage,setLastNameErrorMessage] = useState(null) - const[emailErrorMessage, setEmailErrorMessage] = useState(null) - const[phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null) - const[orgNameErrorMessage, setOrgNameErrorMessage] = useState(null) - const[orgEmailErrorMessage,setOrgEmailErrorMessage] = useState(null) - const[orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null) + const [firstNameErrorMessage, setFirstNameErrorMessage] = useState(null); + const [lastNameErrorMessage, setLastNameErrorMessage] = useState(null); + const [emailErrorMessage, setEmailErrorMessage] = useState(null); + const [phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null); + const [orgNameErrorMessage, setOrgNameErrorMessage] = useState(null); + const [orgEmailErrorMessage, setOrgEmailErrorMessage] = useState(null); + const [orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null); // const[orgSubscriptionErrorMessage, setOrgSubscriptionErrorMessage] = useState(null) - const isValidURL = (string) => { var res = string.match(RegexConstants.NEW_WEBSITE_REGEX); @@ -68,18 +74,17 @@ function AddParticipants(props) { const isValidCapsUrl = (string) => { var res1 = string.match(RegexConstants.NEW_C_WEBSITE_REGEX); return res1 !== null; - } + }; const addNewParticipants = () => { - - setFirstNameErrorMessage(null) - setLastNameErrorMessage(null) - setEmailErrorMessage(null) - setPhoneNumberErrorMessage(null) - setOrgNameErrorMessage(null) - setOrgEmailErrorMessage(null) - setOrgWebsiteErrorMessage(null) + setFirstNameErrorMessage(null); + setLastNameErrorMessage(null); + setEmailErrorMessage(null); + setPhoneNumberErrorMessage(null); + setOrgNameErrorMessage(null); + setOrgEmailErrorMessage(null); + setOrgWebsiteErrorMessage(null); // setOrgSubscriptionErrorMessage(null) - setisorganisationemailerror(null) + setisorganisationemailerror(null); var id = getUserLocal(); var bodyFormData = new FormData(); bodyFormData.append("email", useremail.toLowerCase()); @@ -100,8 +105,8 @@ function AddParticipants(props) { //bodyFormData.append("approval_status", istrusted) // bodyFormData.append("subscription", organisationlength); bodyFormData.append("role", 3); - if(isLoggedInUserCoSteward()){ - bodyFormData.append("on_boarded_by", id) + if (isLoggedInUserCoSteward()) { + bodyFormData.append("on_boarded_by", id); } setIsLoader(true); HTTPService( @@ -114,31 +119,46 @@ function AddParticipants(props) { .then((response) => { setIsLoader(false); setisSuccess(true); - console.log(response) + console.log(response); }) .catch((e) => { setIsLoader(false); console.log(e); - var returnValues = GetErrorKey(e, bodyFormData.keys()) - var errorKeys = returnValues[0] - var errorMessages = returnValues[1] - if (errorKeys.length > 0){ - for (var i=0; i 0) { + for (var i = 0; i < errorKeys.length; i++) { + switch (errorKeys[i]) { + case "first_name": + setFirstNameErrorMessage(errorMessages[i]); + break; + case "last_name": + setLastNameErrorMessage(errorMessages[i]); + break; + case "email": + setEmailErrorMessage(errorMessages[i]); + break; + case "phone_number": + setPhoneNumberErrorMessage(errorMessages[i]); + break; + case "name": + setOrgNameErrorMessage(errorMessages[i]); + break; + case "org_email": + setOrgEmailErrorMessage(errorMessages[i]); + break; + case "website": + setOrgWebsiteErrorMessage(errorMessages[i]); + break; // case "subscription": setOrgSubscriptionErrorMessage(errorMessages[i]); break; - default: history.push(GetErrorHandlingRoute(e)); break; + default: + history.push(GetErrorHandlingRoute(e)); + break; } } - } - else{ - history.push(GetErrorHandlingRoute(e)) + } else { + history.push(GetErrorHandlingRoute(e)); } //setisexisitinguseremail(true); //history.push(GetErrorHandlingRoute(e)); @@ -147,7 +167,7 @@ function AddParticipants(props) { const handleistrusted = (event) => { console.log(event.target.checked); - setistrusted(event.target.checked) + setistrusted(event.target.checked); }; return ( <> @@ -161,7 +181,8 @@ function AddParticipants(props) { btntext={"ok"} heading={"Participant added successfully !"} imageText={"Added"} - msg={"You added a participant."}> + msg={"You added a participant."} + > ) : ( <> { + setlastname={(ref) => { setlastname(ref); }} useremail={useremail} @@ -225,9 +246,7 @@ function AddParticipants(props) { // }} first_heading={screenlabels.addparticipants.first_heading} second_heading={screenlabels.addparticipants.second_heading} - third_heading={ - screenlabels.addparticipants.third_heading - } + third_heading={screenlabels.addparticipants.third_heading} fourth_heading={screenlabels.addparticipants.fourth_heading} firstNameErrorMessage={firstNameErrorMessage} lastNameErrorMessage={lastNameErrorMessage} @@ -237,7 +256,7 @@ function AddParticipants(props) { orgEmailErrorMessage={orgEmailErrorMessage} orgWebsiteErrorMessage={orgWebsiteErrorMessage} // orgSubscriptionErrorMessage={orgSubscriptionErrorMessage} - > + > @@ -245,27 +264,28 @@ function AddParticipants(props) { orginsationemail && !isorganisationemailerror && countryvalue && - mobileNumberMinimunLengthCheck(contactnumber) && + mobileNumberMinimunLengthCheck(contactnumber) && websitelink && !iswebsitelinkrerror && organisationaddress && - pincode && + stringMinimumLengthCheck(pincode, 5) && firstname && useremail && - !isuseremailerror ? - // organisationlength ? - ( + !isuseremailerror ? ( + // organisationlength ? ) : ( )} @@ -277,7 +297,8 @@ function AddParticipants(props) { diff --git a/src/Views/Participants/EditParticipants.js b/src/Views/Participants/EditParticipants.js index d744a9589..64225b30e 100644 --- a/src/Views/Participants/EditParticipants.js +++ b/src/Views/Participants/EditParticipants.js @@ -1,57 +1,77 @@ -import React, { useState, useEffect } from 'react'; -import ParticipantForm from '../../Components/Participants/ParticipantForm' -import Success from '../../Components/Success/Success' -import Row from 'react-bootstrap/Row' -import Col from 'react-bootstrap/Col' -import Container from 'react-bootstrap/Container'; -import labels from '../../Constants/labels'; +import React, { useState, useEffect } from "react"; +import ParticipantForm from "../../Components/Participants/ParticipantForm"; +import Success from "../../Components/Success/Success"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Container from "react-bootstrap/Container"; +import labels from "../../Constants/labels"; import Button from "@mui/material/Button"; -import THEME_COLORS from '../../Constants/ColorConstants' -import HTTPService from '../../Services/HTTPService' -import UrlConstants from '../../Constants/UrlConstants' +import THEME_COLORS from "../../Constants/ColorConstants"; +import HTTPService from "../../Services/HTTPService"; +import UrlConstants from "../../Constants/UrlConstants"; import validator from "validator"; -import { useParams } from 'react-router-dom'; +import { useParams } from "react-router-dom"; import { useHistory } from "react-router-dom"; -import Loader from '../../Components/Loader/Loader'; -import {GetErrorHandlingRoute, GetErrorKey} from '../../Utils/Common'; +import Loader from "../../Components/Loader/Loader"; +import { + GetErrorHandlingRoute, + GetErrorKey, + stringMinimumLengthCheck, +} from "../../Utils/Common"; const useStyles = { - btncolor: { color: "white", "border-color": THEME_COLORS.THEME_COLOR, "background-color": THEME_COLORS.THEME_COLOR, float: "right", "border-radius": 0 }, - marginrowtop: { "margin-top": "20px" }, - btn: { width: "420px", height: "42px", "margin-top": "30px", background: "#ffffff", opacity: "0.5", border: "2px solid #c09507", color: "black" }, - submitbtn: { width: "420px", height: "42px", "margin-top": "30px" }, - marginrowtop8px: { "margin-top": "8px" }, + btncolor: { + color: "white", + "border-color": THEME_COLORS.THEME_COLOR, + "background-color": THEME_COLORS.THEME_COLOR, + float: "right", + "border-radius": 0, + }, + marginrowtop: { "margin-top": "20px" }, + btn: { + width: "420px", + height: "42px", + "margin-top": "30px", + background: "#ffffff", + opacity: "0.5", + border: "2px solid #c09507", + color: "black", + }, + submitbtn: { width: "420px", height: "42px", "margin-top": "30px" }, + marginrowtop8px: { "margin-top": "8px" }, }; function EditParticipants(props) { - const [screenlabels, setscreenlabels] = useState(labels['en']); - const [organisationname, setorganisationname] = useState(""); - const [organisationaddress, setorganisationaddress] = useState(""); - const [orginsationemail, setorginsationemail] = useState(""); - const [countryvalue, setcountryvalue] = useState(""); - const [contactnumber, setcontactnumber] = useState(""); - const [websitelink, setwebsitelink] = useState(""); - const [pincode, setpincode] = useState(""); - const [firstname, setfirstname] = useState(""); - const [lastname, setlastname] = useState(""); - const [useremail, setuseremail] = useState(""); - const [idorg, setidorg] = useState(""); - // const [organisationlength, setorganisationlength] = useState(3); - const [isorganisationemailerror, setisorganisationemailerror] = useState(false); - const [iscontactnumbererror, setiscontactnumbererror] = useState(false); - const [iswebsitelinkrerror, setwebsitelinkerror] = useState(false); - const [isuseremailerror, setisuseremailerror] = useState(false); - const [isexisitinguseremail, setisexisitinguseremail] = useState(false) - const [isSuccess, setisSuccess] = useState(false); - const[isLoader, setIsLoader] = useState(false) - const [istrusted, setistrusted] = React.useState(false); + const [screenlabels, setscreenlabels] = useState(labels["en"]); + const [organisationname, setorganisationname] = useState(""); + const [organisationaddress, setorganisationaddress] = useState(""); + const [orginsationemail, setorginsationemail] = useState(""); + const [countryvalue, setcountryvalue] = useState(""); + const [contactnumber, setcontactnumber] = useState(""); + const [websitelink, setwebsitelink] = useState(""); + const [pincode, setpincode] = useState(""); + const [firstname, setfirstname] = useState(""); + const [lastname, setlastname] = useState(""); + const [useremail, setuseremail] = useState(""); + const [idorg, setidorg] = useState(""); + // const [organisationlength, setorganisationlength] = useState(3); + const [isorganisationemailerror, setisorganisationemailerror] = + useState(false); + const [iscontactnumbererror, setiscontactnumbererror] = useState(false); + const [iswebsitelinkrerror, setwebsitelinkerror] = useState(false); + const [isuseremailerror, setisuseremailerror] = useState(false); + const [isexisitinguseremail, setisexisitinguseremail] = useState(false); + const [isSuccess, setisSuccess] = useState(false); + const [isLoader, setIsLoader] = useState(false); + const [istrusted, setistrusted] = React.useState(false); + + const [firstNameErrorMessage, setFirstNameErrorMessage] = useState(null); + const [lastNameErrorMessage, setLastNameErrorMessage] = useState(null); + const [emailErrorMessage, setEmailErrorMessage] = useState(null); + const [phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null); + const [orgNameErrorMessage, setOrgNameErrorMessage] = useState(null); + const [orgEmailErrorMessage, setOrgEmailErrorMessage] = useState(null); + const [orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null); + // const[orgSubscriptionErrorMessage, setOrgSubscriptionErrorMessage] = useState(null) - const[firstNameErrorMessage, setFirstNameErrorMessage] = useState(null) - const[lastNameErrorMessage,setLastNameErrorMessage] = useState(null) - const[emailErrorMessage, setEmailErrorMessage] = useState(null) - const[phoneNumberErrorMessage, setPhoneNumberErrorMessage] = useState(null) - const[orgNameErrorMessage, setOrgNameErrorMessage] = useState(null) - const[orgEmailErrorMessage,setOrgEmailErrorMessage] = useState(null) - const[orgWebsiteErrorMessage, setOrgWebsiteErrorMessage] = useState(null) - // const[orgSubscriptionErrorMessage, setOrgSubscriptionErrorMessage] = useState(null) const history = useHistory(); const { id } = useParams() @@ -119,6 +139,7 @@ function EditParticipants(props) { console.log("otp valid", response.data); setisSuccess(true) }).catch((e) => { + setIsLoader(false); var returnValues = GetErrorKey(e, bodyFormData.keys()) var errorKeys = returnValues[0] var errorMessages = returnValues[1] @@ -147,6 +168,7 @@ function EditParticipants(props) { setistrusted(event.target.checked) }; +<<<<<<< HEAD return ( <> {isLoader ? : ''} @@ -189,6 +211,141 @@ function EditParticipants(props) { orgEmailErrorMessage={orgEmailErrorMessage} orgWebsiteErrorMessage={orgWebsiteErrorMessage} // orgSubscriptionErrorMessage={orgSubscriptionErrorMessage} +======= + return ( + <> + {isLoader ? : ""} + + {isSuccess ? ( + + history.push( + "/datahub/participants" + + `?costeward=${props.coSteward == true}` + ) + } + route={"datahub/participants"} + imagename={"success"} + btntext={"ok"} + heading={"Changes are updated!"} + imageText={"Updated"} + msg={"Your changes are updated successfully."} + > + ) : ( + <> + { + setorganisationname(ref); + }} + orginsationemail={orginsationemail} + handleistrusted={handleistrusted} + isorganisationemailerror={isorganisationemailerror} + setorginsationemail={(ref) => { + setorginsationemail(ref); + setisorganisationemailerror(!validator.isEmail(ref)); + }} + countryvalue={countryvalue} + setcountryvalue={(ref) => { + setcountryvalue(ref); + }} + contactnumber={contactnumber} + setcontactnumber={(ref) => { + setcontactnumber(ref); + console.log("sss", ref); + }} + iscontactnumbererror={iscontactnumbererror} + websitelink={websitelink} + setwebsitelink={(ref) => { + setwebsitelink(ref); + setwebsitelinkerror(!isValidURL(ref)); + }} + iswebsitelinkrerror={iswebsitelinkrerror} + organisationaddress={organisationaddress} + istrusted={istrusted} + setorganisationaddress={(ref) => { + setorganisationaddress(ref); + }} + pincode={pincode} + setpincode={(ref) => { + setpincode(ref); + }} + firstname={firstname} + setfirstname={(ref) => { + setfirstname(ref); + }} + lastname={lastname} + setlastname={(ref) => { + setlastname(ref); + }} + useremail={useremail} + setuseremail={(ref) => { + setuseremail(ref); + setisuseremailerror(!validator.isEmail(ref)); + setisexisitinguseremail(false); + }} + isuseremailerror={isuseremailerror} + isexisitinguseremail={isexisitinguseremail} + // organisationlength={organisationlength} + // setorganisationlength={ref => { setorganisationlength(ref) }} + first_heading={ + props.coSteward + ? screenlabels.editcosteward.first_heading + : screenlabels.editparticipants.first_heading + } + second_heading={ + props.coSteward + ? screenlabels.editcosteward.second_heading + : screenlabels.editparticipants.second_heading + } + // third_heading={screenlabels.editparticipants.third_heading} + fourth_heading={screenlabels.editparticipants.fourth_heading} + orgNameErrorMessage={orgNameErrorMessage} + orgEmailErrorMessage={orgEmailErrorMessage} + orgWebsiteErrorMessage={orgWebsiteErrorMessage} + // orgSubscriptionErrorMessage={orgSubscriptionErrorMessage} + > + + + + {organisationname && + orginsationemail && + !isorganisationemailerror && + countryvalue && + contactnumber.length == 15 && + websitelink && + !iswebsitelinkrerror && + organisationaddress && + stringMinimumLengthCheck(pincode, 5) && + firstname && + useremail && + !isuseremailerror ? ( + + ) : ( + + )} + + + + + + Organization description* @@ -760,7 +763,8 @@ export default function ParticipantOrganisationSetting(props) {
+ style={{ display: "flex", flexDirection: "column" }} + > + }} + > {orgDescriptionErrorMessage ? orgDescriptionErrorMessage : ""}
@@ -855,16 +860,16 @@ export default function ParticipantOrganisationSetting(props) { address && email && city && - pincode && - (phonenumber.length >= 9) && - // orgfile.size < 2097152 && + stringMinimumLengthCheck(pincode, 5) && + phonenumber.length >= 9 && editorValue.getEditorState().getCurrentContent().hasText() && countryvalue !== "" ? ( ) : ( @@ -881,7 +886,8 @@ export default function ParticipantOrganisationSetting(props) { variant="outlined" className="cancelbtn" type="button" - onClick={orgsettingcancelbtn}> + onClick={orgsettingcancelbtn} + > Cancel From 409b864545fdd048ccdb07341e9eef0b7e1d4449 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 2 Mar 2023 16:24:54 +0530 Subject: [PATCH 09/73] implementing standardization --- src/Views/Participants/EditParticipants.js | 70 +--------------------- 1 file changed, 2 insertions(+), 68 deletions(-) diff --git a/src/Views/Participants/EditParticipants.js b/src/Views/Participants/EditParticipants.js index 64225b30e..9d76e86e2 100644 --- a/src/Views/Participants/EditParticipants.js +++ b/src/Views/Participants/EditParticipants.js @@ -168,50 +168,6 @@ function EditParticipants(props) { setistrusted(event.target.checked) }; -<<<<<<< HEAD - return ( - <> - {isLoader ? : ''} - - {isSuccess ? history.push('/datahub/participants')} route={"datahub/participants"} imagename={'success'} btntext={"ok"} heading={"Changes are updated!"} imageText={"Updated"} msg={"Your changes are updated successfully."}> : <> { setorganisationname(ref) }} - orginsationemail={orginsationemail} - handleistrusted={handleistrusted} - isorganisationemailerror={isorganisationemailerror} - setorginsationemail={ref => { setorginsationemail(ref); setisorganisationemailerror(!validator.isEmail(ref)) }} - countryvalue={countryvalue} - setcountryvalue={ref => { setcountryvalue(ref) }} - contactnumber={contactnumber} - setcontactnumber={ref => { setcontactnumber(ref); console.log("sss", ref) }} - iscontactnumbererror={iscontactnumbererror} - websitelink={websitelink} - setwebsitelink={ref => { setwebsitelink(ref); setwebsitelinkerror(!isValidURL(ref)) }} - iswebsitelinkrerror={iswebsitelinkrerror} - organisationaddress={organisationaddress} - istrusted={istrusted} - setorganisationaddress={ref => { setorganisationaddress(ref) }} - pincode={pincode} - setpincode={ref => { setpincode(ref) }} - firstname={firstname} - setfirstname={ref => { setfirstname(ref) }} - lastname={lastname} - setlastname={ref => { setlastname(ref) }} - useremail={useremail} - setuseremail={ref => { setuseremail(ref); setisuseremailerror(!validator.isEmail(ref)); setisexisitinguseremail(false)}} - isuseremailerror={isuseremailerror} - isexisitinguseremail={isexisitinguseremail} - // organisationlength={organisationlength} - // setorganisationlength={ref => { setorganisationlength(ref) }} - first_heading={props.coSteward ? screenlabels.editcosteward.first_heading : screenlabels.editparticipants.first_heading} - second_heading={props.coSteward ? screenlabels.editcosteward.second_heading : screenlabels.editparticipants.second_heading} - // third_heading={screenlabels.editparticipants.third_heading} - fourth_heading={screenlabels.editparticipants.fourth_heading} - orgNameErrorMessage={orgNameErrorMessage} - orgEmailErrorMessage={orgEmailErrorMessage} - orgWebsiteErrorMessage={orgWebsiteErrorMessage} - // orgSubscriptionErrorMessage={orgSubscriptionErrorMessage} -======= return ( <> {isLoader ? : ""} @@ -345,35 +301,13 @@ function EditParticipants(props) { onClick={() => history.push("/datahub/participants")} variant="outlined" className="cancelbtn" ->>>>>>> 8ed1c28fb991a6ab454bc81056cad46d79fe6b73 > - - - - - - {(organisationname && orginsationemail && !isorganisationemailerror && countryvalue && contactnumber.length==15 && websitelink && !iswebsitelinkrerror && organisationaddress && pincode && firstname && useremail && !isuseremailerror) - ? ( - - ) : ( - - )} - - - - - - - - } + + )} From e41620969c51db265f83a3b8fe82866828b55f79 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 2 Mar 2023 16:27:08 +0530 Subject: [PATCH 10/73] fixed bug FSPROD-1306 --- src/Components/AdminDatasetConnection/LiveApiConnection.jsx | 2 ++ .../AdminDatasetConnection/LocalMachineUploadDataset.css | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/Components/AdminDatasetConnection/LiveApiConnection.jsx b/src/Components/AdminDatasetConnection/LiveApiConnection.jsx index 4329a805b..6e037d03d 100644 --- a/src/Components/AdminDatasetConnection/LiveApiConnection.jsx +++ b/src/Components/AdminDatasetConnection/LiveApiConnection.jsx @@ -105,6 +105,8 @@ export default function LiveApiConnection(props) { <> {loader ? : ""} div :nth-child(2){ + max-width: 1300px !important; + overflow: scroll !important; + height: 35px !important; } \ No newline at end of file From 4ffb34d5071523b968130571a0a82a5555e1cc21 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Thu, 2 Mar 2023 16:34:22 +0530 Subject: [PATCH 11/73] 1317 --- src/Components/Navbar/GuestUserNavbar.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Components/Navbar/GuestUserNavbar.js b/src/Components/Navbar/GuestUserNavbar.js index d3f20000f..1ae4753ff 100644 --- a/src/Components/Navbar/GuestUserNavbar.js +++ b/src/Components/Navbar/GuestUserNavbar.js @@ -12,10 +12,11 @@ import Farmstack from "../../Assets/Img/farmstack.jpg"; import Toolbar from "@mui/material/Toolbar"; const GuestUserNavBar = (props) => { + console.log("navguest") const [screenlabels, setscreenlabels] = useState(labels["en"]); const [isLoader, setIsLoader] = useState(false); const [phoneNumber, setPhoneNumber] = useState(null); - const [adminNotOnboarded, setAdminNotOnboarded] = useState(false); + const [isadminOnboarded, setIsadminOnboarded] = useState(false); useEffect(() => { HTTPService( @@ -26,6 +27,7 @@ const GuestUserNavBar = (props) => { false ) .then((response) => { + console.log(response) setIsLoader(false); if ( response.data.organization && @@ -33,8 +35,9 @@ const GuestUserNavBar = (props) => { ) { setPhoneNumber(response.data.organization.phone_number); } - if(response.data.organization == null) { - setAdminNotOnboarded(true) + if(response?.data?.organization) { + console.log(response?.data?.organization) + setIsadminOnboarded(true) } }) @@ -159,7 +162,7 @@ const GuestUserNavBar = (props) => { */} - {!adminNotOnboarded ? + {isadminOnboarded ? <> From 070e592bb0f85dac281e77756eebc13c6fe82201 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 7 Mar 2023 15:34:40 +0530 Subject: [PATCH 12/73] FSPROD-1371 --- src/Assets/CSS/common.css | 21 +- src/Assets/Img/globe.svg | 3 + src/Assets/Img/line.svg | 3 + .../IntegrationConnectors/ConnectorCard.jsx | 152 +++++++++++++ .../IntegrationConnectors/ConnectorsList.jsx | 213 ++++++++++++++++++ src/Components/Navbar/ParticipantNavbar.js | 4 +- src/Layout/Participant.js | 8 + 7 files changed, 401 insertions(+), 3 deletions(-) create mode 100644 src/Assets/Img/globe.svg create mode 100644 src/Assets/Img/line.svg create mode 100644 src/Components/IntegrationConnectors/ConnectorCard.jsx create mode 100644 src/Components/IntegrationConnectors/ConnectorsList.jsx diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 04d1a64bc..4ecc1eb8f 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1034,4 +1034,23 @@ button.disbalesubmitbtndept { .back_btn_guest .MuiSvgIcon-root { color: #3491EE !important; -} \ No newline at end of file +} +.connectorCard { + padding: 20px 40px 20px 5px; + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-size: 14px; + color: #3d4a52; + line-height: 19px; + border-radius: 10px; + gap: 20px; + width: 368px; + height: 178px; + margin: 30px 15px 15px 15px; + border : 1px solid #C0C7D1; +} +.connectorCard:hover { + border: 1px solid #c09507; + cursor: pointer; +} diff --git a/src/Assets/Img/globe.svg b/src/Assets/Img/globe.svg new file mode 100644 index 000000000..45214fe5d --- /dev/null +++ b/src/Assets/Img/globe.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Assets/Img/line.svg b/src/Assets/Img/line.svg new file mode 100644 index 000000000..fbd589fd5 --- /dev/null +++ b/src/Assets/Img/line.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Components/IntegrationConnectors/ConnectorCard.jsx b/src/Components/IntegrationConnectors/ConnectorCard.jsx new file mode 100644 index 000000000..60f0a163a --- /dev/null +++ b/src/Components/IntegrationConnectors/ConnectorCard.jsx @@ -0,0 +1,152 @@ +import React from "react"; +import Card from "@mui/material/Card"; +import { useState } from "react"; +import CardHeader from "@mui/material/CardHeader"; +import CardContent from "@mui/material/CardContent"; +import Avatar from "@mui/material/Avatar"; +import IconButton from "@mui/material/IconButton"; +import Row from "react-bootstrap/Row"; +import Col from "react-bootstrap/Col"; +import Button from "@mui/material/Button"; +import THEME_COLORS from "../../Constants/ColorConstants"; +import UrlConstants from "../../Constants/UrlConstants"; +import { useHistory } from "react-router-dom"; + +const useStyles = { + btncolor: { + color: THEME_COLORS.THEME_COLOR, + "border-color": THEME_COLORS.THEME_COLOR, + "border-radius": 0, + "text-transform": "capitalize", + "border-radius": "2px", + "text-transform": "capitalize", + width: "116px", + height: "34px", + "margin-left": "-25px", + "font-weight": "400", + "font-family": "Open Sans", + "font-style": "normal", + "font-size": "14px", + }, + btnPosition: { + color: THEME_COLORS.THEME_COLOR, + "border-color": THEME_COLORS.THEME_COLOR, + "border-radius": 0, + "text-transform": "capitalize", + "border-radius": "2px", + "text-transform": "capitalize", + width: "116px", + height: "34px", + "margin-right": "-20px", + "font-weight": "400", + "font-family": "Open Sans", + "font-style": "normal", + "font-size": "14px", + }, + marginrowtop: { "margin-top": "30px" }, + cardDataHeading: { + "font-family": "Open Sans", + "font-weight": "400", + "font-size": "16px", + color: "#3D4A52", + "text-align": "left", + "padding-left": "10px", + }, + cardData: { + "font-family": "Open Sans", + "font-weight": "600", + "font-size": "16px", + color: "#3D4A52", + "text-align": "left", + "padding-left": "0px", + "margin-top": "10px" + }, + cardDataHead:{"color": "#c09507", + 'font-family': 'Open Sans', + "font-weight": "600", + "font-size": "24px", + "font-style":"normal", + "width":"272px", + "height": "19px", + "line-height":"19px", + "textAlign": "left", + marginBottom: "20px" , + "margin-top": "-20px", + "overflow": "hidden", + "text-overflow": "ellipsis", + "display": "-webkit-box", +"-webkit-line-clamp": "1", +"-webkit-box-orient": "vertical"}, + cardDataUser:{'font-family': 'Open Sans', + "font-weight": "400", + "font-size": "14px", + "font-style":"normal", + color: "#3D4A52", + "width":"314px", + "height": "19px", + "line-height":"19px", + "textAlign": "left", + "float" : "left", + "padding-left": "5px"}, + header: {height: "84px", + "text-align": "left", + "font-family": "Open Sans", + "font-style": "normal", + "font-weight": 400, + "font-size": "14px", + "line-height": "19px", + "color": "#9BA0A7", + "margin-top": "-40px" +}, +} + +export default function ConnectorCard(props) { + const history = useHistory(); + return ( + history.push('/datahub/datasets')} + className="connectorCard" + > + + } + title={props.firsttext} + style={useStyles.header} + /> + + + + {props.secondtext} + + + + + Used Datasets +
+
+ {props.useddataset > 9 ? props.useddataset : "0"+props.useddataset } +
+ + + Providers +
+
+ {props.providers > 9 ? props.providers : "0" + props.providers} +
+ + + + + ); +} diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx new file mode 100644 index 000000000..1ffd0f708 --- /dev/null +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -0,0 +1,213 @@ +import React from "react"; +import { useState, useEffect } from "react"; +import { Row, Col } from "react-bootstrap"; +import ConnectorCard from "../IntegrationConnectors/ConnectorCard" +import AddIcon from '@mui/icons-material/Add'; +import { InputAdornment } from "@mui/material"; +import { Button } from "@mui/material"; +import Loader from "../Loader/Loader"; +import HTTPService from "../../Services/HTTPService"; +import { GetErrorHandlingRoute } from "../../Utils/Common"; +import { useHistory } from "react-router-dom"; +export default function ConnectorsList() { + const [createdDate, setCreatedDate] = useState(""); + const [connectorName, setConnectorName] = useState(""); + const [description, setDesription] = useState("") + const [usedDatasets, setUsedDatasets] = useState("") + const [providers, setProviders] = useState("") + const [isLoader, setIsLoader] = useState(false); + const [isShowLoadMoreButton, setisShowLoadMoreButton] = useState(false) + const history = useHistory() + const getListOfConnectors = () => { + setIsLoader(true); + HTTPService( + "GET", + + "", + false, + true + ) + .then((response) => { + setIsLoader(false); + console.log("connectors list", response.data); + // if (response.data.next == null) { + // setisShowLoadMoreButton(false); + // } else { + // setisShowLoadMoreButton(true); + // setparticipantUrl(response.data.next); + // } + // setparticipantList(response.data.results); + }) + .catch((e) => { + setIsLoader(false); + history.push(GetErrorHandlingRoute(e)); + }); + } + const useStyles = { + marginrowtoptab50px: { "margin-top": "50px" }, + marginrowtop: { "margin-top": "20px" }, + background: { + "margin-left": "70px", + "margin-right": "70px", + background: "#FCFCFC", + }, + marginrowtop10px: { "margin-top": "30px" }, + marginrowtop50: { "margin-top": "50px" }, + addButton: { + "border-radius": "2px", + "background": "#c09507", + "width": "166px", + "height": "48px", + "color": "#FFFFFF", + "font-family": "Open Sans", + "font-style": "normal", + "font-weight": "700", + "font-size": "14px", + "align-item": "right", + "float": "right" + } + + + } + + return ( + +
+ {isLoader ? : ""} + +
+ + {"List of Connectors"} + + + + + + + + new + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {/* {isCoStewardShowLoadMoreButton ? ( */} + + + + {/* ) : ( + <> + )} */} + + + ) +} + diff --git a/src/Components/Navbar/ParticipantNavbar.js b/src/Components/Navbar/ParticipantNavbar.js index bd659fac8..6170353ee 100644 --- a/src/Components/Navbar/ParticipantNavbar.js +++ b/src/Components/Navbar/ParticipantNavbar.js @@ -108,7 +108,7 @@ const ParticipantNavbar = (props) => { />   {screenlabels.navbar.integration} - {/* + { alt="new" />   {screenlabels.navbar.connectors} - */} + { e.preventDefault(); diff --git a/src/Layout/Participant.js b/src/Layout/Participant.js index 2d311efea..c86c46f43 100644 --- a/src/Layout/Participant.js +++ b/src/Layout/Participant.js @@ -29,6 +29,7 @@ import DemoDashboardTable from "../Components/Connectors/DemoDashboardTable"; import AddDataset from "../Components/AdminDatasetConnection/AddDataset"; import ViewMetaDatasetDetails from "../Components/AdminDatasetConnection/ViewMetaDatasetDetails"; import DatasetIntegration from "../Components/Datasets/IntegrationDatasets/DatasetIntegration"; +import ConnectorsList from "../Components/IntegrationConnectors/ConnectorsList"; function Participant(props) { return ( @@ -135,6 +136,13 @@ function Participant(props) { > + + + +
From af5d46b85f2bba933eb68051a2aec018130e207a Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 7 Mar 2023 16:40:17 +0530 Subject: [PATCH 13/73] 1301 fixed --- src/Components/CoSteward/AddCoSteward.jsx | 2 +- .../PatricipantRegistration/AddParticipantRegistrationform.js | 2 +- src/Components/signup/OrgRightside.js | 2 +- src/Components/signup/ProfileRightside.js | 3 ++- src/Components/signup/ProfileRightsideParticipant.js | 3 ++- src/Views/Participants/AddParticipants.js | 2 +- src/Views/Participants/EditParticipants.js | 2 +- 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Components/CoSteward/AddCoSteward.jsx b/src/Components/CoSteward/AddCoSteward.jsx index 6ff32d90d..72f386a5f 100644 --- a/src/Components/CoSteward/AddCoSteward.jsx +++ b/src/Components/CoSteward/AddCoSteward.jsx @@ -233,7 +233,7 @@ export default function AddCoSteward(props) { orginsationemail && !isorganisationemailerror && countryvalue && - mobileNumberMinimunLengthCheck(contactnumber) && + contactnumber.length >= 9 && websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js index 1ff0c0347..5f024ff1d 100644 --- a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js +++ b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js @@ -294,7 +294,7 @@ const handlelistofCosteward = (e) => { orginsationemail && !isorganisationemailerror && countryvalue && - mobileNumberMinimunLengthCheck(contactnumber) && + contactnumber.length >= 9 && websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Components/signup/OrgRightside.js b/src/Components/signup/OrgRightside.js index 1897dedf5..15097a0be 100644 --- a/src/Components/signup/OrgRightside.js +++ b/src/Components/signup/OrgRightside.js @@ -820,7 +820,7 @@ export default function OrgRightside(props) { Next */} {props.orgName && - props.validOrgNumber?.length == 15 && + props.validOrgNumber?.length >= 9 && !props.isOrgnameerror && props.Orgemailbtn && !props.isOrgmailerror && diff --git a/src/Components/signup/ProfileRightside.js b/src/Components/signup/ProfileRightside.js index 0dfa05da6..b8c7f8a18 100644 --- a/src/Components/signup/ProfileRightside.js +++ b/src/Components/signup/ProfileRightside.js @@ -263,7 +263,8 @@ export default function ProfileRightside(props) { />
- {props.profilenextbutton ? ( + {props.profilenextbutton && + props.profilephone.length >= 9? ( diff --git a/src/Components/signup/ProfileRightsideParticipant.js b/src/Components/signup/ProfileRightsideParticipant.js index 579ca82e2..fedd1908e 100644 --- a/src/Components/signup/ProfileRightsideParticipant.js +++ b/src/Components/signup/ProfileRightsideParticipant.js @@ -254,7 +254,8 @@ export default function ProfileRightsideParticipant(props) {
*/}
- {props.profilenextbutton ? ( + {props.profilenextbutton && + props.profilephone.length >= 9 ? ( diff --git a/src/Views/Participants/AddParticipants.js b/src/Views/Participants/AddParticipants.js index d84774428..8d930db62 100644 --- a/src/Views/Participants/AddParticipants.js +++ b/src/Views/Participants/AddParticipants.js @@ -264,7 +264,7 @@ function AddParticipants(props) { orginsationemail && !isorganisationemailerror && countryvalue && - mobileNumberMinimunLengthCheck(contactnumber) && + contactnumber.length >= 9 && websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Views/Participants/EditParticipants.js b/src/Views/Participants/EditParticipants.js index cc5fbb3bb..8857f082b 100644 --- a/src/Views/Participants/EditParticipants.js +++ b/src/Views/Participants/EditParticipants.js @@ -314,7 +314,7 @@ function EditParticipants(props) { orginsationemail && !isorganisationemailerror && countryvalue && - contactnumber.length == 15 && + contactnumber.length >= 9 && websitelink && !iswebsitelinkrerror && organisationaddress && From 2728268ff171da08c611087b0b4d0a1f9d64eb48 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 7 Mar 2023 18:05:36 +0530 Subject: [PATCH 14/73] path changed --- src/Constants/UrlConstants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index bee798d1a..ced6ad1ab 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -62,7 +62,7 @@ const UrlConstant = { microsite_legal_documents: "/microsite/legal_documents/", consumer_paring_request: "participant/connectors_map/", provider_connectors: "participant/connectors/get_connectors/?dataset_id=", - microsite_theme: "/microsite/theme/", + microsite_theme: "microsite/theme/", datahub_dashboard: "datahub/dashboard/", add_project: "/participant/project/", register_participant: "accounts/self_register/", From d4109c47757ab870ee4f42b3c64d8cb96f000a6c Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 7 Mar 2023 18:29:45 +0530 Subject: [PATCH 15/73] function changed --- src/Components/CoSteward/AddCoSteward.jsx | 2 +- .../PatricipantRegistration/AddParticipantRegistrationform.js | 2 +- src/Components/signup/OrgRightside.js | 3 ++- src/Components/signup/ProfileRightside.js | 3 ++- src/Components/signup/ProfileRightsideParticipant.js | 4 ++-- src/Utils/Common.js | 2 +- src/Views/Participants/AddParticipants.js | 2 +- src/Views/Participants/EditParticipants.js | 3 ++- 8 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Components/CoSteward/AddCoSteward.jsx b/src/Components/CoSteward/AddCoSteward.jsx index 72f386a5f..6ff32d90d 100644 --- a/src/Components/CoSteward/AddCoSteward.jsx +++ b/src/Components/CoSteward/AddCoSteward.jsx @@ -233,7 +233,7 @@ export default function AddCoSteward(props) { orginsationemail && !isorganisationemailerror && countryvalue && - contactnumber.length >= 9 && + mobileNumberMinimunLengthCheck(contactnumber) && websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js index 5f024ff1d..1ff0c0347 100644 --- a/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js +++ b/src/Components/PatricipantRegistration/AddParticipantRegistrationform.js @@ -294,7 +294,7 @@ const handlelistofCosteward = (e) => { orginsationemail && !isorganisationemailerror && countryvalue && - contactnumber.length >= 9 && + mobileNumberMinimunLengthCheck(contactnumber) && websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Components/signup/OrgRightside.js b/src/Components/signup/OrgRightside.js index 15097a0be..9a83e6282 100644 --- a/src/Components/signup/OrgRightside.js +++ b/src/Components/signup/OrgRightside.js @@ -29,6 +29,7 @@ import { handleAddressCharacters, isLoggedInUserCoSteward, isLoggedInUserParticipant, + mobileNumberMinimunLengthCheck, validateInputField, } from "../../Utils/Common"; import RegexConstants from "../../Constants/RegexConstants"; @@ -820,7 +821,7 @@ export default function OrgRightside(props) { Next */} {props.orgName && - props.validOrgNumber?.length >= 9 && + mobileNumberMinimunLengthCheck(props.validOrgNumber) && !props.isOrgnameerror && props.Orgemailbtn && !props.isOrgmailerror && diff --git a/src/Components/signup/ProfileRightside.js b/src/Components/signup/ProfileRightside.js index b8c7f8a18..4d8085ed9 100644 --- a/src/Components/signup/ProfileRightside.js +++ b/src/Components/signup/ProfileRightside.js @@ -8,6 +8,7 @@ import Footerimg from "../../Components/signup/Footerimg"; import HTTPService from "../../Services/HTTPService"; import UrlConstant from "../../Constants/UrlConstants"; import Footer from "../Footer/Footer"; +import { mobileNumberMinimunLengthCheck } from "../../Utils/Common"; // import "react-phone-input-2/lib/material.css"; @@ -264,7 +265,7 @@ export default function ProfileRightside(props) {
{props.profilenextbutton && - props.profilephone.length >= 9? ( + mobileNumberMinimunLengthCheck(props.profilephone)? ( diff --git a/src/Components/signup/ProfileRightsideParticipant.js b/src/Components/signup/ProfileRightsideParticipant.js index fedd1908e..18e72bfe2 100644 --- a/src/Components/signup/ProfileRightsideParticipant.js +++ b/src/Components/signup/ProfileRightsideParticipant.js @@ -14,7 +14,7 @@ import { LinearProgress } from "@mui/material"; import CancelIcon from '@mui/icons-material/Cancel' import { useHistory } from "react-router-dom"; import Loader from "../Loader/Loader"; -import {GetErrorHandlingRoute, getUserLocal, isLoggedInUserCoSteward, isLoggedInUserParticipant } from "../../Utils/Common"; +import {GetErrorHandlingRoute, getUserLocal, isLoggedInUserCoSteward, isLoggedInUserParticipant, mobileNumberMinimunLengthCheck } from "../../Utils/Common"; import Footer from "../Footer/Footer"; const fileTypes = ['JPEG', 'PNG', 'jpg'] @@ -255,7 +255,7 @@ export default function ProfileRightsideParticipant(props) { */}
{props.profilenextbutton && - props.profilephone.length >= 9 ? ( + mobileNumberMinimunLengthCheck(props.profilephone) ? ( diff --git a/src/Utils/Common.js b/src/Utils/Common.js index 83edc8fc4..e5386f434 100644 --- a/src/Utils/Common.js +++ b/src/Utils/Common.js @@ -246,7 +246,7 @@ export const openLinkInNewTab = (url) => { }; export const mobileNumberMinimunLengthCheck = (number) => { - return number?.length >= 13; + return number?.length >= 9; }; export const stringMinimumLengthCheck = (str, len) => { diff --git a/src/Views/Participants/AddParticipants.js b/src/Views/Participants/AddParticipants.js index 8d930db62..b05b575f6 100644 --- a/src/Views/Participants/AddParticipants.js +++ b/src/Views/Participants/AddParticipants.js @@ -264,7 +264,7 @@ function AddParticipants(props) { orginsationemail && !isorganisationemailerror && countryvalue && - contactnumber.length >= 9 && + mobileNumberMinimunLengthCheck(contactnumber)&& websitelink && !iswebsitelinkrerror && organisationaddress && diff --git a/src/Views/Participants/EditParticipants.js b/src/Views/Participants/EditParticipants.js index 8857f082b..b1b410aa0 100644 --- a/src/Views/Participants/EditParticipants.js +++ b/src/Views/Participants/EditParticipants.js @@ -16,6 +16,7 @@ import Loader from "../../Components/Loader/Loader"; import { GetErrorHandlingRoute, GetErrorKey, + mobileNumberMinimunLengthCheck, stringMinimumLengthCheck, } from "../../Utils/Common"; const useStyles = { @@ -314,7 +315,7 @@ function EditParticipants(props) { orginsationemail && !isorganisationemailerror && countryvalue && - contactnumber.length >= 9 && + mobileNumberMinimunLengthCheck(contactnumber) && websitelink && !iswebsitelinkrerror && organisationaddress && From c6c73c512e86f549b9ef1a2395f312d7b86ee81e Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Mon, 13 Mar 2023 16:05:51 +0530 Subject: [PATCH 16/73] Contact number component changed --- package.json | 2 + src/Assets/CSS/common.css | 57 +++++++++++++++++++ src/Components/CoSteward/CoStewardForm.jsx | 20 ++++++- .../Participants/ParticipantForm.js | 32 +++++++++-- .../ParticipantRegistrationForm.js | 20 ++++++- src/Components/signup/OrgRightside.js | 26 +++++++-- src/Components/signup/ProfileRightside.js | 25 ++++++-- .../signup/ProfileRightsideParticipant.js | 27 +++++++-- src/Views/Participants/AddParticipants.js | 2 +- .../ParticipantAccountSetting.js | 56 +++++++++++------- .../ParticipantOrganisationSetting.js | 23 ++++++-- src/Views/Settings/accounts/accountSetting.js | 25 ++++++-- .../organisation/OrganisationSetting.js | 23 ++++++-- 13 files changed, 280 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 4fbb31cbd..a525e099a 100755 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "html-react-parser": "^3.0.1", "jquery": "^3.6.0", "json-2-csv": "^3.17.2", + "libphonenumber-js": "^1.10.21", "material-ui-phone-number": "^3.0.0", "mdbreact": "^5.0.1", "moment": "^2.24.0", @@ -45,6 +46,7 @@ "react-icons": "^4.4.0", "react-loading-overlay": "^1.0.1", "react-multi-email": "^0.5.3", + "react-phone-number-input": "^3.2.19", "react-quill": "^1.3.5", "react-redux": "^7.1.3", "react-router-dom": "^5.1.2", diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 04d1a64bc..1ffa4194b 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1034,4 +1034,61 @@ button.disbalesubmitbtndept { .back_btn_guest .MuiSvgIcon-root { color: #3491EE !important; +} +.ContactNumberStyle{ + border-bottom: 1px solid #3a3a3a !important; + border-radius: 2px; + color: #212529 !important; + background: #F1F1F1; + width: 520px; + height: 55px; + margin-left: 10px; + margin-top: 0px; + font-size: 14px; + font-family: "Open Sans"; + font-weight: 400; +} +.PhoneInputInput { + height: 50px !important; + border-top: none !important; + border-right: none !important; + border-left:none !important; + border-bottom: none; + background: #F1F1F1 !important; + color: #3D4A52 !important; + font-size: 14px; + font-family: "Open Sans"; + font-weight: 400; +} +.contactNumberStyleOrg { + border-bottom: 1px solid #3a3a3a !important; + border-radius: 2px; + color: #212529 !important; + background: #F1F1F1; + width: 490px; + height: 55px; + margin-left: 90px; + margin-top: 30px; +} +.ContactNumberStyleAccount{ + border-bottom: 1px solid #3a3a3a !important; + border-radius: 2px; + color: #212529 !important; + background: #F1F1F1; + width: 430px; + height: 55px; + margin-left: 60px; + margin-top: 30px; + font-size: 14px; + font-family: "Open Sans"; + font-weight: 400; +} +.ContactNumberStyleOnboard{ + border-radius: 2px; + color: #212529 !important; + background: #F1F1F1; + width: 420px; + height: 55px; + margin-left: 0px; + margin-top: 0px; } \ No newline at end of file diff --git a/src/Components/CoSteward/CoStewardForm.jsx b/src/Components/CoSteward/CoStewardForm.jsx index a70bb6d5a..498acbbe5 100644 --- a/src/Components/CoSteward/CoStewardForm.jsx +++ b/src/Components/CoSteward/CoStewardForm.jsx @@ -10,6 +10,8 @@ import MuiPhoneNumber from "material-ui-phone-number"; import { FormControlLabel } from '@mui/material'; import Checkbox from "@mui/material/Checkbox"; import RegexConstants from '../../Constants/RegexConstants'; +import PhoneInput from 'react-phone-number-input'; +import { isValidPhoneNumber, isPossiblePhoneNumber } from 'react-phone-number-input'; import { handleAddressCharacters, handleNameFieldEntry, preventSpaceKey, validateInputField } from '../../Utils/Common'; // import Select from 'react-select' const useStyles = { @@ -18,7 +20,8 @@ const useStyles = { marginrowtop50: {"margin-top": "50px"}, inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, - headingbold:{fontWeight: "bold"} + headingbold:{fontWeight: "bold"}, + contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function CoStewardForm(props) { @@ -178,7 +181,7 @@ export default function CoStewardForm(props) { />
- */} + props.setcontactnumber(e)} + limitMaxLength={true} /> + + {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber)) ? isValidPhoneNumber(props.contactnumber) : 'Invalid phone number') : ''} + diff --git a/src/Components/Participants/ParticipantForm.js b/src/Components/Participants/ParticipantForm.js index 8c8f52b1d..27681e62e 100644 --- a/src/Components/Participants/ParticipantForm.js +++ b/src/Components/Participants/ParticipantForm.js @@ -10,7 +10,15 @@ import MuiPhoneNumber from "material-ui-phone-number"; import { FormControlLabel } from '@mui/material'; import Checkbox from "@mui/material/Checkbox"; import RegexConstants from '../../Constants/RegexConstants'; +import 'react-phone-number-input/style.css' +import PhoneInput from 'react-phone-number-input'; import { handleAddressCharacters, handleNameFieldEntry, preventSpaceKey, validateInputField } from '../../Utils/Common'; +import { validatePhoneNumberLength } from 'libphonenumber-js' +// import { ValidatePhoneNumberLengthResult } from 'libphonenumber-js/types'; +// import { isValidPhoneNumber } from 'libphonenumber-js/core'; +import {isValidPhoneNumber, + isPossiblePhoneNumber } from 'react-phone-number-input'; +import { style } from '@mui/system'; // import Select from 'react-select' const useStyles = { btncolor: {color: THEME_COLORS.THEME_COLOR, "border-color": THEME_COLORS.THEME_COLOR, "border-radius": 0}, @@ -18,7 +26,8 @@ const useStyles = { marginrowtop50: {"margin-top": "50px"}, inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, - headingbold:{fontWeight: "bold"} + headingbold:{fontWeight: "bold"}, + contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantForm(props) { const [screenlabels, setscreenlabels] = useState(labels['en']); @@ -181,8 +190,8 @@ export default function ParticipantForm(props) { "User is already registered with this email ID" : props.emailErrorMessage} /> - - + {/* props.setcontactnumber(e)} + enableLongNumbers={true} error={props.iscontactnumbererror || props.phoneNumberErrorMessage} helperText={(props.iscontactnumbererror && !props.phoneNumberErrorMessage) ? "Enter Valid Number" : props.phoneNumberErrorMessage} + /> */} + props.setcontactnumber(e)} + limitMaxLength={true} /> + + {props.contactnumber ?((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber) ) ? "" : 'Invalid phone number') : ''} + + +
@@ -250,7 +275,6 @@ export default function ParticipantForm(props) { */} -
); } diff --git a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js index bedbb2563..8bacd207a 100644 --- a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js +++ b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js @@ -14,6 +14,8 @@ import RegexConstants from '../../Constants/RegexConstants'; import { Stack } from '@mui/material'; import Alert from "@mui/material/Alert"; import { handleAddressCharacters, validateInputField } from '../../Utils/Common'; +import PhoneInput from 'react-phone-number-input'; +import { isValidPhoneNumber, isPossiblePhoneNumber } from 'react-phone-number-input'; const useStyles = { btncolor: {color: THEME_COLORS.THEME_COLOR, "border-color": THEME_COLORS.THEME_COLOR, "border-radius": 0}, @@ -22,7 +24,8 @@ const useStyles = { inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthcofield: {"margin-right" : "100px", width: "98%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, - headingbold:{fontWeight: "bold"} + headingbold:{fontWeight: "bold"}, + contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantRegistrationForm(props) { const [screenlabels, setscreenlabels] = useState(labels['en']); @@ -186,7 +189,7 @@ export default function ParticipantRegistrationForm(props) { />
- */} + props.setcontactnumber(e)} + limitMaxLength={true} /> + + {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber)) ? "" : 'Invalid phone number') : ''} +
diff --git a/src/Components/signup/OrgRightside.js b/src/Components/signup/OrgRightside.js index 9a83e6282..6cd19e7a6 100644 --- a/src/Components/signup/OrgRightside.js +++ b/src/Components/signup/OrgRightside.js @@ -2,6 +2,8 @@ import React, { useState, useRef, useMemo, useEffect } from "react"; import "./OrgRightside.css"; import TextField from "@mui/material/TextField"; import Button from "@mui/material/Button"; +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-input"; // import Select from "@mui/material/Select"; import MuiPhoneNumber from "material-ui-phone-number"; @@ -58,7 +60,9 @@ export default function OrgRightside(props) { const [editorValue, setEditorValue] = React.useState( RichTextEditor.createValueFromString(orgdesc, "html") ); - + const useStyles = { + contact: {"padding-right":"300px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + }; const orgNameRef = useRef(); const orgMailRef = useRef(); // const OrgAddress = useRef(); @@ -555,7 +559,7 @@ export default function OrgRightside(props) { />
- + /> */} + + + {props.validOrgNumber ? ((isValidPhoneNumber(props.validOrgNumber) || isPossiblePhoneNumber(props.validOrgNumber)) ? "" : 'Invalid phone number') : ''} +
- + /> */} + + + {props.profilephone ? ((isValidPhoneNumber(props.profilephone) || isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''} +
{props.profilenextbutton && diff --git a/src/Components/signup/ProfileRightsideParticipant.js b/src/Components/signup/ProfileRightsideParticipant.js index 18e72bfe2..8e4d9b9f3 100644 --- a/src/Components/signup/ProfileRightsideParticipant.js +++ b/src/Components/signup/ProfileRightsideParticipant.js @@ -16,6 +16,8 @@ import { useHistory } from "react-router-dom"; import Loader from "../Loader/Loader"; import {GetErrorHandlingRoute, getUserLocal, isLoggedInUserCoSteward, isLoggedInUserParticipant, mobileNumberMinimunLengthCheck } from "../../Utils/Common"; import Footer from "../Footer/Footer"; +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-input"; const fileTypes = ['JPEG', 'PNG', 'jpg'] @@ -33,6 +35,9 @@ export default function ProfileRightsideParticipant(props) { let history = useHistory(); const nameRef = useRef(); + const useStyles = { + contact: {"padding-right":"300px" ,color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + }; useEffect(() => { if (isLoggedInUserParticipant() || isLoggedInUserCoSteward() ) @@ -200,7 +205,7 @@ export default function ProfileRightsideParticipant(props) { />
- + /> */} + + + {props.profilephone ? ((isValidPhoneNumber(props.profilephone) || isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''} +
{/*
@@ -255,7 +272,7 @@ export default function ProfileRightsideParticipant(props) { */}
{props.profilenextbutton && - mobileNumberMinimunLengthCheck(props.profilephone) ? ( + props.profilephone ? ( diff --git a/src/Views/Participants/AddParticipants.js b/src/Views/Participants/AddParticipants.js index b05b575f6..fb422c2f5 100644 --- a/src/Views/Participants/AddParticipants.js +++ b/src/Views/Participants/AddParticipants.js @@ -203,7 +203,7 @@ function AddParticipants(props) { contactnumber={contactnumber} setcontactnumber={(ref) => { setcontactnumber(ref); - console.log("sss", ref); + console.log("contactnumber", ref); }} iscontactnumbererror={iscontactnumbererror} websitelink={websitelink} diff --git a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js index de9d93a3a..593e53a91 100644 --- a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js +++ b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js @@ -10,6 +10,8 @@ import { FileUploader } from "react-drag-drop-files"; import labels from "../../../../Constants/labels"; import HTTPService from "../../../../Services/HTTPService"; import UrlConstants from "../../../../Constants/UrlConstants"; +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-input"; import HandleSessionTimeout, { setTokenLocal, getTokenLocal, @@ -30,6 +32,10 @@ import Loader from "../../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, + contact: {"padding-right": "330px", + "margin-top": "20px", color: "#ff3d00", "font-size": "12px", "font-weight": "400", + "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px" + }, }; export default function ParticipantAccountSetting(props) { @@ -113,8 +119,8 @@ export default function ParticipantAccountSetting(props) { // // setispropfileemailerror(true); // // } }; - const phonenumcheck = (number) =>{ - return number.length>=9 + const phonenumcheck = (number) => { + return number.length >= 9 }; const handleprofilenumber = (value) => { console.log(value); @@ -318,10 +324,10 @@ export default function ParticipantAccountSetting(props) { inputRef={profilelastname} error={lastNameErrorMessage ? true : false} helperText={lastNameErrorMessage} - // error={ispropfilelastnameerror} - // helperText={ - // ispropfilelastnameerror ? "Enter Valid last name" : "" - // } + // error={ispropfilelastnameerror} + // helperText={ + // ispropfilelastnameerror ? "Enter Valid last name" : "" + // } /> @@ -340,14 +346,14 @@ export default function ParticipantAccountSetting(props) { inputProps={{ readOnly: true }} // defaultValue={validemail} disabled - // error={props.ispropfileemailerror} - // helperText={ - // props.ispropfileemailerror ? "Enter Valid Email id" : "" - // } + // error={props.ispropfileemailerror} + // helperText={ + // props.ispropfileemailerror ? "Enter Valid Email id" : "" + // } />
- */} + + + {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + + @@ -398,12 +416,12 @@ export default function ParticipantAccountSetting(props) { {!ispropfilefirstnameerror && - !accfilesize && - accfirstnamebtn && - file != null && - accnumberbtn ? ( - ) : ( diff --git a/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js b/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js index e77beaa7d..56b71eebb 100644 --- a/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js +++ b/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js @@ -14,6 +14,8 @@ import RichTextEditor from "react-rte"; import { FileUploader } from "react-drag-drop-files"; // import UploadBanner from "../../../Components/signup/UploadBanner"; import UploadOrgBanner from "./../../organisation/UploadOrgBanner"; +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-input"; import HTTPService from "../../../../Services/HTTPService"; import UrlConstant from "../../../../Constants/UrlConstants"; @@ -42,6 +44,7 @@ import Loader from "../../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, + contact: {"padding-right": "330px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantOrganisationSetting(props) { @@ -627,7 +630,7 @@ export default function ParticipantOrganisationSetting(props) { /> - + /> */} + + + {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + diff --git a/src/Views/Settings/accounts/accountSetting.js b/src/Views/Settings/accounts/accountSetting.js index 2cf00726b..11c952751 100644 --- a/src/Views/Settings/accounts/accountSetting.js +++ b/src/Views/Settings/accounts/accountSetting.js @@ -27,10 +27,13 @@ import { validateInputField, } from "../../../Utils/Common"; import Loader from "../../../Components/Loader/Loader"; - +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber,isPossiblePhoneNumber } from "react-phone-number-input"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, + contact: {"padding-right": "330px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", + "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function AccountSetting(props) { @@ -349,7 +352,7 @@ export default function AccountSetting(props) { /> - + /> */} + + + {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + + diff --git a/src/Views/Settings/organisation/OrganisationSetting.js b/src/Views/Settings/organisation/OrganisationSetting.js index 3d3c94465..c14af80bf 100644 --- a/src/Views/Settings/organisation/OrganisationSetting.js +++ b/src/Views/Settings/organisation/OrganisationSetting.js @@ -18,6 +18,8 @@ import { FormHelperText } from "@mui/material"; import HTTPService from "../../../Services/HTTPService"; import UrlConstant from "../../../Constants/UrlConstants"; import parse from "html-react-parser"; +import PhoneInput from "react-phone-number-input"; +import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-input"; import HandleSessionTimeout, { setTokenLocal, @@ -42,6 +44,7 @@ import Loader from "../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, + contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function OrganisationSetting(props) { @@ -618,7 +621,7 @@ export default function OrganisationSetting(props) { /> - + /> */} + + + {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + From b51f2e99c295642dcaafb8584a39cf7a8946bf72 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Mon, 13 Mar 2023 23:27:10 +0530 Subject: [PATCH 17/73] working on dataset standardization --- .../DataStandardizationInAddDataset.css | 11 ++- .../DataStandardizationInAddDataset.js | 79 +++++++++++-------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css index d2bc2dd34..50179591b 100644 --- a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css +++ b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.css @@ -1,7 +1,7 @@ .data_standardization_cloumn_container{ display: flex; justify-content: space-around; - padding-right: 200px; + /* padding-right: 200px; */ } .data_standardization_title{ display: flex; @@ -15,6 +15,15 @@ font-size: 18px; } .uploaded_data_column_name_title{ + display: flex; font-weight: 400; font-size: 16px; + align-items: center; + max-width: 150px; + width: 100px; + word-wrap: break-word; +} +.uploaded_data_column_name_title_container{ + display: flex; + align-items: center; } \ No newline at end of file diff --git a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js index c8b795f25..31a134666 100644 --- a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js +++ b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js @@ -3,7 +3,9 @@ import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import FormControl from "@mui/material/FormControl"; import Select, { SelectChangeEvent } from "@mui/material/Select"; -import './DataStandardizationInAddDataset.css' +import "./DataStandardizationInAddDataset.css"; +import Checkbox from "@mui/material/Checkbox"; +import { FormControlLabel, FormGroup } from "@mui/material"; const DataStandardizationInAddDataset = () => { const [keysInUploadedDataset, setKeysInUploadedDataset] = useState([ @@ -16,6 +18,7 @@ const DataStandardizationInAddDataset = () => { { key: "farmer_name", description: "give farmer name" }, { key: "farmer_name", description: "give farmer name" }, ]); + const [checkBox, setCheckBox] = useState(false); const handleChange = (e) => { console.log("handle change clicked"); @@ -24,44 +27,52 @@ const DataStandardizationInAddDataset = () => { return ( <> -
- - Uploaded Data Column Name - - - Standard Data Column Name - -
+
+ Uploaded Data Column Name + Standard Data Column Name +
{keysInUploadedDataset?.map((keyNames, index) => { return ( -
-

{keyNames}

-
- - Select column/key - - + <> +
+
+ +
+ {keyNames} +
+
+
+ + + Select column/key + + + +
+ + setCheckBox(true)} />} + label="Mask" + /> +
-
+
+ ); })} - ); }; From fc3176be9f0b8494d8ecf65df04756d7c77eade7 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 14 Mar 2023 09:04:37 +0530 Subject: [PATCH 18/73] requested changes done --- package.json | 1 - src/Assets/CSS/common.css | 3 ++- src/Components/CoSteward/CoStewardForm.jsx | 4 ++-- src/Components/Participants/ParticipantForm.js | 7 ++++--- .../PatricipantRegistration/ParticipantRegistrationForm.js | 4 ++-- src/Components/signup/OrgRightside.js | 4 ++-- src/Components/signup/ProfileRightside.js | 4 ++-- src/Components/signup/ProfileRightsideParticipant.js | 4 ++-- .../ParticipantAccountSetting.js | 4 ++-- .../ParticipantOrganisationSetting.js | 4 ++-- src/Views/Settings/accounts/accountSetting.js | 4 ++-- src/Views/Settings/organisation/OrganisationSetting.js | 4 ++-- 12 files changed, 24 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index a525e099a..53ed1a0c2 100755 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "html-react-parser": "^3.0.1", "jquery": "^3.6.0", "json-2-csv": "^3.17.2", - "libphonenumber-js": "^1.10.21", "material-ui-phone-number": "^3.0.0", "mdbreact": "^5.0.1", "moment": "^2.24.0", diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 1ffa4194b..40d0ee097 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1067,7 +1067,8 @@ button.disbalesubmitbtndept { background: #F1F1F1; width: 490px; height: 55px; - margin-left: 90px; + float: right; + margin-right: 30px; margin-top: 30px; } .ContactNumberStyleAccount{ diff --git a/src/Components/CoSteward/CoStewardForm.jsx b/src/Components/CoSteward/CoStewardForm.jsx index 498acbbe5..2361458b1 100644 --- a/src/Components/CoSteward/CoStewardForm.jsx +++ b/src/Components/CoSteward/CoStewardForm.jsx @@ -21,7 +21,7 @@ const useStyles = { inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, headingbold:{fontWeight: "bold"}, - contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float: "left", "padding": "inherit", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function CoStewardForm(props) { @@ -206,7 +206,7 @@ export default function CoStewardForm(props) { limitMaxLength={true} /> - {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber)) ? isValidPhoneNumber(props.contactnumber) : 'Invalid phone number') : ''} + {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) && isPossiblePhoneNumber(props.contactnumber)) ? "" : 'Invalid phone number') : ''} diff --git a/src/Components/Participants/ParticipantForm.js b/src/Components/Participants/ParticipantForm.js index 27681e62e..d06a49623 100644 --- a/src/Components/Participants/ParticipantForm.js +++ b/src/Components/Participants/ParticipantForm.js @@ -27,7 +27,7 @@ const useStyles = { inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, headingbold:{fontWeight: "bold"}, - contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float: "left", "padding": "inherit", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantForm(props) { const [screenlabels, setscreenlabels] = useState(labels['en']); @@ -190,7 +190,7 @@ export default function ParticipantForm(props) { "User is already registered with this email ID" : props.emailErrorMessage} /> -
+ {/* */} - {props.contactnumber ?((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber) ) ? "" : 'Invalid phone number') : ''} + {props.contactnumber ?((isValidPhoneNumber(props.contactnumber) && isPossiblePhoneNumber(props.contactnumber) ) ? "" : 'Invalid phone number') : ''} diff --git a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js index 8bacd207a..37b91fd8e 100644 --- a/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js +++ b/src/Components/PatricipantRegistration/ParticipantRegistrationForm.js @@ -25,7 +25,7 @@ const useStyles = { inputwidthcofield: {"margin-right" : "100px", width: "98%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, headingbold:{fontWeight: "bold"}, - contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float : "left", padding : "inherit", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantRegistrationForm(props) { const [screenlabels, setscreenlabels] = useState(labels['en']); @@ -214,7 +214,7 @@ export default function ParticipantRegistrationForm(props) { limitMaxLength={true} /> - {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) || isPossiblePhoneNumber(props.contactnumber)) ? "" : 'Invalid phone number') : ''} + {props.contactnumber ? ((isValidPhoneNumber(props.contactnumber) && isPossiblePhoneNumber(props.contactnumber)) ? "" : 'Invalid phone number') : ''} diff --git a/src/Components/signup/OrgRightside.js b/src/Components/signup/OrgRightside.js index 6cd19e7a6..fbedae2ff 100644 --- a/src/Components/signup/OrgRightside.js +++ b/src/Components/signup/OrgRightside.js @@ -61,7 +61,7 @@ export default function OrgRightside(props) { RichTextEditor.createValueFromString(orgdesc, "html") ); const useStyles = { - contact: {"padding-right":"300px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float: "left", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; const orgNameRef = useRef(); const orgMailRef = useRef(); @@ -583,7 +583,7 @@ export default function OrgRightside(props) { limitMaxLength={true} /> - {props.validOrgNumber ? ((isValidPhoneNumber(props.validOrgNumber) || isPossiblePhoneNumber(props.validOrgNumber)) ? "" : 'Invalid phone number') : ''} + {props.validOrgNumber ? ((isValidPhoneNumber(props.validOrgNumber) && isPossiblePhoneNumber(props.validOrgNumber)) ? "" : 'Invalid phone number') : ''}
diff --git a/src/Components/signup/ProfileRightside.js b/src/Components/signup/ProfileRightside.js index 1d7bc8ad8..f18d3ef3d 100644 --- a/src/Components/signup/ProfileRightside.js +++ b/src/Components/signup/ProfileRightside.js @@ -19,7 +19,7 @@ import { isValidPhoneNumber, isPossiblePhoneNumber } from "react-phone-number-in export default function ProfileRightside(props) { const useStyles = { - contact: {"padding-right":"300px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float: "left", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; // const profilefirstname = useRef(); // const profilelastname = useRef(); @@ -277,7 +277,7 @@ export default function ProfileRightside(props) { limitMaxLength={true} /> - {props.profilephone ? ((isValidPhoneNumber(props.profilephone) || isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''} + {props.profilephone ? ((isValidPhoneNumber(props.profilephone) && isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''}
diff --git a/src/Components/signup/ProfileRightsideParticipant.js b/src/Components/signup/ProfileRightsideParticipant.js index 8e4d9b9f3..79bd6ec34 100644 --- a/src/Components/signup/ProfileRightsideParticipant.js +++ b/src/Components/signup/ProfileRightsideParticipant.js @@ -36,7 +36,7 @@ export default function ProfileRightsideParticipant(props) { const nameRef = useRef(); const useStyles = { - contact: {"padding-right":"300px" ,color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {"float": "left" ,color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; useEffect(() => { @@ -227,7 +227,7 @@ export default function ProfileRightsideParticipant(props) { limitMaxLength={true} /> - {props.profilephone ? ((isValidPhoneNumber(props.profilephone) || isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''} + {props.profilephone ? ((isValidPhoneNumber(props.profilephone) && isPossiblePhoneNumber(props.profilephone)) ? "" : 'Invalid phone number') : ''}
{/* diff --git a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js index 593e53a91..863fc9393 100644 --- a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js +++ b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js @@ -32,7 +32,7 @@ import Loader from "../../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, - contact: {"padding-right": "330px", + contact: {float: "left", "padding-left": "60px", "margin-top": "20px", color: "#ff3d00", "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px" }, @@ -378,7 +378,7 @@ export default function ParticipantAccountSetting(props) { limitMaxLength={true} /> - {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + {phonenumber ? ((isValidPhoneNumber(phonenumber) && isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} diff --git a/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js b/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js index 56b71eebb..82e69b84b 100644 --- a/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js +++ b/src/Views/Settings/ParticipantSettings/ParticipantOrganisationSettings/ParticipantOrganisationSetting.js @@ -44,7 +44,7 @@ import Loader from "../../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, - contact: {"padding-right": "330px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float : "left", "padding-left": "90px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function ParticipantOrganisationSetting(props) { @@ -655,7 +655,7 @@ export default function ParticipantOrganisationSetting(props) { limitMaxLength={true} /> - {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + {phonenumber ? ((isValidPhoneNumber(phonenumber) && isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} diff --git a/src/Views/Settings/accounts/accountSetting.js b/src/Views/Settings/accounts/accountSetting.js index 11c952751..8ff56aac7 100644 --- a/src/Views/Settings/accounts/accountSetting.js +++ b/src/Views/Settings/accounts/accountSetting.js @@ -32,7 +32,7 @@ import { isValidPhoneNumber,isPossiblePhoneNumber } from "react-phone-number-inp const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, - contact: {"padding-right": "330px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", + contact: {float: "left", "padding-left": "60px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; @@ -377,7 +377,7 @@ export default function AccountSetting(props) { limitMaxLength={true} /> - {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + {phonenumber ? ((isValidPhoneNumber(phonenumber) && isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} diff --git a/src/Views/Settings/organisation/OrganisationSetting.js b/src/Views/Settings/organisation/OrganisationSetting.js index c14af80bf..6204ac229 100644 --- a/src/Views/Settings/organisation/OrganisationSetting.js +++ b/src/Views/Settings/organisation/OrganisationSetting.js @@ -44,7 +44,7 @@ import Loader from "../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, - contact: {"text-align": "left", "padding-right": "370px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {float : "left", "padding-left": "90px", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function OrganisationSetting(props) { @@ -646,7 +646,7 @@ export default function OrganisationSetting(props) { limitMaxLength={true} /> - {phonenumber ? ((isValidPhoneNumber(phonenumber) || isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} + {phonenumber ? ((isValidPhoneNumber(phonenumber) && isPossiblePhoneNumber(phonenumber)) ? "" : 'Invalid phone number') : ''} From 04fbc4f58cb31a9a69cc236635af98c33746e98b Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 14 Mar 2023 12:51:56 +0530 Subject: [PATCH 19/73] list --- .../IntegrationConnectors/ConnectorCard.jsx | 40 +---- .../IntegrationConnectors/ConnectorsList.jsx | 148 +++++++----------- src/Constants/UrlConstants.js | 3 +- 3 files changed, 58 insertions(+), 133 deletions(-) diff --git a/src/Components/IntegrationConnectors/ConnectorCard.jsx b/src/Components/IntegrationConnectors/ConnectorCard.jsx index 60f0a163a..3e03d9596 100644 --- a/src/Components/IntegrationConnectors/ConnectorCard.jsx +++ b/src/Components/IntegrationConnectors/ConnectorCard.jsx @@ -13,55 +13,22 @@ import UrlConstants from "../../Constants/UrlConstants"; import { useHistory } from "react-router-dom"; const useStyles = { - btncolor: { - color: THEME_COLORS.THEME_COLOR, - "border-color": THEME_COLORS.THEME_COLOR, - "border-radius": 0, - "text-transform": "capitalize", - "border-radius": "2px", - "text-transform": "capitalize", - width: "116px", - height: "34px", - "margin-left": "-25px", - "font-weight": "400", - "font-family": "Open Sans", - "font-style": "normal", - "font-size": "14px", - }, - btnPosition: { - color: THEME_COLORS.THEME_COLOR, - "border-color": THEME_COLORS.THEME_COLOR, - "border-radius": 0, - "text-transform": "capitalize", - "border-radius": "2px", - "text-transform": "capitalize", - width: "116px", - height: "34px", - "margin-right": "-20px", - "font-weight": "400", - "font-family": "Open Sans", - "font-style": "normal", - "font-size": "14px", - }, marginrowtop: { "margin-top": "30px" }, cardDataHeading: { "font-family": "Open Sans", "font-weight": "400", "font-size": "16px", color: "#3D4A52", - "text-align": "left", - "padding-left": "10px", }, cardData: { "font-family": "Open Sans", "font-weight": "600", "font-size": "16px", color: "#3D4A52", - "text-align": "left", - "padding-left": "0px", "margin-top": "10px" }, cardDataHead:{"color": "#c09507", + "text-transform": "capitalize", 'font-family': 'Open Sans', "font-weight": "600", "font-size": "24px", @@ -77,7 +44,7 @@ const useStyles = { "display": "-webkit-box", "-webkit-line-clamp": "1", "-webkit-box-orient": "vertical"}, - cardDataUser:{'font-family': 'Open Sans', + cardDataUser:{"font-family": "Open Sans", "font-weight": "400", "font-size": "14px", "font-style":"normal", @@ -86,8 +53,7 @@ const useStyles = { "height": "19px", "line-height":"19px", "textAlign": "left", - "float" : "left", - "padding-left": "5px"}, + }, header: {height: "84px", "text-align": "left", "font-family": "Open Sans", diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index 1ffd0f708..a7665b84d 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -9,20 +9,23 @@ import Loader from "../Loader/Loader"; import HTTPService from "../../Services/HTTPService"; import { GetErrorHandlingRoute } from "../../Utils/Common"; import { useHistory } from "react-router-dom"; +import UrlConstant from "../../Constants/UrlConstants"; export default function ConnectorsList() { - const [createdDate, setCreatedDate] = useState(""); - const [connectorName, setConnectorName] = useState(""); - const [description, setDesription] = useState("") - const [usedDatasets, setUsedDatasets] = useState("") - const [providers, setProviders] = useState("") const [isLoader, setIsLoader] = useState(false); const [isShowLoadMoreButton, setisShowLoadMoreButton] = useState(false) + const [connectorList, setConnectorList] = useState([]); + const [connectorUrl, setConnectorUrl]= useState(""); const history = useHistory() + + useEffect(() => { + getListOfConnectors() + }, []) + const getListOfConnectors = () => { setIsLoader(true); HTTPService( "GET", - + UrlConstant.base_url + UrlConstant.list_of_connectors, "", false, true @@ -30,19 +33,44 @@ export default function ConnectorsList() { .then((response) => { setIsLoader(false); console.log("connectors list", response.data); - // if (response.data.next == null) { - // setisShowLoadMoreButton(false); - // } else { - // setisShowLoadMoreButton(true); - // setparticipantUrl(response.data.next); - // } - // setparticipantList(response.data.results); + if (response.data.next == null) { + setisShowLoadMoreButton(false); + } else { + setConnectorUrl(response.data.next); + setisShowLoadMoreButton(true); + } + setConnectorList(response.data.results); }) .catch((e) => { setIsLoader(false); history.push(GetErrorHandlingRoute(e)); }); } + + const connectorsListOnLoadMore = () => { + setIsLoader(true); + HTTPService( + "GET", + connectorUrl, + "", + false, + true + ).then((response) => { + setIsLoader(false); + if(response.data.next == null){ + setisShowLoadMoreButton(false) + } else { + setisShowLoadMoreButton(true); + setConnectorUrl(response.data.next); + } + let initialList = connectorList; + let totalListOfConnectors = [...initialList, ...response.data.results]; + setConnectorList(totalListOfConnectors); + }).catch((e) => { + setIsLoader(false); + history.push(GetErrorHandlingRoute(e)); + }) + } const useStyles = { marginrowtoptab50px: { "margin-top": "50px" }, marginrowtop: { "margin-top": "20px" }, @@ -64,7 +92,6 @@ export default function ConnectorsList() { "font-weight": "700", "font-size": "14px", "align-item": "right", - "float": "right" } @@ -83,7 +110,7 @@ export default function ConnectorsList() { {"List of Connectors"} -
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ))} - {/* {isCoStewardShowLoadMoreButton ? ( */} + {isShowLoadMoreButton ? ( - {/* ) : ( + ) : ( <> - )} */} + )} ) diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index ced6ad1ab..5805a74fb 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -85,7 +85,8 @@ const UrlConstant = { get_dataset_name_list: "datahub/dataset_ops/datasets_names/", get_files_for_selected_datasets: "datahub/dataset_ops/datasets_file_names/", get_columns_for_selected_files: "datahub/dataset_ops/datasets_col_names/", - joining_the_table: "datahub/dataset_ops/datasets_join_condition/" + joining_the_table: "datahub/dataset_ops/datasets_join_condition/", + list_of_connectors: "connectors/", }; From e4d34e9f26024316e4d969e209545e9d1a4ef516 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 14 Mar 2023 18:02:17 +0530 Subject: [PATCH 20/73] connectors list implementation --- .../IntegrationConnectors/ConnectorCard.jsx | 17 +- .../IntegrationConnectors/ConnectorsList.jsx | 170 +++++++++++------- src/Components/Navbar/Navbar.js | 6 +- src/Layout/Datahub.js | 11 +- 4 files changed, 120 insertions(+), 84 deletions(-) diff --git a/src/Components/IntegrationConnectors/ConnectorCard.jsx b/src/Components/IntegrationConnectors/ConnectorCard.jsx index 3e03d9596..849821861 100644 --- a/src/Components/IntegrationConnectors/ConnectorCard.jsx +++ b/src/Components/IntegrationConnectors/ConnectorCard.jsx @@ -1,16 +1,12 @@ import React from "react"; import Card from "@mui/material/Card"; -import { useState } from "react"; import CardHeader from "@mui/material/CardHeader"; import CardContent from "@mui/material/CardContent"; import Avatar from "@mui/material/Avatar"; -import IconButton from "@mui/material/IconButton"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; -import Button from "@mui/material/Button"; -import THEME_COLORS from "../../Constants/ColorConstants"; -import UrlConstants from "../../Constants/UrlConstants"; import { useHistory } from "react-router-dom"; +import { dateTimeFormat } from "../../Utils/Common"; const useStyles = { marginrowtop: { "margin-top": "30px" }, @@ -38,7 +34,7 @@ const useStyles = { "line-height":"19px", "textAlign": "left", marginBottom: "20px" , - "margin-top": "-20px", + "overflow": "hidden", "text-overflow": "ellipsis", "display": "-webkit-box", @@ -54,7 +50,7 @@ const useStyles = { "line-height":"19px", "textAlign": "left", }, - header: {height: "84px", + header: {height: "4px", "text-align": "left", "font-family": "Open Sans", "font-style": "normal", @@ -62,7 +58,7 @@ const useStyles = { "font-size": "14px", "line-height": "19px", "color": "#9BA0A7", - "margin-top": "-40px" + }, } @@ -70,7 +66,8 @@ export default function ConnectorCard(props) { const history = useHistory(); return ( history.push('/datahub/datasets')} + // To add view component of connector when the card is clicked + // onClick={() => history.push("")} className="connectorCard" > } - title={props.firsttext} + title={"Last Updated on: "+ dateTimeFormat(props.firsttext, true)} style={useStyles.header} /> diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index a7665b84d..b222e126f 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -2,21 +2,58 @@ import React from "react"; import { useState, useEffect } from "react"; import { Row, Col } from "react-bootstrap"; import ConnectorCard from "../IntegrationConnectors/ConnectorCard" -import AddIcon from '@mui/icons-material/Add'; -import { InputAdornment } from "@mui/material"; import { Button } from "@mui/material"; import Loader from "../Loader/Loader"; import HTTPService from "../../Services/HTTPService"; import { GetErrorHandlingRoute } from "../../Utils/Common"; import { useHistory } from "react-router-dom"; import UrlConstant from "../../Constants/UrlConstants"; +import ViewModuleIcon from '@mui/icons-material/ViewModule'; +import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted'; + export default function ConnectorsList() { const [isLoader, setIsLoader] = useState(false); const [isShowLoadMoreButton, setisShowLoadMoreButton] = useState(false) const [connectorList, setConnectorList] = useState([]); - const [connectorUrl, setConnectorUrl]= useState(""); - const history = useHistory() + const [connectorUrl, setConnectorUrl] = useState(""); + const [gridView, setGridView] = useState(true); //change of list and grid view state + const history = useHistory() + const useStyles = { + marginrowtoptab50px: { "margin-top": "50px" }, + marginrowtop: { "margin-top": "20px" }, + background: { + "margin-left": "120px", + "margin-right": "120px", + background: "#FCFCFC", + + }, + marginrowtop10px: { "margin-top": "30px" }, + marginrowtop50: { "margin-top": "50px" }, + addButton: { + "border-radius": "8px", + "background": "#c09507", + "width": "176px", + "height": "48px", + "color": "#FFFFFF", + "font-family": "Open Sans", + "font-style": "normal", + "font-weight": "700", + "font-size": "14px", + "align-item": "right", + }, + cardtext: { + color: "#A3B0B8", + "margin-top": "30px", + "font-size": "14px", + 'font-family': 'Open Sans', + 'font-style': 'normal', + 'font-weight': 400, + 'font-size': '14px', + 'line-height': '19px', + 'text-align': 'center', + }, + } useEffect(() => { getListOfConnectors() }, []) @@ -47,6 +84,7 @@ export default function ConnectorsList() { }); } + //list of connectors will display when loadmore button clicks const connectorsListOnLoadMore = () => { setIsLoader(true); HTTPService( @@ -57,7 +95,7 @@ export default function ConnectorsList() { true ).then((response) => { setIsLoader(false); - if(response.data.next == null){ + if (response.data.next == null) { setisShowLoadMoreButton(false) } else { setisShowLoadMoreButton(true); @@ -71,100 +109,94 @@ export default function ConnectorsList() { history.push(GetErrorHandlingRoute(e)); }) } - const useStyles = { - marginrowtoptab50px: { "margin-top": "50px" }, - marginrowtop: { "margin-top": "20px" }, - background: { - "margin-left": "70px", - "margin-right": "70px", - background: "#FCFCFC", - }, - marginrowtop10px: { "margin-top": "30px" }, - marginrowtop50: { "margin-top": "50px" }, - addButton: { - "border-radius": "2px", - "background": "#c09507", - "width": "166px", - "height": "48px", - "color": "#FFFFFF", - "font-family": "Open Sans", - "font-style": "normal", - "font-weight": "700", - "font-size": "14px", - "align-item": "right", - } - - - } return ( -
- {isLoader ? : ""} + {isLoader ? : ""} -
- + + {"List of Connectors"} - + + {/* */} + {/* */} + + New Connector + + new - - {connectorList.map((list, index) => ( + {gridView === true ? <> + + {connectorList.map((list, index) => ( - ))} - - - - {isShowLoadMoreButton ? ( - - - - ) : ( - <> - )} - + ))} + + + + {isShowLoadMoreButton ? ( + + + + ) : ( + <> + )} + + : <> + {/* list view component render here when list view button clicks */} + + + "Currently, there are no connectors available in the list format" + + + } ) } diff --git a/src/Components/Navbar/Navbar.js b/src/Components/Navbar/Navbar.js index 8346d4dd9..32f2c4a60 100644 --- a/src/Components/Navbar/Navbar.js +++ b/src/Components/Navbar/Navbar.js @@ -133,8 +133,8 @@ const Navbar = (props) => { alt="new" />   {screenlabels.navbar.integration} - - {/* + + { alt="new" />   {screenlabels.navbar.connectors} - */} + {!isLoggedInUserCoSteward() ? { @@ -130,7 +131,7 @@ function Datahub(props) { {/* */} - + /> */} + + +
From 87c7bc38fac644822a5880e203f1bb5cb4073321 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 14 Mar 2023 18:14:11 +0530 Subject: [PATCH 21/73] color changed for button --- src/Components/IntegrationConnectors/ConnectorsList.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index b222e126f..42b675946 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; import { Row, Col } from "react-bootstrap"; import ConnectorCard from "../IntegrationConnectors/ConnectorCard" import { Button } from "@mui/material"; +import THEME_COLORS from "../../Constants/ColorConstants"; import Loader from "../Loader/Loader"; import HTTPService from "../../Services/HTTPService"; import { GetErrorHandlingRoute } from "../../Utils/Common"; @@ -41,6 +42,7 @@ export default function ConnectorsList() { "font-weight": "700", "font-size": "14px", "align-item": "right", + "border-color": THEME_COLORS.THEME_COLOR, }, cardtext: { color: "#A3B0B8", From 4243c6ccacc20775c3813547b188e2a5c53b3a84 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Wed, 15 Mar 2023 09:39:42 +0530 Subject: [PATCH 22/73] changes of css done --- src/Components/CoSteward/CoStewardForm.jsx | 4 ++-- src/Components/Participants/ParticipantForm.js | 5 ++--- .../PatricipantRegistration/ParticipantRegistrationForm.js | 4 ++-- src/Components/signup/OrgRightside.js | 2 +- src/Components/signup/ProfileRightside.js | 2 +- src/Components/signup/ProfileRightsideParticipant.js | 2 +- .../ParticipantAccountSettings/ParticipantAccountSetting.js | 4 ++-- src/Views/Settings/accounts/accountSetting.js | 4 ++-- 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Components/CoSteward/CoStewardForm.jsx b/src/Components/CoSteward/CoStewardForm.jsx index 2361458b1..20bebac92 100644 --- a/src/Components/CoSteward/CoStewardForm.jsx +++ b/src/Components/CoSteward/CoStewardForm.jsx @@ -21,7 +21,7 @@ const useStyles = { inputwidth:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52'}, inputwidthlastrow:{width: "95%", "text-align": "left", height: '48px', color: '#3D4A52', "margin-top": "-10px"}, headingbold:{fontWeight: "bold"}, - contact: {float: "left", "padding": "inherit", color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, + contact: {color: "#ff3d00" , "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px"}, }; export default function CoStewardForm(props) { @@ -180,7 +180,7 @@ export default function CoStewardForm(props) { "User is already registered with this email ID" : props.emailErrorMessage} /> -
+ {/* - + {/* */} - + {/* { diff --git a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js index 863fc9393..1192d7c16 100644 --- a/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js +++ b/src/Views/Settings/ParticipantSettings/ParticipantAccountSettings/ParticipantAccountSetting.js @@ -32,7 +32,7 @@ import Loader from "../../../../Components/Loader/Loader"; const useStyles = { marginrowtop: { "margin-top": "20px" }, marginrowtop8px: { "margin-top": "0px" }, - contact: {float: "left", "padding-left": "60px", + contact: { "margin-top": "20px", color: "#ff3d00", "font-size": "12px", "font-weight": "400", "font-family": "Open-Sans", "font-style": "normal", "line-height": "16px" }, @@ -352,7 +352,7 @@ export default function ParticipantAccountSetting(props) { // } /> - + {/* - + {/* Date: Wed, 15 Mar 2023 12:37:48 +0530 Subject: [PATCH 23/73] review changes done --- src/Assets/CSS/common.css | 3 +- .../IntegrationConnectors/ConnectorCard.jsx | 6 ++-- .../IntegrationConnectors/ConnectorsList.jsx | 28 ++++++------------- src/Layout/Datahub.js | 16 ----------- 4 files changed, 12 insertions(+), 41 deletions(-) diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 4ecc1eb8f..4daf680a1 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1044,7 +1044,6 @@ button.disbalesubmitbtndept { color: #3d4a52; line-height: 19px; border-radius: 10px; - gap: 20px; width: 368px; height: 178px; margin: 30px 15px 15px 15px; @@ -1052,5 +1051,5 @@ button.disbalesubmitbtndept { } .connectorCard:hover { border: 1px solid #c09507; - cursor: pointer; + cursor: pointer; } diff --git a/src/Components/IntegrationConnectors/ConnectorCard.jsx b/src/Components/IntegrationConnectors/ConnectorCard.jsx index 849821861..a48cc6ea2 100644 --- a/src/Components/IntegrationConnectors/ConnectorCard.jsx +++ b/src/Components/IntegrationConnectors/ConnectorCard.jsx @@ -32,8 +32,8 @@ const useStyles = { "width":"272px", "height": "19px", "line-height":"19px", - "textAlign": "left", - marginBottom: "20px" , + "text-align": "left", + "margin-bottom": "20px" , "overflow": "hidden", "text-overflow": "ellipsis", @@ -48,7 +48,7 @@ const useStyles = { "width":"314px", "height": "19px", "line-height":"19px", - "textAlign": "left", + "text-align": "left", }, header: {height: "4px", "text-align": "left", diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index 42b675946..b229060d2 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -43,6 +43,7 @@ export default function ConnectorsList() { "font-size": "14px", "align-item": "right", "border-color": THEME_COLORS.THEME_COLOR, + "text-transform": "inherit" }, cardtext: { color: "#A3B0B8", @@ -56,9 +57,6 @@ export default function ConnectorsList() { 'text-align': 'center', }, } - useEffect(() => { - getListOfConnectors() - }, []) const getListOfConnectors = () => { setIsLoader(true); @@ -112,6 +110,12 @@ export default function ConnectorsList() { }) } + + useEffect(() => { + getListOfConnectors() + }, []) + + return (
- {/* */} - {/* */} diff --git a/src/Layout/Datahub.js b/src/Layout/Datahub.js index c43448011..18a3b11b0 100644 --- a/src/Layout/Datahub.js +++ b/src/Layout/Datahub.js @@ -129,23 +129,7 @@ function Datahub(props) { /> - {/* */} - {/* - - */} Date: Wed, 15 Mar 2023 15:39:51 +0530 Subject: [PATCH 24/73] integrate, save and delete with all the cards functionaltiy completed --- src/Assets/CSS/common.css | 64 ++- src/Assets/Img/Join type/Check circle.svg | 3 + src/Assets/Img/Join type/Color/Left.svg | 12 + src/Assets/Img/Join type/Color/Tick icon.svg | 10 + src/Assets/Img/Join type/Color/inner.svg | 12 + src/Assets/Img/Join type/Color/outer.svg | 12 + src/Assets/Img/Join type/Color/right.svg | 12 + .../Img/Join type/Normal state/inner.svg | 12 + .../Img/Join type/Normal state/left.svg | 12 + .../Img/Join type/Normal state/outer.svg | 12 + .../Img/Join type/Normal state/right.svg | 12 + src/Assets/Img/download_data.svg | 10 + src/Assets/Img/integration_bg.svg | 3 + src/Assets/Img/setting.gif | Bin 0 -> 103929 bytes .../CardDetail/CardDetail.jsx | 81 ++++ .../CardDetail/card_detail.module.css | 66 +++ .../DatasetIntegration.jsx | 423 ++++++++++-------- .../DatasetSelect/DatasetSelect.jsx | 302 ++++++++----- .../IntegrationDatasets/Join/Join.jsx | 280 +++++------- .../IntegrationDatasets/Preview/Preview.jsx | 86 +++- .../dataset_integration.module.css | 313 ++++++++++++- src/Components/Navbar/Navbar.js | 30 +- src/Components/Navbar/ParticipantNavbar.js | 2 +- src/Constants/UrlConstants.js | 5 +- src/Layout/Datahub.js | 36 +- src/Layout/Participant.js | 16 +- src/Utils/Common.js | 12 +- 27 files changed, 1293 insertions(+), 545 deletions(-) create mode 100644 src/Assets/Img/Join type/Check circle.svg create mode 100644 src/Assets/Img/Join type/Color/Left.svg create mode 100644 src/Assets/Img/Join type/Color/Tick icon.svg create mode 100644 src/Assets/Img/Join type/Color/inner.svg create mode 100644 src/Assets/Img/Join type/Color/outer.svg create mode 100644 src/Assets/Img/Join type/Color/right.svg create mode 100644 src/Assets/Img/Join type/Normal state/inner.svg create mode 100644 src/Assets/Img/Join type/Normal state/left.svg create mode 100644 src/Assets/Img/Join type/Normal state/outer.svg create mode 100644 src/Assets/Img/Join type/Normal state/right.svg create mode 100644 src/Assets/Img/download_data.svg create mode 100644 src/Assets/Img/integration_bg.svg create mode 100644 src/Assets/Img/setting.gif create mode 100644 src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx create mode 100644 src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 04d1a64bc..975883ce2 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -995,6 +995,10 @@ button.disbalesubmitbtndept { color: #000000 !important; } +.dataset_selector_in_integration .row { + margin-top: 0px !important; +} + .dataset_selector_in_integration .MuiCollapse-entered { background: #FFFFFF !important; box-shadow: 0px 20px 40px -4px rgb(145 158 171 / 16%) !important; @@ -1002,7 +1006,8 @@ button.disbalesubmitbtndept { } .accordion_for_columns_under_integration .accordion_detail .MuiSvgIcon-root, -.accordion_for_columns_under_integration .select_all_btn .MuiSvgIcon-root { +.accordion_for_columns_under_integration .select_all_btn .MuiSvgIcon-root, +.dataset_selector_in_integration .MuiSvgIcon-root { color: #637381 !important; } @@ -1034,4 +1039,61 @@ button.disbalesubmitbtndept { .back_btn_guest .MuiSvgIcon-root { color: #3491EE !important; +} + +.dataset_selector_in_integration .MuiFormControlLabel-label { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dataset_selector_in_integration .deleteicon { + cursor: pointer; +} + +.dataset_selector_in_integration .deleteicon:hover { + color: red !important; +} + +.deleteicon:hover .mainBoxInIntegration { + border: 1px solid red !important; +} + +.dataset_integration_selectors .row { + background-color: #ab8405 !important; +} + +html { + scroll-behavior: smooth; +} + +.MuiInputLabel-asterisk { + color: red !important; +} + +.all_selectors_as_sticky { + transition: all 0.2s; +} + +.ant-affix .all_selectors_as_sticky { + box-shadow: 0px 2px 5px rgb(0 0 0 / 50%) !important; + /* width: 100vw !important; */ + margin: 0px !important; + padding: 5px 0px !important; + border-bottom-left-radius: 10px !important; + border-bottom-right-radius: 10px !important; + + +} + +.dataset_selector_in_integration .MuiDataGrid-row:nth-child(even) { + background-color: #F9EABC !important; + /* color: white; */ + margin: 5px 0px; +} + +.dataset_selector_in_integration .MuiDataGrid-row:nth-child(odd) { + background-color: #f7f4ebd3 !important; + /* color: white; */ + padding: 5px 0px; } \ No newline at end of file diff --git a/src/Assets/Img/Join type/Check circle.svg b/src/Assets/Img/Join type/Check circle.svg new file mode 100644 index 000000000..0c2125b0a --- /dev/null +++ b/src/Assets/Img/Join type/Check circle.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Assets/Img/Join type/Color/Left.svg b/src/Assets/Img/Join type/Color/Left.svg new file mode 100644 index 000000000..e87f8a47c --- /dev/null +++ b/src/Assets/Img/Join type/Color/Left.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Color/Tick icon.svg b/src/Assets/Img/Join type/Color/Tick icon.svg new file mode 100644 index 000000000..456964971 --- /dev/null +++ b/src/Assets/Img/Join type/Color/Tick icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Color/inner.svg b/src/Assets/Img/Join type/Color/inner.svg new file mode 100644 index 000000000..c474fd0c0 --- /dev/null +++ b/src/Assets/Img/Join type/Color/inner.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Color/outer.svg b/src/Assets/Img/Join type/Color/outer.svg new file mode 100644 index 000000000..f847f1309 --- /dev/null +++ b/src/Assets/Img/Join type/Color/outer.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Color/right.svg b/src/Assets/Img/Join type/Color/right.svg new file mode 100644 index 000000000..9cfc9979b --- /dev/null +++ b/src/Assets/Img/Join type/Color/right.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Normal state/inner.svg b/src/Assets/Img/Join type/Normal state/inner.svg new file mode 100644 index 000000000..91df43be5 --- /dev/null +++ b/src/Assets/Img/Join type/Normal state/inner.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Normal state/left.svg b/src/Assets/Img/Join type/Normal state/left.svg new file mode 100644 index 000000000..9c83afad7 --- /dev/null +++ b/src/Assets/Img/Join type/Normal state/left.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Normal state/outer.svg b/src/Assets/Img/Join type/Normal state/outer.svg new file mode 100644 index 000000000..333bb215e --- /dev/null +++ b/src/Assets/Img/Join type/Normal state/outer.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/Join type/Normal state/right.svg b/src/Assets/Img/Join type/Normal state/right.svg new file mode 100644 index 000000000..494f23b1c --- /dev/null +++ b/src/Assets/Img/Join type/Normal state/right.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/download_data.svg b/src/Assets/Img/download_data.svg new file mode 100644 index 000000000..9c907761a --- /dev/null +++ b/src/Assets/Img/download_data.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/Assets/Img/integration_bg.svg b/src/Assets/Img/integration_bg.svg new file mode 100644 index 000000000..c6c70b6e2 --- /dev/null +++ b/src/Assets/Img/integration_bg.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/Assets/Img/setting.gif b/src/Assets/Img/setting.gif new file mode 100644 index 0000000000000000000000000000000000000000..4934ee38e2e0d1454bc8ab92a6bc7428ef9f4006 GIT binary patch literal 103929 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%0AfqybEig7U4#Ue)n1ptvjO9wKdtG52(;; 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 z z=t9tiTP<6+i}^j#eNw^xx0N3V6u#k0+4c|sg@(`KEy&nSfk>~L$HT}3A)C=}m50Xp zG|b%qvG*gLrFFE7B2EzAxDXYi!tu2?!9ZQclr;91IRhCa*g4=yH z=r7N&788wt&|>mEvJWEQf~O1zCUh_?`C@)BQA5~%Fd9?4f!3vtI!*}Q3(-N?5ak&` zq%OF6Asa21DM$cgtHbZ8nB}u2A`0JA;@Ep@bpYs#NI8iJ3@8><%nH0e00fNzS|{$| zZ}}0ra;s85qz1mns;gQlQHhSM;Q2th?uWQxx~nsrKZq7WYH5&aV+M&97^(gVjLxiw zYNBgv#WDbbk^wB!*V4@>pY92I6yU{`LYZU5BpF;J4<`>^m;|F%Rzg;wd=8uLN{wBP z9MKtDksKRo374H3BwSs60eMp8p)e{^1Kf?IL1-RL5w7ocZ9S{QNQTKro#S<}#DlF#$fXmYZF%hQv;ofii>Ge8_V}bzp#+)4>^RQ!x`EtsBtxwNn}4^3+mGb7 zEzCq;tLl2yMXX~|g`?HWUY{(x(S8^&s%cg^no=m1S=KtXxoZFZ*F#h?uusxfg}xJ{ zvD97|-*e@$i}`EGu{-Dt0VP}>VnDOLS}J2IJm6NSt+3{yLh*-Py*< z{?%AC1r0;UJVD=^xPpTxZO<%<5LVaFrZ5LEQ{#asO9FWQ6>_|lupYr;PgzbvBr zk40vb7$K*$gxiOm6+Q8{kEBe_NT|*X03zeRtX*ORdw<(uIrp(CT~I5eE`b>0 z0mM{qE=4Cy6%1$mQ-JhLD2xqy94uu#^d5gaL@bH~$JD*}FW+6{=a=-ongpo^#txw{ zB*(pWL=)O2-r& z=`czVFe*h={ivGe$s{1*;Ou%L+xnE~b9^Fz=`V8nfbgD5yRvji{e5~{bcvq2QHJRa zeCGJHDrMcnq?RTM!Ojy2Wr&0fnty%T5+N!ZtG$?z^%C_DYh_@{{j`fEq28^vjx=~V zG{**tj?1v~a@eONz?MpcShvtQeIbRg#h`nl#(e~ z&e$Qz6NMe7kz461X;7(P6{6g^qg?4|Z^>8fGFK&zS|wwGp_W93UN76C-rG4KJ!i1` z2N0Kkb#xNtzb7A-du3@ebVl6VsnTw!UsD()H>61H52g;EV)$&uX7ifmi#Sqm(E_et zRiqAMKU;=7t*%#x+aAJ>80C1QMa6y@1{p4@T&i z$(D9@N5pRGc<~_v-TnpIjutnQJT0BQ{S3l}{%`OO7G_)VY6;cRO;q#FXqwjhiXESZ ziq`u8dqwrV9m^Xx{JHFu28b*J=Sb!5ks!w)Xf9FEz1F_Dz*`>?Yp5&L);_MaIwo0a ze>hngE+M)*9L21}iT7pHy{`H|CGx1X3L*c zwr_1X6#_0tt>lFA>YWbqZ+u|Sw6GMv#+*Z|-BlRm=Ae)3T#-?udBXkjLJ~)F z1G!EjxUwd9{E0&*$xOr#asbGqwO-Lm5m3+xYwn)IrE+Z04EuN7GSCAOsKBdv;&Qp# zUP>t3A_1<}Mp-m)vt6&?1a5RV(>n12$zrcz1)ayb$ri{;;LCHq3I^JP}Jujsvvh_>KO){5zRzA*T2QKB6;Vehm?I*;p>dI@kh_o%|E$}xllDilH ze>I6AyV}sBofAzKCfH~r`LoakglZQl%I}uw62E+mv0o3vb200f39^O26fGjIh6~HP zqf9i{A^tGSiG@Ae-mv$0DgPanhTXj{@9VTQDJe29(xKzuMNWd(&>Kto@lvVP^pl3g zACjbq4=wVdCr10NgEhJ=Lw8;4K^L8?y)O3^joH)^n7{POZf~pRf=<`GGp4S5Z_cZ` z&Ye~R8+`Mf5gU##9c^7FxmX?F{8M)JZL_L>YF)khK_++B&cc(w|T(cS+O@6&sYSBz;iHlm> z0Nq;l0$|)$P_mwTp#DjRf9m#e6C4Rf&@GrX{@E0J|3G+eiV1W2JSE9$=w|Qh!TaI! zhY|FBgz(E{-AXm_bUV`t_Q6ku3-u zt0Csxc{SKGyR-QM)W7GMe8v<4?kJ3dmHcq-p;5&H4b1eKoSl%4h`e8YQ`aap(E{E9 z&UEHPrA9*DA@%}efmLQf#bCB=$9`nvK@noXkmjJ6YV?Jw4#b5axZTe!JPc|9UmMvrVa&R+KFFfpfT)ouaxFBWJz(sW zU=7I@RzIAf-VmfT@i*tx_2|!qC`on26Y;3&G1iN9{0@w`K45qarYW)^Zy01GCt>6*W{lq} z(XNwu>04;%Nep&4;VFvI6-PYqT=U)CA7as?-9b5g%zDj8G7R`3}M!0R?97xr3IV*PgV( zflu?UHoYH*8lhDL{0bze@|01Gdo;)3oCtX32*BGg{w2X8FP4nHm~v{CoSK9$bENG`VxkdzACS28hG%5%MpzQR7RpS;iRGHXY&eiQhUu%oY2rVT z-pQE!=7<)81q1m6EfQ)c01f$r%83so;|(($xgt&3LRzr{DLf-8#RD3aBb`?y5g3Y` zgq3MpkwWs8Y}k-NBX6uakrbH`Pt%^(tn7b^8Qk!%(E(`haIv3A7~{0;5-KrX9D)q;**k5Ig7%fV^Lz7I{N!179_^6#JUXywF>l8D^bNakbo z%Grp$0s1~ld}YO)r?;~w4M}9XPvrf52h~l5Fe}gd+_0}uf%vtW9MPwhfX#@F<82Q9|2h$Gc3By_ZOQjguG zD3XyZl9S}f9_2&CE^r=;No?1}Lo?ITL}ZtY-V4cFUHD~XX=Y&uC zVl6jt@+%Uz4BF7pYDYbP!=rLAv;reDS>6LKT$9EFJF;@q4d)}RHWG^Kz5MrhN%m${ z;A2%0b(L0$)$j);Sw_V;Ox|Q?wGV3g+=l3^^_TWV0$DK11TgMd70m1|tt(VsZqNM=k=}5=neUojpsP_u5+5U1`58kq`2z zkz}b*lWA)aQO`}BI<-PAPF?KtQkMi(T}MR}(o|y@+R#aDi9bP{%;h}+*+^6sq8mYs zmet^sntQ03!?@VET4_qDRZefISGQVi>DZogulNS;fU|{NkCQ^Hkp( z@l{8&rE7=Hw zKMS-Z3dMFEIeFB_dymSeQ0i#<8koui%SsjsH2IKv`d&Lwn5MN5? zQ}kV4R86k1Wo&7S0lk6@tzeT{;Cq5)s(?I92)jgiP+G!*A^XNln7>=9M4XhYQgjD2 zDg{f{7f}Ng)O{pV19;I&*e#XcCD{}=mv~7%TG~o%p7Lw7p{L56Oixl_t0A?C$~`H4 z9_ixatyXRHVV)1f(r^IeeD8|kup?IrYRPx~6$iswmFkK}krr14PF1)>P@}q0_NtM2 zp-1{{q$^T}972OEtB0f8TE1H$RT3ZXbEx5BbP!u9T2g(xrF)xQf09x$fZAfwWh8tn z`z3h{UR6bhM~3eYwYRyGOQNE$b@YkpdHFWUw zct$i$4qS>pEuS&8XaH)K^X9mL;y@s$UWGMPYj$;XvqZMHcmPdp2QFn7Pf!ACPM)(k zMKyR@hQtV*Y~I%B>%+7UwN#z-v?cna>z~ocVpG_KX%7}N!{7)Ip_v=Psj{i!Q^WoS z5V5t3@q<4z9+Xw@2*1g)ZKQDVqKB%v(Y5#1`S2;e&Eetz|q0fn2~_YvYE4LO^-?$&xg;?x03yc&{Wdi5XW_%K@J!fl4{bjUx<)e z*#6^Ib@gK^y2uE8ktk-Kz(F)Ja?UcCXYmh`&cWhzw#k#w6r%#QDBahnXz|iP#Uf~z z&LEE{JFgB;&*Ga{H#jdmH_@Up3?5IE;F?!IO+a&fr?8sO@XWr0y=l7w_)5f{i41&d zIC;B*F>0-9fq#<_w{?=L54T2UBi_m&0o^*wv%Ti?8kV(i)=(QKpfZwpNc@jqW$JQl zt5%|nMiC}`1(Af~PJJ~}7u@K2wbp_V%Sg-nx|JsSYI(seE#O6K?Ecc}0>Y%UrzI2) zyU7Rn%zK(dku!62ZAWuvePIh6q%RwFTmCS@MQrvYc>6eidrC*gHHN4ZKECDK^kBkZ z_)CR0y`HRu49wpY^uT0@K~rzq_zphECtw`Q!1U3~EkF=m&3rXlb4+(@0mrMbN@Unvc#X-%jb)%NY-YCr64uQZi)=*&5{ zchu1iQr~PgXGU;kQH!~jaC#5g?OhLdRN-zkf_=uQ5f16@2c4(~$!8mmTerw+58-p` z-m!*$#S$Wy?F-2sfkD-eS`SO?4hxNFwyhV5djFRFXF@r?NWZJ9gs)?_fBZqG$f`@j zbfiv?J6hgyjBSMF(0yWUD{8A-9mszo$#p6{MGv9BtFMXc&^zxLyR^N?)ES}%g5Mn! zJCQ@IU~q$g2S2qO$Qfsg5GC8vjqGHGFrOBCo`bA5(fYO8a&-!Kp5sG)VXZi~*?o?= zb1qdx5~pM!k3Gh;a3~iT}8B zLOFA_2G2y7fAyQ@dd9aqvub)h_iFn7Dj0u#r?xCIVDFCDv|M+#_#fh5nK8@cn+cwh z1z6!j`i^z4)LY%#7rtR7c;V51N^W2`g!{?R!9B-v zKU*?WnG`0SoV&9?7Gc*6kjP)(^@BGuBCz((4f6dqlYjTAiWn!di&7izX@%0ggg}#XlPQh zD`iZ2MrIbLb4p%*Dj@rNx~mL1km`H7D@?fjo6s6my41FJSQa&Zr()THI){cW>-)zi zCUL7qX6FRDr5C;XK^L&XfPB{c^geT zfxI`C%n%@KE%CTJmCm8Iy1j8tI-4ix{D50|MLwS_7(sn)@ke;`Xwwkh_$=j*ktCLij&1xp5Z*WQnn`G3X-*A zy#_!T6V331G_@{rkgM*|a<)Pq{`-th&*0%;J*D+06)&e_=JZ#bny}{<7yIe@n1van z?w0%QlyevbP7zP@%~@1!9Q4kqR0?TGz9CjE zM}Zj_t-n7g&iq@ttl&WziINS`9We+As>QfC`wjYjf-i^01OO7z9sqao%$$@$BqMQ* zuV1)80t(@bTq$v5zqq(DBO_#wQ%@0Dg(N@_C82^I(!{fZv2 zEG)xM%~lIAw!EyVQN$wC>~NGX<49b!r>)=U&|LXyM4Z5muIpohT`y@zo2Y_o=IW|! z;qdHI%2>C3jn~+N#39Jr$^_8apOxa&wkPhZ*h1d+jzQEs2qx32{F!vNgV?#*s_U$U z*goxt;(M|)f(pxGkiRzUufu>5BT_v{XcNcM5b)nP?nz;br8??E2nuQ&RPL(y_HO|?Q2)S*0EJ0T6yzJ{BugcBE zm}d&0r?qkyj9#q37W5M0@iie!$7o_I_D%P2pNC1Bxlh3t>M zw6Cb@4Lc=-m+!pHmPGZmj$&{4MBAob{bcFOdl9>bg(EDoTcZ!=iS!?k*gdj2dAIISk%QpgIAcs}JK*X@FaA9QV_xJ`Y z@#>w1=g(s6?TGSQ=xGh2?77Yx*c?LzqXG-1LlFqQoxnk^Hc+;A=m&@vNzjDiO!h_$ z!peq-Jc5FHX*md35F!$;4ghG!*Gpb`KmkF91gx?H5Y-L$?-@Yj@ODeWcH)IWn~V7^ zbB4lg?vqs*n0Pe!9cUR)V+VKl2iw0G&ztz%U7!;Lj0xKt&RIky4IgIc2nV9k7CNg4hDW zCu}=uV)l**M$!2J;E4GE7$86A4AqpSYLNYUu^DrKD7?uDaqKLzTOcKFO1W0KLW_Rrll-Y7rL3*{;-!c4 zFKinsYDi6>sbOGgemqqaa^~#F*;AqJB&B5g`x0hsaxvA0xdPt6Qf{bm1xk0g3>XkO zNl-*b?5pbR{CPrAULWN^8(lRmXR!!XVR93;ImO>cO-&vcH0i z!-Dt{t^i5_V68uO0^frVTCe95shuMhid{g6{C)j0#?dMlPs>Iig!sew=hQN|41`4B z!Ngp@T7xd;DqDWx6`~L~hq}xQM%i;13`dtNtm|;gb_BS&!${CG+PLG8q>6EXCpMRJ zi(oX}&2qkIe&4}->+{!Ef#q@is2YE2P0lBsY0y;Px#_HCo=wnvs#GLxG9~P~ja;AP z7QdllO=noi^*@A@9ka$%9A3ar11uA!hYuUZ2az$)rK!Mm*R~+O9tv+fsXeNfwLWr8 zyP)&U-vA7Qf!2n*HdHNCxFXlVOmF+y{7cv$w<1F?D_G%Va9Su+=p!r)461}z`o;Zk zuuP%zF+uDs*l~no!bKrbEe%F(_%bgOrmBnMCnkE z) z<5{z>jL)(;>+hunbJRKv$xCfTPlHw%0B~oN+SWvKee3v{GHtrjF7kJkA#ba}2k->i z++za=^0~w2MPGbIXSJV+^ZRVoE$mI_cCHwEFNBC=Kyia0Fll86_;b3`Va?w2(dxi0 z*4^Obig_G_c>#OwH5VE2W;=r2NX-l3TO`PHKvxSUg@PNU>(}uiN@o)OTjH3J2nbDb z*JHJEtYQCRSH+#drDsfIp5Ng!i)$mR@qO3FpOY#ccXk6PbGHJBXCPB?J0e)$ z_;c9}I@Aml~Of3)^%X+qP{x>DcLxZL>SJoj0~^+qP}n zwmSVzzByB;rp~G7PwZOv+UsHmV<3cKeH%4VzwPg{eaI!&|Mv8Ckm8X&MKXMfke`C1RvK zB-+9gECEli5y^((_oK*<*kSR~ek7_s9?20wYY}_FVL=ppmdgOuHRMD$BVuWYI(KNT zHLam=I0~2uN-8&TMS=V^DAkm(DoNx~90U>UC~fNCLd(!C8q=SH@TugH!6%WB-#yqB znc%{h_tRke!f+ET-a3%T)HYbJwHOm_kqjqlmV0OWvl#WasQVWFR7EysFobo@$Yb}| zBvv>$b`W9F;1|uf$GK>%KtZr~-~Q70_0w2#Eg|4zJb|a&EoDjLeD*pmsS}^f(i#JNn{)dP@+v#i3qw3 zNa7z)Vy8`3YY+J950jHg)|1f%;vh3gB7I3GP?jgsTd{mXrI?%pjA&y<-hBS72ino5 zx{Ai&gh!ylq%IdmZ(7D_YoS25(!K~spx~yFX{8v|Ma>w30?Jb^`{LR2tc2a^g){*n z?a9MD--a!XMM`ReqD{&;<@sy)DQ5=Ecw!N6tO-sAB9O>uPIXPU zyjAi1cP;afWHVW9e*JW5QeHuc_FOs>tT&uundHI=$Ku7hOx%nBv(e(_!{W}=0wX>X z6IqrFc9;9I5Cj~3j&%lHfX+9eg#s-k=uporPO|Ob9Hq{B;m!7h%l6}ocznn^VlDf- zm;blbQz*misyKT>t(=2f8^BtQ)L&%P!I74c)kTRJw+D1&b_-`RwyQ>~xW{tjHA{Z9 zFA%=qs;a1{!85I^Kx()sFm)YQ-#mn2jpjqOp4)d_XO05y;tD0CZ?Q^U_ zg{s}~3?$pAxv8)l(^mS^=lTLD=nu8qzp!V_sDzQW?UT)_hEqR=V*;0}Lru;5+fl0m zXSXn6=UrjDneIl`Qa_SXI}51SpR2R+s3-T*RpaykURaaqSW)oP|DY?aJE`50%)#z4m=9Osh~|NJ>1Tk8$V3pUK?uen#yDg!#wT4PI<68VRKM2@`jVV(aaD3cR589O`(RM%AHGPpWa`?T9CGg`ZQQf&q6~H%%FE*DcNC(l= z?9}-zMqKqteZ1-N8PM|;*A>**y=u~ZJ_rngyX(1#qZF$*6IFMykP`T;L;|l9S7X(0 zv&kO{>aCh{a)!YIsZ#t~iF7UJ@tt@T)BqVbfz%A7Lj6m}>d?Qvk?MZj7BA;b;yDn@ z+v9IN!0@+juv9%5Z_vdnd*3RJ>n}7CofcTfAoo;t^JJfJRh#%!s+8_fBmEHH=b-H0 z+~@MtpMQsXGdk*)RaLXB@F$WvvxY_RgX<@U^mW1K(*{H%22H$Mo6-jPvPOzJ2l~r% zf7>>~dW~4~jT*?y+D3)DBMdi&6(6jQR@jt1!;}Q-mbv^L@b(_7uoCs!8jkV~P``pF z#u>Lh#n|UYmX(Ln`b3G)$+IU=&QSzfWXU&@B#+a=tGREuHd~uQ22Wg&s8?p$$C(wI zUJe@TO2-~|dhHv$1$PX|{)&<1Soz3i1)X}KP#LskFBRoMs3`1@lAk1CM17bX+e#>y zB8&p0{;03aULV2YoW4?I(tI4J$(js8i{nN6>5nnd!QgHHrnHJM18Vl83r+4saU6lO zeZ+A3I%?!(XmFf(%vR zhz$0(ODEd2n&mp{vCgl7wh3OvPj)?M-n(tGqvBn=f3R`ys<%LxMqfyKu>-ckk9Ixm z_cFY}y1MqXkM?}cw+iMd;9~Y5e(z_NG~HaG;^!dFe)SURTj1m%)-2Fe*zHp5?|9hu z8&)GRSJN}cEMq^;@AvIdIUFiZ?$;n7(kt&Nc0lyKxeO^DV*cJ&f3}z2fum#^Kq6}S z>1#y(&z9uR9m*4Jzaso&$j(rR90>5Z!=*#`TG zD{J@8PnPW%T?_rb5)VCNKsOQLoRe5ts31vWMuUW41u5!w9$+%~YU2?sLCns^<~6f1 z&W6`X){ag^0`=p4ff!Cg3X#5$7iE67WDCRj=NWptWnZkYiX()h7gtzB_8M&4oAymR z7ycskJybhBPd}t-P7doXdv>rECNJCUu10S#7-!l?psrB$`bp!jl+4$r^i4_;YO1NO zs~{pL$j3uYuB(nXBs8p#^yP5T6>=vm*JrNlam%ApZWjKcV4n+Sb6w~TQ!D+m%a**| zUZS$fkzf0Fb8v(3)nhdI`;PAh0ely<7-<9{wx*-+a57pH#7{A<=*R(k2YvS@fqd64 z&oqMBJ(dPxX&a8h<*Z8lN{Vc~own)qZd=GQa3n zv77yQk+x;4t9P)ly41QoZiH8~Gl)_Pqr$f1KOGKzC7; zF;9S9k>}4|{coif3=|CX==*^{0OQ7GD!X|ur#pd$G%==D%A#;EHWMWl471L5yY4l& z-nWG{>XXT`Fj!+nXfl6!bLYyOWvjJ0#YvUoSeSapncTZ9^}n;Rp3}d7HB=eR%SpPT zKX(a@JANy*0f8F!j!se@ZeEd59!x=T|Jn8u7WV{1f2RyszJYCifgn>>NoiROSYg$7 zHWn8Iq`axQIj63@qcbSHrMEAmt!rp_M2WV4V$ySPbarl@x@T&6#k+E0V{;2Y8lMIsuRkalhE9ALIe##W2ZAX} z(}G|q630xsXzX5Y@Eh2Q8J|l#B7?-!sCd$kHxx{yGFvofwI7jBWkPc=99g24{tD)E z``Pr~Sk|5=N}aaM>FgGXpl`OEH zVMtrdCAfl+;AG*Dn=9=r-cfeGIH~;ECSUpMa;(lGrbJ{D>vEGW_k>C79XiswGhi28 zsH^Y_zm^_LBZk%U(O_Ka>E&-$$B)a^`b4nUb+6|;hDI-vUg>TRyQ}%q3?Y+Gf!Evo z;nZ2=kAISH#~M>WzrQXE+n!U5PnrJD6qr=-ijs7qP^mH_C)A8Gw6QUn!=eZmtDHQQ41Zem zJXSoK+(E$$tP&AR4%IR-vq!5UeeF9s^xvKx*2P*ga5hx|DNE;`=t}vQp(bgv%XOSz z8U2+RlF|%7g%LIhx?g~9I2zhnQT*y(V-*X8jkM;I#s1qj4wi}iq4Z2mt5_K&CSE%g zHywOj@apXa{c`>u$+^ez3Y`nrH|v-O2hn{i~{~Q3!68{n0Au zOZT>0l3Lw)p(n<64wQJ8_T?JcFo&f^x*E|A+2-?d*ZJNZGmCpHLU335~K`rJbOUB`CGee~yMLp5)N9e2MdHYZ)aXeN-w zePGX#IeaOOCyytlz%g#C5^v$rfZFfCIbWVru_bNW(MVwN4ZOyL#E>gX)4%9z|9;Kg zD@`(yNs$mY8x|6XM8*E~`fxIEMd7Rq@t9Oh66<~5QE{*{2t@tC0H)4~%NFWrahEwS znSlN4gal!XygRo|m<2?gv_TS2Gm3EB16BxO3LBbv^A1paRn4}l^X?!4SWA6`LL5YF zARj7(?wu@HPocjmNuMvWe5_{8!%#BJu?tB31PC07sPvv(nCe{tXVOvv*S|v;7#0w` z+kz2F&tqd~9uS$bG5RP}sSw5U{V$9KX+jeC*fv=>a%$RG1$8uILRM1>k2q-;_lLwh z3`~ufw-W0&)MW3ZRl39n*&Pm4oP^+FN-^HN$|-ovpe0IV=Mb46u)}OWR0+YFXr|QZ zic@8*PR@Chf918K^O!%zc2P(U|9qdO|DBl02x`E4i1X87Avo*O7MfK; zrr#ZJmN%g=LJ+ZFRAsJ_;wU`k|mC780tOLnJsN4I4V0XkM0$cMJ=v$JZYqWKs-KSdNMcm~UuS zEmi8H^{+Uf&l_pVr*xV56@3Ao&s9LMJwT$84^xUJB= zEf?TY#YGvW0`I6k<6v5X1ZkyHD5YM<2VLW|ZKM|Bx?F8*1gRYt0(aqxs>izIjIkN0 zt-F`T0!mqZqj{;wKY}v|n^*51eJKo4p_;%c&wNTor+kgN9Holos64%wOSGvK=G|iT zv2iX+K&C~@xXkSQKx_0vJ0;ASz7ZTPtD!4{X~R*?vKs%lLN8eSMvGKIJMcKyalc+; zrKN>#hEc8>qb<(5fTQYeJy*)KUoVXDs$)(wV939dqe?!tcJKJQLm9tKcU~j&471eT z&TA7#{JG&3QrtC@)FA1)#q-(GHfU-h`KzI+mx4yiQX+HV*!8;at$Hz-R@+Fu%*_st z%HV1zbNO$f56_+u z*4f_(Ua4%6XtZU&oLdpy=b|31wy^}tZ)@IVcCIsCtDUa%?8Vf!oh#fp&bkTsZL;?! zU*FoQA#HmEv{pmqz===?um5Y0>BHTDHC?P;+w8nAv#C0Xrr$Sy7ovzVQUL)IegZQ> zXd5;_fO63#BTBz`&9wVOT36B6cW3T7w@b@yLN#y2~8?JWxv%t zQqle1C44jPs-->VOXX`>b9~5LYdvDRKU^*I3CzeXWcJh$JXetaSsEO4&6vd+ViT)L zwL_;J`^m&78hAb%2mBQUkh?AB=8(+PHXT$fe3<;eGc>&I--wU%84km(SVo@esWZ6q z&~(1qzo8YOYrMZfZY00SZTlpM9<*RLT$+y+%r5@31H45lV#IHCgk$vaRnmxh;K#p$QlSHBTBcdKpDzm*y)q z3bG0aL~09$hT*7T!!6hFSBAkxF7uso;a0@)r(Gd8(aE%80O? z^*faLyS(LiGVwT}uuNLFqL2q}+|F4-NV^|P%Z~t=RBGI0W1i5NG2%pzIIVL|qwyG* z6T?iIbg%D1EN$8+6>;HtdMs^WQ$CS3hJ}(VC-?msN)AEm3Mp*+%h~*ZCtU51Gs(5wrmJBM;#$ccYwD%vpd= zJBBPVUCF56Az%EMy>KU$XqwA~2SD_TLjRpNhx5aZ$ix|>F?@@bSRzA;S5=Qle#l;1o14o0kfJT;~Ik>of-;#N-P&gsYV95jdfsBHV=@-CM2M^V$uxN-4fJIUg z^bio1M28tzvM*fB;a}Q}A_~vVlTRze-T|3CU$AOaDow%K&ua{5hNMd`h=Rip-pD-} zF>`D!OXb6jxd08!pxu%NI>g+SFRDm2nw#rSfEHSF_-hxlhB3aXSCo7}g5dI1$jai# zFkpEmw_cz!VgS@VRu#ivM`59D~Drk*r!cw`<3%QZTRFUaoR%v>F9e zyV#dmmX@HnRqs_)&E30fdAiNg)$DZ?z@t{E4%?h~Rwh9CT~0vNT4xG+R-R?lV35{I z%GN$l{E?r?xri(GIjO#x_yaFp2+os>y;^tpQfs4?jbW3!VQq=!RliSDADU5LzEaLw%Y{C!DUMv-s+$6A0Z{R1b8?+7qU#PTy=QSy5){)E5jR$F!;thkX zvLSC8rppZ)|H0MC1-;pTO~b1n={BCoV|>}D3-7B}nqxHBvR#o+>D)R$-pa?Gs^TSK z=B#jM-@@=11gIq8p|=i|%gilhm&=4FPix6@XcvLauCvGd0^Gn0c@7k;r{iX-;GfFOEo1b#4gK zk%`_crM*iH5T)KJi>dWR|=~XWDx~{(gl%t_)k<8MiFGH z33suw4?atyY@&0+rjwwm7I!P-17*Npt~1%Hiz=#)NPZxyeL%RgziJY|a@DlCnMS8G zm^jxyZ<)$xJ9rg2sQx}EY}-=`8!s;3Dxw>SV--_Cm=ByE&c zci6>h$d{l<8KF~1VC?Rqfqg17Tz+h*b1Z6WjCli%aa<*#t3J(Z)XRH(MpZga067bx zK6(^5VoxwZ-h^HxKUm@o75LFbQs-K8H6-IXM5sL&bPPu6Na|fNLMe-|Svpv12Hnm8 zwRTrhp)B51l}s9CFEqfZ8W-9iOy)yBz#kLBL%ENi5A7-~SDF#cN@1j& zT|xj5cj(Y$FZjUYsSQlaMzwUxpr2fgY2L>&2+q_C%-f&NK^`yg1pR4Gn3~60!uA9z zc)S{P&CMg6_U>l&4TpMBDma{KEUWu~SvnRKcvU)e#^Q0Y{m{dg_sRX+vi!2OEZSXa zVOznUJw}UeEyI zh#ScCAJyvt7a!W6o@oKw1WtM*4t#V{@Xd!@E5uW)kyfU0bL;K>D|aDfzvPCWUe+BD zYcNq8F{Cz)>^ALQtV=eyyA-U`t}M9k*VL&S`chUH2)5wu*KT;1F$TAg1-G1mlLb(c!PGPw`79kIp4z}3b!U9|o^cn1ECfZ_97dLY zLc_g$Y1BUZsYmpY1C;$>ll6W;VCNLd4h&IexkAgcMmN5{ivofi zYe|=tcGMjPwSf)XSpMwkr28i|>qud=6W${YiEP$~|Dl6n)p_nxHx&L#5U%G8n}_u=B- z!^f4yC)1;IHV@~Y$1yz~z8{Z@SPz1^;B>d=BC+c>Do>~NBEqrhPuMwpaTwn zp9AokRSi0S`aJ_P`LuhVBiNtyZkz58!+K03`L02&3|Q4)N3frnTUp;GhTJ@BgQ@#@{1f zRTT~Ym)3TDfze~lVcMdG3>EE>Nb}^*SsIH}YgZ5Dxc;|ZYai>L_8(e{$7uIs)jHMv zXYJrmSDo3p<&+v1W($)nAo`3;K=U)LTVaObbMBJj>h*VL}5{}F<5SS zMHX#IO>JF0Sy^Rsi(g_xM`u@YQ)^$pMRoV^$f$eoz~n&t*f*`^otRo~1zT9(*d$$A z*{vAbIy~9}**j}FIKH|b-Z{UI2f2BEsk?jl2)z8JwUOVn_AHF3F9_xlhGLB6=Rg?B zV3v*a{IA|{9QKd0G1M55=x`U?!Hv?gXf^N+kW6 zEzH_*b^c&HR|w*PM)-zauHq$|dc*#0y|m>k>u@zssOcY@5B< z^3~fM9yr;c*KBnbZY)5iV$~YRX}&uCeQRZ*>JF@4=bTDYGOmuqm&*xybKo3EWZ#6f zeJ?qgb)|Frjl~;<#+#Q5AYw#tA{25EEk>G1=j>n5Hayg3LxOd3G`)|QVz-y>lf zEUFDr1f>9_oFA^jI1WNe88T)9rF3I%2C4UNULp+=((=epr$RbDg**;+G?g@q*Cr=M1QT!RS@pVfwYm+HG&Pv)PGMUDM8PJ>B2KOoU*3-G zqPO66RuY-k$um6U15Yyyt&dH1N@7{g(^3j{oAcfJ(@R6omUcSA`kzCb;;^ZNGRx8x z(@X0x#n&wqN#Wh>Tfi~FRuXVkW9}vV+b=A`z)SEJ4!_2gSIUUmsTQW_*ii1a5d42{ zy2*ZxZ$P8;LYH=0Pq*LkH1V|p9$fj6NYG$KNl3aaS8Y4#v<*cA5B+SnPg)RLKN}eQkmCfQ`H*wRr*{u&*^eR+ z?LlDnb89}eE)7sT-aEwqOoPD9;Z}W)1ttGT%FZX&>0|Q;JGx}}`#7wHfKxOC6Ne3k z)2B>S_CrUjR$I$xFK4TuzhUjj{R9^4pbk5)${pE-GMxzVN(#?14%yh;J_1f^Ee>hN zKjfSb3Mr_ck778EoPA0X0@`?x;L2W@Pe2ZNHOLwbS z8L^BH2W|qHNTBm|G07nwH$ZUiJy6FsdxdaG%o82EMVwlCwNrJe8y8I zWKITE^7-s04b>3(vFVFNCm99jL$(zZx?xu(+$sxly1|X4(*zbIt>X%zW$cuD0;RP( z=hChdjj~S|S`sn!jAkcJ-Y;F$Lcn)LO^iNPejyy>do%5(Ox#*1%kgqU3i^JY?{bQ?`R(xT(^TWGb3^Q+fzo2f{FfSJ5(Q zidu%XT1wWaJ{MVSNcB=l34I;kGif{F(68df^c}9J7FxM$C5=hR!-CuDKA_7LQBY;t z?{`-c(tIYGQ2x+^05B-EFLl@ANcG#2{02P*sl5lf<=EsD$KK^|*Y?3*k9-lGq)~rZ z>Q|O>VX=}H7O9*gEOv(uUi~E#VVgod>)XFp(W*Y^%%A1pNK}!!F|ld`X%P(P1>F?^vn*+I9DGrdj$kG0npR*Y-Ke0!BW2 zYYD0<|qq7uVgh3ZE z4!#H59trS*c?oTlcwEwRcLEQ=l%EXY!_8Kw;n53xCAeu{V>QaNrHc@_E@f`c#!(`C z-0_9Z0p0EjIy$LIa+*bELWDtjtF*HtM3PHf@LA#%pKIN&wIgXhJ$cg|nnRLxP1E2u zVkcJ{B!HI|sRUbxATK)?-;{CuYDbkj3jzA z=Nsc4cp0I8J^C)1jquezg>HSJnT>MHe2F19!;3wd-j1D*XDu^MR&AyHfnkCc+}l#Q zmVNvnzJ(Qa+w_ZerJTjQV^;m!6#0k=Mf{fyJqU5N66{6VX6#5|)2oYa_ampz_oZ~h zfJ4OoOdsM0weObCixUph}AG3$@S+d1I-4=T`3Zto8klao`?dur8x zQrIvoUQW-xbEEp{&bjT%;8wDny7E1f(&Cpr0PgQPWHUv65NXI++d-fp^W%`Q2!6s`V@|K7Tr!D{oOjFHZa~e7; zP0z%UP?a~;KWT>CZNZ!V#=11Y1!y699D%%GBWB9NJ*AOGaiSK+qRYl&BCsNb3uCUsWA@zjR@MLqZ;>1J zQ8(eCBV&fOapU3FBLyKtuw=el2{FZ%01a5iO3Os< zh{T`evCn3jH0O!^ED1)~NnWPRMiEJBv=J<@(PsO9vJT=2-(w;AQv~V)EYj&bW$-Gf z!xYv{_E5}OReXw$Q+>#EjCkT8MmR9iSVLe9M#Dm`M|s@OO{_I^_R~UkPE&jr)16>^ zYf3_xXad(bEqX^;%irNv9n)E$0ndU+R;Lvkl2Y@-4Qc5qQsK>m_Xn9#VeHQA_TKgWkh$Sr4B6(oY z;r8RX($IN%7CEOfmP%*LL$E@XMWI+9w)hjED;9a%lzyRmdDjWauLA*P<9dkXLF^Cg z7NdEj6O;-sc&P05mKs)=DupHCIrWrr9++?VW6~l@qoou!hi^W-s@~8?Q(482<__HB}3Mp}j=$N=J z4F0C`jEO+~r561&k@wYJr~z<@Q7nZAb5(8yQQ|8Mo`4IoE=4>l@$fJBQCMOFU^PfC zgD1()=)ef&BPtrrPXJ^`PXLi~;RrHP%UCoj0u0Mj>GC$Xe#cH!sMi&@7zNm=6gA3L z0zTaCQ3Kzb9V#a(t>f}qD+1f`N=oq@YCbAjH&PlpDsiy$Vo@ss!dcNg^WRHss!;t! zR|^5c<-K(NhWo*A^QEaC!fosrD^le*z?6xcf% z?VLT?y+!&G8OUZ{gK+)oCFfYy^`_ zJ#5Z4jx07AZ?o9UxJ7BZVrzr7Nlm0r5$_}cWVW{6w<_Sb;Cqp#;iqTdqc+ltE9wN; ze)_LlHKDt!q+HhEMW*57>Ll?e1EG>tNIMp3Q>B(WgopfvGn*^q^anFbawj`w3pxWe zHHYAl7;Ka#bdpXjCE*l1ck^V%F*{w<+6tPxU%~yOUAoz1g81V>wk~0^#2XAV(>*DB z@WnvLMrEkcfNh+cGI#hGp=z46E*eEac~n*{U<^$~{Hg9J211x-~nSk2>mgC+nlS$hi0 zjy<@PzUZxzVq8KmUZ1h9yERUB-mdc}h>b>eW*p3}mdnacz&D>?m79GeF2E)wahh|l zxSEZX+hlIrkbWq1uI+Ame4^N(fIUB*jt6Q!YGtqxeHJwF|wx8J(4rMK7YJkm@pnavFIhYaVT0-s=!*|vjP+40Jug@ z`r=#KC^LosRaCvy{Do6dzgeGcFL$^;C|fCRvi7yL={(;RHoV5CT~Tn|I~Hw_oq<&5 zv%XmYJ)t1%uCy&fz*6kFZK+VHbg}&!^qpW%IhjT{5bRA8>_D7kIm%YN{PN6D0`8{X zM^9BS-hPdpuI!9&mXQK>wbhx6Dkl!4wDphmKew5BkmtK8SEywu=Z-A?B|%3wx7MBT%*e~!9Pf1>&7kgmlKB)q00Dc}-10&YHXP>W_Pzj9EQeMdn5bi0k*Kr&C6rQGf6 zn8VE8g$bDz2vx%EuhQ57(ziAfZ3INI)`*ie<9$ z%PT4q3QKBB%BmWhnypgn+S9>WzKaGbZ5@MA4Sl0y;{-KB(*YwB^9!Q`Gb@f=iyNCQ z%d5M_bKl4{VQ245as3;)hMu0^%O89rSMzV=s`UExFXa<#=9_-y#d(9h&a;oz?L!B{ zK36+Q*ONhqqaG?Wjn$KbN8th&8K0yVh{xj2xKecAZz(4J&}mILpFSKn$Fn=hR$47; z%V!I_y&$}^mnj(vgmDdeG@Vxz$wpwh$f{v3m35S;Z*QE_t?0_P0|bwr=^3g`7P07T zxKcJ+Pc|eG;9HsSS{&u_nwr+p;{lXC;dobwWK~D#7ANs*y}Obg8>kp<3T95J~1C*SC9eBwfle9 zU$Hmo5wLztczBKK_p^Qh zF)a-(Kvw+o*(VW6jWEe82EjvcQ)mVvxV6>}&^5Q##KV7|odt&i=3#yUF00RsWCaFb z&|@=TY0*4{ki^sC$!H>qqVRcWk>l~j+ab(pqYaBC<>5+-MZ-PH#nVZ>!^vz-WQWZ4 zEVQvwGD`h%&7mE7xJtEMW%88G8jw(kdWJw`%z;>SYSal zqQ-lk6|3&aQT%lGhmYJD9TI0>f7-XeltS7T6)Wvg$uxKCJo1g}ktv zp$BuWDxc;xbb>W)&u;2cv$=J+;0L>{IDofut^dvybSEH`Y~bE?O?~9vb09>L-hC1H z=>nF-Fyjs!4V6QZ(#Y{!ZR1E$A$&v5__NcXObEv!>;>hW@IefY(&xVb7ws#59z(G+ zeAz*Y0(Yai{1fzE=i&zbHu~)b>Moj>*~@Z7$G=N*Vs$`(d?CnM^K}sj`R~5Le0Jg` z0A{vS_b}{_`X}ZTQOJAwSS-X}?6q8oe>rD|4KFA+x@DRTh?LlGl)gT-P2%_pFDVO$)pXLWl zhblw)-1C2d2*VTdfrl}RLZ6KE(~_WB&RI@WKruAh7;B*eJqd$$Lr&E=_u4Ck+EpJj%!}^dO*kMgA4S z2_g_QeV`n)Tt8Qs$z6w(1vyH`g2X9O8nTM%#p=1$Pa5L<&yR%c-{rifs#8RSi7~vj zreewv(#?~g*)z|lzPgk%mXc(;^4`HExtKHA@2SWW#wHm9R5Bk(EO_zVf5r}7MxWT0 z@*mR5BTOWc-Kvra-k!(lJ1nM5A6SST6#x8TEuIIyECmG)m`jl^!v1GVBl6I$=qjrU zO#O`77h$%R5BVpW#c^oK-$L6L4Zr|=3PVX#zs@E$7!@a87Rc!FMSIhNmjJA36=wZa zBqYcS_`j@V3+Gk#A)ZT+G2z5wFN9-d3(Fj7XjE)KmwC>TV&$?cgtE0&e5BPXE6V5y zY5-$ZfiBq(!d85<6L9s~S1~$d^g6s_YQIsOYX;@$bf+(VV&(~R`axc~Xc{lZdoHIl z)TO~vm;~114OQ>=S=LcifL*h!)LT_u>N94HEFgr-WoFx2%1EQnGRZ{c$=R5{S0FA< z$gqV@(|2CSoPaK(=SA=7L% z=(k`+U8QN>@*JsUbt`dJD?lu7I3+e?b;p}Ccc;tUx5Hw5*;)(s0XJARmt?Q%tDXPA z?5sBK&AAVF<}dyRaM>0lHmW z??m@4JT;6mY63julZ-V2>J7pP2u$O=?@&Vjl%mS-jrA0Hb#gk{+#o2;-CfdgJmIsw z7qU=SoDZkuM1}(NC{O8r^E%nTL~JZw<%-d;mnv~dF}$Ve zbl)1wLr!pn2(G3c(aw4lo9}3*rM*=F+U^qm=XuLT$NKh-LJb4U{m4kyxt;<4(dNdx zLn>VL-K~)n-pb;3TsNAoy`CF>o_A$ZuMjM=Z>-DiseWD`%kO*7Pp^GCD|gfDFHEJM z?0$h9n4{flit%Aadplfml#zBRY&LzzM7`O)j#0_!#9CX(Veai?zz8R{Dgm-EaXlhC zv?tgAT`-tY=VSvgCzy@*vqf3s`D{g(1x3P2Qmc-|_ZQTFPJR-hRneto(icnL&a2}K zKFpOH2-u&3q;_tf%{kjd?H1JJx)f~`^G#RD^V_(-1{4b+-LYMlgx@hWELNwaxF)|X zwyd7k76#y0u)Mye<3v|ii*InEfiJPEAM}aDY?VFp&ioln7akH&XSp@!DXSIyI-2CO zvv>7nipleUwibEumUrKxHtO;?-m6L{=s^Ca=JBz?+qsAcwUhYY6*4~Ws_HJDOs$iE z(2p;py^LRSw@U(s9iyra?#R-J}8D* zD1}!ThOIS)y%2RCNN`IshBasnZ@7kFNGWzmf^Nu$X_$v?7>G)xhZ7_&KUjx`=!bu} zhjEsONw|oIcw>Uth=9n4lGucJ2#J>Hh~}3lb2xW>sEN(sc$EPEilB&wQlW~&V2TvA8>C2s51Mg_#(KqiBNH;EF^Bi-fp^k64MN$ch89i&W@k#t0V6cpu29QP$v# zt?-PrfQr<(fWdf)t9Xl;IE#!pj8B-2o_LJ8XbT7zihmc4%{VgG*jDXmQ0mBy8S;(- zwvEJSkKx#j;;2&eI9|>mjnRjT-Z+UZn2+FChyuBfcc_r0Sd8-ciT#*YlsFAh2aqZ_ zkL8$*%xI8kwvGc6kpy^<xA%qKnj_G)k*tn7?sgEKlj5k@6 zIXRNfn32#ZlMNV;C8;hTnPChli@iuhiU^dv=#xgdU`kp4hE7?HN2!xL$&>7O6F@eU z%6JTG2a^*5DF%3Jil&hgW0em1Q)78+PzIJclnxfDd;aBI+w_7q2YO7oUs{M1YZ(rU zvup53VP=^X#YIcA1DH=)l|fmQpwyS{p+AUuio6w=jOlNV`5nF$nKQUBGr5<%beYdl zb9LjE1tNXFIG1_@nvGC5wb*9FR(@Ssk5h>+s<|=grkRC@h#?7;E>@d|;gZ@xns66? zuQ-|SP;kB(YXNCb#c7e6F= zGL5Rnde}*NFL{^iLwMpB5NpAn?YVazcueTHH}|RkdG@KE8sVK5C=mXcEGO`76{w#F zx=XOB8S|cq*o;VYt#*u5~;+_}) zp?%gGA;F;^_;$mYad*I?{-H=D`UC(fCJTq65oe;OMKXM+4=@^_7pik~1Eff@D>(`V z4CgP-^P#73a0N(d(J`a~QKSlXq&}LWPb!+Yi7Qx|5lX5X-6N$)b9$3D1HieOW$JzT z^K>NFaX2!k+5&wu8ecma0%*E_H43F&VlR6NKy(TPT55In5^z6ir-gb1ZyFkV(Wgc* zs72DKBqm+%VtjF$qRCgNhdMQJ$D=gLsC3%@srn&zXgY3|$`6mqJ}xwP1gfg5sx__p zJ^|37@{*e!_o;{qEg4v;1j=|8C#=R{0Gf)cx^{k&nx3R;7{=JNZIJ-+ znql)AYQ(B$_qwG$p|2&Be#d5ih8CZH)O(p@u=I+so)fS}dP@wOVGbL53M)AhE3g59 z02TX27mJ$R3N;(cvEx@t#uTzixtwD|uBO@y1Awv#v0!tWIrytkM6<9!sXXwm zL!qMpOPP83uL?u8kH?t=HiELLFlL*U6IPjz1grKEe)?CCa~rkV8ZIs?ndnfq_;#`;Vxbx<{+KIas;;XqxvZyTO}6 zrAw8+Ct0D}S_-hbx$vyNtDCWvxdtHs(VGhckN~Y4m2m02Uz@#=#0Uw10Q=fs#*395 zNm!{w0OuPausQ$+KuPIa5|T^*gwKmtXnVS~`!M`#xg0iHa2UWg+qK7g4FA@t7vmwmB=9j`2jKFBQ zi7q_2pWBclJj1!Mz6?ykI84L7d%}F%!%|C}p3B2RoVORuyv}*Vu`9t!?6yqo!*W~1 zgd4>pYr9lTgH|lXWc!ojyTyg;#Hp}*V7$XWyqGs!#(0^=Wre+JjKpHh#V!2Ca!i=L ztHpE-$0<3+xSPk=M_Up}#C{C1Y@EY7Jjfaf$S=&nh}^e9tfq(D$Q!)B^%}>LJjB*y z#wL8pV8*OEU=Yaamr;mwtd{haYbz_U>YpIE3tfBD^ROvamS?` zmRE7hh}C6b8goPuxA1Aopkbv0m1@DfwgO7b#heAzx6Hj2AFmms3aZH%OBgqD0Y-jiu6$%Z)D%~a3M$jme2mUkDJ=blK;U!VwHFx0z{u^6o0Md)aYy3kIq8}hG6C(ZviGwQLj4DLq zaxXp;G2R5yQ(%+a4Dk~@C9>oDqj8(;b@vx-rT`ZWI-+KwpWYp=(@S4l7L#3wA`~QU1l=(-URh6xdBnSPn)gyydXePPzSgt8zND zGG@1QPoS;PYJLSB*sC-oP=-z1bB^S^Y3S(i=3{{>`Mu|K$mSaT=oghJ1wQDaXz5k* z4Uqo-7Haanz^auqaOy8`cw5(%#OkW*6fltzH)`0_$D+Xj0Q6wQd*vLF%CT zXxOR=Qzah2?&z|f<$kcd#Z(-}ZnB;uxXwOTc=7B*&1Y>a2WtBpI%MtEY-JS}2h7e- zF0r*gJ~#=U>pVWgkfa2ZH16L%IMk*97hANUOyW&;?|XYV>8|e)JU0Hm?`VV80bkJ3 zUhs)~I0&EcMYiw^5#fQ*?+#zvKQr+UpYIl55FUq+aI^9RVe-xE^0%8cGSBi*Gx9b6omnICIgiWb((_P@Vn84CIy3Y{e_=*ny)VN| z^GToBBD3vHe+V#Nvr)fWFN5n<|H(@5K}W03rDV2?GEC04x9i0086y4~F7Mmgb43>dLn63&-+I*Y=I)`p)(tOe&Ymrt=AnN~hGS z^@`1Ex7@Dx3l59N_^!OfdmU0Jcux%!i5YQI(!H*qQr?5D_XpWF{8$f{~SAd{0K6n$dM#V znmmazrOK5oTe^G+Gp5X$G;7+ti8H6pojiN`{0TIu(4j<&8a;|MsnVrPn>u|8HLBF9 zRI6IOiZ!d&tz5f${R%d$*s)~Gnmvm)t=hG0+q!)VH?G{dbnDu^i#M;{y?p!n{R=p- z;K76o8$OIUvEs#y8#{gsIkM!*lq*}lj5)LB&73=X{tP;_=+UH0n?8*?wd&QZTf2S@ zJGSiEv}@bGjXSsQ-MoAI{tZ01@ZrRZ8$XUbx$@=An>&9FJ-YPi)T>*+jy=2f?cBS2 z{|-L9`0?b+n?H{}z54a++q-`cKfe6=^y}Ndk3YZu{rvm;|NjqQfC3IkV1Wi6h+u*W zF34bm4n7EBgc43jVTBf6h+&2rZpdMW9)1X7h$4c6h+>K=uE=7GF1`q3j55wh zV~sZ6h+~dA?#N@0KK=+~kU|bgWRXT5iDZ&WF3Dt*PCf}`lu}MfWtCQ5iDi~rZpmer zUVaH?m|~7eW|?N5iDsH=uE}PbZoUa;oN~@dXPtK5iD#aA?#XALe*Ot)pn?ucXrYE4 zifE#WF3M=5jy?)$q>@fbX{DB4ifN{rZpvw=o_-2ysG^QaYN@84ifXE=uF7hwuD%Lu ztg_BZYpu54ifgXA?#gSgzWxequ)+>YY_Y~3i)^yW|1QgHv(7#XZM4!(OKr8*UW;wE z+HT8jx88mWZn)x(OK!R5o{Mg}>aNRfyY9XVZ@lu(OK-jQ-ivR(`tHkbzyAIUaKHi& zOmM*lAB=Fq3NOrX!wx?Tal{f&OmW2)UyO0a8gI;T#~yzSa>yc&OmfL4pNw+KDzD6P z%PzkRbIdZ&OmodP-;8t4I`7PL&p!VQbkIT%O?1&lAB}X_ z>Z-5Kdh4#g4twmf&rW;ow%?9>?z->Jd+)yg4t(&!4^MpY#vhM-^2#sIeDlsf4}J8~ zPfvaI)?bf(_S$dHefQpf4}SRKk57L2=AVy#`s%OGe*5mf4}bjf&rg5-_TP_x{`&9F zfB*jf55NElaDW6XpaBnvzyvCAfedV*10M*%2ug5*6s({HFNnbmYVZOD001HR1O)>C V001li00001009610s=$<06Xxc+(iHY literal 0 HcmV?d00001 diff --git a/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx b/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx new file mode 100644 index 000000000..32d4c3026 --- /dev/null +++ b/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx @@ -0,0 +1,81 @@ +import React from 'react' +import { Checkbox, FormControlLabel } from '@mui/material' +import { Col, Container, Row } from 'react-bootstrap' +import styles from "./card_detail.module.css" +import DeleteIcon from '@mui/icons-material/Delete'; +import CloseIcon from '@mui/icons-material/Close'; +import { useEffect } from 'react'; +const CardDetail = (props) => { + const { setCompleteJoinData, completedJoinData, setTotalCounter, orgList, data, setCompleteData, index, completeData } = props + + const handleCheckColumns = (e, value) => { + let arr = [...completeData] + let present_card = { ...data } + if (e.target.checked && !present_card.columnsSelected.includes(value) && present_card.availabeColumns.includes(value)) { + present_card["columnsSelected"] = [...present_card.columnsSelected, value] + arr[index] = { ...present_card } + setCompleteData([...arr]) + } + else if (!e.target.checked && present_card?.columnsSelected?.includes(value) && present_card.availabeColumns?.includes(value)) { + let i = present_card.columnsSelected.indexOf(value) + if (i > -1) { + present_card.columnsSelected.splice(i, 1) + } + arr[index] = present_card + setCompleteData([...arr]) + } + } + const handleSelectAll = (e) => { + let arr = [...completeData] + let present_card = { ...data } + if (e.target.checked) { + present_card["columnsSelected"] = [...present_card.availabeColumns] + } else { + present_card["columnsSelected"] = [] + } + arr[index] = { ...present_card } + setCompleteData([...arr]) + } + + const handleDeleteCard = () => { + let arr = [...completeData] + arr.splice(index, 1) + setCompleteData([...arr]) + setTotalCounter((prev) => prev - 1) + } + useEffect(() => { + }) + return ( + <> +
+ +
+
Organisation name
+
{data?.org_name ? data.org_name : ""}
+ +
+
Dataset name
+
{data?.dataset_name ? data.dataset_name : ""}
+
+
{data?.file_name ? data.file_name.split("/")[data.file_name.split("/").length - 1] : ""}
+
+ + + +
Select columns
+
} checked={data?.availabeColumns?.length == data?.columnsSelected?.length} onChange={(e) => handleSelectAll(e)} />} label={data?.availabeColumns?.length != data?.columnsSelected?.length ? "Select all" : "Clear"} />
+ + + +
+ {data?.availabeColumns?.length > 0 && data.availabeColumns.map((eachCol, in_) => { + return handleCheckColumns(e, eachCol)} />} label={eachCol} /> + })} + + + + + ) +} + +export default CardDetail \ No newline at end of file diff --git a/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css b/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css new file mode 100644 index 000000000..54765721a --- /dev/null +++ b/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css @@ -0,0 +1,66 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap'); + +.mainBox { + border-radius: 10px; + border: 1px solid #919EAB; + padding: 0px; + margin: 0px 0px; + overflow: hidden; + font-family: 'Inter', sans-serif; + font-family: 'Montserrat', sans-serif; + font-style: normal; + +} + + +.mainBox:hover { + box-shadow: 0 3px 10px #ab840574; +} + +.topRowOfCard { + height: 90px; + background: #F9EABC; + padding: 20px; + font-weight: 400; + font-size: 16px; + line-height: 24px; + text-align: left; + border-bottom: 1px solid #9AA1A9; +} + +.topRowOfCard div:nth-child(2) { + font-weight: 700; + +} + +.topRowOfCard>div:nth-child(2) { + font-weight: 400; +} + + +.selectAllRow { + text-align: left; + padding: 10px 20px 0px 20px; + border-bottom: 1px solid #9AA1A9; +} + +.columnsRow { + text-align: left; + padding: 20px; + +} + +.selectColumns { + display: grid; + grid-template-columns: auto auto auto auto; + gap: 10px; +} + +.eachCol { + width: 250px; +} + +.deleteicon:hover .topRowOfCard { + background: red !important; + color: white !important; +} \ No newline at end of file diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 9e9eb0dba..0343796fd 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -1,144 +1,121 @@ -import React, { useEffect } from 'react' +import React, { useEffect, useState } from 'react' import { Col, Container, Row } from 'react-bootstrap' import DatasetSelect from './DatasetSelect/DatasetSelect' import Join from './Join/Join' import Preview from './Preview/Preview' import styles from "./dataset_integration.module.css" -import { useState } from 'react' import HTTPService from '../../../Services/HTTPService' import UrlConstant from '../../../Constants/UrlConstants' import Loader from '../../Loader/Loader' -import { Alert, Button, Collapse, IconButton, Snackbar } from '@mui/material' +import { Alert, Button, Collapse, Fab, IconButton, Snackbar } from '@mui/material' import CloseIcon from '@mui/icons-material/Close'; import { CheckLg } from 'react-bootstrap-icons' -import { GetErrorHandlingRoute, GetErrorKey } from '../../../Utils/Common' +import { GetErrorHandlingRoute, GetErrorKey, goToTop } from '../../../Utils/Common' import { useHistory } from 'react-router-dom' +import { Affix } from 'antd' +import { AddIcCallOutlined } from '@material-ui/icons' const converter = require('json-2-csv') const fs = require('fs') -const DatasetIntegration = () => { - const [allAvailableDatasetsAndFiles, setAllAvailableDatasetsAndFiles] = useState([]) +const DatasetIntegration = (props) => { + const { isEditModeOn } = props + const [counterForIntegrator, setCounterForIntegration] = useState(2) + const [isDatasetIntegrationListModeOn, setIsDatasetIntegrationListModeOn] = useState(false) + const [top, setTop] = useState(10); + const [orgList, setOrgList] = useState([]) const [message, setMessage] = useState("") const [alertType, setAlertType] = useState("") const [open, setOpen] = React.useState(false); - // - const [noOfDatasetSelector, setNoOfDatasetSelector] = useState([]) - const [listOfDatasetSelected, setListOfDatasetSelected] = useState([]) - const [allDatasetNameList, setAllDatasetNameList] = useState([]) + const [connectorId, setConnectorId] = useState("") - const [noOfFileSelector, setNoOfFileSelector] = useState([]) - const [listOfFilesSelected, setListOfFilesSelected] = useState([]) - const [listOfFilesAvailableForSelect, setListOfFilesAvailableForSelect] = useState([ + const [template, setTemplate] = useState( + { org_id: "", dataset_list: [], file_list: [], org_name: "", dataset_id: "", dataset_name: "", file_name: "", availabeColumns: [], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + + ) + const [empty, setEmptyTemplate] = useState( + { org_id: "", dataset_list: [], file_list: [], org_name: "", dataset_id: "", dataset_name: "", file_name: "", availabeColumns: [], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + ) + + + + const [joinType, setJoinType] = useState("") + + //This is main array which will have all the data with the format of template or empty + const [completeData, setCompleteData] = useState([ + + //In dev mode this is the dummy data + // { org_id: "A", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c1", "c2", "c3"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + // { org_id: "B", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c4", "c5", "c6"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + // { org_id: "C", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c7", "c8", "c9"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, ]) - const [listOfDatsetFileAvailableForColumn, setListOfDatsetFileAvailableForColumn] = useState([]) + + // const [listOfDatsetFileAvailableForColumn, setListOfDatsetFileAvailableForColumn] = useState([]) const [finalDataNeedToBeGenerated, setFinalDataNeedToBeGenerated] = useState({}) const [finalDatasetAfterIntegration, setFinalDatasetAfterIntegration] = useState([]) + const [finalDatasetAfterSaving, setFinalDatasetAfterSaving] = useState([]) - const [finalJoin, setFinalJoin] = useState({}) - const [joinVal1, setJoinVal1] = useState("") - const [joinVal2, setJoinVal2] = useState("") //loader for every network request const [loader, setLoader] = useState(false) - const [circleLoad, setCircleLoad] = useState(false) + + //connector data + const [connectorData, setConnectorData] = useState({ + name: "", desc: "" + }) + const history = useHistory(); - const handleChangeDatasetNameSelector = (event, i, source) => { - console.log(event.target.value, i, source) - if (source == "dataset") { - let list_selected = [...listOfDatasetSelected] - list_selected[i] = event.target.value - console.log(list_selected, "list_selected") - setListOfDatasetSelected([...list_selected]); - let list_selected_file = [...listOfFilesSelected] - list_selected_file[i] = "" - setListOfFilesSelected([...list_selected_file]); - console.log(finalDataNeedToBeGenerated, "finalDataNeedToBeGenerated") - // setFinalDataNeedToBeGenerated({}) + const handleChangeDatasetNameSelector = (event, i, source, name) => { + if (source == "org") { + let res = getFilesAssociatedForTheSelectedDatasets(source, [], event.target.value, i, name) + return + } + else if (source == "dataset") { if (event.target.value) { - getFilesAssociatedForTheSelectedDatasets(source, list_selected) + let res = getFilesAssociatedForTheSelectedDatasets(source, [event.target.value], event.target.value, i) } - - } else { + } else if (source == "file") { if (event.target.value) { - let list_selected = [...listOfFilesSelected] - list_selected[i] = event.target.value - let res = getFilesAssociatedForTheSelectedDatasets(source, list_selected) + + let res = getFilesAssociatedForTheSelectedDatasets(source, [event.target.value], "", i) res.then((res) => { - console.log(res, "RESPOSE") - if (!res) { - console.log(event, "TARGET") - list_selected[i] = "" - setListOfFilesSelected([...list_selected]); - let data = { ...finalDataNeedToBeGenerated } - let obj = { ...finalJoin } - data[joinVal1] = [] - data[joinVal2] = [] - setJoinVal1("") - setJoinVal2("") - setFinalDataNeedToBeGenerated({ ...data }) - obj.first = "" - obj.second = "" - setFinalJoin({ ...obj }) - - } else { - setListOfFilesSelected([...list_selected]); - } - console.log(list_selected, "list_selectedlist_selectedlist_selectedlist_selectedlist_selected") }) } else { - event.target.value = "" - let list_selected = [...listOfFilesSelected] - list_selected[i] = event.target.value - setListOfFilesSelected([...list_selected]); } } - }; - const handleChangeFileNameSelector = (event, i) => { - }; const handleClickSelectDataset = (source) => { if (source == "dataset") { - let selector = noOfDatasetSelector.length; - let selectedDataset = listOfDatasetSelected.length - let availableDataset = allDatasetNameList.length - if (selectedDataset != availableDataset) { - let max = +selector - +selectedDataset - console.log(max, selector, selectedDataset) - if (max <= 0 && !listOfDatasetSelected.includes("")) { - setNoOfDatasetSelector([...noOfDatasetSelector, ""]) - } - } } else { - let selector = noOfFileSelector.length; - let selectedDataset = listOfFilesSelected.length - let availableDataset = listOfFilesAvailableForSelect.length - if (selectedDataset != availableDataset) { - let max = +selector - +selectedDataset - console.log(max, selector, selectedDataset) - if (max <= 0 && !listOfFilesSelected.includes("")) { - setNoOfFileSelector([...noOfFileSelector, ""]) - } - } } } - const getListOfDatasetNames = () => { + const getDataList = (source, index) => { setLoader(true) - let url = UrlConstant.base_url + UrlConstant.get_dataset_name_list - let method = "GET" + let url = "" + let method + if (source == "org_names") { + url = UrlConstant.base_url + UrlConstant.get_org_name_list + method = "GET" + } else if (source == "dataset_names") { + url = UrlConstant.base_url + UrlConstant.get_dataset_name_list + method = "GET" + } HTTPService(method, url, "", false, true, false).then((res) => { setLoader(false) - setAllDatasetNameList([...res.data]) + if (source == "org_names") { + setOrgList([...res.data]) + } else if (source == "dataset_names") { + setTemplate({ ...template, dataset_list: [...res.data] }) + } }).catch((err) => { - // console.log(e.response) setAlertType("error") setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Error occurred! Dataset could not fetched.") setLoader(false) @@ -147,11 +124,12 @@ const DatasetIntegration = () => { } }) } - const getFilesAssociatedForTheSelectedDatasets = async (source, list) => { + const getFilesAssociatedForTheSelectedDatasets = async (source, list, org, i) => { list = list.filter((item) => item != "") setLoader(true) let url = "" let payload = {} + let method = "POST" if (source == "dataset") { url = UrlConstant.base_url + UrlConstant.get_files_for_selected_datasets payload = { @@ -162,27 +140,35 @@ const DatasetIntegration = () => { payload = { files: [...list] } - } - let method = "POST" + } else if (source == "org") { + method = "GET" + url = UrlConstant.base_url + UrlConstant.get_dataset_name_list + "?org_id=" + org + payload = { + } + } return await HTTPService(method, url, payload, false, true, false).then((res) => { setLoader(false) + if (source == "dataset") { - setListOfFilesAvailableForSelect([...res.data]) + + setTemplate({ ...template, dataset_name: res.data[0]?.dataset_name ? res.data[0].dataset_name : "N/A", dataset_id: org ? org : "", file_list: [...res.data] }) + } else if (source == "file") { - console.log(res.data) - setListOfDatsetFileAvailableForColumn( - { ...res.data } - ) - let obj = {} + let name = list[0] + let resArr = [] + let fileId = res.data?.id ? res.data.id : "" for (var key in res.data) { - obj[key] = [] + resArr.push(res.data[key]) } - setFinalDataNeedToBeGenerated({ ...obj }) + setTemplate({ ...template, file_id: fileId, file_name: name, availabeColumns: [...res.data[name]] }) + } else if (source == "org") { + setTemplate({ ...template, dataset_list: [...res.data], org_id: org, org_name: res?.data?.length > 0 ? res.data[0]?.org_name : "" }) } return true }).catch((err) => { + goToTop(0) // setOpen(true); // setAlertType("error") setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Some error occurred while generating!") @@ -197,11 +183,9 @@ const DatasetIntegration = () => { var errorMessages = returnValues[1] if (errorKeys.length > 0) { for (var i = 0; i < errorKeys.length; i++) { - console.log(errorKeys[i], errorMessages[i]) let id; switch (errorKeys[i]) { case "datasets": - console.log("under datasets") setOpen(true); setLoader(false) setAlertType("error") @@ -212,7 +196,6 @@ const DatasetIntegration = () => { }, 2500) return false case "files": setOpen(true); - console.log("under files") setLoader(false) setAlertType("error") setMessage(errorMessages[i] ? errorMessages[i] : "Some error occurred while fetching files for selected dataset!") @@ -222,8 +205,6 @@ const DatasetIntegration = () => { }, 2500) return false default: - console.log("under default") - if (err?.response?.status == 401) { history.push(GetErrorHandlingRoute(err)); } else { @@ -237,12 +218,10 @@ const DatasetIntegration = () => { }, 2500) } return false - } } } else { - console.log("under else") if (err?.response?.status == 401) { history.push(GetErrorHandlingRoute(err)); @@ -260,76 +239,150 @@ const DatasetIntegration = () => { return false }) } - const deleteTable = (tableName, index) => { - let newArr = listOfDatsetFileAvailableForColumn.filter((each) => each.name != tableName.name) - setListOfDatsetFileAvailableForColumn([...newArr]) - - let list_selected = [...listOfFilesSelected] - console.log(list_selected, tableName.name, index) - list_selected.splice(index, 1) - // list_selected.filter((each) => { - // return each != tableName.name - // }) - console.log(list_selected, tableName.name, index) - setListOfFilesSelected([...list_selected]); + const resetAll = (main, connector, join, goback, func1, func2) => { + + goToTop() } - const generateData = (left_on, right_on, joinType) => { + // const deleteTable = (tableName, index) => { + // let newArr = listOfDatsetFileAvailableForColumn.filter((each) => each.name != tableName.name) + // setListOfDatsetFileAvailableForColumn([...newArr]) + + // let list_selected = [...listOfFilesSelected] + // //console.log(list_selected, tableName.name, index) + // list_selected.splice(index, 1) + // list_selected.filter((each) => { + // return each != tableName.name + // }) + // //console.log(list_selected, tableName.name, index) + // setListOfFilesSelected([...list_selected]); + // } + + //this function is being used to generate the data at first place, Save the generated data and delete the saved connectors + const generateData = (index, condition,) => { + + //condition can be ===> [integrate, delete, save] any one of the listed elements setLoader(true) - let url = UrlConstant.base_url + UrlConstant.joining_the_table - console.log(finalDataNeedToBeGenerated, "finalDataNeedToBeGenerated") - let arr = Object.keys(finalDataNeedToBeGenerated) - let firstFile = arr[0] - let secondFile = arr[1] - let payload = { - file_path1: firstFile, - "columns1": [ - ...finalDataNeedToBeGenerated[firstFile] - ], - "file_path2": secondFile, - "columns2": [ - ...finalDataNeedToBeGenerated[secondFile] - ], - "how": joinType ? joinType : "left", - "left_on": [left_on], - "right_on": [right_on], + let url = "" + + let payload = [] + + + + for (let i = 0; i < completeData.length - 1; i++) { + //Generating the payload as array of objects each object having data friom completeData and completeJoinData + let obj = { + left_dataset_file_id: completeData[i]?.file_id, + right_dataset_file_id: completeData[i + 1]?.file_id, + left_dataset_file_path: completeData[i]?.file_name, + right_dataset_file_path: completeData[i + 1]?.file_name, + condition: { + right_selected: [...completeData[i + 1]?.columnsSelected], left_selected: [...completeData[i]?.columnsSelected], + how: completeData[i]?.type ? completeData[i]?.type : "left", + left_on: completeData[i]?.left_on, + right_on: completeData[i]?.right_on + } + } + payload.push(obj) } - let method = "POST" - HTTPService(method, url, payload, false, true, false).then((res) => { + let finalPayload + let method + if (condition == "save") { + finalPayload = { name: connectorData.name, description: connectorData.desc, map: payload } + url = UrlConstant.base_url + UrlConstant.integration_connectors // for saving + method = "POST" + } else if (condition == "integrate") { + finalPayload = payload + url = UrlConstant.base_url + UrlConstant.joining_the_table //for generating + method = "POST" + } else if (condition == "delete" && connectorId) { + finalPayload = {} + url = UrlConstant.base_url + UrlConstant.integration_connectors + connectorId + "/" + method = "Delete" + } else { setLoader(false) - console.log(JSON.parse(res.data)) - setFinalDatasetAfterIntegration([...JSON.parse(res.data)]) - setOpen(true); - setAlertType("success") - setMessage("Data generated successfully!") - let id = setTimeout(() => { - setOpen(false); - return clearTimeout(id) - }, 2500) + return + } + // console.table(finalPayload, "PAYLOAD") + HTTPService(method, url, finalPayload, false, true, false).then((res) => { + + setLoader(false) + if (condition == "integrate") { + + setFinalDatasetAfterIntegration([...JSON.parse(res.data)]) + let allKeys = JSON.parse(res.data)?.length > 0 ? Object.keys(JSON.parse(res.data)[0]) : [] + if (allKeys.length > 1) { + let arr = [...completeData] + let obj = arr[index + 1] + obj["left"] = [...allKeys] + arr[index + 1] = { ...obj } + setCompleteData([...arr]) + setOpen(true); + setAlertType("success") + setMessage("Data generated successfully!") + let id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + document.querySelector('#previewTable').scrollIntoView({ behavior: 'smooth' }); + } + + } else if (condition == "save") { + setConnectorId(res?.data?.id ? res.data.id : "") + setOpen(true); + setAlertType("success") + setMessage("Data saved successfully!") + let id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + document.querySelector('#previewTable').scrollIntoView({ behavior: 'smooth' }); + + } else if (condition == "delete") { + setOpen(true); + setAlertType("success") + setMessage("Data deleted successfully!") + let id = setTimeout(() => { + setOpen(false); + return clearTimeout(id) + }, 2500) + } + + // goToTop(2000) }).catch((err) => { setOpen(true); setLoader(false) setAlertType("error") - console.log(err.response) setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Some error occurred while generating!") let id = setTimeout(() => { setOpen(false); return clearTimeout(id) }, 2500) + goToTop(0) }) } + + + + //Download functionality const downloadDocument = () => { converter.json2csv(finalDatasetAfterIntegration, async (err, csv) => { if (err) { throw err } // print CSV string - console.log(csv) download(csv) }) } + //number of integration handler + const integrateMore = (value) => { + if (counterForIntegrator == completeData.length) { + setCounterForIntegration((pre) => pre + value) + } + } + const download = (data) => { const blob = new Blob([data], { type: 'text/csv' }) const url = window.URL.createObjectURL(blob); @@ -340,48 +393,58 @@ const DatasetIntegration = () => { document.body.appendChild(a); a.click(); document.body.removeChild(a); - + } + const deleteConnector = () => { + setCompleteData([]) + generateData(1, "delete") + setFinalDataNeedToBeGenerated([]) + setIsDatasetIntegrationListModeOn(true) } useEffect(() => { - setNoOfDatasetSelector(["", ""]) - setNoOfFileSelector(["", ""]) - getListOfDatasetNames() - + getDataList("org_names") }, []) return ( <> {loader ? : ""} - - - {open ? { - setOpen(false); - }} - > - - - } - sx={{ mb: 2 }} - > - {message ? message : ""} - : ""} - - - - {listOfFilesSelected.length > 0 && } - + + + + {open ? + + { + setOpen(false); + }} + > + + + } + // sx={{ mb: 1 }} + > + {message ? message : ""} + + + + : ""} + + + + {!isDatasetIntegrationListModeOn && } + {!isDatasetIntegrationListModeOn && completeData.length > 0 && < Preview generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} + {isDatasetIntegrationListModeOn && listing} ) } -export default DatasetIntegration \ No newline at end of file +export default DatasetIntegration + diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index d9d508a82..a9bd357b5 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -11,15 +11,50 @@ import AccordionDetails from '@mui/material/AccordionDetails'; import Typography from '@mui/material/Typography'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import DeleteIcon from '@mui/icons-material/Delete'; -import { Checkbox, FormControlLabel } from '@mui/material'; +import { Checkbox, Fab, FormControlLabel, TextField } from '@mui/material'; import { CheckLg } from 'react-bootstrap-icons'; -import { useEffect } from 'react'; +import CardDetail from '../CardDetail/CardDetail'; +import { Button, Affix } from 'antd'; +import { handleUnwantedSpace, validateInputField } from '../../../../Utils/Common'; +import RegexConstants from '../../../../Constants/RegexConstants'; +import Join from '../Join/Join'; +import leftG from "../../../../Assets/Img/Join type/Color/Left.svg" +import leftB from "../../../../Assets/Img/Join type/Normal state/left.svg" +import rightB from "../../../../Assets/Img/Join type/Normal state/right.svg" +import rightG from "../../../../Assets/Img/Join type/Color/right.svg" +import fullB from "../../../../Assets/Img/Join type/Normal state/outer.svg" +import fullG from "../../../../Assets/Img/Join type/Color/outer.svg" +import innerB from "../../../../Assets/Img/Join type/Normal state/inner.svg" +import innerG from "../../../../Assets/Img/Join type/Color/inner.svg" +import settinggif from "../../../../Assets/Img/setting.gif" const DatasetSelect = (props) => { - const { setFinalDataNeedToBeGenerated, finalDataNeedToBeGenerated, deleteTable, listOfFilesSelected, handleChangeFileNameSelector, noOfFileSelector, listOfFilesAvailableForSelect, allDatasetNameList, listOfDatasetSelected, handleChangeDatasetNameSelector, noOfDatasetSelector, handleClickSelectDataset, listOfDatsetFileAvailableForColumn } = props + const { integrateMore, empty, template, setTemplate, counterForIntegrator, completedJoinData, setCompleteJoinData, resetAll, generateData, orgList, joinType, setJoinType, setCompleteData, setConnectorData, connectorData, completeData, setFinalDataNeedToBeGenerated, finalDataNeedToBeGenerated, listOfFilesSelected, allDatasetNameList, listOfDatasetSelected, handleChangeDatasetNameSelector, listOfDatsetFileAvailableForColumn, } = props + const [errorConnectorName, setErrorConnectorName] = useState("") + const [errorConnectorDesc, setErrorConnectorDesc] = useState("") + const [show, setShow] = useState(false) + const [indexShow, setIndex] = useState(-1) + const handleChange = (e) => { + let value = e.target.name + if (value == "name") { + setErrorConnectorName("") + validateInputField(e.target.value, RegexConstants.connector_name) + ? setConnectorData({ ...connectorData, [e.target.name]: e.target.value }) + : e.preventDefault(); + } else { + setErrorConnectorDesc("") + validateInputField(e.target.value, RegexConstants.connector_name) + ? setConnectorData({ ...connectorData, [e.target.name]: e.target.value }) + : e.preventDefault(); + } + + } + const [selectAll, setSelectAll] = useState(false) + const [totalCounter, setTotalCounter] = useState(-1) const [selectedColumns, setSelectedColumns] = useState({}) + const [top, setTop] = useState(0); const changeAllSelect = (file) => { - console.log(selectedColumns) + //console.log(selectedColumns) if (selectedColumns[file.name]) { let obj = { ...selectedColumns } delete obj[file.name]; @@ -30,8 +65,17 @@ const DatasetSelect = (props) => { setSelectedColumns({ ...obj }) } } + const [joinTypeArr, setJoinTypeArr] = useState([ + { name: "left", black: leftB, green: leftG }, + { name: "right", black: rightB, green: rightG }, + { name: "inner", black: innerB, green: innerG }, + { name: "outer", black: fullB, green: fullG }, + ]) + const selectThisType = (name) => { + setJoinType(name) + } const handleChangeColumns = (e, file, col) => { - console.log(e.target.checked, file, col) + //console.log(e.target.checked, file, col) let obj = { ...finalDataNeedToBeGenerated } if (obj[file]) { if (e.target.checked && !obj[file].includes(col)) { @@ -53,142 +97,172 @@ const DatasetSelect = (props) => { setFinalDataNeedToBeGenerated({ ...obj }) } + + //after all selection field is filled this func will be triggered when clicked on add + const addNewForm = () => { + let arr = [...completeData] + console.log("template", template, arr) + arr.push(template) + setCompleteData([...arr]) + setTotalCounter((prev) => prev + 1) + setTemplate({ ...empty }) + console.log(arr, "ARR NEW") + + } + + //datasetname no space handler + const handleConnectorNameKeydown = (e) => { + if (e.target.name == "name") { + handleUnwantedSpace(connectorData.name, e); + } else { + handleUnwantedSpace(connectorData.desc, e); + } + }; + const handleMoreDataShow = (index, condition, e) => { + e.stopPropagation() + if (condition) { + setIndex(index) + setShow(true) + } + else { + setIndex(-1) + setShow(false) + } + + } + return ( + + + + Dataset Integration details + + + + + + + - - - - Select datasets - - + + - - - - Select files - = allDatasetNameList.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn_dis} onClick={() => handleClickSelectDataset("dataset")}>+ Add datasets - - + + + + + Select datasets for connector + + {counterForIntegrator === completeData.length &&
Click on integrate more datasets to select files for integration.
} -
+ - {noOfDatasetSelector.map((eachDatasetName, i) => { - return - - - Dataset name + + + + + Organization name * + + + + + + Dataset name * - - })} - - - {noOfDatasetSelector.map((eachFileName, i) => { - return - - - File name + + + + File name * - + + + + + + +
+ {/* {completeData?.length > 0 && completeData.map((each, index) => { + //console.log(show, indexShow) + if (totalCounter >= index && index < counterForIntegrator) { + return + {index != 0 && handleMoreDataShow(index, false)} onMouseOver={() => handleMoreDataShow(index, true)} style={{ height: `${show && index == indexShow ? "300px" : "50px"}`, overflow: "hidden", width: `${show && index == indexShow ? "700px" : "50px"}`, margin: "auto", backgroundImage: index != indexShow ? `url(${settinggif})` : "none", backgroundRepeat: "no-repeat", backgroundSize: "50px 50px", backgroundPosition: "center", boxShadow: "0 3px 10px #ab840574", }} className={index == indexShow ? styles.hoveredOne : styles.alwaysHave}> + {index == indexShow ? : } + } + {index != 0 && } + {each?.availabeColumns?.length > 0 && } + {index != totalCounter && handleMoreDataShow(index, true)} style={{ border: index == indexShow - 1 && "1.5px solid #C09507" }} class={styles.vl} >} + + } + })} */} + {completeData?.length > 0 && completeData.map((each, index) => { + return + {} + {index < completeData.length - 1 && } + {index < completeData.length - 1 && + handleMoreDataShow(index, true, e)} style={{ display: "flex", justifyContent: "center", alignItems: "center", cursor: !show ? "pointer" : "", height: `${show && index == indexShow ? "350px" : "50px"}`, overflow: "hidden", width: `${show && index == indexShow ? "700px" : "50px"}`, margin: "auto", backgroundRepeat: "no-repeat", backgroundSize: "50px 50px", backgroundPosition: "center", boxShadow: "0 3px 10px #ab840574", }} className={index == indexShow ? styles.hoveredOne : styles.alwaysHave}> + { + {/* handleMoreDataShow(index, false, e)} > */} + + {/* */} + {indexShow != index && } + + } + + } + {index < completeData.length - 1 && handleMoreDataShow(index, true)} style={{ border: index == indexShow && "1.5px solid #C09507" }} class={styles.vl} >} + })} - - - {/* - - */} - {/* -
- Select Files - - - handleClickSelectDataset("file")}>+ Add files - = listOfFilesAvailableForSelect.length ? styles.add_dataset_btn_dis : styles.add_dataset_btn} onClick={() => handleClickSelectDataset("file")}>+ Add files - - */} - {/* - - */} - {/* {listOfDatsetFileAvailableForColumn.length > 0 && */} - {listOfFilesSelected.length > 0 && - - Select columns - - - - {Object.keys(listOfDatsetFileAvailableForColumn).map((eachDatasetFile, index) => { - console.log(eachDatasetFile, "eachDatasetFile", listOfDatasetSelected, listOfFilesSelected) - if (listOfFilesSelected.includes(eachDatasetFile)) { - return - } - aria-controls="panel1a-content" - id="summary_id_accordion" - > - {eachDatasetFile.split("/")[eachDatasetFile.split("/").length - 1]} - {/* - deleteTable(eachDatasetFile, index)} /> - */} - - {/* - changeAllSelect(eachDatasetFile)} control={} label={"Select all"} /> - */} - - {listOfDatsetFileAvailableForColumn[eachDatasetFile]?.length > 0 && listOfDatsetFileAvailableForColumn[eachDatasetFile]?.map((eachColumn, index) => { - return handleChangeColumns(e, eachDatasetFile, eachColumn + "")} />} label={eachColumn} /> - })} - - - } - })} - } - {/* } */} - - + + ) } diff --git a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx index 382780faf..04db81c78 100644 --- a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx @@ -6,193 +6,149 @@ import FormControl from '@mui/material/FormControl'; import Select from '@mui/material/Select'; import styles from "../dataset_integration.module.css" import DragHandleIcon from '@mui/icons-material/DragHandle'; -import { Button, CircularProgress } from '@mui/material'; +import { CircularProgress } from '@mui/material'; import { Cpu } from 'react-bootstrap-icons'; +import leftG from "../../../../Assets/Img/Join type/Color/Left.svg" +import leftB from "../../../../Assets/Img/Join type/Normal state/left.svg" +import rightB from "../../../../Assets/Img/Join type/Normal state/right.svg" +import rightG from "../../../../Assets/Img/Join type/Color/right.svg" +import fullB from "../../../../Assets/Img/Join type/Normal state/outer.svg" +import fullG from "../../../../Assets/Img/Join type/Color/outer.svg" +import innerB from "../../../../Assets/Img/Join type/Normal state/inner.svg" +import innerG from "../../../../Assets/Img/Join type/Color/inner.svg" +import CloseIcon from '@mui/icons-material/Close'; +import { Button } from 'antd'; const Join = (props) => { - const { joinVal1, setJoinVal1, joinVal2, setJoinVal2, finalJoin, setFinalJoin, circleLoad, listOfDatasetSelected, listOfFilesSelected, listOfDatsetFileAvailableForColumn, generateData, finalDataNeedToBeGenerated } = props - const [join, setJoin] = useState({}) - - const [age, setAge] = React.useState(''); - const [joinType, setJoinType] = useState("") - const handleChange = (event, source) => { - console.log(event.target.value) - if (source == "val1") { - setJoinVal1(event.target.value); - } else { - setJoinVal2(event.target.value) - } - if (finalJoin[event.target.value]) { - let obj = { ...finalJoin } - delete obj[event.target.value] - setFinalJoin(obj) - } - let list = [...Object.keys(listOfDatsetFileAvailableForColumn)]; - let join1Obj = list.filter((each, index) => { - return each == event.target.value - }) - let obj = { [event.target.value]: listOfDatsetFileAvailableForColumn[join1Obj[0]] } - setJoin({ ...obj, ...join }) - }; - + const { handleMoreDataShow, indexShow, file_right, file_left, setCompleteJoinData, right_on, left_on, completedJoinData, type, left, right, index, each, resetAll, joinType, setJoinType, connectorData, setCompleteData, completeData, listOfDatsetFileAvailableForColumn, generateData } = props + const [joinTypeArr, setJoinTypeArr] = useState([ + { name: "left", black: leftB, green: leftG }, + { name: "right", black: rightB, green: rightG }, + { name: "inner", black: innerB, green: innerG }, + { name: "outer", black: fullB, green: fullG }, + ]) const handleChangeJoin = (e, source) => { + let arr = [...completeData] + let obj1 = { ...each } + const { + target: { value }, + } = e; + // On autofill we get a stringified value. + if (typeof value === 'string') { + value.split(',') + } if (source == "join1") { - setFinalJoin({ ...finalJoin, [joinVal1]: e.target.value }) + // console.log(value) + obj1["left_on"] = [...value] + arr[index] = { ...obj1 } } else { - setFinalJoin({ ...finalJoin, [joinVal2]: e.target.value }) + obj1["right_on"] = [...value] + arr[index] = { ...obj1 } } + + setCompleteData([...arr]) + } + + const selectThisType = (name) => { + let arr = [...completeData] + let obj = { ...each } + // let arr1 = [...completedJoinData] + // let obj1 = { ...arr1[index - 1] } + obj["type"] = name + // arr1[index - 1] = { ...obj1 } + // setCompleteJoinData([...arr1]) + // obj["joinTypeWithNextOrBack"] = name + // arr[index - 1] = { ...obj } + arr[index] = obj + setCompleteData([...arr]) + setJoinType(name) } - console.log(listOfDatsetFileAvailableForColumn, "listOfDatsetFileAvailableForColumn") - let arr = Object.keys(finalDataNeedToBeGenerated) - let firstColms = finalDataNeedToBeGenerated[arr[0]] - let secondColms = finalDataNeedToBeGenerated[arr[1]] useEffect(() => { + // console.log(index, "[index]", each) }, []) return ( - + index == indexShow && - + Join + handleMoreDataShow(indexShow, false, e)} className='deleteicon' color='secondary' /> - - - - Join type + + + + Primary dataset column name + {/* {console.log(each)} */} - - - - - - - Primary dataset - - - - - - Primary dataset column name - - - - + {/* + */} - - - - - Primary dataset - handleChangeJoin(e, "join2")} + label="Primary dataset colounm name" + multiple + > + {completeData[index + 1]?.columnsSelected?.map((eachFile, ind_) => { + if (completeData[index + 1]?.availabeColumns.includes(eachFile)) { + return {eachFile} + } + })} + + - } - })} - - - - - - Primary dataset column name - - - - - - - - - {console.log(joinVal1, joinVal2, finalJoin)} - - + {/* + Join type + */} + + { + completeData.length >= 2 && + + + {joinTypeArr.map((eachT, ind) => { + return selectThisType(eachT.name)} className={each.type == eachT.name ? styles.stypeMainBox : styles.typeMainBox}> +
+ {eachT.name} +
{eachT.name}
+
+ })} + +
+ + + + + + + + } + ) } diff --git a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx index ab2dbdb4c..dd08678ac 100644 --- a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx @@ -1,10 +1,11 @@ -import { Button, Stack } from '@mui/material' +import { Stack } from '@mui/material' import React, { useEffect, useState } from 'react' import { Col, Container, Row } from 'react-bootstrap' import styles from "../dataset_integration.module.css" -import downloadIcon from "../../../../Assets/Img/download_btn_white.svg"; +import download_data from "../../../../Assets/Img/download_data.svg"; import { DataGrid } from '@mui/x-data-grid'; import NoDataAvailable from '../../../Dashboard/NoDataAvailable/NoDataAvailable'; +import { Affix, Button } from 'antd'; function NoResultsOverlay() { @@ -27,16 +28,11 @@ function NoRowsOverlay() { } const Preview = (props) => { - const { finalDatasetAfterIntegration, downloadDocument } = props + const { generateData, setIsDatasetIntegrationListModeOn, deleteConnector, counterForIntegrator, completeData, isEditModeOn, integrateMore, resetAll, generatedConnectorData, finalDatasetAfterIntegration, downloadDocument } = props const [col, setCol] = useState([]) const [row, setRow] = useState([]) useEffect(() => { - // console.log(finalDatasetAfterIntegration) - - - if (finalDatasetAfterIntegration.length > 0) { - // console.log(arr) let val = [] for (let key in finalDatasetAfterIntegration[0]) { @@ -45,11 +41,17 @@ const Preview = (props) => { } let rowArr = [] for (let i = 0; i < finalDatasetAfterIntegration.length; i++) { - let obj1 = { "id": i, ...finalDatasetAfterIntegration[i] } - console.log(obj1) + let obj1 + if (finalDatasetAfterIntegration[i]["id"]) { + obj1 = { ...finalDatasetAfterIntegration[i] } + //console.log(obj1) + } else { + //console.log(obj1) + obj1 = { "id": i, ...finalDatasetAfterIntegration[i] } + } rowArr.push(obj1) } - console.log(val, rowArr) + //console.log(val, rowArr) setCol([...val]) setRow([...rowArr]) } @@ -57,15 +59,15 @@ const Preview = (props) => { return ( - - - Preview + + + Preview - { } - + - - - + Download + + + + +
File name
+ {/*
{generatedConnectorData?.file_name}.csv
*/} + +
+
Datasets
+ {/*
{generatedConnectorData.datasets?.map((each) => `${each}, `)}
*/} + +
+
No.of records
+ {/*
{generatedConnectorData?.no_of_records}
*/} + +
+ {/* console.log(affixed, "read for dowload")} style={{ backgrond: "white", transition: "all 2s", visibility: counterForIntegrator != completeData.length ? "hidden" : "visible" }} offsetBottom={20}> */} + {/*
*/} + {/* integrateMore(1)} style={{ color: "white", background: "#c09507", }} variant="extended" aria-label="add"> + Integrate more + */} + + {/*
*/} + {/*
*/} + + +
+ +
+ + + + + + + + {finalDatasetAfterIntegration.length > 0 && + } + + + {true && + } - + ) } diff --git a/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css b/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css index 2e55581f7..ce384b0c4 100644 --- a/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css +++ b/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css @@ -1,16 +1,22 @@ .select_dataset_logo { text-align: left; - font-family: 'Open Sans'; - font-style: normal; - font-weight: 700; - font-size: 20px; - line-height: 138.69%; - /* identical to box height, or 28px */ /* headings */ color: #3D4A52; width: 100%; + /* margin: 10px 0px; */ + /* padding: 50px 0px 0px 0px; */ + + font-weight: 600; + font-size: 32px; + line-height: 40px; + + + color: #000000; + font-family: 'Inter', sans-serif; + font-family: 'Montserrat', sans-serif; + font-style: normal; margin-bottom: 20px; } @@ -59,24 +65,75 @@ } .generate_btn_parent_col { - text-align: right; - margin-top: 30px; + text-align: left; + /* margin-top: 30px; */ } .generate_data_btn { - width: 200px !important; - height: 42px !important; + /* width: 20px !important; */ + transition: all 0.3s; + border-radius: 8px; + border: 1px solid #C09507 !important; + text-transform: none !important; background: #C09507 !important; color: white !important; + /* outline-width: 8px; + outline-offset: -8px; */ + height: 48px; + width: 100% !important; + text-align: center; +} + +.generate_data_btn:hover { + background: #b7931bd5 !important; +} + +.generate_data_btn:hover .download_btn { + height: 68px !important; + width: 68px !important; +} + +.delete_btn { + /* width: 20px !important; */ + border-radius: 8px; + border: 1px solid #FF5630 !important; + color: #FF5630 !important; text-transform: none !important; - padding: 11.5px 23px; + height: 48px; + width: 100%; +} +.delete_btn:hover { + background-color: #FF5630 !important; + color: white !important; +} + +.save_btn { + /* width: 20px !important; */ + border-radius: 8px; + background-color: #C09507 !important; + border: 1px solid #C09507 !important; + color: white !important; + text-transform: none !important; + height: 48px; + /* width: 171px; */ +} + +.save_btn:hover { + background: #b7931bd5 !important; + color: white !important; +} + +.heightwidth { + width: 250px !important; + height: 182px !important; } .download_btn { - height: 16px !important; - width: 16px !important; - margin-right: 14px !important; + transition: all 0.3s ease-in-out; + height: 64px !important; + width: 64px !important; + /* margin-right: 14px !important; */ } .table_head { @@ -123,8 +180,7 @@ } .generate_data_btn_dis { - font-family: 'Open Sans'; - font-style: normal; + font-weight: 600; font-size: 14px; line-height: 19px; @@ -133,13 +189,10 @@ background-color: #9aa7b5 !important; cursor: auto !important; - - width: 200px !important; - height: 42px !important; + border-radius: 8px; color: white !important; text-transform: none !important; - padding: 11.5px 23px; } .select_file_main_col { @@ -153,4 +206,222 @@ .disabled_option { display: flex; justify-content: space-between; -} \ No newline at end of file +} + +.button { + /* background-color: #C09507 !important; */ + height: 48px !important; + width: 171px !important; + color: #C09507 !important; + border: 1px solid #C09507 !important; +} + +.button:hover { + background-color: #C09507 !important; + color: white !important; + outline-width: 8px; + outline-offset: -8px; +} + +.selectors { + margin: 20px 0px; + display: flex; + align-items: center; + justify-content: space-evenly; + background-color: white; +} + +.typeMainBox { + border: 2px solid #C09507; + width: 108px; + height: 108px; + background: #FFFFFF; + border-radius: 6px; + display: inline-block; + cursor: pointer; + text-transform: capitalize; + margin: 12px; +} + +.stypeMainBox { + border: 2px solid green; + text-transform: capitalize; + width: 108px; + height: 108px; + background: #FFFFFF; + border-radius: 6px; + display: inline-block; + cursor: pointer; + box-shadow: 5px 10px 1px 0.5 #C09507; + background-color: #f0cd59b9; + margin: 12px; +} + +.typeMainBox:hover { + /* border: 2px solid #C09507; */ + background-color: #f0cd59b9; +} + +.selectedTypeMainBox { + text-align: right; +} + +.selectedTypeImage { + text-align: center; +} + +.labelTypeJoin {} + +.flexForBtn { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.cancelBtn { + font-weight: 700; + font-size: 15px; + line-height: 26px; + /* identical to box height, or 173% */ + + + /* Primary/Main */ + box-shadow: none !important; + color: #C09507; + border: none !important; + background-color: transparent !important; +} + +.cancelBtn:hover { + color: #C09507 !important; +} + +.data_before_download div:nth-child(1) { + font-weight: 400; + font-size: 16px; + line-height: 24px; + /* identical to box height, or 150% */ + + + color: #000000; +} + +.data_before_download div:nth-child(2) { + font-weight: 600; +} + +.vl { + border-left: 1px dashed #C09507; + height: 50px; +} + +.alwaysHave { + transition: all 0.3s; + display: block; + height: 50px; + border: 1px solid black !important; + border-radius: 50%; +} + +.hoveredOne { + transition: all 0.3s; + display: block; + height: 50px; + border: 1px solid black !important; + border-radius: 16px; +} + +.settingGif { + height: 0px; + width: 0px; + /* transition: all 0.6s; */ + -webkit-animation: slide 3s linear infinite; + -moz-animation: slide 3s linear infinite; + animation: slide 3s linear infinite; +} + + +@-webkit-keyframes slide { + 0% { + height: 30px; + width: 30px; + } + + 50% { + height: 70px; + width: 70px; + } + + 100% { + height: 30px; + width: 30px; + } +} + + + +@-moz-keyframes slide { + 0% { + height: 30px; + width: 30px; + } + + 50% { + height: 70px; + width: 70px; + } + + 100% { + height: 30px; + width: 30px; + } +} + +@keyframes slide { + 0% { + height: 30px; + width: 30px; + } + + 50% { + height: 70px; + width: 70px; + } + + 100% { + height: 30px; + width: 30px; + } +} + +.alwaysHave:hover { + transition: all 0.3s; + /* height: 300px; */ + border: 1px solid black !important; +} + +/* .hideData { + transition: all 2s; + height: 0px; + visibility: visible; + display: none; + width: 0px; +} */ + +/* .showMoreData { + margin: auto; + transition: all 2s; + display: block; + border: 1px solid black; + border-radius: 16px; + height: 300px; + width: 400px; + visibility: visible; +} */ + +/* .vl:hover .showMoreData { + height: 300px; + width: 400px; + display: block; +} */ \ No newline at end of file diff --git a/src/Components/Navbar/Navbar.js b/src/Components/Navbar/Navbar.js index 8346d4dd9..11f71b9ad 100644 --- a/src/Components/Navbar/Navbar.js +++ b/src/Components/Navbar/Navbar.js @@ -121,7 +121,7 @@ const Navbar = (props) => { />   {screenlabels.navbar.datasets} - + { src={require("../../Assets/Img/datasets.svg")} alt="new" /> -   {screenlabels.navbar.integration} +   {screenlabels.navbar.connectors} {/* {   {screenlabels.navbar.connectors} */} {!isLoggedInUserCoSteward() ? - - new - new -   {screenlabels.navbar.Support} - : <> } + + new + new +   {screenlabels.navbar.Support} + : <>} { />   {screenlabels.navbar.datasets} - + - {(getTokenLocal() && (isLoggedInUserAdmin() || isLoggedInUserCoSteward()))? ( + {(getTokenLocal() && (isLoggedInUserAdmin() || isLoggedInUserCoSteward())) ? (
- - + /> */} - - - +
diff --git a/src/Layout/Participant.js b/src/Layout/Participant.js index 2d311efea..e91c1d5ce 100644 --- a/src/Layout/Participant.js +++ b/src/Layout/Participant.js @@ -124,16 +124,16 @@ function Participant(props) { path="/participant/connectors/detail" component={DemoDashboardTable} /> - - - +
diff --git a/src/Utils/Common.js b/src/Utils/Common.js index 83edc8fc4..f08f7f11c 100644 --- a/src/Utils/Common.js +++ b/src/Utils/Common.js @@ -150,7 +150,7 @@ export const getErrorLocal = () => { export const isLoggedInUserAdmin = () => { return getRoleLocal() ? getRoleLocal().toLowerCase() == - LocalStorageConstants.ROLES.DATAHUB_ADMIN.toLowerCase() + LocalStorageConstants.ROLES.DATAHUB_ADMIN.toLowerCase() : false; }; @@ -158,14 +158,14 @@ export const isLoggedInUserParticipant = () => { //return true; return getRoleLocal() ? getRoleLocal().toLowerCase() == - LocalStorageConstants.ROLES.DATAHUB_PARTICIPANT_ROOT.toLowerCase() + LocalStorageConstants.ROLES.DATAHUB_PARTICIPANT_ROOT.toLowerCase() : false; }; export const isLoggedInUserCoSteward = () => { //return true; return getRoleLocal() ? getRoleLocal().toLowerCase() == - LocalStorageConstants.ROLES.DATAHUB_CO_STEWARD.toLowerCase() + LocalStorageConstants.ROLES.DATAHUB_CO_STEWARD.toLowerCase() : false; }; @@ -306,3 +306,9 @@ export const adminNotFoundRoute = (e) => { return "/error"; } }; + +//function to scroll on top +export function goToTop(no) { + document.body.scrollTop = no ? no : 0; // For Safari + document.documentElement.scrollTop = no ? no : 0; // For Chrome, Firefox, IE and Opera +} \ No newline at end of file From 6d2a411d0f78a6c9b49c608df26d0f318bc01e71 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Thu, 16 Mar 2023 11:32:23 +0530 Subject: [PATCH 25/73] fixed some css and one label to display in meta download box --- .../DatasetIntegration.jsx | 19 +++++++++----- .../IntegrationDatasets/Join/Join.jsx | 2 +- .../IntegrationDatasets/Preview/Preview.jsx | 26 +++++++++---------- .../dataset_integration.module.css | 2 +- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index fce08a1f6..94768812b 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -64,7 +64,7 @@ const DatasetIntegration = (props) => { //connector data const [connectorData, setConnectorData] = useState({ - name: "", desc: "" + name: "", desc: "", }) @@ -243,7 +243,14 @@ const DatasetIntegration = (props) => { } const resetAll = (main, connector, join, goback, func1, func2) => { - goToTop() + // goToTop() + setConnectorId("") + setCounterForIntegration(2) + setCompleteData([]) + setFinalDatasetAfterIntegration([]) + setConnectorData({ name: "", desc: "" }) + setIsDatasetIntegrationListModeOn(true) + } // const deleteTable = (tableName, index) => { // let newArr = listOfDatsetFileAvailableForColumn.filter((each) => each.name != tableName.name) @@ -342,7 +349,7 @@ const DatasetIntegration = (props) => { setOpen(true); setAlertType("success") setMessage("Data saved successfully!") - setIsDatasetIntegrationListModeOn(true) + resetAll() let id = setTimeout(() => { setOpen(false); return clearTimeout(id) @@ -408,10 +415,8 @@ const DatasetIntegration = (props) => { document.body.removeChild(a); } const deleteConnector = () => { - setCompleteData([]) generateData(1, "delete") - setFinalDataNeedToBeGenerated([]) - setIsDatasetIntegrationListModeOn(true) + resetAll() } @@ -454,7 +459,7 @@ const DatasetIntegration = (props) => { {!isDatasetIntegrationListModeOn && } - {!isDatasetIntegrationListModeOn && completeData.length > 0 && < Preview generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} + {!isDatasetIntegrationListModeOn && completeData.length > 0 && } {isDatasetIntegrationListModeOn && } ) diff --git a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx index 04db81c78..3b3519e99 100644 --- a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx @@ -140,7 +140,7 @@ const Join = (props) => {
- diff --git a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx index dd08678ac..5d46b4b81 100644 --- a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx @@ -28,7 +28,7 @@ function NoRowsOverlay() { } const Preview = (props) => { - const { generateData, setIsDatasetIntegrationListModeOn, deleteConnector, counterForIntegrator, completeData, isEditModeOn, integrateMore, resetAll, generatedConnectorData, finalDatasetAfterIntegration, downloadDocument } = props + const { connectorData, generateData, setIsDatasetIntegrationListModeOn, deleteConnector, counterForIntegrator, completeData, isEditModeOn, integrateMore, resetAll, generatedConnectorData, finalDatasetAfterIntegration, downloadDocument } = props const [col, setCol] = useState([]) const [row, setRow] = useState([]) useEffect(() => { @@ -55,7 +55,7 @@ const Preview = (props) => { setCol([...val]) setRow([...rowArr]) } - }, [finalDatasetAfterIntegration]) + }, [finalDatasetAfterIntegration,]) return ( @@ -93,15 +93,15 @@ const Preview = (props) => { - {/*
{generatedConnectorData?.file_name}.csv
*/} +
{connectorData?.name}.csv
- {/*
{generatedConnectorData.datasets?.map((each) => `${each}, `)}
*/} +
{completeData?.map((each) => `${each.dataset_name}, `)}
- {/*
{generatedConnectorData?.no_of_records}
*/} +
{finalDatasetAfterIntegration?.length}
{/* console.log(affixed, "read for dowload")} style={{ backgrond: "white", transition: "all 2s", visibility: counterForIntegrator != completeData.length ? "hidden" : "visible" }} offsetBottom={20}> */} @@ -119,17 +119,17 @@ const Preview = (props) => {
- - - - + + + {/* */} + {/* */} - - + {/* */} + {/* */} {finalDatasetAfterIntegration.length > 0 && } - - + {/* */} + {/* */} {true && } diff --git a/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css b/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css index c71c785c7..aebdc341c 100644 --- a/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css +++ b/src/Components/Datasets/IntegrationDatasets/dataset_integration.module.css @@ -190,7 +190,7 @@ background-color: #9aa7b5 !important; cursor: auto !important; border-radius: 8px; - + height: 48px; color: white !important; text-transform: none !important; } From c39adcf467145944e1f7c3cd9b4ebcd7d58e7edf Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Thu, 16 Mar 2023 11:52:00 +0530 Subject: [PATCH 26/73] routing for participant handled --- src/Components/Navbar/ParticipantNavbar.js | 6 +++--- src/Layout/Participant.js | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Components/Navbar/ParticipantNavbar.js b/src/Components/Navbar/ParticipantNavbar.js index c74bee327..e4d849fb0 100644 --- a/src/Components/Navbar/ParticipantNavbar.js +++ b/src/Components/Navbar/ParticipantNavbar.js @@ -106,9 +106,9 @@ const ParticipantNavbar = (props) => { src={require("../../Assets/Img/datasets.svg")} alt="new" /> -   {screenlabels.navbar.integration} +   {screenlabels.navbar.connectors} - + {/* { alt="new" />   {screenlabels.navbar.connectors} - + */} { e.preventDefault(); diff --git a/src/Layout/Participant.js b/src/Layout/Participant.js index 0ca1118e5..fcae17eae 100644 --- a/src/Layout/Participant.js +++ b/src/Layout/Participant.js @@ -44,11 +44,11 @@ function Participant(props) { path="/participant/datasets" component={DatasetParticipant} /> - + /> */} {/* - - + */} From 1b17708c517860d0047d44f6e85164243c9b6ead Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Thu, 16 Mar 2023 11:53:10 +0530 Subject: [PATCH 27/73] fixed one issue --- .../Datasets/IntegrationDatasets/DatasetIntegration.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 94768812b..6da335bbf 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -459,7 +459,7 @@ const DatasetIntegration = (props) => { {!isDatasetIntegrationListModeOn && } - {!isDatasetIntegrationListModeOn && completeData.length > 0 && } + {!isDatasetIntegrationListModeOn && completeData.length > 0 && } {isDatasetIntegrationListModeOn && } ) From df84e554bc16b4fd64bf363bf7c1283eb89b0151 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Thu, 16 Mar 2023 12:30:26 +0530 Subject: [PATCH 28/73] saving scroll effect stopped --- .../Datasets/IntegrationDatasets/DatasetIntegration.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 6da335bbf..7a7673322 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -345,7 +345,7 @@ const DatasetIntegration = (props) => { } else if (condition == "save") { console.log("inside save", res.data) - setConnectorId(res?.data?.id ? res.data.id : "") + // setConnectorId(res?.data?.id ? res.data.id : "") setOpen(true); setAlertType("success") setMessage("Data saved successfully!") @@ -354,7 +354,7 @@ const DatasetIntegration = (props) => { setOpen(false); return clearTimeout(id) }, 2500) - document.querySelector('#previewTable').scrollIntoView({ behavior: 'smooth' }); + // document.querySelector('#previewTable').scrollIntoView({ behavior: 'smooth' }); } else if (condition == "delete") { console.log("inside delete", res) @@ -369,6 +369,7 @@ const DatasetIntegration = (props) => { // goToTop(2000) }).catch((err) => { + console.log(err) setOpen(true); setLoader(false) setAlertType("error") From ef6de00206b9c2d72a2539a20118989008d5f54c Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 16 Mar 2023 14:38:30 +0530 Subject: [PATCH 29/73] Added data standrization template --- .../StandardizationInOnbording.js | 608 ++++++++++++++++++ .../standardizationInOnbording.css | 96 +++ src/Constants/UrlConstants.js | 9 +- src/Views/Login/Login.js | 17 +- src/Views/Settings/Settings/Settings.js | 27 +- 5 files changed, 743 insertions(+), 14 deletions(-) create mode 100644 src/Components/Standardization/StandardizationInOnbording.js create mode 100644 src/Components/Standardization/standardizationInOnbording.css diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js new file mode 100644 index 000000000..f8377bd45 --- /dev/null +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -0,0 +1,608 @@ +import React, { useEffect, useState } from "react"; +import TextField from "@mui/material/TextField"; +import "./standardizationInOnbording.css"; +// import { Button } from 'antd'; +import Button from "@mui/material/Button"; +import Accordion from "@mui/material/Accordion"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import Typography from "@mui/material/Typography"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import InfoIcon from '@mui/icons-material/Info'; +import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; +import AddIcon from '@mui/icons-material/Add'; +import Tooltip from '@mui/material/Tooltip'; +import { IconButton } from "@mui/material"; +import { useHistory, useLocation, Redirect } from "react-router-dom"; +import HTTPService from "../../Services/HTTPService"; +import { GetErrorHandlingRoute } from "../../Utils/Common"; +import UrlConstant from "../../Constants/UrlConstants"; +import Loader from "../Loader/Loader"; +import { message, Space } from "antd"; + +const StandardizationInOnbord = (props) => { + const { inSettings, isaccesstoken, showBrandingScreen, isOnborading } = props; + const [allDatapoints, setAllDataPoints] = useState([ + // { datapoint_category: "Farmer profile", datapoint_description: "Add Datapoint attributes" }, + // { datapoint_category: "Farmer profile", datapoint_description: "Add Datapoint attributes" }, + ]); + const [allAttributes, setAllAttributes] = useState({}); + const [allAttributesDes, setAllAttributesDes] = useState({}); + const [datapointName, setDatapointName] = useState(""); + const [datapointDes, setDatapointDes] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(false); + const [errorMessages, setErrorMessage] = useState(""); + + const history = useHistory(); + + const [messageApi, contextHolder] = message.useMessage(); + const success = (text, type) => { + messageApi.open({ + type: type, + content: text, + duration: 5, + }); + }; + + console.log("all datapoints", allDatapoints); + + const handleAddDatapoint = () => { + if(!datapointName || !datapointDes ){ + return + } + let tmpAllDatapoints = [...allDatapoints]; + let newDatapoint = { + datapoint_category: datapointName, + datapoint_description: datapointDes, + }; + + let tmpAllAttributes = { ...allAttributes }; + let tmpAllAttributesDes = { ...allAttributesDes }; + + let keys = Object.keys(allAttributes); + console.log("keys", keys); + + tmpAllAttributes[keys.length] = []; + tmpAllAttributesDes[keys.length] = []; + + console.log("all attribute tmp in add", tmpAllAttributes); + + setAllAttributes({ ...tmpAllAttributes }); + setAllAttributesDes({ ...tmpAllAttributesDes }); + + tmpAllDatapoints.push(newDatapoint); + setAllDataPoints(tmpAllDatapoints); + setDatapointName(""); + setDatapointDes(""); + }; + const hanldeAttributeInputChange = ( + index, + allAttributesArrIndex, + newValue + ) => { + console.log("allAttribute in start of function", allAttributes); + let tmpAllAttributes = { ...allAttributes }; + + tmpAllAttributes[index][allAttributesArrIndex] = newValue; + setAllAttributes(tmpAllAttributes); + console.log("allAttribute", allAttributes); + }; + const hanldeAttributeDesInputChange = ( + index, + allAttributesArrIndex, + newValue + ) => { + console.log("allAttribute Des in start of function", allAttributesDes); + let tmpAllAttributesDes = { ...allAttributesDes }; + + tmpAllAttributesDes[index][allAttributesArrIndex] = newValue; + setAllAttributesDes(tmpAllAttributesDes); + console.log("allAttributeDes", allAttributesDes); + }; + + const handleAddDatapointAttribute = (index) => { + + if(!allAttributes[index][0] || !allAttributesDes[index][0]){ + return + } + + let tmpAllAttributes = { ...allAttributes }; + tmpAllAttributes[index].push(tmpAllAttributes[index][0]); + tmpAllAttributes[index][0] = ""; + setAllAttributes(tmpAllAttributes); + + // For Des + let tmpAllAttributesDes = { ...allAttributesDes }; + tmpAllAttributesDes[index].push(tmpAllAttributesDes[index][0]); + tmpAllAttributesDes[index][0] = ""; + setAllAttributesDes(tmpAllAttributesDes); + console.log("all Des", tmpAllAttributesDes); + }; + + const handleDatapointAtticuteDelete = (index, arrIndex) => { + let tmpAllAttributes = { ...allAttributes }; + tmpAllAttributes[index].splice(arrIndex, 1); + setAllAttributes(tmpAllAttributes); + console.log("tmpAllAttributes", tmpAllAttributes); + }; + + const handleDatapointCategoryDelete = (index) => { + if (allDatapoints[index]["id"]) { + console.log("id", allDatapoints[index]["id"]); + deleteDatapointCategory(allDatapoints[index]["id"], index); + } else { + let tmpAllDatapoints = [...allDatapoints]; + tmpAllDatapoints.splice(index, 1); + setAllDataPoints(tmpAllDatapoints); + } + }; + + // API calls + + const handleSubmit = () => { + let payload = [...allDatapoints]; + + for (let index = 0; allAttributes[index]; index++) { + let attributeObj = {}; + for (let i = 1; i < allAttributes[index].length; i++) { + attributeObj[allAttributes[index][i]] = allAttributesDes[index][i]; + } + payload[index]["datapoint_attributes"] = attributeObj; + } + + console.log("final payload", payload); + + let method = inSettings ? "PUT" : isOnborading ? "POST" : "POST"; + let url = isOnborading + ? UrlConstant.base_url + UrlConstant.standardization_post_data + : inSettings + ? UrlConstant.base_url + UrlConstant.standardization_update_data + : UrlConstant.base_url + UrlConstant.standardization_post_data; + + setIsLoading(true); + HTTPService(method, url, payload, false, true, isaccesstoken) + .then((response) => { + setIsLoading(false); + console.log("response", response); + if (response.status == 201) { + if (inSettings) { + success("Standardization template updated!", "success"); + } else { + success( + "Standardization template created successfully.", + "success" + ); + } + console.log("success"); + if (isOnborading) { + showBrandingScreen(); + } + } + }) + .catch((e) => { + setIsLoading(false); + // success('Standardization template created successfully') + console.log(e); + if ( + e.response != null && + e.response != undefined && + e.response.status === 401 + ) { + setError(true); + // success( + // e.response.data && e.response.data.message + // ? e.response.data.message + // : "User not registered", "error" + // ); + history.push(GetErrorHandlingRoute(e)); + } else { + setError(false); + success( + e.response.data && e.response.data.message + ? e.response.data.message + : "Something went wrong.", + "error" + ); + } + }); + }; + + const getStandardiziedTemplate = () => { + let url = UrlConstant.base_url + UrlConstant.standardization_get_data; + + setIsLoading(true); + HTTPService("GET", url, false, false, true) + .then((response) => { + setIsLoading(false); + console.log("response", response); + if (response.status == 200) { + setAllDataPoints(response?.data); + let tmp = { ...allAttributes }; + let tmpDes = { ...allAttributesDes }; + response.data.forEach((item, index) => { + tmp[index] = Object.keys(item.datapoint_attributes); + tmp[index].push(tmp[index]?.[0]); + tmp[index][0] = ""; + + tmpDes[index] = Object.values(item.datapoint_attributes); + tmpDes[index].push(tmpDes[index]?.[0]); + tmpDes[index][0] = ""; + }); + setAllAttributes(tmp); + setAllAttributesDes(tmpDes); + console.log("tmp in get call attributes", tmp,tmpDes, allAttributes); + } + }) + .catch((e) => { + setIsLoading(false); + // success('Standardization template created successfully') + console.log(e); + if ( + e.response != null && + e.response != undefined && + e.response.status === 401 + ) { + setError(true); + // success( + // e.response.data && e.response.data.message + // ? e.response.data.message + // : "User not registered", "error" + // ); + history.push(GetErrorHandlingRoute(e)); + } else { + setError(false); + success( + e.response.data && e.response.data.message + ? e.response.data.message + : "Something went wrong.", + "error" + ); + } + }); + }; + + const deleteDatapointCategory = (id, index) => { + let url = + UrlConstant.base_url + + UrlConstant.standardization_delete_category + + id + + "/"; + + HTTPService("DELETE", url, false, false, true) + .then((response) => { + setIsLoading(false); + console.log("response", response); + success("Category deleted successfully.", "success"); + + let tmpAllDatapoints = [...allDatapoints]; + tmpAllDatapoints.splice(index, 1); + setAllDataPoints(tmpAllDatapoints); + return true; + }) + .catch((e) => { + setIsLoading(false); + console.log(e); + if ( + e.response != null && + e.response != undefined && + e.response.status === 401 + ) { + setError(true); + history.push(GetErrorHandlingRoute(e)); + } else { + setError(false); + success( + e.response.data && e.response.data.message + ? e.response.data.message + : "Something went wrong.", + "error" + ); + } + }); + }; + + // useEffect(()=>{ + // console.log('attribute in use effect to check', allAttributes) + // },[allAttributes]) + + // useEffect(() => { + // console.log('use effect run 1') + // let tmpAllAttributes = { ...allAttributes }; + // let tmpAllAttributesDes = { ...allAttributesDes }; + // allDatapoints.forEach((item, index) => { + + // // if(!allAttributes[index]){ + // // // console.log('in use effect loop', allAttributes, index, tmpAllAttributes) + // // tmpAllAttributes[index] = []; + // // tmpAllAttributesDes[index] = []; + + // // } + // }); + // console.log("all attribute in map", allAttributes,tmpAllAttributes); + // // setAllAttributes(tmpAllAttributes); + // // setAllAttributesDes(tmpAllAttributesDes) + + // }, [allDatapoints]); + + useEffect(() => { + if (inSettings) { + getStandardiziedTemplate(); + } + }, []); + + console.log("all attribute", allAttributes); + + return ( + <> + {isLoading ? : ""} + {contextHolder} +
+
+

Datapoint category details

+

+ Enter the datapoints and datapoints attributes, we will show to + others! +

+
+
+ setDatapointName(e.target.value)} + className="datapoint-name-input-box" + id="datapoint-name-input-box-id" + label="Datapoint category name" + variant="outlined" + /> + e.target.value.length<256 ? setDatapointDes(e.target.value) : ""} + multiline + size="small" + className="datapoint-name-input-box-description" + id="datapoint-name-input-box-description-id" + label="Datapoint category description" + variant="outlined" + /> +
+
+ +
+ +
+

Datapoint attributes

+ {allDatapoints?.map((item, index) => { + // let tmpAllAttributes = {...allAttributes} + // tmpAllAttributes[index] = [] + // setAllAttributes(tmpAllAttributes) + // console.log('all attribute in map', allAttributes) + + return ( + <> + + } + aria-controls="panel1a-content" + id="panel1a-header" + className="attribute-accordion-titile" + > + + {item.datapoint_category} + +
+ handleDatapointCategoryDelete(index)} + > + + +
+
+ +
+ {/*

Farmer profile

*/} +

{item.datapoint_description}

+
+ + hanldeAttributeInputChange(index, 0, e.target.value) + } + /> + + hanldeAttributeDesInputChange( + index, + 0, + e.target.value + ) + } + /> + handleAddDatapointAttribute(index)} + > + + + + {/* + + + + + + + */} + + +
+
+ {allAttributes?.[index]?.map((inputValue, arrIndex) => { + console.log('in category map ',allAttributesDes?.[index]?.[arrIndex], allAttributesDes?.[index]) + return ( + <> + {arrIndex != 0 ? ( + + + + + + handleDatapointAtticuteDelete( + index, + arrIndex + ) + } + > + + + + // + ), + }} + className="datapoint-attribute-input-box" + id="datapoint-attribute-input-box-id" + label="Datapoint attributes" + variant="outlined" + value={inputValue} + // onChange={(e) => + // // hanldeAttributeInputChange(index, 0, e.target.value) + // } + /> + ) : ( + "" + )} + + ); + })} +
+
+
+
+ + ); + })} + + {/*

Datapoint attributes

+ +
+

Farmer profile

+

Add Datapoint attributes

+
+ + + + + + + + + + + + +
+
*/} +
+
+
+ {inSettings ? ( + <> + + + ) : ( + <> + + + + )} +
+ + ); +}; + +export default StandardizationInOnbord; diff --git a/src/Components/Standardization/standardizationInOnbording.css b/src/Components/Standardization/standardizationInOnbording.css new file mode 100644 index 000000000..66df5da02 --- /dev/null +++ b/src/Components/Standardization/standardizationInOnbording.css @@ -0,0 +1,96 @@ +.main-container { + text-align: left; + width: 1150px !important; + margin: auto; + background: #ffffff; + border-radius: 30px; +} +.datapoint-name-input-box { + width: 950px; + height: 50px; + margin: 20px auto !important; +} +.datapoint-name-input-box-description { + width: 950px; + /* height: 120px; */ +} +.datapoint-name-input-box-description > div { + /* height: 100%; */ +} +.datapoint-name-input-box-description > div > textarea { + /* height: 120px !important; */ + min-height: 120px !important; + max-height: 120px !important; + overflow: hidden !important; +} +.data-point-input-box-container { + margin: auto !important; +} +.title-container, +.data-point-input-box-container, +.datapoint-add-button-classname { + margin: auto; + width: 950px !important; +} +.datapoint-add-button-classname { + margin: 50px auto; +} +.title-container > h1 { + font-weight: 700; + font-size: 32px; +} +.title-container > p { + font-weight: 300; + font-size: 18px; +} +.datapoint-add-button-classname { + text-align: right; +} +.datapoint-add-button { + width: 172px !important; + height: 48px !important; + text-transform: none !important; + color: #ffffff; + margin-top: 30px; + margin-bottom: 30px; + font-weight: 700; + background: #c09507; + border: 2px solid #c09507 !important; + box-shadow: none !important; +} +.finish-later-button{ + border: none !important; + color: black; +} + +.attribute-container { + width: 950px; + margin: auto; +} +.attribute-accordion-titile :nth-child(1) { + width: 100% !important; +} +.datapoint-name-input-box input { + height: 15px !important; +} +.attribute-container > h1 { + font-weight: 700; + font-size: 32px; + margin: 20px auto; +} +.accordion-title { + font-weight: 700 !important; + font-size: 20px !important; +} +.datapoint-attribute-input-box{ + width: 45%; + margin: 0 20px 20px 0 !important; +} + +.accordion-main-classname{ + box-shadow: 0px 20px 40px -4px rgba(145, 158, 171, 0.16) !important; +} +#add-attribute-icon-id{ + color: black !important; + /* font-size: small; */ +} diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index ced6ad1ab..ac28b5b2b 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -85,7 +85,14 @@ const UrlConstant = { get_dataset_name_list: "datahub/dataset_ops/datasets_names/", get_files_for_selected_datasets: "datahub/dataset_ops/datasets_file_names/", get_columns_for_selected_files: "datahub/dataset_ops/datasets_col_names/", - joining_the_table: "datahub/dataset_ops/datasets_join_condition/" + joining_the_table: "datahub/dataset_ops/datasets_join_condition/", + + // Standardization + + standardization_post_data: "datahub/standardise/", + standardization_update_data: "datahub/standardise/update_standardisation_template/", + standardization_delete_category: "datahub/standardise/", + standardization_get_data: "datahub/standardise/" }; diff --git a/src/Views/Login/Login.js b/src/Views/Login/Login.js index 211997b1b..41c8997da 100644 --- a/src/Views/Login/Login.js +++ b/src/Views/Login/Login.js @@ -46,6 +46,7 @@ import LeftintroParticipant from "../../Components/intros/LeftIntroParticipant"; import LocalStorageConstants from "../../Constants/LocalStorageConstants"; import AddingCategory from "../../Components/Catergories/AddingCategory"; import { ConsoleSqlOutlined } from "@ant-design/icons"; +import StandardizationInOnbord from "../../Components/Standardization/StandardizationInOnbording"; export default function Login(props) { const [button, setButton] = useState(false); const email = useRef(); @@ -72,6 +73,7 @@ export default function Login(props) { const [isDataSet, setIsDataSet] = useState(false); const [isCategorySetup, setIsCategorySetup] = useState(false); const [isaccesstoken, setisaccesstoken] = useState(false); + const [isDataStandardization, setIsDataStandardization] = useState(false); //const [userid, setUserId] = useState(false) const [orgName, setOrgName] = useState(""); @@ -937,8 +939,8 @@ export default function Login(props) { ) : (
- {!isCategorySetup &&

{screenlabels.login.signup_header}

} - {(isParticipantRoute(location.pathname) && !isCategorySetup) ? : !isCategorySetup ? : ""} + {!isCategorySetup && !isDataStandardization &&

{screenlabels.login.signup_header}

} + {(isParticipantRoute(location.pathname) && !isCategorySetup && !isDataStandardization) ? : !isCategorySetup && !isDataStandardization ? : ""} {isemail || isOtp ? : ""} {/* */} @@ -1127,9 +1129,18 @@ export default function Login(props) { {isCategorySetup && isLoggedInUserAdmin() && ( { setIsCategorySetup(false) - setisBranding(true); + // setisBranding(true); + setIsDataStandardization(true) }} isOnborading={true} /> )} + { + isDataStandardization && isLoggedInUserAdmin() && ( + { + setIsDataStandardization(false) + setisBranding(true); + }} isOnborading={true}/> + ) + }
); } diff --git a/src/Views/Settings/Settings/Settings.js b/src/Views/Settings/Settings/Settings.js index b0f20ae28..144589755 100644 --- a/src/Views/Settings/Settings/Settings.js +++ b/src/Views/Settings/Settings/Settings.js @@ -23,7 +23,7 @@ import OrganisationSetting from "../organisation/OrganisationSetting"; import { useParams } from "react-router-dom"; import PolicySettings from "../PolicySettings/PolicySettings"; import BrandingSetting from "../branding/BrandingSetting"; -import HandleSessionTimeout, { isLoggedInUserCoSteward } from "../../../Utils/Common"; +import HandleSessionTimeout, { isLoggedInUserAdmin, isLoggedInUserCoSteward } from "../../../Utils/Common"; import Loader from "../../../Components/Loader/Loader"; import { GetErrorHandlingRoute } from "../../../Utils/Common"; import DepartmentSettingsCard from "../ParticipantSettings/DepartmentSettingsCard"; @@ -31,6 +31,7 @@ import ProjectListing from "../ParticipantSettings/Project/ProjectListing"; import DepartmentListing from "../Department/DepartmentListing"; import AdminCategorySetupAndEdit from "../../../Components/Catergories/AdminCategorySetupAndEdit"; import AddingCategory from "../../../Components/Catergories/AddingCategory"; +import StandardizationInOnbord from "../../../Components/Standardization/StandardizationInOnbording"; const useStyles = { btncolor: { @@ -288,10 +289,15 @@ function Settings(props) { : "" } {!isLoggedInUserCoSteward() ? : "" } - - {!isLoggedInUserCoSteward() ? - : " "} + : " "} + { + isLoggedInUserAdmin() ? + + : "" + } + {/* + // */} @@ -390,8 +396,8 @@ function Settings(props) { {/* */} - - + {/* + */} {/* My departments @@ -428,12 +434,13 @@ function Settings(props) { ))} */} + {/* */} + + - - - - + {/* */} + From f608677a8825d055345fa2e244366529da06cdbf Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 16 Mar 2023 14:41:14 +0530 Subject: [PATCH 30/73] Added data standrization template --- src/Constants/UrlConstants.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index 7c56b670c..23fefe480 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -86,7 +86,6 @@ const UrlConstant = { get_dataset_name_list: "datahub/dataset_ops/datasets_names/", get_files_for_selected_datasets: "datahub/dataset_ops/datasets_file_names/", get_columns_for_selected_files: "datahub/dataset_ops/datasets_col_names/", -<<<<<<< HEAD joining_the_table: "datahub/dataset_ops/datasets_join_condition/", // Standardization @@ -94,12 +93,10 @@ const UrlConstant = { standardization_post_data: "datahub/standardise/", standardization_update_data: "datahub/standardise/update_standardisation_template/", standardization_delete_category: "datahub/standardise/", - standardization_get_data: "datahub/standardise/" -======= + standardization_get_data: "datahub/standardise/", joining_the_table: "connectors/integration/", integration_connectors: "connectors/", list_of_connectors: "connectors/", ->>>>>>> c83a7a9e2ebad5ead3f6a03afa9c20ae5cbec2ce }; From 976a8315e81f25507c73dd52d2955d9fd0810b19 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 16 Mar 2023 15:49:27 +0530 Subject: [PATCH 31/73] give background color to button --- src/Components/Standardization/standardizationInOnbording.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Standardization/standardizationInOnbording.css b/src/Components/Standardization/standardizationInOnbording.css index 66df5da02..b53ef78aa 100644 --- a/src/Components/Standardization/standardizationInOnbording.css +++ b/src/Components/Standardization/standardizationInOnbording.css @@ -54,7 +54,7 @@ margin-top: 30px; margin-bottom: 30px; font-weight: 700; - background: #c09507; + background: #c09507 !important; border: 2px solid #c09507 !important; box-shadow: none !important; } From 54680043d3846ae0adf30a7962a735fa3c1806e2 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Fri, 17 Mar 2023 14:35:10 +0530 Subject: [PATCH 32/73] view edit and some bugs fixed in this --- src/Assets/CSS/common.css | 10 +- src/Assets/Img/join_inner_black_.jpg | Bin 0 -> 2453 bytes src/Assets/Img/join_left_selected.svg | 12 + src/Assets/Img/join_right_black_.svg | 12 + .../CardDetail/CardDetail.jsx | 10 +- .../CardDetail/card_detail.module.css | 4 + .../DatasetIntegration.jsx | 210 +++++++++++++----- .../DatasetSelect/DatasetSelect.jsx | 64 ++++-- .../IntegrationDatasets/Join/Join.jsx | 29 +-- .../IntegrationDatasets/Preview/Preview.jsx | 44 +++- .../dataset_integration.module.css | 70 +++++- .../IntegrationConnectors/ConnectorCard.jsx | 119 +++++----- .../IntegrationConnectors/ConnectorsList.jsx | 8 +- src/Components/Navbar/Navbar.js | 4 +- src/Components/Navbar/ParticipantNavbar.js | 4 +- 15 files changed, 438 insertions(+), 162 deletions(-) create mode 100644 src/Assets/Img/join_inner_black_.jpg create mode 100644 src/Assets/Img/join_left_selected.svg create mode 100644 src/Assets/Img/join_right_black_.svg diff --git a/src/Assets/CSS/common.css b/src/Assets/CSS/common.css index 7769dd51d..396072bae 100644 --- a/src/Assets/CSS/common.css +++ b/src/Assets/CSS/common.css @@ -1008,7 +1008,7 @@ button.disbalesubmitbtndept { .accordion_for_columns_under_integration .accordion_detail .MuiSvgIcon-root, .accordion_for_columns_under_integration .select_all_btn .MuiSvgIcon-root, .dataset_selector_in_integration .MuiSvgIcon-root { - color: #637381 !important; + color: #c09507 !important; } .dataset_selector_in_integration .MuiDataGrid-columnHeaders { @@ -1116,4 +1116,12 @@ html { .connectorCard:hover { border: 1px solid #c09507; cursor: pointer; +} + +.dataset_selector_in_integration .backButtonMainDiv .MuiSvgIcon-root { + color: #3491ee !important; +} + +.dataset_selector_in_integration .Mui-focused { + /* border: 1px solid #ab8405 !important; */ } \ No newline at end of file diff --git a/src/Assets/Img/join_inner_black_.jpg b/src/Assets/Img/join_inner_black_.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05ce8f858270d2c1879b6bb6d9929c9a437c4365 GIT binary patch literal 2453 zcmbu+dpOhk9{}+0m`g6lT~QKq35_t+sVFp!BaKKTr;EmNKW-~Va;YeHbDJH_wOMl8 zT*e}zq>hngZcSN9VaVAsc682p&hL4CfBl}{d4HbI^Zw)ge%{aXdcTElgl_?PM>qlw zfJ8vRiLD0+#{oM4^e^N4kbgM>1QI?56eNKIzyVQ^0wAIQ5>)^RdjL%U0EzuI8~8gw zBBEe1aS6$7Qqo%u&GLW&|W~nb_L8o5Ml3Z=? zI1p0B4^mbXXAMpG9I8cVzfHZT10`>e{Xr?;6AC>sWnC+Pqt6VA7Hh@P}5@f~>x% za`-`Gw0a}&+fI_{^j0NQznS2^+i2xWCZ*W7tm0eb)TE2zYpm77yc(Z?VcyAa2ZQwX zzr=av%AbSO@EesasbTVPHT6StEJ&te!J5z|<;v731xkD82J)fJx-lG05<$kAWZcw%#2LJCF7zN^4BU0<^q{om=kg z4lgFT!iKRc%x6$#NMhHk(%{U04rrhF9MepHvTrxfs z{S=`FPJgel-@8ysR_=2;%X6q}U7nG#7L)ERXkOj@l+d_#j+8x0ou7{j>G*m$^=@RrkUt1B+2H_?5KC(*T#Lnat>y9Lo#pPE(7 zm0%m=!m1`dP3>q_RZlJt2{SGZAvE~*5Dt^T_E|yUStT{3CEI-88H@ae1 z$?NI_iLI;6$m+#GT=ObNBHWW4!XUx<^Dek>TZYn$Y*rga@i``DYO`$%iG?(-DFxiWNoZe#zc%h0+UrHQ&E5l7NJYULyWjM=7N?(o;0&)X; z(lgBnEVJo)2;>Dyt$$BUVRC1Em0OZo+kU!cXz=6y`$fWGrea{o5!m=;7Q_ z6SK{%pNfP_BP^G&3M%Hrg5*@vR@0<(XcSBks4n4@FCSVlP-rfoV$ikrr>6b z-ZX7oWWf@ACi}IUM~1eePX_xc*hL+6FFl9{GYDoA)Pmo-4|EoTuassu@N)zqJPc6~ z%yWOInewIjO-0|Wru?|wpHF6!^P8(&REhU}+qwshSX~cTUd3J82cd;6N%EITMC1@j zDxY_rL_44D`%Bb{il<@ItQ^P7dJs*h_!1A{R||n;-*>Ngp7f;}A;8{67XnE_VEy{0 z0-fhTsbj@AA0BLv9h^q3YvyehZV)*esp~eIdYb<0nv0~5apgw{&75;3w24XRW*oF* zb%GmL!rvemeV{{WLSTTrMrqe%)IDBIEpq5GN!~5X3pM#H%S>&`i$l-9OwqzT{N(0T zGapUFAgl+Ct0E&Pda=(mlA<1MzaUvxN=A;7ek@vlb)02n-#J@{e}&FfF$_yy^WsxU zSX>9~R;O01JELhpnr!rhnT1yG9dY$8ZbyJAZ5K~e=#-p$`cwGSULEgV>6R2EXF^4x z*4#F2{?RO~$&23aa?@JAWhi0*AC0_SMjIt22mPF7`%JtfslUOBYtRveh;2+iE+cbv z-_h{s;YYTXufGa10;~5e+b9V%mN*?@(670T{?R##jE(HQocert(4f(n>8;wkIRxz) zu+D=2fTFX31;;KC>tIfdRT^oEJIQpTa52rLFa7cjf+C2Vl3g&=3%cp&yln_Y`ywm& z>6v+Z|wZqxzXk?GEgI*Q_bP4h z1vR_SFMr-i??R~vNMpHowkJWyK>dljc5Q&V_MHkNBX6z{NU%$uJd&>roB|yc K1O7~aaO@9xlz5E* literal 0 HcmV?d00001 diff --git a/src/Assets/Img/join_left_selected.svg b/src/Assets/Img/join_left_selected.svg new file mode 100644 index 000000000..7966a5e10 --- /dev/null +++ b/src/Assets/Img/join_left_selected.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Assets/Img/join_right_black_.svg b/src/Assets/Img/join_right_black_.svg new file mode 100644 index 000000000..a8c2920c0 --- /dev/null +++ b/src/Assets/Img/join_right_black_.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx b/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx index 32d4c3026..4c73ead04 100644 --- a/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx +++ b/src/Components/Datasets/IntegrationDatasets/CardDetail/CardDetail.jsx @@ -39,6 +39,14 @@ const CardDetail = (props) => { const handleDeleteCard = () => { let arr = [...completeData] + let obj + if (index != 0) { + obj = arr[index - 1] + obj["right_on"] = [] + obj["type"] = "" + obj["next_left"] = [] + arr[index - 1] = obj + } arr.splice(index, 1) setCompleteData([...arr]) setTotalCounter((prev) => prev - 1) @@ -58,7 +66,7 @@ const CardDetail = (props) => {
{data?.dataset_name ? data.dataset_name : ""}
- + diff --git a/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css b/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css index 54765721a..f0a1cb371 100644 --- a/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css +++ b/src/Components/Datasets/IntegrationDatasets/CardDetail/card_detail.module.css @@ -63,4 +63,8 @@ .deleteicon:hover .topRowOfCard { background: red !important; color: white !important; +} + +.deleteicon { + /* align-self: flex-end; */ } \ No newline at end of file diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 7a7673322..95cddb2aa 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -20,8 +20,13 @@ const fs = require('fs') const DatasetIntegration = (props) => { - const { isEditModeOn, connectorIdForView } = props + const [isEditModeOn, setIsEditModeOn] = useState(false) const [counterForIntegrator, setCounterForIntegration] = useState(2) + const [isEdited, setIsEdited] = useState(false) + + const [isConditionForConnectorDataForSaveMet, setIsConditionForConnectorDataForSaveMet] = useState(false) + const [isAllConditionForSaveMet, setIsAllConditionForSaveMet] = useState(false) + const [isDatasetIntegrationListModeOn, setIsDatasetIntegrationListModeOn] = useState(true) const [top, setTop] = useState(10); const [orgList, setOrgList] = useState([]) @@ -30,6 +35,10 @@ const DatasetIntegration = (props) => { const [open, setOpen] = React.useState(false); const [connectorId, setConnectorId] = useState("") + const [connectorTimeData, setConnectorTimeData] = useState({ + create_at: "", last_updated: "" + }) + const [connectorIdForView, setConnectorIdForView] = useState("") const [template, setTemplate] = useState( { org_id: "", dataset_list: [], file_list: [], org_name: "", dataset_id: "", dataset_name: "", file_name: "", availabeColumns: [], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, @@ -100,7 +109,7 @@ const DatasetIntegration = (props) => { const getDataList = (source, index) => { - setLoader(true) + // setLoader(true) let url = "" let method if (source == "org_names") { @@ -111,7 +120,9 @@ const DatasetIntegration = (props) => { method = "GET" } HTTPService(method, url, "", false, true, false).then((res) => { - setLoader(false) + // if (!isEditModeOn && !connectorIdForView) { + // setLoader(false) + // } if (source == "org_names") { setOrgList([...res.data]) } else if (source == "dataset_names") { @@ -120,7 +131,7 @@ const DatasetIntegration = (props) => { }).catch((err) => { setAlertType("error") setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Error occurred! Dataset could not fetched.") - setLoader(false) + // setLoader(false) if (err?.response.status == 401) { history.push(GetErrorHandlingRoute(err)); } @@ -151,11 +162,8 @@ const DatasetIntegration = (props) => { } return await HTTPService(method, url, payload, false, true, false).then((res) => { setLoader(false) - if (source == "dataset") { - - setTemplate({ ...template, dataset_name: res.data[0]?.dataset_name ? res.data[0].dataset_name : "N/A", dataset_id: org ? org : "", file_list: [...res.data] }) - + setTemplate({ ...template, availabeColumns: [], dataset_name: res.data[0]?.dataset_name ? res.data[0].dataset_name : "N/A", dataset_id: org ? org : "", file_name: "", availabeColumns: [], file_list: [...res.data] }) } else if (source == "file") { let name = list[0] @@ -166,7 +174,8 @@ const DatasetIntegration = (props) => { } setTemplate({ ...template, file_id: fileId, file_name: name, availabeColumns: [...res.data[name]] }) } else if (source == "org") { - setTemplate({ ...template, dataset_list: [...res.data], org_id: org, org_name: res?.data?.length > 0 ? res.data[0]?.org_name : "" }) + console.log(template) + setTemplate({ ...template, availabeColumns: [], dataset_name: "", dataset_id: "", file_name: "", file_list: [], dataset_list: [...res.data], org_id: org, org_name: res?.data?.length > 0 ? res.data[0]?.org_name : "" }) } return true }).catch((err) => { @@ -244,27 +253,80 @@ const DatasetIntegration = (props) => { const resetAll = (main, connector, join, goback, func1, func2) => { // goToTop() + if (isEditModeOn) { + setIsConditionForConnectorDataForSaveMet(false) + setIsAllConditionForSaveMet(false) + } setConnectorId("") setCounterForIntegration(2) setCompleteData([]) setFinalDatasetAfterIntegration([]) setConnectorData({ name: "", desc: "" }) + setIsEditModeOn(false) setIsDatasetIntegrationListModeOn(true) } - // const deleteTable = (tableName, index) => { - // let newArr = listOfDatsetFileAvailableForColumn.filter((each) => each.name != tableName.name) - // setListOfDatsetFileAvailableForColumn([...newArr]) - - // let list_selected = [...listOfFilesSelected] - // //console.log(list_selected, tableName.name, index) - // list_selected.splice(index, 1) - // list_selected.filter((each) => { - // return each != tableName.name - // }) - // //console.log(list_selected, tableName.name, index) - // setListOfFilesSelected([...list_selected]); - // } + const completeDataGenerator = (maps) => { + // { org_id: "", dataset_list: [], file_list: [], org_name: "", dataset_id: "", dataset_name: "", file_name: "", availabeColumns: [], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + + let arr = [] + for (let i = 0; i < maps.length; i++) { + let currentObj = {} + let nextObj = {} + + //Current obj + currentObj["file_name"] = maps[i]?.left_dataset_file?.file ? maps[i]?.left_dataset_file?.file : "N/A" + currentObj["file_id"] = maps[i]?.left_dataset_file?.id ? maps[i]?.left_dataset_file?.id : "" + // currentObj["dataset_id"] = maps[i]?.left_dataset_file?.dataset?. ? maps[i]?.left_dataset_file?.file.split("/").at(-1) : "N/A" + currentObj["dataset_name"] = maps[i]?.left_dataset_file?.dataset?.name ? maps[i]?.left_dataset_file?.dataset?.name : "" + currentObj["org_name"] = maps[i]?.left_dataset_file?.dataset?.user_map?.organization?.name ? maps[i]?.left_dataset_file?.dataset?.user_map?.organization?.name : "" + currentObj["org_id"] = maps[i]?.left_dataset_file?.dataset?.user_map?.id ? maps[i]?.left_dataset_file?.dataset?.user_map?.id : "" + currentObj["type"] = maps[i]?.condition?.how ? maps[i]?.condition?.how : "left" + currentObj["left_on"] = maps[i]?.condition?.left_on + currentObj["right_on"] = maps[i]?.condition?.right_on + currentObj["columnsSelected"] = maps[i]?.condition?.left_selected + currentObj["left"] = maps[i]?.condition?.left?.length > 0 ? maps[i]?.condition?.left : [] + currentObj["next_left"] = maps[i]?.condition?.left?.length > 0 ? maps[i]?.condition?.left : [] + currentObj["map_id"] = maps[i]?.id ? maps[i]?.id : null + + currentObj["availabeColumns"] = maps[i]?.condition?.left_available_columns?.length > 0 ? maps[i]?.condition?.left_available_columns : maps[i]?.condition?.left_selected + arr[i] = currentObj + + //Next obj + nextObj["left"] = maps[i]?.condition?.left?.length > 0 ? maps[i]?.condition?.left : [] + nextObj["file_name"] = maps[i]?.right_dataset_file?.file ? maps[i]?.right_dataset_file?.file : "N/A" + nextObj["file_id"] = maps[i]?.right_dataset_file?.id ? maps[i]?.right_dataset_file?.id : "" + nextObj["dataset_name"] = maps[i]?.right_dataset_file?.dataset?.name ? maps[i]?.right_dataset_file?.dataset?.name : "" + nextObj["columnsSelected"] = maps[i]?.condition?.right_selected.length > 0 ? maps[i]?.condition?.right_selected : [] + nextObj["availabeColumns"] = maps[i]?.condition?.right_available_columns?.length > 0 ? maps[i]?.condition?.right_available_columns : maps[i]?.condition?.left_selected + nextObj["org_name"] = maps[i]?.right_dataset_file?.dataset?.user_map?.organization?.name ? maps[i]?.right_dataset_file?.dataset?.user_map?.organization?.name : "" + nextObj["org_id"] = maps[i]?.right_dataset_file?.dataset?.user_map?.id ? maps[i]?.right_dataset_file?.dataset?.user_map?.id : "" + arr[i + 1] = nextObj + } + // let obj = {} + // obj["left"] = maps[maps.length - 1]?.next_left + // arr[arr.length] = { ...obj } + console.log(arr) + setCompleteData([...arr]) + setCounterForIntegration(arr.length >= 2 ? arr.length : 2) + } + + const setterForPreRender = (dataForRender) => { + //set name and desc + setConnectorData({ + ...completeData, name: dataForRender?.name ? dataForRender?.name : "", desc: dataForRender?.description ? dataForRender?.description : "" + }) + //set connector id for deleting the connector if user wants + setConnectorId(dataForRender?.id) + //file path setting + setIntegratedFilePath(dataForRender?.integrated_file) + + //set already generated data + setFinalDatasetAfterIntegration([...dataForRender?.data ? JSON.parse(dataForRender?.data) : []]) + + //A function to generate complete Data from maps of dataForRender + completeDataGenerator(dataForRender?.maps?.length > 0 ? dataForRender?.maps : []) + } //this function is being used to generate the data at first place, Save the generated data and delete the saved connectors const generateData = (index, condition,) => { @@ -279,32 +341,49 @@ const DatasetIntegration = (props) => { let payload = [] - - for (let i = 0; i < completeData.length - 1; i++) { - //Generating the payload as array of objects each object having data friom completeData and completeJoinData - let obj = { - left_dataset_file: completeData[i]?.file_id, - right_dataset_file: completeData[i + 1]?.file_id, - left_dataset_file_path: completeData[i]?.file_name, - right_dataset_file_path: completeData[i + 1]?.file_name, - condition: { - right_selected: [...completeData[i + 1]?.columnsSelected], left_selected: [...completeData[i]?.columnsSelected], - how: completeData[i]?.type ? completeData[i]?.type : "left", - left_on: completeData[i]?.left_on, - right_on: completeData[i]?.right_on + if (condition !== "view_details" && condition != "delete") { + for (let i = 0; i < index + 1; i++) { + console.log(index, i, completeData[i], "MAIN DATA") + //Generating the payload as array of objects each object having data friom completeData and completeJoinData + let obj = { + left_dataset_file: completeData[i]?.file_id, + right_dataset_file: completeData[i + 1]?.file_id, + left_dataset_file_path: completeData[i]?.file_name, + right_dataset_file_path: completeData[i + 1]?.file_name, + condition: { + left: completeData[i]?.next_left?.length > 0 ? completeData[i].next_left : [], right: completeData[i]?.right?.length > 0 ? completeData[i].right : [], + left_available_columns: completeData[i]?.availabeColumns?.length > 0 ? [...completeData[i]?.availabeColumns] : [], + right_available_columns: completeData[i + 1]?.availabeColumns?.length > 0 ? [...completeData[i + 1]?.availabeColumns] : [], + right_selected: [...completeData[i + 1]?.columnsSelected], left_selected: [...completeData[i]?.columnsSelected], + how: completeData[i]?.type ? completeData[i]?.type : "left", + left_on: completeData[i]?.left_on, + right_on: completeData[i]?.right_on + } } + if (isEditModeOn) { + obj["id"] = completeData[i]?.map_id ? completeData[i]?.map_id : null + } + payload.push(obj) } - payload.push(obj) } let finalPayload let method if (condition == "save") { finalPayload = { name: connectorData.name, description: connectorData.desc, maps: payload, integrated_file: integratedFilePath } - url = UrlConstant.base_url + UrlConstant.integration_connectors // for saving - method = "POST" + if (isEditModeOn) { + url = UrlConstant.base_url + UrlConstant.integration_connectors + connector_id + "/" // for saving + method = "PUT" + } else { + url = UrlConstant.base_url + UrlConstant.integration_connectors // for saving + method = "POST" + } } else if (condition == "integrate") { finalPayload = { name: connectorData.name, description: connectorData.desc, maps: payload } - url = UrlConstant.base_url + UrlConstant.joining_the_table //for generating + if (isEditModeOn) { + url = UrlConstant.base_url + UrlConstant.joining_the_table + "?edit=True" //for generating + } else { + url = UrlConstant.base_url + UrlConstant.joining_the_table //for generating + } method = "POST" } else if (condition == "delete" && connector_id) { finalPayload = {} @@ -312,6 +391,7 @@ const DatasetIntegration = (props) => { method = "DELETE" } else if (condition == "view_details") { url = UrlConstant.base_url + UrlConstant.integration_connectors + connector_id + "/" + finalPayload = {} method = "GET" } else { @@ -330,7 +410,21 @@ const DatasetIntegration = (props) => { if (allKeys.length > 1) { let arr = [...completeData] let obj = arr[index + 1] + let first_obj = arr[index] + first_obj["next_left"] = [...allKeys] obj["left"] = [...allKeys] + obj["left_on"] = [] + console.log("HERE IS THE CALL", arr.length, index,) + if (arr.length > 2 && index != arr.length - 2) { + for (let i = index; i < arr.length; i++) { + arr["left_on"] = [] + } + setIsAllConditionForSaveMet(false) + } else { + setIsConditionForConnectorDataForSaveMet(true) + setIsAllConditionForSaveMet(true) + } + arr[index] = { ...first_obj } arr[index + 1] = { ...obj } setCompleteData([...arr]) setOpen(true); @@ -358,17 +452,24 @@ const DatasetIntegration = (props) => { } else if (condition == "delete") { console.log("inside delete", res) - setOpen(true); - setAlertType("success") - setMessage("Data deleted successfully!") - let id = setTimeout(() => { - setOpen(false); - return clearTimeout(id) - }, 2500) + // setOpen(true); + // setAlertType("success") + // setMessage("Data deleted successfully!") + // let id = setTimeout(() => { + // setOpen(false); + // return clearTimeout(id) + // }, 2500) + } else if (condition == "view_details") { + console.log(res.data, "inside view_details") + //setter function for pre prendering of the data + setterForPreRender(res.data) } // goToTop(2000) }).catch((err) => { + if (condition == "integrate") { + setIsAllConditionForSaveMet(false) + } console.log(err) setOpen(true); setLoader(false) @@ -378,7 +479,12 @@ const DatasetIntegration = (props) => { setOpen(false); return clearTimeout(id) }, 2500) + // if (condition == "view_details") { + // setIsEditModeOn(false) + // setIsDatasetIntegrationListModeOn(true) + // } goToTop(0) + }) } @@ -423,8 +529,10 @@ const DatasetIntegration = (props) => { useEffect(() => { getDataList("org_names") - // isEditModeOn ? - }, []) + if (isEditModeOn && connectorIdForView) { + generateData(0, "view_details") + } + }, [isEditModeOn, connectorIdForView, isDatasetIntegrationListModeOn]) return ( @@ -459,9 +567,9 @@ const DatasetIntegration = (props) => { - {!isDatasetIntegrationListModeOn && } - {!isDatasetIntegrationListModeOn && completeData.length > 0 && } - {isDatasetIntegrationListModeOn && } + {!isDatasetIntegrationListModeOn && } + {!isDatasetIntegrationListModeOn && completeData.length > 0 && finalDatasetAfterIntegration?.length > 0 && < Preview isConditionForConnectorDataForSaveMet={isConditionForConnectorDataForSaveMet} isAllConditionForSaveMet={isAllConditionForSaveMet} isEdited={isEdited} setIsEdited={setIsEdited} generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} + {isDatasetIntegrationListModeOn && } ) } diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index 09932adb0..bff6b997a 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -15,7 +15,7 @@ import { Checkbox, Fab, FormControlLabel, TextField } from '@mui/material'; import { CheckLg } from 'react-bootstrap-icons'; import CardDetail from '../CardDetail/CardDetail'; import { Button, Affix } from 'antd'; -import { handleUnwantedSpace, validateInputField } from '../../../../Utils/Common'; +import { dateTimeFormat, handleUnwantedSpace, validateInputField } from '../../../../Utils/Common'; import RegexConstants from '../../../../Constants/RegexConstants'; import Join from '../Join/Join'; import leftG from "../../../../Assets/Img/Join type/Color/Left.svg" @@ -27,14 +27,19 @@ import fullG from "../../../../Assets/Img/Join type/Color/outer.svg" import innerB from "../../../../Assets/Img/Join type/Normal state/inner.svg" import innerG from "../../../../Assets/Img/Join type/Color/inner.svg" import settinggif from "../../../../Assets/Img/setting.gif" +import ArrowBackIcon from "@mui/icons-material/ArrowBack"; + const DatasetSelect = (props) => { - const { integrateMore, empty, template, setTemplate, counterForIntegrator, completedJoinData, setCompleteJoinData, resetAll, generateData, orgList, joinType, setJoinType, setCompleteData, setConnectorData, connectorData, completeData, setFinalDataNeedToBeGenerated, finalDataNeedToBeGenerated, listOfFilesSelected, allDatasetNameList, listOfDatasetSelected, handleChangeDatasetNameSelector, listOfDatsetFileAvailableForColumn, } = props + const { connectorTimeData, isEditModeOn, setIsConditionForConnectorDataForSaveMet, isEdited, setIsEdited, setIsEditModeOn, setIsDatasetIntegrationListModeOn, integrateMore, empty, template, setTemplate, counterForIntegrator, completedJoinData, setCompleteJoinData, resetAll, generateData, orgList, joinType, setJoinType, setCompleteData, setConnectorData, connectorData, completeData, setFinalDataNeedToBeGenerated, finalDataNeedToBeGenerated, listOfFilesSelected, allDatasetNameList, listOfDatasetSelected, handleChangeDatasetNameSelector, listOfDatsetFileAvailableForColumn, } = props const [errorConnectorName, setErrorConnectorName] = useState("") const [errorConnectorDesc, setErrorConnectorDesc] = useState("") const [show, setShow] = useState(false) const [indexShow, setIndex] = useState(-1) const handleChange = (e) => { let value = e.target.name + if (e.target.value) { + setIsConditionForConnectorDataForSaveMet(true) + } if (value == "name") { setErrorConnectorName("") validateInputField(e.target.value, RegexConstants.connector_name) @@ -132,18 +137,33 @@ const DatasetSelect = (props) => { } return ( - - + + + { + resetAll() + } + } + className={styles.backButtonMainDiv + " backButtonMainDiv"} + > + {" "} +
+ Back +
+ +
Dataset Integration details + {isEditModeOn && {"Last updated on: " + dateTimeFormat(connectorTimeData.last_updated, true)}} - + @@ -158,7 +178,7 @@ const DatasetSelect = (props) => { - {counterForIntegrator === completeData.length &&
Click on integrate more datasets to select files for integration.
} + {counterForIntegrator === completeData.length &&
To choose other files for integration, click on integrate more datasets.
}
@@ -222,7 +242,7 @@ const DatasetSelect = (props) => { - + @@ -241,20 +261,32 @@ const DatasetSelect = (props) => { } })} */} {completeData?.length > 0 && completeData.map((each, index) => { - return + return {} {index < completeData.length - 1 && } {index < completeData.length - 1 && - handleMoreDataShow(index, true, e)} style={{ display: "flex", justifyContent: "center", alignItems: "center", cursor: !show ? "pointer" : "", height: `${show && index == indexShow ? "350px" : "50px"}`, overflow: "hidden", width: `${show && index == indexShow ? "700px" : "50px"}`, margin: "auto", backgroundRepeat: "no-repeat", backgroundSize: "50px 50px", backgroundPosition: "center", boxShadow: "0 3px 10px #ab840574", }} className={index == indexShow ? styles.hoveredOne : styles.alwaysHave}> - { - {/* handleMoreDataShow(index, false, e)} > */} - - {/* */} + handleMoreDataShow(index, true, e)} style={{ display: "flex", justifyContent: "center", alignItems: "center", cursor: !show ? "pointer" : "", height: `${show && index == indexShow ? "350px" : "50px"}`, overflow: "hidden", width: `${show && index == indexShow ? "700px" : "50px"}`, margin: "auto", backgroundRepeat: "no-repeat", backgroundSize: "50px 50px", backgroundPosition: "center", }} className={index == indexShow ? styles.hoveredOne : styles.alwaysHave}> + { {indexShow != index && } + } + } + {index !== indexShow && index < completeData.length - 1 && +
Joined by
+
+ +
Left column
+
{each?.left_on?.length > 0 ? each?.left_on[0] : "Not selected"}
+
+ +
Right column
+
{each?.right_on?.length > 0 ? each?.right_on[0] : "Not selected"}
+
+ +
Join type
+
{each?.type ? each?.type : "Not selected"}
- } - - } +
+
} {index < completeData.length - 1 && handleMoreDataShow(index, true, e)} style={{ border: index == indexShow && "1.5px solid #C09507" }} class={styles.vl} >}
})} diff --git a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx index 3b3519e99..e334f0110 100644 --- a/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Join/Join.jsx @@ -16,6 +16,9 @@ import fullB from "../../../../Assets/Img/Join type/Normal state/outer.svg" import fullG from "../../../../Assets/Img/Join type/Color/outer.svg" import innerB from "../../../../Assets/Img/Join type/Normal state/inner.svg" import innerG from "../../../../Assets/Img/Join type/Color/inner.svg" + +import smallG from "../../../../Assets/Img/Join type/Color/Tick icon.svg" + import CloseIcon from '@mui/icons-material/Close'; import { Button } from 'antd'; const Join = (props) => { @@ -33,15 +36,15 @@ const Join = (props) => { target: { value }, } = e; // On autofill we get a stringified value. - if (typeof value === 'string') { - value.split(',') - } + // if (typeof value === 'string') { + // value.split(',') + // } if (source == "join1") { - // console.log(value) - obj1["left_on"] = [...value] + console.log(value) + obj1["left_on"] = [value] arr[index] = { ...obj1 } } else { - obj1["right_on"] = [...value] + obj1["right_on"] = [value] arr[index] = { ...obj1 } } @@ -81,15 +84,15 @@ const Join = (props) => { @@ -106,10 +109,10 @@ const Join = (props) => { { + setFileName(e.target.value) + + console.log('file on chnage',fileName, e.target) + }} + > + {allFileNames?.map((item, index) => { + console.log('file name in loop', item) + return ( + + {item} + + ); + })} + + + + + + {/*
*/} +
Uploaded Data Column Name - Standard Data Column Name - + + + Standard Data Calegory + + + Standard Data Attribute + + + Mask + + + {/* */} + + +
+ + + {keysInUploadedDataset?.map((keyNames, index) => { return ( <> -
-
+ +
-
+ {keyNames} -
- -
- + + +
+ + - Select column/key + Select datapoint category - + + + + + + + Select column/key + + + + + + + - setCheckBox(true)}/> + {/* setCheckBox(true)} />} - label="Mask" - /> + + /> */} - + +
); })} - + + ); }; diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index f8377bd45..e203b0386 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -135,6 +135,7 @@ const StandardizationInOnbord = (props) => { let tmpAllDatapoints = [...allDatapoints]; tmpAllDatapoints.splice(index, 1); setAllDataPoints(tmpAllDatapoints); + success("Category deleted successfully.", "success"); } }; diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index 23fefe480..0d57f9f18 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -94,6 +94,9 @@ const UrlConstant = { standardization_update_data: "datahub/standardise/update_standardisation_template/", standardization_delete_category: "datahub/standardise/", standardization_get_data: "datahub/standardise/", + standardization_get_all_file_name: "datahub/dataset/v2/temp_dataset_files/?dataset_name=", + standardization_get_file_columns: "datahub/dataset/v2/temp_dataset_file_columns/", + joining_the_table: "connectors/integration/", integration_connectors: "connectors/", list_of_connectors: "connectors/", From f84950dfd3ffda906b3adeb6857c011eedcf3493 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Fri, 17 Mar 2023 19:04:44 +0530 Subject: [PATCH 35/73] fixed add button color and added validation on add and save button --- .../Standardization/StandardizationInOnbording.js | 6 ++++-- .../Standardization/standardizationInOnbording.css | 12 ++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index f8377bd45..28d3a3c34 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -371,6 +371,7 @@ const StandardizationInOnbord = (props) => { className="datapoint-add-button" id="add-datapoint-button" onClick={handleAddDatapoint} + disabled={!datapointName && !datapointDes } > Add @@ -574,10 +575,11 @@ const StandardizationInOnbord = (props) => { ) : ( diff --git a/src/Components/Standardization/standardizationInOnbording.css b/src/Components/Standardization/standardizationInOnbording.css index b53ef78aa..94644f450 100644 --- a/src/Components/Standardization/standardizationInOnbording.css +++ b/src/Components/Standardization/standardizationInOnbording.css @@ -50,14 +50,19 @@ width: 172px !important; height: 48px !important; text-transform: none !important; - color: #ffffff; + color: #c09507 !important; margin-top: 30px; margin-bottom: 30px; font-weight: 700; - background: #c09507 !important; + background: #ffffff !important; border: 2px solid #c09507 !important; box-shadow: none !important; } +.datapoint-add-button:hover{ + background: #c09507 !important; + color: #ffffff !important; + +} .finish-later-button{ border: none !important; color: black; @@ -94,3 +99,6 @@ color: black !important; /* font-size: small; */ } +.add-datapoint-svg{ + cursor: pointer !important; +} From a810ab2d20efda53e3dcccae964ecfc0f61c925d Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Mon, 20 Mar 2023 10:59:01 +0530 Subject: [PATCH 36/73] fixed leading and trailing space in data standardization --- .../StandardizationInOnbording.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index e203b0386..bc417a1c7 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -19,6 +19,7 @@ import { GetErrorHandlingRoute } from "../../Utils/Common"; import UrlConstant from "../../Constants/UrlConstants"; import Loader from "../Loader/Loader"; import { message, Space } from "antd"; +import RegexConstants from "../../Constants/RegexConstants"; const StandardizationInOnbord = (props) => { const { inSettings, isaccesstoken, showBrandingScreen, isOnborading } = props; @@ -47,6 +48,17 @@ const StandardizationInOnbord = (props) => { console.log("all datapoints", allDatapoints); + const handleDatapointCategoryName = (e) =>{ + + if(e.target.value.length<256 && e.target.value.match(RegexConstants.NEW_NAME_REGEX)) setDatapointName(e.target.value) + } + + const handleDatapointCategoryDescription = (e) =>{ + + if(e.target.value.length<256 && e.target.value.match(RegexConstants.NEW_NAME_REGEX)) setDatapointDes(e.target.value) + + } + const handleAddDatapoint = () => { if(!datapointName || !datapointDes ){ return @@ -349,7 +361,7 @@ const StandardizationInOnbord = (props) => {
setDatapointName(e.target.value)} + onChange={(e) => handleDatapointCategoryName(e)} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" @@ -357,7 +369,7 @@ const StandardizationInOnbord = (props) => { /> e.target.value.length<256 ? setDatapointDes(e.target.value) : ""} + onChange={(e) => handleDatapointCategoryDescription(e)} multiline size="small" className="datapoint-name-input-box-description" From 2d0a0654d81e4daade9eba727e2af1787d0dce1e Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Mon, 20 Mar 2023 11:46:54 +0530 Subject: [PATCH 37/73] 1375, 1379 --- .../IntegrationDatasets/DatasetSelect/DatasetSelect.jsx | 2 +- src/Components/IntegrationConnectors/ConnectorsList.jsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index bff6b997a..3f196aabb 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -168,7 +168,7 @@ const DatasetSelect = (props) => {
+ helperText={errorConnectorDesc ? errorConnectorDesc : ""} rows={4} fullWidth placeholder='Connector description not more that 512 character' id="outlined-basic" label="Connector description" variant="outlined" inputProps={{ maxLength: 512 }} /> diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index ac26d69c4..4e1e1282a 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -149,7 +149,7 @@ export default function ConnectorsList(props) { /> - {gridView === true ? <> + {connectorList.length > 0 ? <> {connectorList.map((list, index) => ( @@ -190,7 +190,7 @@ export default function ConnectorsList(props) { {/* list view component render here when list view button clicks */} - "Currently, there are no connectors available in the list format" + "Currently, there are no connectors at this moment" } From bd1964ecd0eaf596aa355786a417bf7168778b7e Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Mon, 20 Mar 2023 12:22:50 +0530 Subject: [PATCH 38/73] component imported --- src/Components/IntegrationConnectors/ConnectorsList.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index 4e1e1282a..5ef26f413 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -11,6 +11,7 @@ import { useHistory } from "react-router-dom"; import UrlConstant from "../../Constants/UrlConstants"; import ViewModuleIcon from '@mui/icons-material/ViewModule'; import FormatListBulletedIcon from '@mui/icons-material/FormatListBulleted'; +import NoDataAvailable from "../Dashboard/NoDataAvailable/NoDataAvailable"; export default function ConnectorsList(props) { const { setConnectorTimeData, setIsEditModeOn, setConnectorIdForView, setIsDatasetIntegrationListModeOn } = props @@ -149,7 +150,7 @@ export default function ConnectorsList(props) { /> - {connectorList.length > 0 ? <> + {connectorList.length < 0 ? <> {connectorList.map((list, index) => ( @@ -187,10 +188,10 @@ export default function ConnectorsList(props) { )} : <> - {/* list view component render here when list view button clicks */} + {/* If there is no connectors available this component will render */} - - "Currently, there are no connectors at this moment" + + } From 9268db0b056f5680c08c0bbd4a27fbb5dca320d6 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Mon, 20 Mar 2023 12:25:37 +0530 Subject: [PATCH 39/73] no conflicts --- src/Components/IntegrationConnectors/ConnectorsList.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index 5ef26f413..d20d92d1b 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -150,7 +150,7 @@ export default function ConnectorsList(props) { /> - {connectorList.length < 0 ? <> + {connectorList.length > 0 ? <> {connectorList.map((list, index) => ( From b3bc7dcc653ce4e00e60a7831ce9098dcc34b499 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Mon, 20 Mar 2023 13:04:40 +0530 Subject: [PATCH 40/73] fixed all bugs related to standardizatin --- .../StandardizationInOnbording.js | 39 +++++++++++++-- .../standardizationInOnbording.css | 48 +++++++++++++------ src/Constants/RegexConstants.js | 3 +- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index 28d3a3c34..03cf1de02 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -19,6 +19,7 @@ import { GetErrorHandlingRoute } from "../../Utils/Common"; import UrlConstant from "../../Constants/UrlConstants"; import Loader from "../Loader/Loader"; import { message, Space } from "antd"; +import RegexConstants from "../../Constants/RegexConstants"; const StandardizationInOnbord = (props) => { const { inSettings, isaccesstoken, showBrandingScreen, isOnborading } = props; @@ -47,6 +48,17 @@ const StandardizationInOnbord = (props) => { console.log("all datapoints", allDatapoints); + const handleDatapointCategoryName = (e) =>{ + + if(e.target.value.length<251 && e.target.value.match(RegexConstants.NEW_NAME_REGEX)) setDatapointName(e.target.value) + } + + const handleDatapointCategoryDescription = (e) =>{ + + if(e.target.value.length<251 && e.target.value.match(RegexConstants.NEW_NAME_REGEX)) setDatapointDes(e.target.value) + + } + const handleAddDatapoint = () => { if(!datapointName || !datapointDes ){ return @@ -81,6 +93,9 @@ const StandardizationInOnbord = (props) => { allAttributesArrIndex, newValue ) => { + if(newValue.length>=251 || !newValue.match(RegexConstants.DATAPOINT_ATTRIBUTE_REGEX)){ + return + } console.log("allAttribute in start of function", allAttributes); let tmpAllAttributes = { ...allAttributes }; @@ -93,6 +108,10 @@ const StandardizationInOnbord = (props) => { allAttributesArrIndex, newValue ) => { + + if(newValue.length>=251 || !newValue.match(RegexConstants.NEW_NAME_REGEX)){ + return + } console.log("allAttribute Des in start of function", allAttributesDes); let tmpAllAttributesDes = { ...allAttributesDes }; @@ -135,6 +154,11 @@ const StandardizationInOnbord = (props) => { let tmpAllDatapoints = [...allDatapoints]; tmpAllDatapoints.splice(index, 1); setAllDataPoints(tmpAllDatapoints); + + let tmpAllAttributes = {...allAttributes}; + tmpAllAttributes[index] = [] + setAllAttributes(tmpAllAttributes) + success("Category deleted successfully.", "success"); } }; @@ -143,7 +167,9 @@ const StandardizationInOnbord = (props) => { const handleSubmit = () => { let payload = [...allDatapoints]; - for (let index = 0; allAttributes[index]; index++) { + console.log('payload before setting up', payload) + + for (let index = 0; allDatapoints[index]; index++) { let attributeObj = {}; for (let i = 1; i < allAttributes[index].length; i++) { attributeObj[allAttributes[index][i]] = allAttributesDes[index][i]; @@ -273,6 +299,9 @@ const StandardizationInOnbord = (props) => { .then((response) => { setIsLoading(false); console.log("response", response); + let tmpAllAttributes = {...allAttributes}; + tmpAllAttributes[index] = [] + setAllAttributes(tmpAllAttributes) success("Category deleted successfully.", "success"); let tmpAllDatapoints = [...allDatapoints]; @@ -348,7 +377,7 @@ const StandardizationInOnbord = (props) => {
setDatapointName(e.target.value)} + onChange={(e) => handleDatapointCategoryName(e)} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" @@ -356,7 +385,7 @@ const StandardizationInOnbord = (props) => { /> e.target.value.length<256 ? setDatapointDes(e.target.value) : ""} + onChange={(e) => handleDatapointCategoryDescription(e)} multiline size="small" className="datapoint-name-input-box-description" @@ -408,7 +437,7 @@ const StandardizationInOnbord = (props) => {
{/*

Farmer profile

*/} -

{item.datapoint_description}

+

{item.datapoint_description}

{ <>
handleDatapointCategoryName(e)} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" variant="outlined" + error={datapointNameError ? datapointNameError : "" } + helperText={datapointNameError ? datapointNameError : "" } /> handleDatapointCategoryDescription(e)} multiline @@ -400,7 +459,7 @@ const StandardizationInOnbord = (props) => { className="datapoint-add-button" id="add-datapoint-button" onClick={handleAddDatapoint} - disabled={!datapointName && !datapointDes } + disabled={!datapointName || !datapointDes } > Add @@ -423,16 +482,60 @@ const StandardizationInOnbord = (props) => { id="panel1a-header" className="attribute-accordion-titile" > - + {/* + {item.datapoint_category} + */} + + { + editCategoryTitle[index] ? + handleUpdateCategoryName(index,e.target.value)} + className="datapoint-name-input-box" + id="datapoint-name-input-box-id" + label="Datapoint category name" + variant="outlined" + helperText={accordionDatapointNameError[index] ? accordionDatapointNameError[index] : accordionDatapointNameError[index]} + error={accordionDatapointNameError[index] ? accordionDatapointNameError[index] : accordionDatapointNameError[index]} + /> + : +
+ + {item.datapoint_category} -
+
+ }{ + editCategoryTitle[index] ? + + + + : + null + } + {/*
*/} + { + // this funtion will make a particular index of editCategoryTitle array true + let tmp = [...editCategoryTitle] + tmp[index] = true + console.log('edit title', tmp, editCategoryTitle) + setEditCategoryTitle(tmp) + }}> + + handleDatapointCategoryDelete(index)} > -
+ {/*
*/}
@@ -440,6 +543,7 @@ const StandardizationInOnbord = (props) => {

{item.datapoint_description}

{ } /> { className="datapoint-add-button" id="addte-add-datapoint-button" onClick={handleSubmit} - disabled={!allDatapoints.length} + disabled={!allDatapoints.length || !saveButtonEnabled} > Save diff --git a/src/Components/Standardization/standardizationInOnbording.css b/src/Components/Standardization/standardizationInOnbording.css index 851923a26..db9b10b68 100644 --- a/src/Components/Standardization/standardizationInOnbording.css +++ b/src/Components/Standardization/standardizationInOnbording.css @@ -122,3 +122,15 @@ .add-datapoint-svg { cursor: pointer !important; } +.update-category-button{ + width: 90px !important; + height: 30px !important; + text-transform: none !important; + color: #c09507 !important; + margin-top: 30px; + margin-bottom: 30px; + font-weight: 700; + background: #ffffff !important; + border: 2px solid #c09507 !important; + box-shadow: none !important; +} From 2ec4e6b1254374f70fc79ecc3c490ab4d4ac2390 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Tue, 21 Mar 2023 12:10:57 +0530 Subject: [PATCH 43/73] user id handled for sending it to the backend --- .../Datasets/IntegrationDatasets/DatasetIntegration.jsx | 4 ++-- src/Components/IntegrationConnectors/ConnectorsList.jsx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 240747c57..353bc1e21 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -10,7 +10,7 @@ import Loader from '../../Loader/Loader' import { Alert, Button, Collapse, Fab, IconButton, Snackbar } from '@mui/material' import CloseIcon from '@mui/icons-material/Close'; import { CheckLg } from 'react-bootstrap-icons' -import { GetErrorHandlingRoute, GetErrorKey, goToTop } from '../../../Utils/Common' +import { GetErrorHandlingRoute, GetErrorKey, getUserLocal, goToTop } from '../../../Utils/Common' import { useHistory } from 'react-router-dom' import { Affix } from 'antd' import { AddIcCallOutlined } from '@material-ui/icons' @@ -372,7 +372,7 @@ const DatasetIntegration = (props) => { let finalPayload let method if (condition == "save") { - finalPayload = { name: connectorData.name, description: connectorData.desc, maps: payload, integrated_file: integratedFilePath } + finalPayload = { name: connectorData.name, description: connectorData.desc, user: getUserLocal(), maps: payload, integrated_file: integratedFilePath } if (isEditModeOn) { url = UrlConstant.base_url + UrlConstant.integration_connectors + connector_id + "/" // for saving method = "PUT" diff --git a/src/Components/IntegrationConnectors/ConnectorsList.jsx b/src/Components/IntegrationConnectors/ConnectorsList.jsx index d20d92d1b..569cd79d2 100644 --- a/src/Components/IntegrationConnectors/ConnectorsList.jsx +++ b/src/Components/IntegrationConnectors/ConnectorsList.jsx @@ -6,7 +6,7 @@ import { Button } from "@mui/material"; import THEME_COLORS from "../../Constants/ColorConstants"; import Loader from "../Loader/Loader"; import HTTPService from "../../Services/HTTPService"; -import { GetErrorHandlingRoute } from "../../Utils/Common"; +import { GetErrorHandlingRoute, getUserLocal } from "../../Utils/Common"; import { useHistory } from "react-router-dom"; import UrlConstant from "../../Constants/UrlConstants"; import ViewModuleIcon from '@mui/icons-material/ViewModule'; @@ -64,7 +64,7 @@ export default function ConnectorsList(props) { setIsLoader(true); HTTPService( "GET", - UrlConstant.base_url + UrlConstant.list_of_connectors, + UrlConstant.base_url + UrlConstant.list_of_connectors + "?user=" + getUserLocal(), "", false, true @@ -190,8 +190,8 @@ export default function ConnectorsList(props) { : <> {/* If there is no connectors available this component will render */} -
- + + } From d489a83dde45ccdf3e39aee1ad3cfc3ba30b3c00 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Tue, 21 Mar 2023 12:26:36 +0530 Subject: [PATCH 44/73] added event propagation on edit and delete button --- .../Standardization/StandardizationInOnbording.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index e88ba1775..74f827831 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -491,7 +491,7 @@ const StandardizationInOnbord = (props) => { handleUpdateCategoryName(index,e.target.value)} + onChange={(e) => handleUpdateCategoryName(index,e.target.value,e)} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" @@ -511,6 +511,7 @@ const StandardizationInOnbord = (props) => { - From c437d0138d5bc539a32008152819c6c029fdbd7c Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Tue, 21 Mar 2023 14:18:07 +0530 Subject: [PATCH 47/73] changed one equal condition --- .../Datasets/IntegrationDatasets/DatasetIntegration.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index ad02dd6a6..aaeabdde4 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -399,7 +399,7 @@ const DatasetIntegration = (props) => { url = UrlConstant.base_url + UrlConstant.integration_connectors + connector_id + "/" finalPayload = {} method = "GET" - } else if (condition = "delete_map_card" && isEditModeOn && map_id) { + } else if (condition == "delete_map_card" && isEditModeOn && map_id) { method = "DELETE" url = UrlConstant.base_url + UrlConstant.integration_connectors + map_id + "/?maps=True" From 8c900e9e5814e037aadcb5c150979f803b9d30d1 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 21 Mar 2023 15:36:47 +0530 Subject: [PATCH 48/73] card header height changed --- src/Components/IntegrationConnectors/ConnectorCard.jsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Components/IntegrationConnectors/ConnectorCard.jsx b/src/Components/IntegrationConnectors/ConnectorCard.jsx index 4e6482b4e..b7da1cb79 100644 --- a/src/Components/IntegrationConnectors/ConnectorCard.jsx +++ b/src/Components/IntegrationConnectors/ConnectorCard.jsx @@ -31,16 +31,13 @@ const useStyles = { "font-size": "24px", "font-style": "normal", "width": "272px", - "height": "19px", + "height": "25px", "line-height": "19px", "text-align": "left", "margin-bottom": "20px", - "overflow": "hidden", - "text-overflow": "ellipsis", - "display": "-webkit-box", - "-webkit-line-clamp": "1", - "-webkit-box-orient": "vertical" + "textOverflow": "ellipsis", + "white-space": "nowrap", }, cardDataUser: { "font-family": "Open Sans", From eb83c18d982b18deeacabadd0009a33bf535eabf Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Tue, 21 Mar 2023 16:04:18 +0530 Subject: [PATCH 49/73] 1401 fixed --- src/Components/Standardization/StandardizationInOnbording.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index 8489f432a..9d7af59d5 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -457,6 +457,7 @@ const StandardizationInOnbord = (props) => { value={datapointName} onChange={(e) => handleDatapointCategoryName(e)} onKeyDown={handleNameField} + inputProps={{ maxLength: 250 }} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" @@ -469,6 +470,7 @@ const StandardizationInOnbord = (props) => { value={datapointDes} onChange={(e) => handleDatapointCategoryDescription(e)} onKeyDown={handledescriptionKeydowndes} + inputProps={{ maxLength: 250 }} multiline size="small" className="datapoint-name-input-box-description" @@ -516,6 +518,7 @@ const StandardizationInOnbord = (props) => { value={item.datapoint_category} required onChange={(e) => handleUpdateCategoryName(index,e.target.value,e)} + inputProps={{ maxLength: 250 }} className="datapoint-name-input-box" id="datapoint-name-input-box-id" label="Datapoint category name" @@ -582,6 +585,7 @@ const StandardizationInOnbord = (props) => { hanldeAttributeInputChange(index, 0, e.target.value) } onKeyDown={handleAllAttributesName} + inputProps={{ maxLength: 250 }} /> { ) } onKeyDown={handleAllAttributesDes} + inputProps={{ maxLength: 250 }} /> Date: Thu, 23 Mar 2023 14:19:02 +0530 Subject: [PATCH 50/73] bug fixing --- .../DatasetIntegration.jsx | 38 +++++++++++++------ .../DatasetSelect/DatasetSelect.jsx | 11 ++++-- .../IntegrationDatasets/Preview/Preview.jsx | 6 +-- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index aaeabdde4..1995dc81b 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -15,6 +15,7 @@ import { useHistory } from 'react-router-dom' import { Affix } from 'antd' import { AddIcCallOutlined } from '@material-ui/icons' import ConnectorsList from '../../IntegrationConnectors/ConnectorsList' +import FileSaver from 'file-saver' const converter = require('json-2-csv') const fs = require('fs') @@ -56,15 +57,16 @@ const DatasetIntegration = (props) => { const [completeData, setCompleteData] = useState([ //In dev mode this is the dummy data - // { org_id: "A", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c1", "c2", "c3"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, - // { org_id: "B", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c4", "c5", "c6"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, - // { org_id: "C", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c7", "c8", "c9"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + { org_id: "A", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c1", "c2", "c3"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + { org_id: "B", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c4", "c5", "c6"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + { org_id: "C", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c7", "c8", "c9"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, ]) // const [listOfDatsetFileAvailableForColumn, setListOfDatsetFileAvailableForColumn] = useState([]) const [finalDataNeedToBeGenerated, setFinalDataNeedToBeGenerated] = useState({}) const [integratedFilePath, setIntegratedFilePath] = useState("") + const [noOfRecords, setNoOfRecords] = useState(0) const [finalDatasetAfterIntegration, setFinalDatasetAfterIntegration] = useState([]) const [finalDatasetAfterSaving, setFinalDatasetAfterSaving] = useState([]) @@ -260,6 +262,7 @@ const DatasetIntegration = (props) => { setIsConditionForConnectorDataForSaveMet(false) setIsAllConditionForSaveMet(false) } + setTemplate({ ...empty }) setConnectorId("") setCounterForIntegration(2) setCompleteData([]) @@ -323,6 +326,7 @@ const DatasetIntegration = (props) => { setConnectorId(dataForRender?.id) //file path setting setIntegratedFilePath(dataForRender?.integrated_file) + setNoOfRecords(dataForRender?.no_of_records ? dataForRender?.no_of_records : 0) //set already generated data setFinalDatasetAfterIntegration([...dataForRender?.data ? JSON.parse(dataForRender?.data) : []]) @@ -414,6 +418,8 @@ const DatasetIntegration = (props) => { if (condition == "integrate") { console.log("inside integrate", res.data) setIntegratedFilePath(res?.data?.integrated_file ? res?.data?.integrated_file : "") + setNoOfRecords(res?.data?.no_of_records ? res?.data?.no_of_records : 0) + setFinalDatasetAfterIntegration([...JSON.parse(res.data?.data)]) let allKeys = JSON.parse(res.data.data)?.length > 0 ? Object.keys(JSON.parse(res.data.data)[0]) : [] if (allKeys.length > 1) { @@ -479,7 +485,7 @@ const DatasetIntegration = (props) => { if (condition == "integrate") { setIsAllConditionForSaveMet(false) } - console.log(err.response.data) + // console.log(err.response.data) console.log(Object.values(err?.response?.data)[0]) setOpen(true); setLoader(false) @@ -504,13 +510,21 @@ const DatasetIntegration = (props) => { //Download functionality const downloadDocument = () => { - converter.json2csv(finalDatasetAfterIntegration, async (err, csv) => { - if (err) { - throw err - } - // print CSV string - download(csv) - }) + // converter.json2csv(finalDatasetAfterIntegration, async (err, csv) => { + // if (err) { + // throw err + // } + // // print CSV string + // download(csv) + // }) + let uri + if (integratedFilePath[0] === "/") { + uri = UrlConstant.base_url_without_slash + integratedFilePath + } else { + uri = UrlConstant.base_url + integratedFilePath + + } + FileSaver.saveAs(uri, connectorData.name ? connectorData.name : "Integrated_dataset"); } //number of integration handler @@ -578,7 +592,7 @@ const DatasetIntegration = (props) => { {!isDatasetIntegrationListModeOn && } - {!isDatasetIntegrationListModeOn && completeData.length > 0 && finalDatasetAfterIntegration?.length > 0 && < Preview isConditionForConnectorDataForSaveMet={isConditionForConnectorDataForSaveMet} isAllConditionForSaveMet={isAllConditionForSaveMet} isEdited={isEdited} setIsEdited={setIsEdited} generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} + {!isDatasetIntegrationListModeOn && completeData.length > 0 && finalDatasetAfterIntegration?.length > 0 && < Preview noOfRecords={noOfRecords} isConditionForConnectorDataForSaveMet={isConditionForConnectorDataForSaveMet} isAllConditionForSaveMet={isAllConditionForSaveMet} isEdited={isEdited} setIsEdited={setIsEdited} generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} {isDatasetIntegrationListModeOn && } ) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx index 7fd5d639b..7be09d6ac 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetSelect/DatasetSelect.jsx @@ -14,7 +14,7 @@ import DeleteIcon from '@mui/icons-material/Delete'; import { Checkbox, Fab, FormControlLabel, TextField } from '@mui/material'; import { CheckLg } from 'react-bootstrap-icons'; import CardDetail from '../CardDetail/CardDetail'; -import { Button, Affix } from 'antd'; +import { Button, Affix, Alert } from 'antd'; import { dateTimeFormat, handleUnwantedSpace, validateInputField } from '../../../../Utils/Common'; import RegexConstants from '../../../../Constants/RegexConstants'; import Join from '../Join/Join'; @@ -154,13 +154,13 @@ const DatasetSelect = (props) => { - Dataset Integration details + Dataset integration details {isEditModeOn && {"Last updated on: " + dateTimeFormat(connectorTimeData.last_updated, true)}} - @@ -168,7 +168,7 @@ const DatasetSelect = (props) => { + helperText={errorConnectorDesc ? errorConnectorDesc : ""} rows={4} fullWidth placeholder='Connector description not more that 512 character' id="outlined-basic" label="Connector description" variant="outlined" inputProps={{ maxLength: 250 }} /> @@ -287,6 +287,9 @@ const DatasetSelect = (props) => { } + {index !== indexShow && index < completeData.length - 1 && each.left_on?.length <= 0 && + + } {index < completeData.length - 1 && handleMoreDataShow(index, true, e)} style={{ border: index == indexShow && "1.5px solid #C09507" }} class={styles.vl} >} })} diff --git a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx index 996116b20..fe8287c96 100644 --- a/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx +++ b/src/Components/Datasets/IntegrationDatasets/Preview/Preview.jsx @@ -29,7 +29,7 @@ function NoRowsOverlay() { } const Preview = (props) => { - const { isConditionForConnectorDataForSaveMet, isAllConditionForSaveMet, connectorData, generateData, setIsDatasetIntegrationListModeOn, deleteConnector, counterForIntegrator, completeData, isEditModeOn, integrateMore, resetAll, generatedConnectorData, finalDatasetAfterIntegration, downloadDocument } = props + const { noOfRecords, isConditionForConnectorDataForSaveMet, isAllConditionForSaveMet, connectorData, generateData, setIsDatasetIntegrationListModeOn, deleteConnector, counterForIntegrator, completeData, isEditModeOn, integrateMore, resetAll, generatedConnectorData, finalDatasetAfterIntegration, downloadDocument } = props const [col, setCol] = useState([]) const [row, setRow] = useState([]) @@ -112,8 +112,8 @@ const Preview = (props) => {
    {completeData?.map((each) =>
  1. {each.dataset_name}
  2. )}
-
No.of records
-
{finalDatasetAfterIntegration?.length}
+
No. of records
+
{noOfRecords}
{/* console.log(affixed, "read for dowload")} style={{ backgrond: "white", transition: "all 2s", visibility: counterForIntegrator != completeData.length ? "hidden" : "visible" }} offsetBottom={20}> */} From 4e89459548907a81d9ba9540866af8caf8823d9c Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Thu, 23 Mar 2023 15:39:02 +0530 Subject: [PATCH 51/73] bug fixes --- .../DatasetIntegration.jsx | 18 +++++++++------ .../Participants/ViewParticipantForm.js | 3 ++- .../StandardizationInOnbording.js | 22 +++++-------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index aaeabdde4..b9dadaa0d 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -130,11 +130,12 @@ const DatasetIntegration = (props) => { } }).catch((err) => { setAlertType("error") - setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Error occurred! Dataset could not fetched.") - // setLoader(false) - if (err?.response.status == 401) { + if (err?.response.status == 401 || err?.response.status == 502) { history.push(GetErrorHandlingRoute(err)); + } else { + setMessage(err?.response?.data?.error ? err?.response?.data?.error : "Error occurred! Dataset could not fetched.") } + // setLoader(false) }) } const getFilesAssociatedForTheSelectedDatasets = async (source, list, org, i) => { @@ -217,7 +218,7 @@ const DatasetIntegration = (props) => { }, 2500) return false default: - if (err?.response?.status == 401) { + if (err?.response?.status == 401 || err?.response?.status == 502) { history.push(GetErrorHandlingRoute(err)); } else { setOpen(true); @@ -236,7 +237,7 @@ const DatasetIntegration = (props) => { } else { - if (err?.response?.status == 401) { + if (err?.response?.status == 401 || err?.response?.status == 502) { history.push(GetErrorHandlingRoute(err)); } else { setOpen(true); @@ -476,9 +477,12 @@ const DatasetIntegration = (props) => { // goToTop(2000) }).catch((err) => { + if (err?.response?.status == 401 || err?.response?.status == 502) { + history.push(GetErrorHandlingRoute(err)); + } else { if (condition == "integrate") { setIsAllConditionForSaveMet(false) - } + } console.log(err.response.data) console.log(Object.values(err?.response?.data)[0]) setOpen(true); @@ -494,7 +498,7 @@ const DatasetIntegration = (props) => { // setIsDatasetIntegrationListModeOn(true) // } goToTop(0) - + } }) } diff --git a/src/Components/Participants/ViewParticipantForm.js b/src/Components/Participants/ViewParticipantForm.js index 72e7dc0f6..317147746 100644 --- a/src/Components/Participants/ViewParticipantForm.js +++ b/src/Components/Participants/ViewParticipantForm.js @@ -27,7 +27,8 @@ export default function ViewParticipantForm(props) { <> - - - - - Select file name - - - - + + + + Select file name + + + + + {fileNameError} + + + - - {/*
*/} -
- Uploaded Data Column Name - - - Standard Data Calegory - - - Standard Data Attribute - - - Mask - - - {/* */} + {keysInUploadedDataset.length ? ( + + {/*
*/} +
+ Uploaded Data Column Name + + + Standard Data Calegory + + + Standard Data Attribute + + + Mask + - + {/* */} + + ) : null}
+ {keysInUploadedDataset?.map((keyNames, index) => { + return ( + <> + +
+ + {keyNames} + + + + + + Select datapoint category + + + + - - - {keysInUploadedDataset?.map((keyNames, index) => { - return ( - <> - - - - - {keyNames} - - - - - - - Select datapoint category - - - - - - - - - - Select column/key - - - - - - - - - setCheckBox(true)}/> - {/* setCheckBox(true)} />} + + Select column/key + + + + + + + handleMaskedColumClicked(keyNames)} /> + {/* setCheckBox(true)} />} /> */} - + - -
- - ); - })} + +
+ + ); + })} + {keysInUploadedDataset.length ? ( + +
+ + + + ) : null} ); }; diff --git a/src/Constants/UrlConstants.js b/src/Constants/UrlConstants.js index 0d57f9f18..28bda31d9 100644 --- a/src/Constants/UrlConstants.js +++ b/src/Constants/UrlConstants.js @@ -96,6 +96,7 @@ const UrlConstant = { standardization_get_data: "datahub/standardise/", standardization_get_all_file_name: "datahub/dataset/v2/temp_dataset_files/?dataset_name=", standardization_get_file_columns: "datahub/dataset/v2/temp_dataset_file_columns/", + standardise_file: "datahub/dataset/v2/standardise/", joining_the_table: "connectors/integration/", integration_connectors: "connectors/", From e96bd008218c252593f88fa921cfd2c6fee6af8e Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Thu, 23 Mar 2023 22:30:33 +0530 Subject: [PATCH 53/73] worked on data standardistion in add dataset --- src/Components/AdminDatasetConnection/AddDataset.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Components/AdminDatasetConnection/AddDataset.jsx b/src/Components/AdminDatasetConnection/AddDataset.jsx index e666b6ee4..927acb559 100644 --- a/src/Components/AdminDatasetConnection/AddDataset.jsx +++ b/src/Components/AdminDatasetConnection/AddDataset.jsx @@ -683,6 +683,9 @@ const AddDataset = (props) => { return main_list } + console.log("allStandardisedFile",allStandardisedFile, standardisedFileLink) + + const handleAddDatasetSubmit = (e) => { console.log(finalJson, "Main") e.preventDefault(); @@ -731,8 +734,9 @@ const AddDataset = (props) => { bodyFormData.append("constantly_update", Switchchecked); bodyFormData.append("data_capture_start", fromdate ? fromdate.toISOString() : ""); bodyFormData.append("data_capture_end", todate ? todate.toISOString() : ""); - bodyFormData.append("standardisation_template", standardisedFileLink); - bodyFormData.append("standardisation_config", allStandardisedFile); + console.log("allStandardisedFile",allStandardisedFile, standardisedFileLink) + bodyFormData.append("standardisation_template", JSON.stringify(standardisedFileLink)); + bodyFormData.append("standardisation_config", JSON.stringify(allStandardisedFile)); let obj = { "name": datasetname, description: govLawDesc, category: JSON.stringify(finalJson), user_map: id, geography: geography, deleted: JSON.stringify(idsForFilesDeleted), constantly_update: Switchchecked, data_capture_start: fromdate ? fromdate.toISOString() : "", data_capture_end: todate ? todate.toISOString() : "" } From a406f6657f885241a2ab055dfa26bd2ee4a27100 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Fri, 24 Mar 2023 12:12:13 +0530 Subject: [PATCH 54/73] download func changed and some css --- .../IntegrationDatasets/DatasetIntegration.jsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 1995dc81b..ad00e15f5 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -57,9 +57,9 @@ const DatasetIntegration = (props) => { const [completeData, setCompleteData] = useState([ //In dev mode this is the dummy data - { org_id: "A", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c1", "c2", "c3"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, - { org_id: "B", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c4", "c5", "c6"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, - { org_id: "C", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c7", "c8", "c9"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + // { org_id: "A", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c1", "c2", "c3"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + // { org_id: "B", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c4", "c5", "c6"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, + // { org_id: "C", dataset_list: ["d1", "d2", "d3"], file_list: ["f1", "f2", "f3"], org_name: "org_nameA", dataset_id: "id", dataset_name: "dataset_name1", file_name: "file_name1", availabeColumns: ["c7", "c8", "c9"], columnsSelected: [], left: [], right: [], left_on: [], right_on: [], type: "" }, ]) @@ -262,6 +262,8 @@ const DatasetIntegration = (props) => { setIsConditionForConnectorDataForSaveMet(false) setIsAllConditionForSaveMet(false) } + setIntegratedFilePath("") + setNoOfRecords(0) setTemplate({ ...empty }) setConnectorId("") setCounterForIntegration(2) @@ -325,7 +327,7 @@ const DatasetIntegration = (props) => { //set connector id for deleting the connector if user wants setConnectorId(dataForRender?.id) //file path setting - setIntegratedFilePath(dataForRender?.integrated_file) + setIntegratedFilePath(dataForRender?.integrated_file?.replace("/media", "")) setNoOfRecords(dataForRender?.no_of_records ? dataForRender?.no_of_records : 0) //set already generated data From 19f821dc34ad76b9aad1a25c6c41decd6464b5a2 Mon Sep 17 00:00:00 2001 From: ShruthiMonika Date: Fri, 24 Mar 2023 14:13:43 +0530 Subject: [PATCH 55/73] 1394, 1398 --- .../StandardizationInOnbording.js | 39 ++++++++++--------- src/Constants/RegexConstants.js | 2 +- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Components/Standardization/StandardizationInOnbording.js b/src/Components/Standardization/StandardizationInOnbording.js index 07cbc3bc7..2c39fe9e9 100644 --- a/src/Components/Standardization/StandardizationInOnbording.js +++ b/src/Components/Standardization/StandardizationInOnbording.js @@ -128,23 +128,21 @@ const StandardizationInOnbord = (props) => { console.log('error array', accordionDatapointNameError) // Check if category name already exist or not - let returnFromFuntion = false - tmpAllDatapoints.forEach((category)=>{ - if(category.datapoint_category === newValue) { - let tmpDatapointNameError = [...accordionDatapointNameError] - tmpDatapointNameError[index] = ` ${newValue} Category already exists!` - setAccordionDatapointNameError(tmpDatapointNameError) - returnFromFuntion = true; - return - } - }) - if(returnFromFuntion) return - - let tmpDatapointNameError = [...accordionDatapointNameError] - tmpDatapointNameError[index] = "" - setAccordionDatapointNameError(tmpDatapointNameError) - - + //let returnFromFuntion = false + // tmpAllDatapoints.forEach((category)=>{ + // if(category.datapoint_category === newValue) { + // let tmpDatapointNameError = [...accordionDatapointNameError] + // // tmpDatapointNameError[index] = ` ${newValue} Category already exists!` + // //setAccordionDatapointNameError(tmpDatapointNameError) + // returnFromFuntion = true; + // return + // } + // }) + // if(returnFromFuntion) return + // let tmpDatapointNameError = [...accordionDatapointNameError] + // tmpDatapointNameError[index] = "" + // setAccordionDatapointNameError(tmpDatapointNameError) + //commented out this error handling func, becoz it is handled in catch block of Submit tmpAllDatapoints[index].datapoint_category = newValue; setAllDataPoints(tmpAllDatapoints); } @@ -175,6 +173,9 @@ const StandardizationInOnbord = (props) => { if(newValue.length>=251){ return } + if(newValue == " "){ + newValue.replace("") + } setSaveButtonEnabled(true) console.log("allAttribute Des in start of function", allAttributesDes); @@ -294,8 +295,8 @@ const StandardizationInOnbord = (props) => { } else { setError(false); success( - e.response.data && e.response.data.message - ? e.response.data.message + e.response.data + ? e.response.data : "Something went wrong.", "error" ); diff --git a/src/Constants/RegexConstants.js b/src/Constants/RegexConstants.js index ee2003e96..ed1b5dcb2 100644 --- a/src/Constants/RegexConstants.js +++ b/src/Constants/RegexConstants.js @@ -23,7 +23,7 @@ const RegexConstants = { city_name: /^$|^[a-zA-Z][a-zA-Z ]*$/, address: /^$|^[a-zA-Z0-9#,][a-zA-Z0-9#, ]*$/, NEW_NAME_REGEX: /^([a-zA-Z0-9]+\s?)*$/, //allows only one space and no spl characters allowed - DATAPOINT_ATTRIBUTE_REGEX: /^([a-zA-Z0-9_-]+)*$/ // accepts only 2 spl charecters "-" and "_" and no spl characters and no space + DATAPOINT_ATTRIBUTE_REGEX: /^([a-zA-Z0-9_]+)*$/ // accepts only 1 spl charecter "_" and no spl characters and no space }; export default RegexConstants; From 6764d2d60d49a3b0f641a84420f7ee8ddea6e5b5 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Fri, 24 Mar 2023 14:27:31 +0530 Subject: [PATCH 56/73] change in object while getting --- .../Datasets/IntegrationDatasets/DatasetIntegration.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index da7eeea32..93c265b35 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -329,10 +329,10 @@ const DatasetIntegration = (props) => { setConnectorId(dataForRender?.id) //file path setting setIntegratedFilePath(dataForRender?.integrated_file?.replace("/media", "")) - setNoOfRecords(dataForRender?.no_of_records ? dataForRender?.no_of_records : 0) + setNoOfRecords(dataForRender?.data?.no_of_records ? dataForRender?.data?.no_of_records : 0) //set already generated data - setFinalDatasetAfterIntegration([...dataForRender?.data ? JSON.parse(dataForRender?.data) : []]) + setFinalDatasetAfterIntegration([...dataForRender?.data?.records ? JSON.parse(dataForRender?.data?.records) : []]) //A function to generate complete Data from maps of dataForRender completeDataGenerator(dataForRender?.maps?.length > 0 ? dataForRender?.maps : []) From 5c989f65344aba2a5b41213d47c23c70a6b30712 Mon Sep 17 00:00:00 2001 From: kanhaiya suthar Date: Fri, 24 Mar 2023 16:38:07 +0530 Subject: [PATCH 57/73] some changes in response type --- .../DatasetIntegration.jsx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx index 93c265b35..814817e02 100644 --- a/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx +++ b/src/Components/Datasets/IntegrationDatasets/DatasetIntegration.jsx @@ -332,7 +332,7 @@ const DatasetIntegration = (props) => { setNoOfRecords(dataForRender?.data?.no_of_records ? dataForRender?.data?.no_of_records : 0) //set already generated data - setFinalDatasetAfterIntegration([...dataForRender?.data?.records ? JSON.parse(dataForRender?.data?.records) : []]) + setFinalDatasetAfterIntegration([...dataForRender?.data?.data ? (dataForRender?.data?.data) : []]) //A function to generate complete Data from maps of dataForRender completeDataGenerator(dataForRender?.maps?.length > 0 ? dataForRender?.maps : []) @@ -423,8 +423,8 @@ const DatasetIntegration = (props) => { setIntegratedFilePath(res?.data?.integrated_file ? res?.data?.integrated_file : "") setNoOfRecords(res?.data?.no_of_records ? res?.data?.no_of_records : 0) - setFinalDatasetAfterIntegration([...JSON.parse(res.data?.data)]) - let allKeys = JSON.parse(res.data.data)?.length > 0 ? Object.keys(JSON.parse(res.data.data)[0]) : [] + setFinalDatasetAfterIntegration([...res.data?.data?.data]) + let allKeys = (res.data?.data?.data)?.length > 0 ? Object.keys((res.data.data.data)[0]) : [] if (allKeys.length > 1) { let arr = [...completeData] let obj = arr[index + 1] @@ -434,8 +434,8 @@ const DatasetIntegration = (props) => { obj["left_on"] = [] console.log("HERE IS THE CALL", arr.length, index,) if (arr.length > 2 && index != arr.length - 2) { - for (let i = index; i < arr.length; i++) { - arr["left_on"] = [] + for (let i = index + 1; i < arr.length; i++) { + arr[i]["left_on"] = [] } setIsAllConditionForSaveMet(false) } else { @@ -530,7 +530,7 @@ const DatasetIntegration = (props) => { uri = UrlConstant.base_url + integratedFilePath } - FileSaver.saveAs(uri, connectorData.name ? connectorData.name : "Integrated_dataset"); + download(uri, connectorData.name ? connectorData.name : "Integrated_dataset"); } //number of integration handler @@ -540,13 +540,11 @@ const DatasetIntegration = (props) => { } } - const download = (data) => { - const blob = new Blob([data], { type: 'text/csv' }) - const url = window.URL.createObjectURL(blob); + const download = (url, connector_name) => { const a = document.createElement('a'); a.setAttribute('hidden', '') a.setAttribute('href', url) - a.setAttribute('download', "Dataset.csv"); + a.setAttribute('download', connector_name); document.body.appendChild(a); a.click(); document.body.removeChild(a); @@ -598,7 +596,7 @@ const DatasetIntegration = (props) => { {!isDatasetIntegrationListModeOn && } - {!isDatasetIntegrationListModeOn && completeData.length > 0 && finalDatasetAfterIntegration?.length > 0 && < Preview noOfRecords={noOfRecords} isConditionForConnectorDataForSaveMet={isConditionForConnectorDataForSaveMet} isAllConditionForSaveMet={isAllConditionForSaveMet} isEdited={isEdited} setIsEdited={setIsEdited} generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} + {!isDatasetIntegrationListModeOn && completeData.length > 0 && finalDatasetAfterIntegration?.length > 0 && < Preview integratedFilePath={integratedFilePath} noOfRecords={noOfRecords} isConditionForConnectorDataForSaveMet={isConditionForConnectorDataForSaveMet} isAllConditionForSaveMet={isAllConditionForSaveMet} isEdited={isEdited} setIsEdited={setIsEdited} generateData={generateData} setIsDatasetIntegrationListModeOn={setIsDatasetIntegrationListModeOn} deleteConnector={deleteConnector} counterForIntegrator={counterForIntegrator} completeData={completeData} isEditModeOn={isEditModeOn} integrateMore={integrateMore} resetAll={resetAll} connectorData={connectorData} downloadDocument={downloadDocument} finalDatasetAfterIntegration={finalDatasetAfterIntegration} />} {isDatasetIntegrationListModeOn && } ) From 050f7849a79b56296f7c5e8dc838fec3fc3ccf81 Mon Sep 17 00:00:00 2001 From: Nilesh Tiwari Date: Fri, 24 Mar 2023 22:19:01 +0530 Subject: [PATCH 58/73] inetegrated edit api --- .../AdminDatasetConnection/AddDataset.jsx | 10 +- .../DataStandardizationInAddDataset.js | 95 ++++++++++++++++--- 2 files changed, 92 insertions(+), 13 deletions(-) diff --git a/src/Components/AdminDatasetConnection/AddDataset.jsx b/src/Components/AdminDatasetConnection/AddDataset.jsx index 927acb559..5bfe7bfa9 100644 --- a/src/Components/AdminDatasetConnection/AddDataset.jsx +++ b/src/Components/AdminDatasetConnection/AddDataset.jsx @@ -1096,7 +1096,15 @@ const AddDataset = (props) => { { activeStep == 2 ? - + : "" } diff --git a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js index ed20acb8e..1b4a01bee 100644 --- a/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js +++ b/src/Components/AdminDatasetConnection/DataStandardizationInAddDataset.js @@ -19,7 +19,9 @@ import { GetErrorHandlingRoute } from "../../Utils/Common"; import { message, Space } from "antd"; const DataStandardizationInAddDataset = (props) => { - const { datasetname, setAllStandardisedFile, allStandardisedFile, standardisedFileLink, setStandardisedFileLink } = props; + const { datasetname, setAllStandardisedFile, allStandardisedFile, standardisedFileLink, setStandardisedFileLink, listOfFilesExistInDbForEdit, isDatasetEditModeOn } = props; + + console.log("type of ", typeof(listOfFilesExistInDbForEdit)) const [keysInUploadedDataset, setKeysInUploadedDataset] = useState([]); const [standardColumnNames, setStandardColumnNames] = useState([]); @@ -57,6 +59,7 @@ const DataStandardizationInAddDataset = (props) => { }; const datapointCategoryChange = (value, index) => { + console.log("value on change datapointCategoryChange", value) // first removing value of selected column let tmpStandardisedColum = [...standardisedColum] @@ -98,6 +101,7 @@ const DataStandardizationInAddDataset = (props) => { } const getAllFileNames = () => { + // console.log("filename in getAllFileNames api call 1",allFileNames) let url = UrlConstant.base_url + UrlConstant.standardization_get_all_file_name + @@ -105,9 +109,15 @@ const DataStandardizationInAddDataset = (props) => { setIsLoading(true); HTTPService("GET", url, false, false, true) .then((response) => { + // console.log("filename in getAllFileNames api call 2",allFileNames) setIsLoading(false); console.log("response", response); - setAllFileNames(response.data); + let tmpAllFileName = [...allFileNames,...response.data] + // console.log("filename in getAllFileNames api call 3", allFileNames,tmpAllFileName) + setAllFileNames(tmpAllFileName); + if(isDatasetEditModeOn){ + handleExistingStandardizedFiles(tmpAllFileName) + } }) .catch((e) => { setIsLoading(false); @@ -227,7 +237,7 @@ const DataStandardizationInAddDataset = (props) => { } else { setError(false); success( - e.response.data && e.response.data.message + e?.response?.data && e.response?.data?.message ? e.response.data.message : "Something went wrong while getting file column names.", "error" @@ -300,9 +310,34 @@ const DataStandardizationInAddDataset = (props) => { } + const handleExistingStandardizedFiles = (fileNames) =>{ + let tmpAllFileName = [...fileNames] + console.log('filename in handleExistingStandardizedFiles', allFileNames,tmpAllFileName ) + let tmpStandardized = {...allStandardisedFile} + + listOfFilesExistInDbForEdit.forEach((dataset,index)=>{ + tmpAllFileName.push(dataset.file) + console.log("tmpAllFileName in handleExistingStandardizedFiles", tmpAllFileName) + if(Object.keys(dataset.standardisation_config).length){ + tmpStandardized[dataset.file] = dataset.standardisation_config + } + console.log("tmpStandardized in handleExistingStandardizedFiles",tmpStandardized) + }) + setAllStandardisedFile(tmpStandardized) + setAllFileNames(tmpAllFileName); + } + useEffect(() => { getAllFileNames(); getStandardiziedTemplate(); + console.log("isDatasetEditModeOn in standardistion", isDatasetEditModeOn) + // if(isDatasetEditModeOn){ + // handleExistingStandardizedFiles() + // } + + + + }, []); useEffect(() => { @@ -313,9 +348,37 @@ const DataStandardizationInAddDataset = (props) => { if(allStandardisedFile[fileName]){ console.log("allStandardisedFile[fileName]",allStandardisedFile[fileName], standardisedFileLink) setStandardisedTempleteCategory(allStandardisedFile[fileName]?.standardised_templete_category) - setStandardisedColumn(allStandardisedFile[fileName]?.standardised_column) setMaskedColumns(allStandardisedFile[fileName]?.masked_columns) + + // Chnage object reference + if(isDatasetEditModeOn){ + let tmpArr = [...allStandardisedFile[fileName]?.standardised_templete_category]; + tmpArr.forEach((attribute,index)=>{ + allStandardisedTempleteCategory.forEach(((tmpAttribute)=>{ + if(attribute?.id==tmpAttribute?.id){ + tmpArr[index] = tmpAttribute + } + // console.log("checking true of false in useeffect",attribute.id==tmpAttribute.id,attribute.id,tmpAttribute.id,attribute) + })) + }) + // tmpArr[index] = value; + setStandardisedTempleteCategory(tmpArr); + setStandardisedColumn(allStandardisedFile[fileName]?.standardised_column) + + // getting attribute keys to show on render + let tmpColumn = [...standardisedTempleteAttribute]; + tmpArr.forEach((attribute, index) => { + console.log("attribute in for each", attribute); + if (attribute?.datapoint_attributes) + tmpColumn[index] = Object.keys(attribute.datapoint_attributes); + }); + setStandardisedTempleteAttribute(tmpColumn); + } + + if(!isDatasetEditModeOn) setStandardisedColumn(allStandardisedFile[fileName]?.standardised_column) + } + }, [fileName]); console.log("allFileNames", allFileNames); console.log( @@ -325,7 +388,8 @@ const DataStandardizationInAddDataset = (props) => { allFileNames ); - console.log('all data',keysInUploadedDataset, standardisedTempleteCategory, standardisedColum) + console.log('all data',keysInUploadedDataset, standardisedTempleteCategory, standardisedColum,maskedColumns) + console.log("listOfFilesExistInDbForEdit", listOfFilesExistInDbForEdit) return (
{contextHolder} @@ -354,7 +418,7 @@ const DataStandardizationInAddDataset = (props) => { {allFileNames?.map((item, index) => { console.log("file name in loop", item); return ( - + {item} ); @@ -394,8 +458,8 @@ const DataStandardizationInAddDataset = (props) => {
{keysInUploadedDataset?.map((keyNames, index) => { return ( - <> - +
+
{