From 4a10a94728ec6d62897e3299c2c924301ad86f0f Mon Sep 17 00:00:00 2001 From: Jeeva Ramachandran <120017870+JeevaRamu0104@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:07:21 +0530 Subject: [PATCH 01/14] chore: Add eslint hook (#166) Co-authored-by: Sagar Naik Co-authored-by: Pritish Budhiraja <1805317@kiit.ac.in> --- .eslintrc.json | 17 + .github/ISSUE_TEMPLATE/bug_report.yml | 1 - .github/workflows/eslint-check.yml | 30 ++ docs/CODE_OF_CONDUCT.md | 2 +- docs/SECURITY.md | 4 +- package.json | 6 +- .../NestedDropdownWithCalendar.res | 121 -------- src/components/Button.res | 3 +- .../CustomCharts/HighchartTimeSeriesChart.res | 37 +-- src/components/DateRangePicker.res | 26 +- src/components/InputFields.res | 17 +- src/components/InputFields.resi | 1 + src/components/LoadedTable.res | 98 +++--- src/components/LoadedTable.resi | 2 +- src/components/MultipleFileUpload.res | 3 +- src/components/NestedDropdown.res | 291 ------------------ src/components/NewDateRangePicker.res | 26 +- src/components/ReactWindowTable.res | 76 +++-- src/components/TableUtils.res | 25 +- src/components/TableUtils.resi | 2 +- src/components/form/FileUpload.res | 3 +- src/components/form/TextInput.res | 2 +- src/entities/analytics/AnalyticsUtils.res | 2 - src/hooks/AnalyticsHooks.res | 71 ----- src/libraries/Recoil.res | 2 +- src/libraries/SankeyHighcharts.res | 2 +- .../HyperSwitch/Analytics/Analytics.res | 28 +- .../SystemMetrics/SystemMetricsAnalytics.res | 26 +- .../Connectors/ConnectorPreview.res | 4 +- .../HyperSwitch/HSwitchRemoteFilter.res | 53 ++-- src/screens/HyperSwitch/Order/OrderHooks.res | 2 +- src/screens/HyperSwitch/Order/ShowOrder.res | 2 +- .../PostLoginScreen/PostLoginScreen.res | 3 +- .../PostLoginScreen/PostLoginUtils.res | 3 - .../HyperSwitch/Refunds/RefundHook.res | 2 +- .../HyperSwitch/Refunds/ShowRefund.res | 4 +- .../UserOnboardingUIUtils.res | 122 ++++---- .../UserManagement/InviteUsers.res | 8 +- 38 files changed, 342 insertions(+), 785 deletions(-) create mode 100644 .eslintrc.json create mode 100644 .github/workflows/eslint-check.yml delete mode 100644 src/components/AnalyticsComponent/NestedDropdownWithCalendar.res delete mode 100644 src/components/NestedDropdown.res diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..0e6e03f8c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true, + "shelljs": true + }, + "extends": [], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["react-hooks"], + "rules": { + "react-hooks/rules-of-hooks": "error" + } +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3cc5a7f9f..c85300ffc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -60,7 +60,6 @@ body: validations: required: false - - type: checkboxes id: no-duplicate-issues attributes: diff --git a/.github/workflows/eslint-check.yml b/.github/workflows/eslint-check.yml new file mode 100644 index 000000000..3d24b5ebe --- /dev/null +++ b/.github/workflows/eslint-check.yml @@ -0,0 +1,30 @@ +name: ESLint + +on: [push] + +jobs: + eslint: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + token: ${{ secrets.AUTO_RELEASE_PAT }} + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install dependencies + run: npm install --force + + - name: Build Rescript + run: npm run re:build + + - name: Run ESLint + run: npm run lint:hooks + env: + CI: true diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md index 3abf4809a..acb75d539 100644 --- a/docs/CODE_OF_CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -2,4 +2,4 @@ The hyperswitch control center project adheres to the [Rescript](https://rescript-lang.org/community/code-of-conduct) and [React](https://github.com/facebook/react/blob/main/CODE_OF_CONDUCT.md) code of conduct. -This describes the minimum behavior expected from all contributors. \ No newline at end of file +This describes the minimum behavior expected from all contributors. diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 601c3fa0d..8a3551a62 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -1,3 +1,5 @@ # Security Policy + ## Reporting a security issue -The hyperswitch project team welcomes security reports and is committed to providing prompt attention to security issues. Security issues should be reported privately via the [advisories page on GitHub](https://github.com/juspay/hyperswitch/security/advisories/new) or by email at hyperswitch@juspay.in. Security issues should not be reported via the public GitHub Issue tracker. \ No newline at end of file + +The hyperswitch project team welcomes security reports and is committed to providing prompt attention to security issues. Security issues should be reported privately via the [advisories page on GitHub](https://github.com/juspay/hyperswitch/security/advisories/new) or by email at hyperswitch@juspay.in. Security issues should not be reported via the public GitHub Issue tracker. diff --git a/package.json b/package.json index 3caffb776..49ff19d99 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "re:format": "rescript format -all", "postinstall": "git config core.hooksPath .githooks && chmod +x .githooks/commit-msg", "cy:open": "cypress open", - "cy:run": "cypress run" + "cy:run": "cypress run", + "lint:hooks": "eslint src/ --max-warnings 0" }, "husky": { "hooks": { @@ -27,11 +28,14 @@ } }, "devDependencies": { + "@eslint/create-config": "0.4.6", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1", "copy-webpack-plugin": "^9.0.0", "css-loader": "^5.0.1", "css-minimizer-webpack-plugin": "^5.0.1", "cypress": "^13.6.0", + "eslint": "latest", + "eslint-plugin-react-hooks": "^4.6.0", "file-loader": "^6.2.0", "husky": "^8.0.3", "mini-css-extract-plugin": "^1.3.1", diff --git a/src/components/AnalyticsComponent/NestedDropdownWithCalendar.res b/src/components/AnalyticsComponent/NestedDropdownWithCalendar.res deleted file mode 100644 index d4bb51706..000000000 --- a/src/components/AnalyticsComponent/NestedDropdownWithCalendar.res +++ /dev/null @@ -1,121 +0,0 @@ -@react.component -let make = ( - ~input: ReactFinalForm.fieldRenderPropsInput, - ~options, - ~title: string, - ~dateRangeLimit: int=60, - ~addMore: bool=true, -) => { - let (startDateArr, setStartDateArr) = React.useState(_ => [""]) - let (endDateArr, setEndDateArr) = React.useState(_ => [""]) - let onClickAdd = _ => { - setEndDateArr(prev => Array.concat([""], prev)) - setStartDateArr(prev => Array.concat([""], prev)) - } - React.useEffect1(() => { - setStartDateArr(_ => [""]) - setEndDateArr(_ => [""]) - None - }, [input.value]) - - let onClick = _ => { - let newArr = - startDateArr->Array.mapWithIndex((x, i) => ( - x, - endDateArr->Belt.Array.get(i)->Belt.Option.getWithDefault(x), - )) - - input.onChange(newArr->Identity.anyTypeToReactEvent) - } - - let showCalendars = React.useMemo1(() => { - input.value - ->Js.Json.decodeArray - ->Belt.Option.getWithDefault([]) - ->Belt.Array.get(0) - ->Belt.Option.getWithDefault(Js.Json.null) - ->Js.Json.decodeString - ->Belt.Option.getWithDefault("") == "timeP" || - input.value - ->Js.Json.decodeArray - ->Belt.Option.getWithDefault([]) - ->Belt.Array.get(0) - ->Belt.Option.getWithDefault(Js.Json.null) - ->Js.Json.decodeArray - ->Belt.Option.getWithDefault([]) - ->Belt.Array.get(0) - ->Belt.Option.getWithDefault(Js.Json.null) - ->Js.Json.decodeString - ->Belt.Option.getWithDefault("") - ->Js.Date.fromString - ->Js.Date.getTime >= 0.0 - }, [input.value]) -
- - -
- {startDateArr - ->Array.mapWithIndex((_x, i) => { -
- Belt.Option.getWithDefault("")} - setStartDateVal={fn => { - setStartDateArr(prev => { - let newArr = prev->Array.mapWithIndex( - (x2, i2) => { - if i2 == i { - fn(prev[i]->Belt.Option.getWithDefault("")) - } else { - x2 - } - }, - ) - - newArr - }) - }} - endDateVal={endDateArr[i]->Belt.Option.getWithDefault("")} - setEndDateVal={fn => { - setEndDateArr(prev => { - let newArr = prev->Array.mapWithIndex( - (x2, i2) => { - if i2 == i { - fn(prev[i]->Belt.Option.getWithDefault("")) - } else { - x2 - } - }, - ) - - newArr - }) - }} - showTime=false - disablePastDates=false - disableFutureDates=true - predefinedDays=[] - format="YYYY-MM-DDTHH:mm:ss.SSS[Z]" - numMonths=1 - disableApply=true - removeFilterOption=false - textHideInMobileView=true - showSeconds=true - hideDate=false - selectStandardTime=false - dateRangeLimit - /> -
- }) - ->React.array} - {addMore - ?
-
- - -} diff --git a/src/components/Button.res b/src/components/Button.res index 49fa7628f..59b89f0a2 100644 --- a/src/components/Button.res +++ b/src/components/Button.res @@ -364,8 +364,9 @@ let make = ( let parentRef = React.useRef(Js.Nullable.null) let dummyRef = React.useRef(Js.Nullable.null) let buttonRef = disableRipple ? dummyRef : parentRef + let rippleEffect = RippleEffectBackground.useHorizontalRippleHook(buttonRef) if !isPhoneDropdown { - RippleEffectBackground.useHorizontalRippleHook(buttonRef) + rippleEffect } let customTextOverFlowClass = switch textStyleClass { diff --git a/src/components/CustomCharts/HighchartTimeSeriesChart.res b/src/components/CustomCharts/HighchartTimeSeriesChart.res index 98c8863cc..7686592e6 100644 --- a/src/components/CustomCharts/HighchartTimeSeriesChart.res +++ b/src/components/CustomCharts/HighchartTimeSeriesChart.res @@ -802,7 +802,7 @@ module LegendItem = { } module RenderMultiDimensionalChart = { - type props = { + type config = { chartDictData: Js.Dict.t>, class: string, selectedMetrics: LineChartUtils.metricsConfig, @@ -812,17 +812,18 @@ module RenderMultiDimensionalChart = { legendType: legendType, chartType: string, } - let make = (props: props) => { + @react.component + let make = (~config: config) => { let (selectedRow, setSelectedRow) = React.useState(_ => None) let chartNames = - props.chartDictData + config.chartDictData ->Dict.toArray ->Array.reduce([], (acc: array>, (_, value)) => { let chartdata = LineChartUtils.timeSeriesDataMaker( ~data=value, - ~groupKey=props.groupBy, - ~xAxis=props.xAxis, - ~metricsConfig=props.selectedMetrics, + ~groupKey=config.groupBy, + ~xAxis=config.xAxis, + ~metricsConfig=config.selectedMetrics, (), ) chartdata @@ -848,28 +849,28 @@ module RenderMultiDimensionalChart = {
{ let chartArr = { - props.chartDictData + config.chartDictData ->Dict.toArray ->Array.mapWithIndex((item, index) => { let (key, value) = item Belt.Int.toString} - class=props.class + class=config.class rawChartData=value commonColorsArr={LineChartUtils.removeDuplicates(chartNames)} - selectedMetrics=props.selectedMetrics - xAxis=props.xAxis - groupKey=props.groupBy + selectedMetrics=config.selectedMetrics + xAxis=config.xAxis + groupKey=config.groupBy chartTitle=true chartTitleText=key showTableLegend=false showLegend=false - legendType=props.legendType + legendType=config.legendType isMultiDimensional=true - chartKey=props.chartKey + chartKey=config.chartKey selectedRow={selectedRow} - chartType=props.chartType + chartType=config.chartType /> }) } @@ -910,7 +911,7 @@ module LineChart2D = { chartDictData->LineChartUtils.appendToDictValue(groupBy, item) }) - let compProps: RenderMultiDimensionalChart.props = { + let compProps: RenderMultiDimensionalChart.config = { chartDictData, class, selectedMetrics, @@ -921,7 +922,7 @@ module LineChart2D = { chartType, } - + } } @@ -958,7 +959,7 @@ module LineChart3D = { chartDictData->LineChartUtils.appendToDictValue(groupBy1 ++ " / " ++ groupBy2, item) }) - let compProps: RenderMultiDimensionalChart.props = { + let compProps: RenderMultiDimensionalChart.config = { chartDictData, class, selectedMetrics, @@ -969,6 +970,6 @@ module LineChart3D = { chartType, } - + } } diff --git a/src/components/DateRangePicker.res b/src/components/DateRangePicker.res index 841e451bf..944f9f44a 100644 --- a/src/components/DateRangePicker.res +++ b/src/components/DateRangePicker.res @@ -168,7 +168,7 @@ module Base = { ~disableApply=true, ~removeFilterOption=false, ~dateRangeLimit=?, - ~optFieldKey=?, + ~optFieldKey as _=?, ~textHideInMobileView=true, ~showSeconds=true, ~hideDate=false, @@ -194,16 +194,10 @@ module Base = { let isoStringToCustomTimezoneInFloat = TimeZoneHook.useIsoStringToCustomTimeZoneInFloat() let (clickedDates, setClickedDates) = React.useState(_ => []) - let optInput = optFieldKey->Belt.Option.map(key => ReactFinalForm.useField(key).input) - - let optInputVal = - optInput->Belt.Option.mapWithDefault("", optInput => - optInput.value->LogicUtils.getStringFromJson("") - ) let (localStartDate, setLocalStartDate) = React.useState(_ => startDateVal) let (localEndDate, setLocalEndDate) = React.useState(_ => endDateVal) - let (localOpt, setLocalOpt) = React.useState(_ => optInputVal) + let (_localOpt, setLocalOpt) = React.useState(_ => "") let (showMsg, setShowMsg) = React.useState(_ => false) let (isDropdownExpanded, setIsDropdownExpanded) = React.useState(_ => false) @@ -225,12 +219,12 @@ module Base = { let initialStartTime = disableFutureDates || selectStandardTime ? "00:00:00" : "23:59:59" let initialEndTime = disableFutureDates || selectStandardTime ? "23:59:59" : "00:00:00" - React.useEffect3(() => { + React.useEffect2(() => { setLocalStartDate(_ => startDateVal) setLocalEndDate(_ => endDateVal) - setLocalOpt(_ => optInputVal) + setLocalOpt(_ => "") None - }, (startDateVal, endDateVal, optInputVal)) + }, (startDateVal, endDateVal)) let resetStartEndInput = () => { setLocalStartDate(_ => "") @@ -273,16 +267,12 @@ module Base = { if localStartDate !== "" && localEndDate !== "" { setStartDateVal(_ => localStartDate) setEndDateVal(_ => localEndDate) - switch optInput { - | Some(ip) => ip.onChange(localOpt->Identity.stringToFormReactEvent) - | None => () - } } } let resetToInitalValues = () => { setLocalStartDate(_ => startDateVal) setLocalEndDate(_ => endDateVal) - setLocalOpt(_ => optInputVal) + setLocalOpt(_ => "") } OutsideClick.useOutsideClick( @@ -414,10 +404,6 @@ module Base = { setCalendarVisibility(p => !p) setIsDropdownExpanded(_ => false) saveDates() - switch optInput { - | Some(ip) => ip.onChange("custom_range"->Identity.stringToFormReactEvent) - | None => () - } } let cancelButton = _ => { diff --git a/src/components/InputFields.res b/src/components/InputFields.res index 8d9ea8b37..f2fd96f1c 100644 --- a/src/components/InputFields.res +++ b/src/components/InputFields.res @@ -9,13 +9,6 @@ type comboCustomInputRecord = { names: array, } -let useGetAccessLevel = () => { - let accessLevel = React.useContext(FormAuthContext.formAuthContext) - () => { - accessLevel - } -} - let selectInput = ( ~input: ReactFinalForm.fieldRenderPropsInput, ~options: array, @@ -50,7 +43,6 @@ let selectInput = ( ~descriptionOnHover=false, (), ) => { - let accessHook = useGetAccessLevel() { - let accessHook = useGetAccessLevel() { - let accessHook = useGetAccessLevel() React.element=?, + ~disableSelect: bool=?, unit, ) => React.element let radioInput: ( diff --git a/src/components/LoadedTable.res b/src/components/LoadedTable.res index b0e7f3b9f..b59de1bee 100644 --- a/src/components/LoadedTable.res +++ b/src/components/LoadedTable.res @@ -69,63 +69,61 @@ let useSortedObj = (title: string, defaultSort) => { (sortedObj, setSortedObj) } -let useSortArray = () => { - (originalData, key, sortOrder: Table.sortOrder) => { - let getValue = val => { - switch val { - | Some(x) => - switch x->Js.Json.classify { - | JSONString(str) => str->String.toLowerCase->Js.Json.string - | JSONNumber(_num) => x - | JSONFalse => "false"->Js.Json.string - | JSONTrue => "true"->Js.Json.string - | _ => ""->Js.Json.string - } - | None => ""->Js.Json.string +let sortArray = (originalData, key, sortOrder: Table.sortOrder) => { + let getValue = val => { + switch val { + | Some(x) => + switch x->Js.Json.classify { + | JSONString(str) => str->Js.String.toLowerCase->Js.Json.string + | JSONNumber(_num) => x + | JSONFalse => "false"->Js.Json.string + | JSONTrue => "true"->Js.Json.string + | _ => ""->Js.Json.string } + | None => ""->Js.Json.string } - let sortedArrayByOrder = { - let _ = originalData->Js.Array2.sortInPlaceWith((i1, i2) => { - let item1 = i1->Js.Json.stringifyAny->Belt.Option.getWithDefault("")->LogicUtils.safeParse - let item2 = i2->Js.Json.stringifyAny->Belt.Option.getWithDefault("")->LogicUtils.safeParse - // flatten items and get data - - let val1 = - JsonFlattenUtils.flattenObject(item1, true) - ->Js.Json.object_ - ->Js.Json.decodeObject - ->Belt.Option.flatMap(dict => dict->Dict.get(key)) - let val2 = - JsonFlattenUtils.flattenObject(item2, true) - ->Js.Json.object_ - ->Js.Json.decodeObject - ->Belt.Option.flatMap(dict => dict->Dict.get(key)) - let value1 = getValue(val1) - let value2 = getValue(val2) - if value1 === ""->Js.Json.string || value2 === ""->Js.Json.string { - if value1 === value2 { - 0 - } else if value2 === ""->Js.Json.string { - sortOrder === DEC ? 1 : -1 - } else if sortOrder === DEC { - -1 - } else { - 1 - } - } else if value1 === value2 { + } + let sortedArrayByOrder = { + let _ = originalData->Js.Array2.sortInPlaceWith((i1, i2) => { + let item1 = i1->Js.Json.stringifyAny->Option.getWithDefault("")->LogicUtils.safeParse + let item2 = i2->Js.Json.stringifyAny->Option.getWithDefault("")->LogicUtils.safeParse + // flatten items and get data + + let val1 = + JsonFlattenUtils.flattenObject(item1, true) + ->Js.Json.object_ + ->Js.Json.decodeObject + ->Option.flatMap(dict => dict->Dict.get(key)) + let val2 = + JsonFlattenUtils.flattenObject(item2, true) + ->Js.Json.object_ + ->Js.Json.decodeObject + ->Option.flatMap(dict => dict->Dict.get(key)) + let value1 = getValue(val1) + let value2 = getValue(val2) + if value1 === ""->Js.Json.string || value2 === ""->Js.Json.string { + if value1 === value2 { 0 - } else if value1 > value2 { + } else if value2 === ""->Js.Json.string { sortOrder === DEC ? 1 : -1 } else if sortOrder === DEC { -1 } else { 1 } - }) - originalData - } - sortedArrayByOrder + } else if value1 === value2 { + 0 + } else if value1 > value2 { + sortOrder === DEC ? 1 : -1 + } else if sortOrder === DEC { + -1 + } else { + 1 + } + }) + originalData } + sortedArrayByOrder } type pageDetails = { offset: int, @@ -327,7 +325,7 @@ let make = ( let newObj = oldFitlers->Dict.toArray->Dict.fromArray let filterValue = filterValue->Array.filter( item => { - let updatedItem = item->String.make + let updatedItem = item->Js.String.make updatedItem !== "" }, ) @@ -514,8 +512,6 @@ let make = ( } }, (actualData, totalResults, visibleColumns, columnFilter)) - let sortArray = useSortArray() - let filteredDataLength = columnFilter->Dict.keysToArray->Array.length !== 0 ? actualData->Array.length : totalResults @@ -930,7 +926,7 @@ let make = ( } else { `${ignoreHeaderBg ? "" : backgroundClass} empty:hidden` } - let dataId = title->String.split("-")->Belt.Array.get(0)->Belt.Option.getWithDefault("") + let dataId = title->Js.String2.split("-")->Belt.Array.get(0)->Belt.Option.getWithDefault("")
diff --git a/src/components/LoadedTable.resi b/src/components/LoadedTable.resi index f43376ddd..a2453f93e 100644 --- a/src/components/LoadedTable.resi +++ b/src/components/LoadedTable.resi @@ -15,7 +15,7 @@ let useSortedObj: ( option, (option => option) => unit, ) -let useSortArray: (unit, Js.Array2.t<'a>, Js.Dict.key, Table.sortOrder) => Js.Array2.t<'a> +// let sortArray: (Js.Array2.t<'a>, RescriptCoreFuture.Dict.key, Table.sortOrder) => Js.Array2.t<'a> type pageDetails = {offset: int, resultsPerPage: int} let table_pageDetails: Recoil.recoilAtom> @react.component diff --git a/src/components/MultipleFileUpload.res b/src/components/MultipleFileUpload.res index 52f5f95b3..6b3d375b8 100644 --- a/src/components/MultipleFileUpload.res +++ b/src/components/MultipleFileUpload.res @@ -31,9 +31,10 @@ let make = ( ~pointerDisable=false, ) => { let (key, setKey) = React.useState(_ => 1) + let formValues = ReactFinalForm.useField(input.name ++ "_filenames").input let fileNamesInput = switch fileNamesInput { | Some(filenamesInput) => filenamesInput - | None => ReactFinalForm.useField(input.name ++ "_filenames").input + | None => formValues } let fileTypeInput = ReactFinalForm.useField(input.name ++ "_filemimes").input diff --git a/src/components/NestedDropdown.res b/src/components/NestedDropdown.res deleted file mode 100644 index c842718e9..000000000 --- a/src/components/NestedDropdown.res +++ /dev/null @@ -1,291 +0,0 @@ -type rec options = { - title: string, - value: string, - options?: array, -} - -module RenderOption = { - @react.component - let make = ( - ~option, - ~input: ReactFinalForm.fieldRenderPropsInput, - ~selectedInd, - ~setSelectedInd, - ~index, - ~depth, - ~setMaxDepthSelection, - ~maxDepthSelection as _, - ~prevMaxDepthSelection as _, - ~selectedData, - ~setSelectedData, - ~selectedDataVal, - ~setSelectedDataVal, - ) => { - let hasOptions = option.options->Belt.Option.isSome || option.value == "timeP" - - let onClick = _ => { - if option.value == "timeP" { - let data = if Array.includes(selectedData, option.value) { - selectedData->Array.filter(x => x !== option.value) - } else { - Array.concat(selectedData, [option.value]) - } - let dataN = if Array.includes(selectedDataVal, option.title) { - selectedDataVal->Array.filter(x => x !== option.title) - } else { - Array.concat(selectedDataVal, [option.title]) - } - setSelectedData(_ => data) - setSelectedDataVal(_ => dataN) - input.onChange(data->Identity.anyTypeToReactEvent) - } - if selectedInd != index { - setSelectedInd(_ => index) - // setPrevMaxDepthSelection(_ => maxDepthSelection) - setMaxDepthSelection(_ => depth) - } else { - setSelectedInd(_ => -1) - // setPrevMaxDepthSelection(_ => maxDepthSelection) - setMaxDepthSelection(_ => depth - 1) - } - } - - if hasOptions { -
- {React.string(option.title)} - -
- } else { - let isSelected = selectedData->Array.indexOf(option.value) > -1 - let onClick = _ => { - let data = if Array.includes(selectedData, option.value) { - selectedData->Array.filter(x => x !== option.value) - } else { - Array.concat(selectedData, [option.value]) - } - let dataN = if Array.includes(selectedDataVal, option.title) { - selectedDataVal->Array.filter(x => x !== option.title) - } else { - Array.concat(selectedDataVal, [option.title]) - } - setSelectedData(_ => data) - setSelectedDataVal(_ => dataN) - } -
- -
{React.string(option.title)}
-
- } - } -} -module RenderOptionList = { - @react.component - let rec make = ( - ~options: array, - ~input: ReactFinalForm.fieldRenderPropsInput, - ~depth, - ~setDepth, - ~maxDepthSelection, - ~setMaxDepthSelection, - ~prevMaxDepthSelection, - ~selectedData, - ~setSelectedData, - ~selectedDataVal, - ~setSelectedDataVal, - ) => { - let (selectedInd, setSelectedIndOrig) = React.useState(_ => -1) - let setSelectedInd = React.useCallback1(fn => { - setSelectedIndOrig(fn) - setSelectedData(_ => []) - setSelectedDataVal(_ => []) - }, [setSelectedIndOrig]) - let nestedOptions = React.useMemo1(() => { - switch Belt.Array.get(options, selectedInd) { - | Some(opt) => - switch opt.options { - | Some(arr) => arr - | None => [] - } - | None => [] - } - }, [selectedInd]) - - // React.useEffect1(() => { - - // None - // }, [selectedInd]) - React.useEffect2(() => { - if prevMaxDepthSelection > maxDepthSelection { - setSelectedInd(_ => -1) - } - None - }, (prevMaxDepthSelection, maxDepthSelection)) - let hasNestedOptions = switch Belt.Array.get(options, 1) { - | Some(opt) => - switch opt.options { - | Some(_arr) => true - | None => false - } - | None => false - } - let onClick = _ => { - input.onChange(selectedData->Identity.anyTypeToReactEvent) - } - <> -
Belt.Int.toString}px`}, - ~marginTop={`${(depth * 35)->Belt.Int.toString}px`}, - (), - )}> -
- - {React.string("Please select 2 or more values to compare")} - - {options - ->Array.mapWithIndex((opt, index) => - Belt.Int.toString} - /> - ) - ->React.array} - -
-
- 0}> - {React.createElement( - make, - { - options: nestedOptions, - input, - depth: {depth + 1}, - setDepth, - maxDepthSelection, - setMaxDepthSelection, - prevMaxDepthSelection, - selectedData, - setSelectedData, - selectedDataVal, - setSelectedDataVal, - }, - )} - - - } -} - -@react.component -let make = ( - ~input: ReactFinalForm.fieldRenderPropsInput, - ~options: array, - ~title: string, -) => { - let (showDropDown, setShowDropDown) = React.useState(_ => false) - let (selectedData, setSelectedDataOrig) = React.useState(_ => []) - let setSelectedData = React.useCallback1(fn => { - setSelectedDataOrig(p => { - let next = fn(p) - if next->Array.length == 0 && p->Array.length == 0 { - p - } else { - next - } - }) - }, [setSelectedDataOrig]) - let (selectedDataVal, setSelectedDataValOrig) = React.useState(_ => []) - let setSelectedDataVal = React.useCallback1(fn => { - setSelectedDataValOrig(p => { - let next = fn(p) - if next->Array.length == 0 && p->Array.length == 0 { - p - } else { - next - } - }) - }, [setSelectedDataValOrig]) - let (btnText, setButtonText) = React.useState(_ => title) - React.useEffect1(() => { - setShowDropDown(_ => false) - - if selectedDataVal->Array.length > 0 { - let valStr = selectedDataVal->Array.joinWith(", ") - setButtonText(_ => `${title}: ${valStr}`) - } - None - }, [input.value]) - let (depthTuple, setDepthTuple) = React.useState(_ => (0, 0)) - let (prevMaxDepthSelection, maxDepthSelection) = depthTuple - let setMaxDepthSelection = React.useCallback1(fn => { - setDepthTuple(prevTuple => { - let (_oldPrev, oldCurr) = prevTuple - let newCurr = fn(oldCurr) - (oldCurr, newCurr) - }) - }, [setDepthTuple]) - // let (maxDepthSelection, setMaxDepthSelection) = React.useState(_ => 0) - // let (prevMaxDepthSelection, setPrevMaxDepthSelection) = React.useState(_ => 0) - let onClick = _ev => { - setShowDropDown(val => !val) - } - let buttonIcon = if showDropDown { - "angle-up" - } else { - "angle-down" - } - let (depth, setDepth) = React.useState(_ => 0) - -
-
-} diff --git a/src/components/NewDateRangePicker.res b/src/components/NewDateRangePicker.res index 40e813083..7fa813da9 100644 --- a/src/components/NewDateRangePicker.res +++ b/src/components/NewDateRangePicker.res @@ -190,7 +190,7 @@ module Base = { ~disableApply=true, ~removeFilterOption=false, ~dateRangeLimit=?, - ~optFieldKey=?, + ~optFieldKey as _=?, ~textHideInMobileView=true, ~showSeconds=true, ~hideDate=false, @@ -209,16 +209,10 @@ module Base = { let isoStringToCustomTimezoneInFloat = TimeZoneHook.useIsoStringToCustomTimeZoneInFloat() let (clickedDates, setClickedDates) = React.useState(_ => []) - let optInput = optFieldKey->Belt.Option.map(key => ReactFinalForm.useField(key).input) - - let optInputVal = - optInput->Belt.Option.mapWithDefault("", optInput => - optInput.value->LogicUtils.getStringFromJson("") - ) let (localStartDate, setLocalStartDate) = React.useState(_ => startDateVal) let (localEndDate, setLocalEndDate) = React.useState(_ => endDateVal) - let (localOpt, setLocalOpt) = React.useState(_ => optInputVal) + let (_localOpt, setLocalOpt) = React.useState(_ => "") let (_showMsg, setShowMsg) = React.useState(_ => false) let (isDropdownExpanded, setIsDropdownExpanded) = React.useState(_ => false) @@ -242,12 +236,12 @@ module Base = { let initialStartTime = disableFutureDates || selectStandardTime ? "00:00:00" : "23:59:59" let initialEndTime = disableFutureDates || selectStandardTime ? "23:59:59" : "00:00:00" - React.useEffect3(() => { + React.useEffect2(() => { setLocalStartDate(_ => startDateVal) setLocalEndDate(_ => endDateVal) - setLocalOpt(_ => optInputVal) + setLocalOpt(_ => "") None - }, (startDateVal, endDateVal, optInputVal)) + }, (startDateVal, endDateVal)) let resetStartEndInput = () => { setLocalStartDate(_ => "") @@ -290,16 +284,12 @@ module Base = { if localStartDate !== "" && localEndDate !== "" { setStartDateVal(_ => localStartDate) setEndDateVal(_ => localEndDate) - switch optInput { - | Some(ip) => ip.onChange(localOpt->Identity.stringToFormReactEvent) - | None => () - } } } let resetToInitalValues = () => { setLocalStartDate(_ => startDateVal) setLocalEndDate(_ => endDateVal) - setLocalOpt(_ => optInputVal) + setLocalOpt(_ => "") } let changeEndDate = (ele, isFromCustomInput, time) => { @@ -419,10 +409,6 @@ module Base = { setCalendarVisibility(p => !p) setIsDropdownExpanded(_ => false) saveDates() - switch optInput { - | Some(ip) => ip.onChange("custom_range"->Identity.stringToFormReactEvent) - | None => () - } } let cancelButton = _ => { diff --git a/src/components/ReactWindowTable.res b/src/components/ReactWindowTable.res index 786af7060..315c227b9 100644 --- a/src/components/ReactWindowTable.res +++ b/src/components/ReactWindowTable.res @@ -588,47 +588,45 @@ let useSortedObj = (title: string, defaultSort) => { (sortedObj, setSortedObj) } -let useSortArray = () => { - (originalData, key, sortOrder: Table.sortOrder) => { - let getValue = val => { - switch val { - | Some(x) => - switch x->Js.Json.classify { - | JSONString(_str) => x - | JSONNumber(_num) => x - | JSONFalse => "false"->Js.Json.string - | JSONTrue => "true"->Js.Json.string - | _ => ""->Js.Json.string - } - | None => ""->Js.Json.string +let sortArray = (originalData, key, sortOrder: Table.sortOrder) => { + let getValue = val => { + switch val { + | Some(x) => + switch x->Js.Json.classify { + | JSONString(_str) => x + | JSONNumber(_num) => x + | JSONFalse => "false"->Js.Json.string + | JSONTrue => "true"->Js.Json.string + | _ => ""->Js.Json.string } + | None => ""->Js.Json.string } - let sortedArrayByOrder = { - let _ = originalData->Js.Array2.sortInPlaceWith((i1, i2) => { - let item1 = i1->Js.Json.stringifyAny->Belt.Option.getWithDefault("")->LogicUtils.safeParse - let item2 = i2->Js.Json.stringifyAny->Belt.Option.getWithDefault("")->LogicUtils.safeParse - // flatten items and get data - - let val1 = item1->Js.Json.decodeObject->Belt.Option.flatMap(dict => dict->Dict.get(key)) - - let val2 = item2->Js.Json.decodeObject->Belt.Option.flatMap(dict => dict->Dict.get(key)) - - let value1 = getValue(val1) - let value2 = getValue(val2) - if value1 === value2 { - 0 - } else if value1 > value2 { - sortOrder === DEC ? 1 : -1 - } else if sortOrder === DEC { - -1 - } else { - 1 - } - }) - originalData - } - sortedArrayByOrder } + let sortedArrayByOrder = { + let _ = originalData->Js.Array2.sortInPlaceWith((i1, i2) => { + let item1 = i1->Js.Json.stringifyAny->Option.getWithDefault("")->LogicUtils.safeParse + let item2 = i2->Js.Json.stringifyAny->Option.getWithDefault("")->LogicUtils.safeParse + // flatten items and get data + + let val1 = item1->Js.Json.decodeObject->Option.flatMap(dict => dict->Dict.get(key)) + + let val2 = item2->Js.Json.decodeObject->Option.flatMap(dict => dict->Dict.get(key)) + + let value1 = getValue(val1) + let value2 = getValue(val2) + if value1 === value2 { + 0 + } else if value1 > value2 { + sortOrder === DEC ? 1 : -1 + } else if sortOrder === DEC { + -1 + } else { + 1 + } + }) + originalData + } + sortedArrayByOrder } @react.component @@ -886,8 +884,6 @@ let make = ( } }, (actualData, columToConsider, totalResults, visibleColumns, columnFilter)) - let sortArray = useSortArray() - let actualData = if tableLocalFilter { filteredData(actualData, columnFilter, visibleColumns, entity, dateFormatConvertor) } else { diff --git a/src/components/TableUtils.res b/src/components/TableUtils.res index a1011fd45..c9a3521b4 100644 --- a/src/components/TableUtils.res +++ b/src/components/TableUtils.res @@ -477,15 +477,6 @@ module LinkCell = { } module DateCell = { - let getFormattedDate = (dateStr, dateFormat) => { - try { - let isoStringToCustomTimeZone = TimeZoneHook.useIsoStringToCustomTimeZoneInFloat() - let customTimeZone = isoStringToCustomTimeZone(dateStr) - TimeZoneHook.formattedDateTimeFloat(customTimeZone, dateFormat) - } catch { - | _ => `${dateStr} - unable to parse` - } - } @react.component let make = ( ~timestamp, @@ -499,6 +490,16 @@ module DateCell = { let dateFormat = React.useContext(DateFormatProvider.dateFormatContext) let dateFormat = isMobileView ? "DD MMM HH:mm" : dateFormat + let isoStringToCustomTimeZone = TimeZoneHook.useIsoStringToCustomTimeZoneInFloat() + let getFormattedDate = dateStr => { + try { + let customTimeZone = isoStringToCustomTimeZone(dateStr) + TimeZoneHook.formattedDateTimeFloat(customTimeZone, dateFormat) + } catch { + | _ => `${dateStr} - unable to parse` + } + } + let fontType = switch textStyle { | Some(font) => font | None => "font-semibold" @@ -514,11 +515,11 @@ module DateCell = { ? fontType : `dark:text-jp-gray-text_darktheme dark:text-opacity-75 ${textAlignClass} ${fontStyle}` - getFormattedDate(dateFormat))]> + getFormattedDate)]>
{hideTime - ? React.string(timestamp->getFormattedDate(dateFormat)->String.slice(~start=0, ~end=12)) - : {React.string(`${timestamp->getFormattedDate(dateFormat)} ${selectedTimeZoneAlias}`)}} + ? React.string(timestamp->getFormattedDate->String.slice(~start=0, ~end=12)) + : {React.string(`${timestamp->getFormattedDate} ${selectedTimeZoneAlias}`)}}
} diff --git a/src/components/TableUtils.resi b/src/components/TableUtils.resi index f5ed0a51f..4a2e77ec4 100644 --- a/src/components/TableUtils.resi +++ b/src/components/TableUtils.resi @@ -143,7 +143,7 @@ module LinkCell: { let make: (~data: Js.String.t, ~trimLength: int=?) => React.element } module DateCell: { - let getFormattedDate: (string, string) => string + // let getFormattedDate: (string, string) => string @react.component let make: ( ~timestamp: string, diff --git a/src/components/form/FileUpload.res b/src/components/form/FileUpload.res index 608b5bb6f..582c25f16 100644 --- a/src/components/form/FileUpload.res +++ b/src/components/form/FileUpload.res @@ -16,9 +16,10 @@ let make = ( ~validateUploadedFile=?, ) => { let (key, setKey) = React.useState(_ => 1) + let formInput = ReactFinalForm.useField(input.name ++ "_filename").input let fileNameInput = switch fileNameInput { | Some(filenameInput) => filenameInput - | None => ReactFinalForm.useField(input.name ++ "_filename").input + | None => formInput } let defaultFileName = fileNameInput.value->LogicUtils.getStringFromJson("") diff --git a/src/components/form/TextInput.res b/src/components/form/TextInput.res index b155fec85..236ba3bdb 100644 --- a/src/components/form/TextInput.res +++ b/src/components/form/TextInput.res @@ -39,11 +39,11 @@ let make = ( ~removeValidationCheck=false, ) => { let showPopUp = PopUpState.useShowPopUp() + let {meta} = ReactFinalForm.useField(input.name) let isInValid = if removeValidationCheck { false } else { try { - let {meta} = ReactFinalForm.useField(input.name) if !meta.valid && meta.touched { // if there is a submission error and field value hasn't been updated after last submit, field is invalid // or if there is any field error, field is invalid diff --git a/src/entities/analytics/AnalyticsUtils.res b/src/entities/analytics/AnalyticsUtils.res index 778516a1b..8a2f190e9 100644 --- a/src/entities/analytics/AnalyticsUtils.res +++ b/src/entities/analytics/AnalyticsUtils.res @@ -622,8 +622,6 @@ let filterBody = (filterBodyEntity: filterBodyEntity) => { ~source=filterBodyEntity.source, (), ) - ->Js.Json.object_ - ->Js.Json.stringify } let deltaDate = (~fromTime: string, ~_toTime: string, ~typeTime: string) => { diff --git a/src/hooks/AnalyticsHooks.res b/src/hooks/AnalyticsHooks.res index 999d13c22..e0e633ad9 100644 --- a/src/hooks/AnalyticsHooks.res +++ b/src/hooks/AnalyticsHooks.res @@ -19,77 +19,6 @@ let handleError = (json: Js.Json.t) => { } } -let useGetFiltersData = () => { - let (filterData, setFilterData) = React.useState(_ => None) - let {filterValueJson} = React.useContext(FilterContext.filterContext) - let startTimeVal = filterValueJson->getString("startTime", "") - let endTimeVal = filterValueJson->getString("endTime", "") - let addLogsAroundFetch = EulerAnalyticsLogUtils.useAddLogsAroundFetch() - - let fetchApi = AuthHooks.useApiFetcher() - - (uri, method, filterBody) => { - open Promise - - React.useEffect3(() => { - setFilterData(_ => None) - - if startTimeVal !== "" && endTimeVal !== "" { - fetchApi( - uri, - ~method_=method, - ~bodyStr=filterBody, - ~headers=[("QueryType", "Filter")]->Dict.fromArray, - (), - ) - ->addLogsAroundFetch(~logTitle="Filter Data Api") - ->thenResolve(json => setFilterData(_ => json->Some)) - ->catch(_err => resolve()) - ->ignore - } - None - }, (startTimeVal, endTimeVal, filterBody)) - filterData - } -} - -let useGetLiveFiltersData = () => { - let (filterData, setFilterData) = React.useState(_ => None) - - let addLogsAroundFetch = EulerAnalyticsLogUtils.useAddLogsAroundFetch() - - let fetchApi = AuthHooks.useApiFetcher() - - (uri, method, filterBody) => { - open Promise - - React.useEffect1(() => { - let endTimeVal = Js.Date.make()->Js.Date.toISOString - let endTimeInMs = Js.Date.make()->Js.Date.getTime - let ttlTime = 1.0 *. 3600.0 *. 1000.0 - let startTimeInMs = endTimeInMs -. ttlTime - let startTimeVal = Js.Date.fromFloat(startTimeInMs)->Js.Date.toISOString - setFilterData(_ => None) - - if startTimeVal !== "" && endTimeVal !== "" { - fetchApi( - uri, - ~method_=method, - ~bodyStr=filterBody, - ~headers=[("QueryType", "Filter")]->Dict.fromArray, - (), - ) - ->addLogsAroundFetch(~logTitle="Filter Data Api") - ->thenResolve(json => setFilterData(_ => json->Some)) - ->catch(_err => resolve()) - ->ignore - } - None - }, [filterBody]) - filterData - } -} - let useAnalyticsFetch = () => { let fetchApi = AuthHooks.useApiFetcher() let fetchChartData = (~url, ~body, ~setState, ~setDataLoading) => { diff --git a/src/libraries/Recoil.res b/src/libraries/Recoil.res index 495925db1..4d75ec19b 100644 --- a/src/libraries/Recoil.res +++ b/src/libraries/Recoil.res @@ -35,7 +35,7 @@ module DebugObserver = { } `) - let make: unit => React.element = () => { + let useMake: unit => React.element = () => { let snapshot = useRecoilSnapshot() React.useEffect1(() => { diff --git a/src/libraries/SankeyHighcharts.res b/src/libraries/SankeyHighcharts.res index 9be669d22..257183eaa 100644 --- a/src/libraries/SankeyHighcharts.res +++ b/src/libraries/SankeyHighcharts.res @@ -179,7 +179,7 @@ type highchartsSankey @module("highcharts") external highchartsModule: highcharts = "default" @module("highcharts/modules/sankey") external highchartsSankey: highcharts => unit = "default" -let init = (data: array<(string, string, int, int, int)>, nodes) => { +let useInit = (data: array<(string, string, int, int, int)>, nodes) => { highchartsSankey(highchartsModule) let theme = ThemeProvider.useTheme() let options: Js.Json.t = { diff --git a/src/screens/HyperSwitch/Analytics/Analytics.res b/src/screens/HyperSwitch/Analytics/Analytics.res index a96213e0d..a407fad53 100644 --- a/src/screens/HyperSwitch/Analytics/Analytics.res +++ b/src/screens/HyperSwitch/Analytics/Analytics.res @@ -530,7 +530,6 @@ let make = ( } let filterValueDict = filterValueJson - let getFilterData = AnalyticsHooks.useGetFiltersData() let (activeTav, setActiveTab) = React.useState(_ => filterValueDict->getStrArrayFromDict( @@ -601,8 +600,29 @@ let make = ( AnalyticsUtils.filterBody(filterBodyEntity) }, (startTimeVal, endTimeVal, filteredTabKeys->Array.joinWith(","))) - let filterDataOrig = getFilterData(filterUri, Fetch.Post, filterBody) - let filterData = filterDataOrig->Belt.Option.getWithDefault(Js.Json.object_(Dict.make())) + open APIUtils + open Promise + let (filterDataJson, setFilterDataJson) = React.useState(_ => None) + let updateDetails = useUpdateMethod() + let {filterValueJson} = FilterContext.filterContext->React.useContext + let startTimeVal = filterValueJson->getString("startTime", "") + let endTimeVal = filterValueJson->getString("endTime", "") + open HSwitchRemoteFilter + React.useEffect3(() => { + setFilterDataJson(_ => None) + if startTimeVal->isStringNonEmpty && endTimeVal->isStringNonEmpty { + try { + updateDetails(filterUri, filterBody->Js.Json.object_, Post) + ->thenResolve(json => setFilterDataJson(_ => json->Some)) + ->catch(_ => resolve()) + ->ignore + } catch { + | _ => () + } + } + None + }, (startTimeVal, endTimeVal, filterBody->Js.Json.object_->Js.Json.stringify)) + let filterData = filterDataJson->Belt.Option.getWithDefault(Dict.make()->Js.Json.object_) let activeTab = React.useMemo1(() => { Some( @@ -624,7 +644,7 @@ let make = ( ->Array.filter(item => tabKeys->Array.find(key => key == item)->Belt.Option.isSome) ->Array.length < 1 - let topFilterUi = switch filterDataOrig { + let topFilterUi = switch filterDataJson { | Some(filterData) => { let filterData = switch analyticsType { | USER_JOURNEY => { diff --git a/src/screens/HyperSwitch/Analytics/SystemMetrics/SystemMetricsAnalytics.res b/src/screens/HyperSwitch/Analytics/SystemMetrics/SystemMetricsAnalytics.res index a9731008a..38ae37960 100644 --- a/src/screens/HyperSwitch/Analytics/SystemMetrics/SystemMetricsAnalytics.res +++ b/src/screens/HyperSwitch/Analytics/SystemMetrics/SystemMetricsAnalytics.res @@ -228,7 +228,6 @@ module SystemMetricsAnalytics = { ~filterUri, ~moduleName: string, ) => { - let getFilterData = AnalyticsHooks.useGetFiltersData() let {filterValueJson} = React.useContext(FilterContext.filterContext) let getModuleFilters = filterValueJson let startTimeVal = getModuleFilters->getString(startTimeFilterKey, "") @@ -264,8 +263,29 @@ module SystemMetricsAnalytics = { AnalyticsUtils.filterBody(filterBodyEntity) }, (startTimeVal, endTimeVal, filteredTabKeys->Array.joinWith(","))) - let filterDataOrig = getFilterData(filterUri, Fetch.Post, filterBody) - let filterData = filterDataOrig->Belt.Option.getWithDefault(Js.Json.object_(Dict.make())) + open APIUtils + open Promise + let (filterDataJson, setFilterDataJson) = React.useState(_ => None) + let updateDetails = useUpdateMethod() + let {filterValueJson} = FilterContext.filterContext->React.useContext + let startTimeVal = filterValueJson->getString("startTime", "") + let endTimeVal = filterValueJson->getString("endTime", "") + open HSwitchRemoteFilter + React.useEffect3(() => { + setFilterDataJson(_ => None) + if startTimeVal->isStringNonEmpty && endTimeVal->isStringNonEmpty { + try { + updateDetails(filterUri, filterBody->Js.Json.object_, Post) + ->thenResolve(json => setFilterDataJson(_ => json->Some)) + ->catch(_ => resolve()) + ->ignore + } catch { + | _ => () + } + } + None + }, (startTimeVal, endTimeVal, filterBody->Js.Json.object_->Js.Json.stringify)) + let filterData = filterDataJson->Belt.Option.getWithDefault(Dict.make()->Js.Json.object_) Dict.toArray->Array.length > 0}> {switch chartEntity1 { diff --git a/src/screens/HyperSwitch/Connectors/ConnectorPreview.res b/src/screens/HyperSwitch/Connectors/ConnectorPreview.res index d99cb80c5..10c0ad00a 100644 --- a/src/screens/HyperSwitch/Connectors/ConnectorPreview.res +++ b/src/screens/HyperSwitch/Connectors/ConnectorPreview.res @@ -235,11 +235,11 @@ let make = ( let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success) let connectorInfo = connectorInfo->LogicUtils.getDictFromJsonObject->ConnectorTableUtils.getProcessorPayloadType + let connectorCount = ListHooks.useListCount(~entityName=CONNECTOR) let isFeedbackModalToBeOpen = featureFlagDetails.feedback && !isUpdateFlow && - ListHooks.useListCount(~entityName=CONNECTOR) <= - HSwitchUtils.feedbackModalOpenCountForConnectors + connectorCount <= HSwitchUtils.feedbackModalOpenCountForConnectors let redirectPath = switch url.path { | list{"payoutconnectors", _} => "/payoutconnectors" | _ => "/connectors" diff --git a/src/screens/HyperSwitch/HSwitchRemoteFilter.res b/src/screens/HyperSwitch/HSwitchRemoteFilter.res index e457ac1b8..f6ba1f6f7 100644 --- a/src/screens/HyperSwitch/HSwitchRemoteFilter.res +++ b/src/screens/HyperSwitch/HSwitchRemoteFilter.res @@ -107,35 +107,6 @@ let useSetInitialFilters = (~updateExistingKeys, ~startTimeFilterKey, ~endTimeFi } } -let useGetFiltersData = () => { - open APIUtils - open Promise - open LogicUtils - let (filterData, setFilterData) = React.useState(_ => None) - let updateDetails = useUpdateMethod() - let {filterValueJson} = FilterContext.filterContext->React.useContext - let startTimeVal = filterValueJson->getString("start_time", "") - let endTimeVal = filterValueJson->getString("end_time", "") - - (url, body) => { - React.useEffect3(() => { - setFilterData(_ => None) - if startTimeVal->isStringNonEmpty && endTimeVal->isStringNonEmpty { - try { - updateDetails(url, body->Js.Json.object_, Post) - ->thenResolve(json => setFilterData(_ => json->Some)) - ->catch(_ => resolve()) - ->ignore - } catch { - | _ => () - } - } - None - }, (startTimeVal, endTimeVal, body->Js.Json.object_->Js.Json.stringify)) - filterData - } -} - module SearchBarFilter = { @react.component let make = (~placeholder, ~setSearchVal, ~searchVal) => { @@ -208,7 +179,6 @@ module RemoteTableFilters = { FilterContext.filterContext->React.useContext let defaultFilters = {""->Js.Json.string} - let getFilterData = useGetFiltersData() let setInitialFilters = useSetInitialFilters( ~updateExistingKeys, ~startTimeFilterKey, @@ -232,7 +202,28 @@ module RemoteTableFilters = { ]->Dict.fromArray }, (startTimeVal, endTimeVal, filterValue)) - let filterDataJson = filterUrl->getFilterData(filterBody) + open APIUtils + open Promise + let (filterDataJson, setFilterDataJson) = React.useState(_ => None) + let updateDetails = useUpdateMethod() + let {filterValueJson} = FilterContext.filterContext->React.useContext + let startTimeVal = filterValueJson->getString("start_time", "") + let endTimeVal = filterValueJson->getString("end_time", "") + + React.useEffect3(() => { + setFilterDataJson(_ => None) + if startTimeVal->isStringNonEmpty && endTimeVal->isStringNonEmpty { + try { + updateDetails(filterUrl, filterBody->Js.Json.object_, Post) + ->thenResolve(json => setFilterDataJson(_ => json->Some)) + ->catch(_ => resolve()) + ->ignore + } catch { + | _ => () + } + } + None + }, (startTimeVal, endTimeVal, filterBody->Js.Json.object_->Js.Json.stringify)) let filterData = filterDataJson->Belt.Option.getWithDefault(Dict.make()->Js.Json.object_) React.useEffect1(() => { diff --git a/src/screens/HyperSwitch/Order/OrderHooks.res b/src/screens/HyperSwitch/Order/OrderHooks.res index 0148c0fb1..022be2960 100644 --- a/src/screens/HyperSwitch/Order/OrderHooks.res +++ b/src/screens/HyperSwitch/Order/OrderHooks.res @@ -1,6 +1,6 @@ open APIUtils -let getOrdersData = (orderId, refetchCounter, setScreenState) => { +let useGetOrdersData = (orderId, refetchCounter, setScreenState) => { let (orderData, setOrderData) = React.useState(() => Js.Json.null) let fetchDetails = useGetMethod() let accountUrl = getURL( diff --git a/src/screens/HyperSwitch/Order/ShowOrder.res b/src/screens/HyperSwitch/Order/ShowOrder.res index f35f4a84a..0e492bd89 100644 --- a/src/screens/HyperSwitch/Order/ShowOrder.res +++ b/src/screens/HyperSwitch/Order/ShowOrder.res @@ -626,7 +626,7 @@ let make = (~id) => { let frmDetailsRef = React.useRef(Js.Nullable.null) - let orderData = OrderHooks.getOrdersData(id, refetchCounter, setScreenState) + let orderData = OrderHooks.useGetOrdersData(id, refetchCounter, setScreenState) let order = OrderEntity.itemToObjMapper(orderData->getDictFromJsonObject) let refundData = diff --git a/src/screens/HyperSwitch/PostLoginScreen/PostLoginScreen.res b/src/screens/HyperSwitch/PostLoginScreen/PostLoginScreen.res index 935f615bc..bfd877eb0 100644 --- a/src/screens/HyperSwitch/PostLoginScreen/PostLoginScreen.res +++ b/src/screens/HyperSwitch/PostLoginScreen/PostLoginScreen.res @@ -3,7 +3,8 @@ type cardFlowDirection = LEFT | RIGHT module SurveyComponent = { @react.component let make = (~currentStep, ~setCurrentStep, ~currentQuestionDict, ~setCarouselDirection) => { - let currentQuestionValue = currentQuestionDict.key->getStringValueFromForm + let currentQuestionValue = + ReactFinalForm.useField(currentQuestionDict.key).input.value->LogicUtils.getStringFromJson("") let isNextButtonEnabled = currentQuestionValue->String.length > 0
diff --git a/src/screens/HyperSwitch/PostLoginScreen/PostLoginUtils.res b/src/screens/HyperSwitch/PostLoginScreen/PostLoginUtils.res index 67c384050..da7e82f8d 100644 --- a/src/screens/HyperSwitch/PostLoginScreen/PostLoginUtils.res +++ b/src/screens/HyperSwitch/PostLoginScreen/PostLoginUtils.res @@ -41,9 +41,6 @@ let requirementsQuestion: questionsType = { } let questionForSurvey = [userRoleQuestions, paymentProcessorQuestions, requirementsQuestion] -let getStringValueFromForm = valueToExtract => - ReactFinalForm.useField(valueToExtract).input.value->LogicUtils.getStringFromJson("") - let getBrowswerDetailsPayload = () => { open CountryUtils let browserDetails = HSwitchUtils.getBrowswerDetails() diff --git a/src/screens/HyperSwitch/Refunds/RefundHook.res b/src/screens/HyperSwitch/Refunds/RefundHook.res index 101d62bab..7a65c185c 100644 --- a/src/screens/HyperSwitch/Refunds/RefundHook.res +++ b/src/screens/HyperSwitch/Refunds/RefundHook.res @@ -1,6 +1,6 @@ open APIUtils -let getRefundData = (refundId, setScreenState) => { +let useGetRefundData = (refundId, setScreenState) => { let (refundData, setRefundData) = React.useState(() => Js.Json.null) let fetchDetails = useGetMethod() let accountUrl = getURL(~entityName=REFUNDS, ~methodType=Get, ~id=Some(refundId), ()) diff --git a/src/screens/HyperSwitch/Refunds/ShowRefund.res b/src/screens/HyperSwitch/Refunds/ShowRefund.res index 30dc07297..2c9569f54 100644 --- a/src/screens/HyperSwitch/Refunds/ShowRefund.res +++ b/src/screens/HyperSwitch/Refunds/ShowRefund.res @@ -81,12 +81,12 @@ let make = (~id) => { ) let (offset, setOffset) = React.useState(_ => 0) let (orderData, setOrdersData) = React.useState(_ => []) - let refundData = RefundHook.getRefundData(id, setScreenStateForRefund) + let refundData = RefundHook.useGetRefundData(id, setScreenStateForRefund) let paymentId = refundData->LogicUtils.getDictFromJsonObject->LogicUtils.getString("payment_id", "") - let orderDataForPaymentId = OrderHooks.getOrdersData(paymentId, 0, setScreenStateForOrder) + let orderDataForPaymentId = OrderHooks.useGetOrdersData(paymentId, 0, setScreenStateForOrder) React.useEffect1(() => { let jsonArray = [orderDataForPaymentId] diff --git a/src/screens/HyperSwitch/SelfServe/HSwitchSandboxOnboarding/UserOnboardingUIUtils.res b/src/screens/HyperSwitch/SelfServe/HSwitchSandboxOnboarding/UserOnboardingUIUtils.res index 457655a7b..0bfebfccb 100644 --- a/src/screens/HyperSwitch/SelfServe/HSwitchSandboxOnboarding/UserOnboardingUIUtils.res +++ b/src/screens/HyperSwitch/SelfServe/HSwitchSandboxOnboarding/UserOnboardingUIUtils.res @@ -576,10 +576,10 @@ let getTabsForIntegration = ( ) => { open Tabs let defaultEditorStyle = "flex flex-col gap-8 bg-white flex flex-col px-6 py-4 border !shadow-hyperswitch_box_shadow rounded-md" - let updateDetails = APIUtils.useUpdateMethod(~showErrorToast=false, ()) - let {integrationDetails, setIntegrationDetails, dashboardPageState} = React.useContext( - GlobalProvider.defaultContext, - ) + // let updateDetails = APIUtils.useUpdateMethod(~showErrorToast=false, ()) + // let {integrationDetails, setIntegrationDetails, dashboardPageState} = React.useContext( + // GlobalProvider.defaultContext, + // ) switch currentRoute { | MigrateFromStripe => [ { @@ -862,63 +862,63 @@ let getTabsForIntegration = (
, }, - { - title: "3. Manage", - renderContent: () => { - let skipAndContinue = async () => { - try { - let url = APIUtils.getURL(~entityName=INTEGRATION_DETAILS, ~methodType=Post, ()) - let metaDataDict = - Dict.fromArray([("is_skip", true->Js.Json.boolean)])->Js.Json.object_ - let body = HSwitchUtils.constructOnboardingBody( - ~dashboardPageState, - ~integrationDetails, - ~is_done=false, - ~metadata=metaDataDict, - (), - ) - let _ = await updateDetails(url, body, Post) - setIntegrationDetails(_ => body->ProviderHelper.getIntegrationDetails) - } catch { - | _ => () - } - } - let skipOnboarding = async path => { - let _ = await skipAndContinue() - Window._open(path) - } -
- -
skipOnboarding(`/connectors`)->ignore} className="cursor-pointer"> -
- -
-
-
- -
skipOnboarding(`/routing`)->ignore} className="cursor-pointer"> -
- -
-
-
- -
skipOnboarding(`/payments`)->ignore} className="cursor-pointer"> -
- -
-
-
- // -
- }, - }, + // { + // title: "3. Manage", + // renderContent: () => { + // let skipAndContinue = async () => { + // try { + // let url = APIUtils.getURL(~entityName=INTEGRATION_DETAILS, ~methodType=Post, ()) + // let metaDataDict = + // Dict.fromArray([("is_skip", true->Js.Json.boolean)])->Js.Json.object_ + // let body = HSwitchUtils.constructOnboardingBody( + // ~dashboardPageState, + // ~integrationDetails, + // ~is_done=false, + // ~metadata=metaDataDict, + // (), + // ) + // let _ = await updateDetails(url, body, Post) + // setIntegrationDetails(_ => body->ProviderHelper.getIntegrationDetails) + // } catch { + // | _ => () + // } + // } + // let skipOnboarding = async path => { + // let _ = await skipAndContinue() + // Window._open(path) + // } + //
+ // + //
skipOnboarding(`/connectors`)->ignore} className="cursor-pointer"> + //
+ // + //
+ //
+ //
+ // + //
skipOnboarding(`/routing`)->ignore} className="cursor-pointer"> + //
+ // + //
+ //
+ //
+ // + //
skipOnboarding(`/payments`)->ignore} className="cursor-pointer"> + //
+ // + //
+ //
+ //
+ // // + //
+ // }, + // }, ] | _ => [] } diff --git a/src/screens/HyperSwitch/UserManagement/InviteUsers.res b/src/screens/HyperSwitch/UserManagement/InviteUsers.res index 04a50e41e..9823d77ac 100644 --- a/src/screens/HyperSwitch/UserManagement/InviteUsers.res +++ b/src/screens/HyperSwitch/UserManagement/InviteUsers.res @@ -6,12 +6,12 @@ module InviteEmailForm = { open APIUtils let fetchDetails = useGetMethod() let (roleListData, setRoleListData) = React.useState(_ => []) - let getArrayFromForm = key => ReactFinalForm.useField(key).input.value->getArrayFromJson([]) - let emailList = `emailList`->getArrayFromForm->Array.joinWith(",") + let emailList = + ReactFinalForm.useField("emailList").input.value->getArrayFromJson([])->Array.joinWith(",") let role = - `roleType` - ->getArrayFromForm + ReactFinalForm.useField(`roleType`).input.value + ->getArrayFromJson([]) ->LogicUtils.getValueFromArray(0, ""->Js.Json.string) ->getStringFromJson("") From 7bc7226cf2ee0c70b8dc49c73de91020c2f9b8e7 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja <1805317@kiit.ac.in> Date: Mon, 8 Jan 2024 13:32:19 +0530 Subject: [PATCH 02/14] fix: add merchant fix (#184) --- src/screens/HyperSwitch/SwitchMerchant/SwitchMerchant.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/HyperSwitch/SwitchMerchant/SwitchMerchant.res b/src/screens/HyperSwitch/SwitchMerchant/SwitchMerchant.res index 61291bf3f..5a5bd3c5b 100644 --- a/src/screens/HyperSwitch/SwitchMerchant/SwitchMerchant.res +++ b/src/screens/HyperSwitch/SwitchMerchant/SwitchMerchant.res @@ -96,7 +96,7 @@ module AddNewMerchantButton = { {props =>