Skip to content

Commit

Permalink
Merge pull request #3675 from LiteFarmOrg/LF-4691/UI_to_connect_to_En…
Browse files Browse the repository at this point in the history
…semble

LF-4691: UI to connect to ensemble
  • Loading branch information
Duncan-Brain authored Feb 7, 2025
2 parents 4e2528d + 43754f2 commit 312f57c
Show file tree
Hide file tree
Showing 26 changed files with 482 additions and 130 deletions.
2 changes: 2 additions & 0 deletions packages/webapp/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"HERE": "here",
"INVALID_DATE": "Invalid date",
"LOADING": "Loading...",
"MANAGE_ENTITY": "Manage {{entity}}",
"MARK_ABANDON": "Abandon",
"MARK_COMPLETE": "Mark Complete",
"MARK_COMPLETED": "Mark completed",
Expand Down Expand Up @@ -80,6 +81,7 @@
"SAVE": "Save",
"SAVE_CHANGES": "Save Changes",
"SEARCH": "Search",
"SEE_ON_MAP": "See on map",
"SELECT": "Select",
"SELECT_ALL": "Select all",
"SELECTED_COUNT": "{{count}} selected",
Expand Down
15 changes: 14 additions & 1 deletion packages/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1789,14 +1789,27 @@
"BRAND": "Brand",
"BRAND_TOOLTIP": "Brands that LiteFarm can integrate with are shown below. If you would no longer like to use this sensor brand, try retiring this sensor instead.",
"DEPTH": "Depth",
"DEVICE_TYPE": "Device type",
"DITECTED_FIELD": "We detected the field location to be:",
"EDIT": "Edit",
"EXTERNAL_ID_TOOLTIP": "This id is used to uniquely identify this sensor in other, integrated systems and cannot be changed. If it is no longer being used, try retiring this sensor and adding a new one.",
"EXTERNAL_IDENTIFIER": "External Identifier",
"LATITUDE": "Latitude",
"LONGITUDE": "Longitude",
"MODEL": "Model",
"NAME": "Sensor Name",
"RETIRE": "Retire"
"RETIRE": "Retire",
"SEE_FULL_SENSOR_SETUP": "See full sensor setup"
},
"ESCI": {
"ACTIVE_CONNECTION": "You have an active ESCI connection",
"CONNECT_NEW_SENSOR": "Connect a new sensor setup from ESCI",
"CURRENT_SUPPORT": "We currently only support sensors from \"Ensemble Scientific\"",
"ENSEMBLE_ESID": "Ensemble ESID",
"ENTER_ID": "Enter your Ensemble Scientific organisation ID",
"ORGANISATION_ID": "ESCI organisation ID",
"ORGANISATION_ID_ERROR": "Invalid Organisation ID",
"ORGANISATION_ID_GENERIC_ERROR": "Failed to connect to ESCI. Please try again later."
},
"EXTERNAL_IDENTIFIER": "External identifier",
"HOURS_AGO": "{{time}} hour(s) ago",
Expand Down
2 changes: 2 additions & 0 deletions packages/webapp/src/apiConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const soilAmendmentMethodsUrl = `${URI}/soil_amendment_methods`;
export const soilAmendmentPurposesUrl = `${URI}/soil_amendment_purposes`;
export const soilAmendmentFertiliserTypesUrl = `${URI}/soil_amendment_fertiliser_types`;
export const productUrl = `${URI}/product`;
export const farmAddonUrl = `${URI}/farm_addon`;

export const url = URI;

Expand Down Expand Up @@ -152,5 +153,6 @@ export default {
soilAmendmentPurposesUrl,
soilAmendmentFertiliserTypesUrl,
productUrl,
farmAddonUrl,
url,
};
4 changes: 4 additions & 0 deletions packages/webapp/src/assets/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@

--Colors-Primary-Primary-teal-50: #ebf5f4;
--Colors-Primary-Primary-teal-100: #c0e1dd;
--Colors-Primary-Primary-teal-200: #a2d2cd;
--Colors-Primary-Primary-teal-300: #78bdb6;
--Colors-Primary-Primary-teal-400: #5db1a8;
--Colors-Primary-Primary-teal-500: #359d92;
Expand Down Expand Up @@ -109,6 +110,8 @@
--Btn-primary-hover: #e8a700;
--Btn-primary-disabled: #e7ebf2;

--Colors-Backgrounds-Disabled-grey: #e7ebf2;

--Brand-Accents-colors-and-overlays-Accent-red: #eb6034;

--Colors-Accent-Accent-yellow-50: #fff8e6;
Expand All @@ -130,6 +133,7 @@
--Colors-Accent---singles-Purple-full: #8f26f0;

--Form-focus: #89d1c7;
--Box-bg: #f5fafa;

// Named in Figma but not in design system
--Colors-Primary-green: #247360;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
.overflowStyle {
display: flex;
justify-content: center;
overflow-y: scroll;
overflow-y: auto;
}

