diff --git a/packages/api/package-lock.json b/packages/api/package-lock.json index 861e486164..033513f82b 100644 --- a/packages/api/package-lock.json +++ b/packages/api/package-lock.json @@ -1,6 +1,6 @@ { "name": "litefarm-api", - "version": "3.6.1", + "version": "3.6.2", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/packages/api/package.json b/packages/api/package.json index 8f1c99626e..8541373e02 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "litefarm-api", - "version": "3.6.1", + "version": "3.6.2", "description": "LiteFarm API server", "main": "./api/src/server.js", "type": "module", diff --git a/packages/api/src/server.js b/packages/api/src/server.js index 4781ecf576..691bbf0308 100644 --- a/packages/api/src/server.js +++ b/packages/api/src/server.js @@ -39,7 +39,7 @@ if (process.env.SENTRY_DSN && environment !== 'development') { // Automatically instrument Node.js libraries and frameworks ...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(), ], - release: '3.6.1', + release: '3.6.2', // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 0cd3cb3120..32a97e6a03 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -1,6 +1,6 @@ { "name": "litefarm-webapp", - "version": "3.6.1", + "version": "3.6.2", "description": "LiteFarm Web application", "type": "module", "scripts": { diff --git a/packages/webapp/src/components/Finances/AddTransactionButton/index.jsx b/packages/webapp/src/components/Finances/AddTransactionButton/index.jsx index 78d406a2f0..135adaec86 100644 --- a/packages/webapp/src/components/Finances/AddTransactionButton/index.jsx +++ b/packages/webapp/src/components/Finances/AddTransactionButton/index.jsx @@ -22,19 +22,25 @@ import useIsAboveBreakpoint from '../../../hooks/useIsAboveBreakpoint'; import DropdownButton from '../../Form/DropDownButton'; import FloatingButtonMenu from '../../Menu/FloatingButtonMenu'; import FloatingMenu from '../../Menu/FloatingButtonMenu/FloatingMenu'; +import { + ADD_EXPENSE_URL, + ADD_REVENUE_URL, + EXPENSE_CATEGORIES_URL, + REVENUE_TYPES_URL, +} from '../../../util/siteMapConstants'; const Menu = forwardRef((props, ref) => { const { t } = useTranslation(); const dispatch = useDispatch(); const handleAddRevenueClick = () => { - dispatch(setPersistedPaths(['/revenue_types', '/add_sale'])); - history.push('/revenue_types'); + dispatch(setPersistedPaths([REVENUE_TYPES_URL, ADD_REVENUE_URL])); + history.push(REVENUE_TYPES_URL); }; const handleAddExpenseClick = () => { - dispatch(setPersistedPaths(['/expense_categories', '/add_expense'])); - history.push('/expense_categories'); + dispatch(setPersistedPaths([EXPENSE_CATEGORIES_URL, ADD_EXPENSE_URL])); + history.push(EXPENSE_CATEGORIES_URL); }; return ( diff --git a/packages/webapp/src/components/Finances/FinancesCarrousel/index.jsx b/packages/webapp/src/components/Finances/FinancesCarrousel/index.jsx index 0bc6385a8d..9e7146b1e7 100644 --- a/packages/webapp/src/components/Finances/FinancesCarrousel/index.jsx +++ b/packages/webapp/src/components/Finances/FinancesCarrousel/index.jsx @@ -29,6 +29,11 @@ import styles from './styles.module.scss'; import { Semibold, Text } from '../../Typography'; import clsx from 'clsx'; import TextButton from '../../Form/Button/TextButton'; +import { + ESTIMATED_REVENUE_URL, + LABOUR_URL, + OTHER_EXPENSE_URL, +} from '../../../util/siteMapConstants'; ChartJS.register(ArcElement, Tooltip); @@ -143,7 +148,7 @@ const FinancesCarrousel = ({
history.push('/labour')} + onClick={() => history.push(LABOUR_URL)} > @@ -159,7 +164,7 @@ const FinancesCarrousel = ({ history.push('/other_expense')} + onClick={() => history.push(OTHER_EXPENSE_URL)} > {t('SALE.FINANCES.TOTAL_OTHER')} @@ -194,7 +199,7 @@ const FinancesCarrousel = ({ /> history.push('/estimated_revenue')} + onClick={() => history.push(ESTIMATED_REVENUE_URL)} > diff --git a/packages/webapp/src/components/Finances/Transaction/ExpandedContent/CropSaleTable.jsx b/packages/webapp/src/components/Finances/Transaction/ExpandedContent/CropSaleTable.jsx index 4e9a07f9a6..cde42decfa 100644 --- a/packages/webapp/src/components/Finances/Transaction/ExpandedContent/CropSaleTable.jsx +++ b/packages/webapp/src/components/Finances/Transaction/ExpandedContent/CropSaleTable.jsx @@ -17,6 +17,7 @@ import { useTranslation } from 'react-i18next'; import Table from '../../../Table/v2'; import history from '../../../../history'; import styles from './styles.module.scss'; +import { createRevenueDetailsUrl } from '../../../../util/siteMapConstants'; const getColumns = (t, mobileView, totalAmount, quantityTotal, currencySymbol) => [ { @@ -91,7 +92,7 @@ export default function CropSaleTable({ data, currencySymbol, mobileView }) { ? () => : null } - onClickMore={() => history.push(`/revenue/${relatedId}`)} + onClickMore={() => history.push(createRevenueDetailsUrl(relatedId))} /> ); } diff --git a/packages/webapp/src/components/Finances/Transaction/ExpandedContent/index.jsx b/packages/webapp/src/components/Finances/Transaction/ExpandedContent/index.jsx index 5b4f2c808c..1e32da7cdf 100644 --- a/packages/webapp/src/components/Finances/Transaction/ExpandedContent/index.jsx +++ b/packages/webapp/src/components/Finances/Transaction/ExpandedContent/index.jsx @@ -17,6 +17,11 @@ import { useTranslation } from 'react-i18next'; import { BsChevronRight } from 'react-icons/bs'; import { transactionTypeEnum } from '../../../../containers/Finances/useTransactions'; import history from '../../../../history'; +import { + createExpenseDetailsUrl, + createRevenueDetailsUrl, + LABOUR_URL, +} from '../../../../util/siteMapConstants'; import TextButton from '../../../Form/Button/TextButton'; import CropSaleTable from './CropSaleTable'; import GeneralTransactionTable from './GeneralTransactionTable'; @@ -32,10 +37,10 @@ const components = { const getDetailPageLink = ({ transactionType, relatedId }) => { return { - LABOUR_EXPENSE: '/labour', - EXPENSE: `/expense/${relatedId}`, - REVENUE: `/revenue/${relatedId}`, - CROP_REVENUE: `/revenue/${relatedId}`, + LABOUR_EXPENSE: LABOUR_URL, + EXPENSE: createExpenseDetailsUrl(relatedId), + REVENUE: createRevenueDetailsUrl(relatedId), + CROP_REVENUE: createRevenueDetailsUrl(relatedId), }[transactionType]; }; diff --git a/packages/webapp/src/containers/Finances/ActualRevenue/index.jsx b/packages/webapp/src/containers/Finances/ActualRevenue/index.jsx index d9c02d430e..e39cbf31ee 100644 --- a/packages/webapp/src/containers/Finances/ActualRevenue/index.jsx +++ b/packages/webapp/src/containers/Finances/ActualRevenue/index.jsx @@ -21,14 +21,15 @@ import { mapSalesToRevenueItems, } from '../util'; import { getCropVarieties } from '../../saga'; +import { ADD_REVENUE_URL, REVENUE_TYPES_URL } from '../../../util/siteMapConstants'; export default function ActualRevenue({ history, match }) { const { t } = useTranslation(); const dispatch = useDispatch(); const onGoBack = () => history.back(); const onAddRevenue = () => { - dispatch(setPersistedPaths(['/revenue_types', '/add_sale'])); - history.push('/revenue_types'); + dispatch(setPersistedPaths([REVENUE_TYPES_URL, ADD_REVENUE_URL])); + history.push(REVENUE_TYPES_URL); }; // TODO: refactor sale data after finance reducer is remade const sales = useSelector(salesSelector); diff --git a/packages/webapp/src/containers/Finances/ActualRevenueItem/index.jsx b/packages/webapp/src/containers/Finances/ActualRevenueItem/index.jsx index 4c33b7140a..b1259264e4 100644 --- a/packages/webapp/src/containers/Finances/ActualRevenueItem/index.jsx +++ b/packages/webapp/src/containers/Finances/ActualRevenueItem/index.jsx @@ -4,6 +4,7 @@ import { useDispatch } from 'react-redux'; import FinanceGroup from '../../../components/Finances/FinanceGroup'; import { getManagementPlanCardDate } from '../../../util/moment'; import { setSelectedSale } from '../actions'; +import { createRevenueDetailsUrl } from '../../../util/siteMapConstants'; const ActualRevenueItem = ({ revenueItem, history, ...props }) => { const { sale_id, sale_date, customer_name } = revenueItem.sale; @@ -12,7 +13,7 @@ const ActualRevenueItem = ({ revenueItem, history, ...props }) => { const onClickForward = () => { dispatch(setSelectedSale(revenueItem.sale)); - history.push(`/revenue/${sale_id}`); + history.push(createRevenueDetailsUrl(sale_id)); }; return ( diff --git a/packages/webapp/src/containers/Finances/AddSale/RevenueTypes/index.jsx b/packages/webapp/src/containers/Finances/AddSale/RevenueTypes/index.jsx index 7a0b0aac0a..57810abdcd 100644 --- a/packages/webapp/src/containers/Finances/AddSale/RevenueTypes/index.jsx +++ b/packages/webapp/src/containers/Finances/AddSale/RevenueTypes/index.jsx @@ -25,6 +25,7 @@ import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookF import ManageCustomRevenueTypesSpotlight from '../ManageCustomRevenueTypeSpotlight'; import useSortedRevenueTypes from './useSortedRevenueTypes'; import { getFinanceTypeSearchableStringFunc } from '../../util'; +import { ADD_REVENUE_URL, MANAGE_CUSTOM_REVENUES_URL } from '../../../../util/siteMapConstants'; export const icons = { CROP_SALE: , @@ -39,7 +40,7 @@ export default function RevenueTypes({ useHookFormPersist, history }) { const getOnTileClickFunc = (setValue) => { return (typeId) => { setValue('revenue_type_id', typeId); - history.push('/add_sale'); + history.push(ADD_REVENUE_URL); }; }; @@ -76,7 +77,7 @@ export default function RevenueTypes({ useHookFormPersist, history }) { types={revenueTypes} onGoBack={history.back} progressValue={33} - onGoToManageCustomType={() => history.push('/manage_custom_revenues')} + onGoToManageCustomType={() => history.push(MANAGE_CUSTOM_REVENUES_URL)} getFormatListItemDataFunc={getFormatListItemDataFunc} listItemType={listItemTypes.ICON_DESCRIPTION} useHookFormPersist={useHookFormPersist} diff --git a/packages/webapp/src/containers/Finances/CustomExpenseType/ReadOnlySimpleCustomExpense.jsx b/packages/webapp/src/containers/Finances/CustomExpenseType/ReadOnlySimpleCustomExpense.jsx index 89565ce987..ab122c755f 100644 --- a/packages/webapp/src/containers/Finances/CustomExpenseType/ReadOnlySimpleCustomExpense.jsx +++ b/packages/webapp/src/containers/Finances/CustomExpenseType/ReadOnlySimpleCustomExpense.jsx @@ -20,6 +20,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { retireCustomExpenseType } from '../saga'; import { expenseTypeByIdSelector } from '../selectors'; import { CUSTOM_EXPENSE_NAME } from './constants'; +import { createEditCustomExpenseURL } from '../../../util/siteMapConstants'; function ReadOnlyCustomExpense({ history, match }) { const expense_type_id = match.params.expense_type_id; @@ -40,7 +41,7 @@ function ReadOnlyCustomExpense({ history, match }) { }; const handleEdit = () => { - history.push(`/edit_custom_expense/${expense_type_id}`); + history.push(createEditCustomExpenseURL(expense_type_id)); }; const onRetire = () => { diff --git a/packages/webapp/src/containers/Finances/CustomRevenueType/ReadOnlyCustomRevenue.jsx b/packages/webapp/src/containers/Finances/CustomRevenueType/ReadOnlyCustomRevenue.jsx index df07d86680..46bba2eaa0 100644 --- a/packages/webapp/src/containers/Finances/CustomRevenueType/ReadOnlyCustomRevenue.jsx +++ b/packages/webapp/src/containers/Finances/CustomRevenueType/ReadOnlyCustomRevenue.jsx @@ -21,6 +21,7 @@ import { revenueTypeByIdSelector } from '../../revenueTypeSlice'; import { CUSTOM_REVENUE_NAME, CROP_GENERATED } from './constants'; import { HookFormPersistProvider } from '../../hooks/useHookFormPersist/HookFormPersistProvider'; import CustomRevenueRadios from './CustomRevenueRadios'; +import { createEditCustomRevenueUrl } from '../../../util/siteMapConstants'; function ReadOnlyCustomRevenue({ history, match }) { const { revenue_type_id } = match.params; @@ -41,7 +42,7 @@ function ReadOnlyCustomRevenue({ history, match }) { }; const handleEdit = () => { - history.push(`/edit_custom_revenue/${revenue_type_id}`); + history.push(createEditCustomRevenueUrl(revenue_type_id)); }; const onRetire = () => { diff --git a/packages/webapp/src/containers/Finances/EstimatedCropRevenue/index.jsx b/packages/webapp/src/containers/Finances/EstimatedCropRevenue/index.jsx index dd3546493d..1f08f18497 100644 --- a/packages/webapp/src/containers/Finances/EstimatedCropRevenue/index.jsx +++ b/packages/webapp/src/containers/Finances/EstimatedCropRevenue/index.jsx @@ -7,6 +7,7 @@ import { cropVarietySelector } from '../../cropVarietySlice'; import { useTranslation } from 'react-i18next'; import { getTasksMinMaxDate } from '../../Task/getTasksMinMaxDate'; import { taskEntitiesByManagementPlanIdSelector } from '../../taskSlice'; +import { createManagementPlanEstimatedRevenueURL } from '../../../util/siteMapConstants'; const EstimatedCropRevenue = ({ cropVarietyId, managementPlans, history, ...props }) => { const dispatch = useDispatch(); @@ -41,7 +42,7 @@ const EstimatedCropRevenue = ({ cropVarietyId, managementPlans, history, ...prop amount: plan.estimated_revenue || 0, isPlan: true, onClickForward: () => - history.push(`/finances/estimated_revenue/plan/${plan.management_plan_id}`), + history.push(createManagementPlanEstimatedRevenueURL(plan.management_plan_id)), }; })} isDropDown diff --git a/packages/webapp/src/containers/Finances/ExpenseDetail/index.jsx b/packages/webapp/src/containers/Finances/ExpenseDetail/index.jsx index a232fd9d0f..0087208d96 100644 --- a/packages/webapp/src/containers/Finances/ExpenseDetail/index.jsx +++ b/packages/webapp/src/containers/Finances/ExpenseDetail/index.jsx @@ -13,6 +13,7 @@ import PureExpenseDetail from '../../../components/Finances/PureExpenseDetail'; import { setPersistedPaths } from '../../hooks/useHookFormPersist/hookFormPersistSlice'; import useHookFormPersist from '../../hooks/useHookFormPersist'; import { updateExpense } from '../saga'; +import { createEditExpenseDetailsUrl } from '../../../util/siteMapConstants'; const ExpenseDetail = ({ history, match }) => { const { t } = useTranslation(); @@ -63,8 +64,8 @@ const ExpenseDetail = ({ history, match }) => { }; const handleEdit = () => { - dispatch(setPersistedPaths([`/expense/${expense_id}/edit`])); - history.push(`/expense/${expense_id}/edit`); + dispatch(setPersistedPaths([createEditExpenseDetailsUrl(expense_id)])); + history.push(createEditExpenseDetailsUrl(expense_id)); }; const onRetire = () => { diff --git a/packages/webapp/src/containers/Finances/Labour/index.jsx b/packages/webapp/src/containers/Finances/Labour/index.jsx index 0d46b88ffc..b290ef81b6 100644 --- a/packages/webapp/src/containers/Finances/Labour/index.jsx +++ b/packages/webapp/src/containers/Finances/Labour/index.jsx @@ -19,6 +19,7 @@ import { setDateRange } from '../actions'; import { dateRangeOptions } from '../../../components/DateRangeSelector/constants'; import DateRange, { SUNDAY } from '../../../util/dateRange'; import { getManagementPlansAndTasks } from '../../saga'; +import { FINANCES_HOME_URL } from '../../../util/siteMapConstants'; class Labour extends Component { constructor(props) { @@ -88,7 +89,7 @@ class Labour extends Component { return (
- +
{this.props.t('SALE.LABOUR.BY')}
diff --git a/packages/webapp/src/containers/Finances/ManageCustomExpenseTypes/index.jsx b/packages/webapp/src/containers/Finances/ManageCustomExpenseTypes/index.jsx index 63ed282550..d65825e54e 100644 --- a/packages/webapp/src/containers/Finances/ManageCustomExpenseTypes/index.jsx +++ b/packages/webapp/src/containers/Finances/ManageCustomExpenseTypes/index.jsx @@ -20,12 +20,21 @@ import { setPersistedPaths } from '../../hooks/useHookFormPersist/hookFormPersis import { icons } from '../NewExpense/ExpenseCategories'; import labelIconStyles from '../../../components/Tile/styles.module.scss'; import useCustomExpenseTypeTileContents from '../useCustomExpenseTypeTileContents'; +import { + ADD_CUSTOM_EXPENSE_URL, + ADD_EXPENSE_URL, + EXPENSE_CATEGORIES_URL, + FINANCES_HOME_URL, + MANAGE_CUSTOM_EXPENSES_URL, + createEditCustomExpenseURL, + createReadonlyCustomExpenseURL, +} from '../../../util/siteMapConstants'; -const addCustomTypePath = '/add_custom_expense'; +const addCustomTypePath = ADD_CUSTOM_EXPENSE_URL; const getPaths = (typeId) => ({ - readOnly: `/readonly_custom_expense/${typeId}`, - edit: `/edit_custom_expense/${typeId}`, + readOnly: createReadonlyCustomExpenseURL(typeId), + edit: createEditCustomExpenseURL(typeId), }); export default function ManageExpenseTypes({ history }) { @@ -41,20 +50,20 @@ export default function ManageExpenseTypes({ history }) { }; useEffect(() => { - // Manipulate page navigation by pushing "/expense_categories" on top of "/Finances". + // Manipulate page navigation by pushing EXPENSE_CATEGORIES_URL on top of FINANCES_HOME_URL. // When browser's back button or form's back button is clicked, we want to - // navigate the user to "/expense_categories" not "/Finances". + // navigate the user to EXPENSE_CATEGORIES_URL not FINANCES_HOME_URL. const unlisten = history.listen(() => { - if (history.action === 'POP' && history.location.pathname === '/Finances') { - dispatch(setPersistedPaths(['/expense_categories', '/add_expense'])); + if (history.action === 'POP' && history.location.pathname === FINANCES_HOME_URL) { + dispatch(setPersistedPaths([EXPENSE_CATEGORIES_URL, ADD_EXPENSE_URL])); unlisten(); - history.push('/expense_categories'); + history.push(EXPENSE_CATEGORIES_URL); } else if ( - // unlisten when the user gets out of the page without going back to '/Finances'. + // unlisten when the user gets out of the page without going back to FINANCES_HOME_URL. // pathname: "/manage_custom_expenses" happens when the user lands on this page. !( - history.location.pathname === `/manage_custom_expenses` || - (history.action === 'POP' && history.location.pathname === '/Finances') + history.location.pathname === MANAGE_CUSTOM_EXPENSES_URL || + (history.action === 'POP' && history.location.pathname === FINANCES_HOME_URL) ) ) { unlisten(); diff --git a/packages/webapp/src/containers/Finances/ManageCustomRevenueTypes/index.jsx b/packages/webapp/src/containers/Finances/ManageCustomRevenueTypes/index.jsx index 90dba2717d..fcd0e8fcef 100644 --- a/packages/webapp/src/containers/Finances/ManageCustomRevenueTypes/index.jsx +++ b/packages/webapp/src/containers/Finances/ManageCustomRevenueTypes/index.jsx @@ -20,12 +20,21 @@ import { setPersistedPaths } from '../../hooks/useHookFormPersist/hookFormPersis import useSortedCustomRevenueTypes from '../useSortedCustomRevenueTypes'; import { icons } from '../AddSale/RevenueTypes'; import labelIconStyles from '../../../components/Tile/styles.module.scss'; +import { + ADD_REVENUE_URL, + FINANCES_HOME_URL, + MANAGE_CUSTOM_REVENUES_URL, + REVENUE_TYPES_URL, + ADD_CUSTOM_REVENUE_URL, + createReadonlyCustomRevenueUrl, + createEditCustomRevenueUrl, +} from '../../../util/siteMapConstants'; -const addCustomTypePath = '/add_custom_revenue'; +const addCustomTypePath = ADD_CUSTOM_REVENUE_URL; const getPaths = (typeId) => ({ - readOnly: `/readonly_custom_revenue/${typeId}`, - edit: `/edit_custom_revenue/${typeId}`, + readOnly: createReadonlyCustomRevenueUrl(typeId), + edit: createEditCustomRevenueUrl(typeId), }); export default function ManageRevenueTypes({ history }) { @@ -41,20 +50,20 @@ export default function ManageRevenueTypes({ history }) { }; useEffect(() => { - // Manipulate page navigation by pushing "/revenue_types" on top of "/Finances". + // Manipulate page navigation by pushing REVENUE_TYPES_URL on top of FINANCES_HOME_URL. // When browser's back button or form's back button is clicked, we want to - // navigate the user to "/revenue_types" not "/Finances". + // navigate the user to REVENUE_TYPES_URL not FINANCES_HOME_URL. const unlisten = history.listen(() => { - if (history.action === 'POP' && history.location.pathname === '/Finances') { - dispatch(setPersistedPaths(['/revenue_types', '/add_sale'])); + if (history.action === 'POP' && history.location.pathname === FINANCES_HOME_URL) { + dispatch(setPersistedPaths([REVENUE_TYPES_URL, ADD_REVENUE_URL])); unlisten(); - history.push('/revenue_types'); + history.push(REVENUE_TYPES_URL); } else if ( - // unlisten when the user gets out of the page without going back to '/Finances'. + // unlisten when the user gets out of the page without going back to FINANCES_HOME_URL. // pathname: "/manage_custom_revenue" happens when the user lands on this page. !( - history.location.pathname === `/manage_custom_revenues` || - (history.action === 'POP' && history.location.pathname === '/Finances') + history.location.pathname === MANAGE_CUSTOM_REVENUES_URL || + (history.action === 'POP' && history.location.pathname === FINANCES_HOME_URL) ) ) { unlisten(); diff --git a/packages/webapp/src/containers/Finances/NewExpense/AddExpense/index.jsx b/packages/webapp/src/containers/Finances/NewExpense/AddExpense/index.jsx index e4cc8778bc..454504da03 100644 --- a/packages/webapp/src/containers/Finances/NewExpense/AddExpense/index.jsx +++ b/packages/webapp/src/containers/Finances/NewExpense/AddExpense/index.jsx @@ -7,6 +7,7 @@ import { userFarmSelector } from '../../../userFarmSlice'; import { withTranslation } from 'react-i18next'; import { HookFormPersistProvider } from '../../../hooks/useHookFormPersist/HookFormPersistProvider'; import PureAddExpense from '../../../../components/Finances/AddExpense'; +import { FINANCES_HOME_URL } from '../../../../util/siteMapConstants'; class AddExpense extends Component { constructor(props) { @@ -76,7 +77,7 @@ class AddExpense extends Component { formattedData.filter((expense) => expense.value < 0 || isNaN(expense.value)).length === 0 ) { this.props.dispatch(addExpenses(formattedData)); - history.push('/finances'); + history.push(FINANCES_HOME_URL); } } diff --git a/packages/webapp/src/containers/Finances/NewExpense/ExpenseCategories/index.jsx b/packages/webapp/src/containers/Finances/NewExpense/ExpenseCategories/index.jsx index 7f5753963f..71f1e34732 100644 --- a/packages/webapp/src/containers/Finances/NewExpense/ExpenseCategories/index.jsx +++ b/packages/webapp/src/containers/Finances/NewExpense/ExpenseCategories/index.jsx @@ -25,6 +25,7 @@ import { HookFormPersistProvider } from '../../../hooks/useHookFormPersist/HookF import labelIconStyles from '../../../../components/Tile/styles.module.scss'; import { listItemTypes } from '../../../../components/List/constants'; import { getFinanceTypeSearchableStringFunc } from '../../util'; +import { ADD_EXPENSE_URL, MANAGE_CUSTOM_EXPENSES_URL } from '../../../../util/siteMapConstants'; export const icons = { EQUIPMENT: , @@ -60,7 +61,7 @@ class ExpenseCategories extends Component { nextPage(event) { event.preventDefault(); this.props.dispatch(setSelectedExpenseTypes(this.state.selectedTypes)); - history.push('/add_expense'); + history.push(ADD_EXPENSE_URL); } addRemoveType(id) { @@ -98,7 +99,7 @@ class ExpenseCategories extends Component { onContinue={this.nextPage} onGoBack={this.props.history.back} progressValue={33} - onGoToManageCustomType={() => history.push('/manage_custom_expenses')} + onGoToManageCustomType={() => history.push(MANAGE_CUSTOM_EXPENSES_URL)} isTypeSelected={!!this.state.selectedTypes.length} formatListItemData={(data) => { const { diff --git a/packages/webapp/src/containers/Finances/OtherExpense/index.jsx b/packages/webapp/src/containers/Finances/OtherExpense/index.jsx index 75cc046f87..ef545b5746 100644 --- a/packages/webapp/src/containers/Finances/OtherExpense/index.jsx +++ b/packages/webapp/src/containers/Finances/OtherExpense/index.jsx @@ -30,6 +30,7 @@ import { useCurrencySymbol } from '../../hooks/useCurrencySymbol'; import { useSelector, useDispatch } from 'react-redux'; import useDateRangeSelector from '../../../components/DateRangeSelector/useDateRangeSelector'; import { SUNDAY } from '../../../util/dateRange'; +import { createExpenseDetailsUrl, FINANCES_HOME_URL } from '../../../util/siteMapConstants'; const OtherExpense = () => { const { t } = useTranslation(); @@ -185,7 +186,7 @@ const OtherExpense = () => { return (
- + {t('EXPENSE.SUMMARY')} @@ -220,7 +221,7 @@ const OtherExpense = () => { onClick: (e, handleOriginal) => { if (rowInfo && rowInfo.original) { const expense_id = rowInfo.original.expense_item_id; - history.push(`/expense/${expense_id}`); + history.push(createExpenseDetailsUrl(expense_id)); } if (handleOriginal) { handleOriginal(); diff --git a/packages/webapp/src/containers/Finances/RevenueDetail/index.jsx b/packages/webapp/src/containers/Finances/RevenueDetail/index.jsx index 84115d07f1..84590491f9 100644 --- a/packages/webapp/src/containers/Finances/RevenueDetail/index.jsx +++ b/packages/webapp/src/containers/Finances/RevenueDetail/index.jsx @@ -27,6 +27,7 @@ import useHookFormPersist from '../../hooks/useHookFormPersist'; import { mapRevenueFormDataToApiCallFormat, mapRevenueTypesToReactSelectOptions } from '../util'; import useSortedRevenueTypes from '../AddSale/RevenueTypes/useSortedRevenueTypes'; import { REVENUE_TYPE_OPTION } from '../../../components/Forms/GeneralRevenue/constants'; +import { createEditRevenueDetailsUrl } from '../../../util/siteMapConstants'; function RevenueDetail({ history, match }) { const isEditing = match.path.endsWith('/edit'); @@ -56,8 +57,8 @@ function RevenueDetail({ history, match }) { }; const handleEdit = () => { - dispatch(setPersistedPaths([`/revenue/${sale_id}/edit`])); - history.push(`/revenue/${sale_id}/edit`); + dispatch(setPersistedPaths([createEditRevenueDetailsUrl(sale_id)])); + history.push(createEditRevenueDetailsUrl(sale_id)); }; const onRetire = () => { diff --git a/packages/webapp/src/containers/Finances/saga.js b/packages/webapp/src/containers/Finances/saga.js index d3427b04ad..1ba4f7c49d 100644 --- a/packages/webapp/src/containers/Finances/saga.js +++ b/packages/webapp/src/containers/Finances/saga.js @@ -54,6 +54,13 @@ import { GET_FARM_EXPENSE_TYPE, UPDATE_SALE, } from './constants'; +import { + ESTIMATED_REVENUE_URL, + FINANCES_HOME_URL, + MANAGE_CUSTOM_EXPENSES_URL, + MANAGE_CUSTOM_REVENUES_URL, + OTHER_EXPENSE_URL, +} from '../../util/siteMapConstants'; export const getSales = createAction('getSales'); @@ -82,7 +89,7 @@ export function* addSale(action) { const result = yield call(axios.post, salesURL, action.sale, header); yield put(enqueueSuccessSnackbar(i18n.t('message:SALE.SUCCESS.ADD'))); yield call(getSalesSaga); - history.push('/finances'); + history.push(FINANCES_HOME_URL); } catch (e) { yield put(enqueueErrorSnackbar(i18n.t('message:SALE.ERROR.ADD'))); } @@ -101,7 +108,7 @@ export function* updateSaleSaga(action) { yield call(axios.patch, `${salesURL}/${sale_id}`, sale, header); yield put(enqueueSuccessSnackbar(i18n.t('message:SALE.SUCCESS.UPDATE'))); yield call(getSalesSaga); - history.push('/finances'); + history.push(FINANCES_HOME_URL); } catch (e) { console.log(`failed to update sale`); yield put(enqueueErrorSnackbar(i18n.t('message:SALE.ERROR.UPDATE'))); @@ -118,7 +125,7 @@ export function* deleteSale(action) { yield call(axios.delete, salesURL + '/' + sale_id, header); yield put(enqueueSuccessSnackbar(i18n.t('message:SALE.SUCCESS.DELETE'))); yield call(getSalesSaga); - history.push('/finances'); + history.push(FINANCES_HOME_URL); } catch (e) { console.log(`failed to delete sale`); yield put(enqueueErrorSnackbar(i18n.t('message:SALE.ERROR.DELETE'))); @@ -175,7 +182,7 @@ export function* addCustomExpenseTypeSaga({ payload: { expense_name, custom_desc if (result) { yield put(enqueueSuccessSnackbar(i18n.t('message:EXPENSE_TYPE.SUCCESS.ADD'))); yield call(getFarmExpenseTypeSaga); - history.push('/manage_custom_expenses'); + history.push(MANAGE_CUSTOM_EXPENSES_URL); } } catch (e) { console.log('failed to add new expense type to the database'); @@ -202,7 +209,7 @@ export function* updateCustomExpenseTypeSaga({ if (result) { yield put(enqueueSuccessSnackbar(i18n.t('message:EXPENSE_TYPE.SUCCESS.UPDATE'))); yield call(getFarmExpenseTypeSaga); - history.push('/manage_custom_expenses'); + history.push(MANAGE_CUSTOM_EXPENSES_URL); } } catch (e) { console.log('failed to update expense type in the database'); @@ -222,7 +229,7 @@ export function* retireCustomExpenseTypeSaga({ payload: { expense_type_id } }) { if (result) { yield put(enqueueSuccessSnackbar(i18n.t('message:EXPENSE_TYPE.SUCCESS.DELETE'))); yield call(getFarmExpenseTypeSaga); - history.push('/manage_custom_expenses'); + history.push(MANAGE_CUSTOM_EXPENSES_URL); } } catch (e) { console.log('failed to delete new expense type in the database'); @@ -259,7 +266,7 @@ export function* deleteExpenseSaga(action) { const result = yield call(axios.delete, `${expenseUrl}/${expense_id}`, header); if (result) { yield put(enqueueSuccessSnackbar(i18n.t('message:EXPENSE.SUCCESS.DELETE'))); - history.push('/other_expense'); + history.push(FINANCES_HOME_URL); } } catch (e) { yield put(enqueueErrorSnackbar(i18n.t('message:EXPENSE.ERROR.DELETE'))); @@ -326,7 +333,7 @@ export function* editExpenseSaga(action) { yield put(setExpense(result.data)); } } - history.push('/other_expense'); + history.push(FINANCES_HOME_URL); } catch (e) { console.log(e); yield put(enqueueErrorSnackbar(i18n.t('message:EXPENSE.ERROR.UPDATE'))); @@ -363,7 +370,7 @@ export function* deleteRevenueTypeSaga({ payload: id }) { yield put(deleteRevenueTypeSuccess({ revenue_type_id: id, deleted, retired })); yield put(enqueueSuccessSnackbar(i18n.t('message:REVENUE_TYPE.SUCCESS.DELETE'))); - history.push('/manage_custom_revenues'); + history.push(MANAGE_CUSTOM_REVENUES_URL); } catch (e) { yield put(enqueueErrorSnackbar(i18n.t('message:REVENUE_TYPE.ERROR.DELETE'))); } @@ -391,7 +398,7 @@ export function* addRevenueTypeSaga({ yield put(postRevenueTypeSuccess(result.data)); yield put(enqueueSuccessSnackbar(i18n.t('message:REVENUE_TYPE.SUCCESS.ADD'))); - history.push('/manage_custom_revenues'); + history.push(MANAGE_CUSTOM_REVENUES_URL); } catch (e) { yield put(enqueueErrorSnackbar(i18n.t('message:REVENUE_TYPE.ERROR.ADD'))); } @@ -416,7 +423,7 @@ export function* updateRevenueTypeSaga({ yield put(putRevenueTypeSuccess({ revenue_type_id, revenue_name, custom_description })); yield put(enqueueSuccessSnackbar(i18n.t('message:REVENUE_TYPE.SUCCESS.UPDATE'))); - history.push('/manage_custom_revenues'); + history.push(MANAGE_CUSTOM_REVENUES_URL); } catch (e) { yield put(enqueueErrorSnackbar(i18n.t('message:REVENUE_TYPE.ERROR.UPDATE'))); } @@ -437,7 +444,7 @@ export function* patchEstimatedCropRevenueSaga({ payload: managementPlan }) { ); yield call(getManagementPlanAndPlantingMethodSuccessSaga, { payload: [managementPlan] }); yield put(enqueueSuccessSnackbar(i18n.t('message:REVENUE.SUCCESS.EDIT'))); - history.push(`/estimated_revenue`); + history.push(ESTIMATED_REVENUE_URL); } catch (e) { console.log('Failed to update managementPlan to database'); yield put(enqueueErrorSnackbar(i18n.t('message:REVENUE.ERROR.EDIT'))); diff --git a/packages/webapp/src/hooks/useGetMenuItems.jsx b/packages/webapp/src/hooks/useGetMenuItems.jsx index 1e5b42b685..4d7bf92ffa 100644 --- a/packages/webapp/src/hooks/useGetMenuItems.jsx +++ b/packages/webapp/src/hooks/useGetMenuItems.jsx @@ -27,6 +27,12 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import { isAdminSelector } from '../containers/userFarmSlice'; import styles from '../components/Navigation/SideMenu/styles.module.scss'; +import { + ESTIMATED_REVENUE_URL, + FINANCES_HOME_URL, + LABOUR_URL, + OTHER_EXPENSE_URL, +} from '../util/siteMapConstants'; export const useGetMenuItems = () => { const { t } = useTranslation(); @@ -49,20 +55,20 @@ export const useGetMenuItems = () => { list.splice(3, 0, { label: t('MENU.FINANCES'), icon: , - path: '/finances', + path: FINANCES_HOME_URL, key: 'finances', subMenu: [ { label: t('MENU.TRANSACTION_LIST'), - path: '/finances/transactions', + path: FINANCES_HOME_URL, key: 'transactions', }, { label: t('MENU.OTHER_EXPENSES'), - path: '/finances/other_expense', + path: OTHER_EXPENSE_URL, key: 'other_expense', }, - { label: t('MENU.LABOUR_EXPENSES'), path: '/finances/labour', key: 'labour' }, + { label: t('MENU.LABOUR_EXPENSES'), path: LABOUR_URL, key: 'labour' }, { label: t('MENU.ACTUAL_REVENUES'), path: '/finances/actual_revenue', @@ -70,7 +76,7 @@ export const useGetMenuItems = () => { }, { label: t('MENU.ESTIMATED_REVENUES'), - path: '/finances/estimated_revenue', + path: ESTIMATED_REVENUE_URL, key: 'estimated_revenue', }, ], diff --git a/packages/webapp/src/main.jsx b/packages/webapp/src/main.jsx index 64b082078e..393eb8338a 100644 --- a/packages/webapp/src/main.jsx +++ b/packages/webapp/src/main.jsx @@ -86,7 +86,7 @@ if (import.meta.env.VITE_SENTRY_DSN) { Sentry.init({ dsn: import.meta.env.VITE_SENTRY_DSN, integrations: [new Integrations.BrowserTracing()], - release: '3.6.1', + release: '3.6.2', // Set tracesSampleRate to 1.0 to capture 100% // of transactions for performance monitoring. // We recommend adjusting this value in production diff --git a/packages/webapp/src/routes/DeprecatedRoutes.jsx b/packages/webapp/src/routes/DeprecatedRoutes.jsx deleted file mode 100644 index 6a5a2f5f50..0000000000 --- a/packages/webapp/src/routes/DeprecatedRoutes.jsx +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2023 LiteFarm.org - * This file is part of LiteFarm. - * - * LiteFarm is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LiteFarm is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details, see . - */ - -import { Redirect, Route, Switch } from 'react-router-dom'; - -// Redirects from previous routes -const DeprecatedRoutes = () => ( - - {/* Redirect old routes to nested finances routes for backwards compatibility */} - - - - - - - - - - - - - - - - - - - - - - -); - -export default DeprecatedRoutes; diff --git a/packages/webapp/src/routes/FinancesRoutes.jsx b/packages/webapp/src/routes/FinancesRoutes.jsx index e942d3be18..a3cfefffc8 100644 --- a/packages/webapp/src/routes/FinancesRoutes.jsx +++ b/packages/webapp/src/routes/FinancesRoutes.jsx @@ -15,6 +15,29 @@ import React from 'react'; import { Route, Switch, Redirect } from 'react-router-dom'; +import { + ADD_CUSTOM_EXPENSE_URL, + ADD_CUSTOM_REVENUE_URL, + ADD_EXPENSE_URL, + ADD_REVENUE_URL, + createEditCustomExpenseURL, + createEditCustomRevenueUrl, + createEditExpenseDetailsUrl, + createEditRevenueDetailsUrl, + createExpenseDetailsUrl, + createManagementPlanEstimatedRevenueURL, + createReadonlyCustomExpenseURL, + createReadonlyCustomRevenueUrl, + createRevenueDetailsUrl, + ESTIMATED_REVENUE_URL, + EXPENSE_CATEGORIES_URL, + FINANCES_HOME_URL, + LABOUR_URL, + MANAGE_CUSTOM_EXPENSES_URL, + MANAGE_CUSTOM_REVENUES_URL, + OTHER_EXPENSE_URL, + REVENUE_TYPES_URL, +} from '../util/siteMapConstants'; const Finances = React.lazy(() => import('../containers/Finances')); const ActualRevenue = React.lazy(() => import('../containers/Finances/ActualRevenue')); const UpdateEstimatedCropRevenue = React.lazy(() => @@ -58,45 +81,45 @@ const EditCustomRevenue = React.lazy(() => const FinancesRoutes = () => ( - + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + diff --git a/packages/webapp/src/routes/index.jsx b/packages/webapp/src/routes/index.jsx index 37dca60d55..c720bf5980 100644 --- a/packages/webapp/src/routes/index.jsx +++ b/packages/webapp/src/routes/index.jsx @@ -30,7 +30,6 @@ import useScrollToTop from '../containers/hooks/useScrollToTop'; import { useReduxSnackbar } from '../containers/Snackbar/useReduxSnackbar'; //dynamic imports -const DeprecatedRoutes = React.lazy(() => import('./DeprecatedRoutes')); const Home = React.lazy(() => import('../containers/Home')); const HelpRequest = React.lazy(() => import('../containers/Help')); const Account = React.lazy(() => import('../containers/Profile/Account')); @@ -611,7 +610,6 @@ const Routes = ({ isCompactSideMenu }) => { /> - { /> - diff --git a/packages/webapp/src/util/siteMapConstants.ts b/packages/webapp/src/util/siteMapConstants.ts new file mode 100644 index 0000000000..322057c870 --- /dev/null +++ b/packages/webapp/src/util/siteMapConstants.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2024 LiteFarm.org + * This file is part of LiteFarm. + * + * LiteFarm is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LiteFarm is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details, see . + */ + +// Type of string has the dual purpose of being used in routes parameter pathing +// as well as accomodating UUID types. + +// Finances +export const FINANCES_HOME_URL = '/finances/transactions'; +export const REVENUE_TYPES_URL = '/finances/revenue_types'; +export const ADD_REVENUE_URL = '/finances/add_revenue'; +export const MANAGE_CUSTOM_REVENUES_URL = '/finances/manage_custom_revenues'; +export const ESTIMATED_REVENUE_URL = '/finances/estimated_revenue'; +export const LABOUR_URL = '/finances/labour'; +export const OTHER_EXPENSE_URL = '/finances/other_expense'; +export const EXPENSE_CATEGORIES_URL = '/finances/expense_categories'; +export const ADD_EXPENSE_URL = '/finances/add_expense'; +export const MANAGE_CUSTOM_EXPENSES_URL = '/finances/manage_custom_expenses'; +export const ADD_CUSTOM_EXPENSE_URL = '/finances/add_custom_expense'; +export const ADD_CUSTOM_REVENUE_URL = '/finances/add_custom_revenue'; +export const createExpenseDetailsUrl = (id: string | number): string => { + return `/finances/expense/${id}`; +}; +export const createEditExpenseDetailsUrl = (id: string | number): string => { + return `${createExpenseDetailsUrl(id)}/edit`; +}; +export const createRevenueDetailsUrl = (id: string | number): string => { + return `/finances/revenue/${id}`; +}; +export const createEditRevenueDetailsUrl = (id: string | number): string => { + return `${createRevenueDetailsUrl(id)}/edit`; +}; +export const createManagementPlanEstimatedRevenueURL = (id: string | number): string => { + return `${ESTIMATED_REVENUE_URL}/plan/${id}}`; +}; +export const createReadonlyCustomExpenseURL = (id: string | number): string => { + return `/finances/readonly_custom_expense/${id}`; +}; +export const createEditCustomExpenseURL = (id: string | number): string => { + return `/finances/edit_custom_expense/${id}`; +}; + +export const createEditCustomRevenueUrl = (id: string | number): string => { + return `/finances/edit_custom_revenue/${id}`; +}; + +export const createReadonlyCustomRevenueUrl = (id: string | number): string => { + return `/finances/readonly_custom_revenue/${id}`; +};