.childrenWrapper {
Expand Down
3 changes: 1 addition & 2 deletions packages/webapp/src/components/FloatingContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
*/

import clsx from 'clsx';
import { CSSLength } from '../../types';
import styles from './styles.module.scss';

type CSSLength = `${number}px` | `${number}%` | `${number}vw` | `${number}vh` | 'auto';

interface FloatingContainerProps {
isCompactSideMenu: boolean;
children: React.ReactNode;
Expand Down
41 changes: 34 additions & 7 deletions packages/webapp/src/components/Form/ContextForm/Loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,52 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

import { CSSProperties } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import Spinner from '../../Spinner';
import FloatingContainer from '../../FloatingContainer';
import type { CSSLength } from '../../../types';
import styles from './styles.module.scss';

interface LoadingProps {
dataName?: string;
isCompactSideMenu: boolean;
verticalMargin?: CSSLength;
horizontalMargin?: CSSLength;
mobileMargin?: CSSLength;
}

const Loading = ({ dataName = '' }: LoadingProps) => {
const Loading = ({
dataName = '',
isCompactSideMenu,
verticalMargin = '36px',
horizontalMargin = '64px',
mobileMargin = '16px',
}: LoadingProps) => {
const { t } = useTranslation(['translation', 'common']);
const style = {
'--vertical-margin': verticalMargin,
'--horizontal-margin': horizontalMargin,
'--mobile-margin': mobileMargin,
} as CSSProperties;

return (
<div className={styles.loadingScreen}>
<div>
<Spinner />
<FloatingContainer isCompactSideMenu={isCompactSideMenu} distanceFromBottom={verticalMargin}>
<div
className={clsx(
styles.loadingScreen,
isCompactSideMenu ? styles.withCompactSideMenu : styles.withExpandedSideMenu,
)}
style={style}
>
<div>
<Spinner />
</div>
<div className={styles.loadingText}>{t('common:LOADING')}</div>
<div className={styles.loadingMessage}>{t('common:FETCHING_YOUR_DATA', { dataName })}</div>
</div>
<div className={styles.loadingText}>{t('common:LOADING')}</div>
<div className={styles.loadingMessage}>{t('common:FETCHING_YOUR_DATA', { dataName })}</div>
</div>
</FloatingContainer>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ interface WithStepperProgressBarProps {
steps: {
formContent: ReactNode;
title: string;
onContinueAction?: (values: any) => Promise<void>;
dataName?: string;
}[];
activeStepIndex: number;
Expand Down Expand Up @@ -66,6 +65,9 @@ interface WithStepperProgressBarProps {
showCancelFlow?: boolean;
setShowCancelFlow?: React.Dispatch<React.SetStateAction<boolean>>;
headerComponent?: ((props: HeaderProps) => JSX.Element) | null;
showPreviousButton?: boolean;
showLoading?: boolean;
onAfterSave?: () => void;
}

export const WithStepperProgressBar = ({
Expand All @@ -92,29 +94,39 @@ export const WithStepperProgressBar = ({
showCancelFlow,
setShowCancelFlow,
headerComponent = StepperProgressBar,
showPreviousButton = true,
showLoading,
onAfterSave,
}: WithStepperProgressBarProps) => {
const [transition, setTransition] = useState<{ unblock?: () => void; retry?: () => void }>({
unblock: undefined,
retry: undefined,
});
const [isSaving, setIsSaving] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [isSaved, setIsSaved] = useState(false);

const isSummaryPage = hasSummaryWithinForm && activeStepIndex === steps.length - 1;
const isSingleStep = steps.length === 1;

// Block the page transition
// https://github.com/remix-run/history/blob/dev/docs/blocking-transitions.md
useEffect(() => {
if (isSummaryPage || !isDirty) {
if (isSummaryPage || !isDirty || isSaved) {
return;
}
const unblock = history.block((tx) => {
setTransition({ unblock, retry: tx.retry });
});

return () => unblock();
}, [isSummaryPage, isDirty, history]);
}, [isSummaryPage, isDirty, history, isSaved]);

useEffect(() => {
if (isSaved && onAfterSave) {
onAfterSave();
}
}, [isSaved, onAfterSave]);

useEffect(() => {
// Reset loading state whenever the step changes
Expand All @@ -139,23 +151,16 @@ export const WithStepperProgressBar = ({
};

const onContinue = async () => {
const { onContinueAction } = steps[activeStepIndex];

if (onContinueAction) {
if (isFinalStep) {
setIsLoading(true);
setIsSaving(true);
try {
// Execute the custom action for the current step before proceeding to the next one
await onContinueAction(getValues());
await handleSubmit((data: FieldValues) => onSave(data, onSuccess, setFormResultData))();
setIsSaved(true);
} catch (error) {
console.error(error);
setIsLoading(false);
return;
console.error(error);
}
}

if (isFinalStep) {
setIsSaving(true);
await handleSubmit((data: FieldValues) => onSave(data, onSuccess, setFormResultData))();
setIsSaving(false);
return;
}
Expand All @@ -179,8 +184,10 @@ export const WithStepperProgressBar = ({
setShowCancelFlow?.(false);
};

if (isLoading) {
return <Loading dataName={steps[activeStepIndex].dataName} />;
if (showLoading && isLoading) {
return (
<Loading dataName={steps[activeStepIndex].dataName} isCompactSideMenu={isCompactSideMenu} />
);
}

return (
Expand All @@ -200,7 +207,7 @@ export const WithStepperProgressBar = ({
<FormNavigationButtons
onContinue={onContinue}
onCancel={onCancel}
onPrevious={isSingleStep ? undefined : onGoBack}
onPrevious={isSingleStep || !showPreviousButton ? undefined : onGoBack}
isFirstStep={!activeStepIndex}
isFinalStep={isFinalStep}
isDisabled={!isValid || isSaving}
Expand Down Expand Up @@ -235,7 +242,7 @@ const StepperProgressBarWrapper = ({
headerComponent,
...stepperProgressBarProps
}: StepperProgressBarWrapperProps) => {
if (isSingleStep) {
if (isSingleStep && !headerComponent) {
return <>{children}</>;
}

Expand Down
6 changes: 4 additions & 2 deletions packages/webapp/src/components/Form/ContextForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/

import { useState, useMemo } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { FormProvider, useForm, ValidationMode } from 'react-hook-form';
import { WithPageTitle } from './WithPageTitle';
import { WithStepperProgressBar } from './WithStepperProgressBar';

Expand All @@ -35,6 +35,7 @@ interface ContextFormProps {
variant?: Variant;
isEditing?: boolean;
setIsEditing?: React.Dispatch<React.SetStateAction<boolean>>;
formMode?: keyof ValidationMode;
[key: string]: any;
}

Expand All @@ -45,6 +46,7 @@ export const ContextForm = ({
variant = Variant.PAGE_TITLE,
isEditing = true,
setIsEditing,
formMode = 'onBlur',
...props
}: ContextFormProps) => {
const [activeStepIndex, setActiveStepIndex] = useState(0);
Expand All @@ -53,7 +55,7 @@ export const ContextForm = ({
const [showCancelFlow, setShowCancelFlow] = useState(false);

const form = useForm({
mode: 'onBlur',
mode: formMode,
defaultValues: defaultFormValues,
});

Expand Down
23 changes: 23 additions & 0 deletions packages/webapp/src/components/Form/ContextForm/styles.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@
flex-direction: column;
justify-content: center;
align-items: center;

padding: 16px;
background-color: var(--White);
border-radius: 8px;
box-shadow: 0px 0px 1px 0px #2b303a4d;

height: calc(100vh - var(--global-navbar-height) - var(--vertical-margin) * 2);

&.withCompactSideMenu {
width: calc(100vw - var(--global-compact-side-menu-width) - var(--horizontal-margin) * 2);
}
&.withExpandedSideMenu {
width: calc(100vw - var(--global-side-menu-width) - var(--horizontal-margin) * 2);
}

@include xs-breakpoint {
&.withCompactSideMenu,
&.withExpandedSideMenu {
width: calc(100vw - var(--mobile-margin) * 2);
height: calc(100vh - var(--global-navbar-height) - var(--mobile-margin) * 2);
margin: var(--mobile-margin);
}
}
}

.loadingText {
Expand Down
8 changes: 6 additions & 2 deletions packages/webapp/src/components/PageTitle/v2/index.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Title } from '../../Typography';
import React, { useState } from 'react';
import clsx from 'clsx';
import styles from './styles.module.scss';
import { BsChevronLeft } from 'react-icons/bs';
import PropTypes from 'prop-types';
import { CancelButton } from '../CancelButton';

function PageTitle({ title, onGoBack, onCancel, style, cancelModalTitle, label }) {
function PageTitle({ title, onGoBack, onCancel, style, cancelModalTitle, label, classNames = {} }) {
const [showConfirmCancelModal, setShowConfirmCancelModal] = useState(false);
return (
<div className={styles.container} style={style}>
<div className={clsx(styles.container, classNames.wrapper)} style={style}>
<div className={styles.leftContainer} style={{ overflow: 'hidden', wordBreak: 'break-word' }}>
{onGoBack && (
<button type={'button'} className={styles.buttonContainer} onClick={onGoBack}>
Expand Down Expand Up @@ -41,4 +42,7 @@ PageTitle.propTypes = {
style: PropTypes.object,
label: PropTypes.node,
cancelModalTitle: PropTypes.string,
classNames: {
wrapper: PropTypes.string,
},
};
Loading

0 comments on commit 312f57c

Please sign in to comment.