Skip to content

Commit

Permalink
Merge pull request #3693 from LiteFarmOrg/Reorganize_and_finalize_Ens…
Browse files Browse the repository at this point in the history
…emble_addon_UI

Reorganize and finalize ensemble addon UI
  • Loading branch information
Duncan-Brain authored Feb 20, 2025
2 parents f8c1c66 + cae63cd commit 0741c93
Show file tree
Hide file tree
Showing 21 changed files with 178 additions and 235 deletions.
20 changes: 11 additions & 9 deletions packages/webapp/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,10 +285,10 @@
"CANCEL": "Don't disconnect"
},
"ESCI": {
"MODAL_INFO": "You will not be able to access your ESCI sensors data until you reconnect",
"MODAL_TITLE": "Are you sure you want to disconnect your ESCI sensors?",
"DISCONNECT_ESCI": "Disconnect ESCI",
"INFO": "You can disconnect Ensemble Scientific sensors from your farm, this will remove all sensors from ESCI. You can still access your sensors and associated data on your ESCI dashboard."
"MODAL_INFO": "You will not be able to access your ESci sensors data until you reconnect",
"MODAL_TITLE": "Are you sure you want to disconnect your ESci sensors?",
"DISCONNECT_ESCI": "Disconnect ESci",
"INFO": "You can disconnect Ensemble Scientific sensors from your farm, this will remove all sensors from ESci. You can still access your sensors and associated data on your ESci dashboard."
},
"ORGANISATION_ID": "Organisation ID:"
},
Expand Down Expand Up @@ -1829,15 +1829,17 @@
"WIND_SPEED_SENSOR": "Wind speed sensor"
},
"ESCI": {
"ACTIVE_CONNECTION": "You have an active ESCI connection",
"CONNECT_NEW_SENSOR": "Connect a new sensor setup from 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",
"NAME": "Ensemble Scientific",
"ORGANISATION_ID": "ESci organisation ID",
"ORGANISATION_ID_ERROR": "Invalid Organisation ID",
"ORGANISATION_ID_GENERIC_ERROR": "Failed to connect to ESCI. Please try again later.",
"SEE_ENSEMBLE_SENSOR_LIST": "See Ensemble sensor list"
"ORGANISATION_ID_GENERIC_ERROR": "Failed to connect to ESci. Please try again later.",
"SEE_ENSEMBLE_SENSOR_LIST": "See Ensemble sensor list",
"SHORT_NAME": "ESci"
},
"EXTERNAL_IDENTIFIER": "External identifier",
"HOURS_AGO": "{{time}} hour(s) ago",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,15 @@ import { Link } from 'react-router-dom';
import { useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { validate as uuidValidate } from 'uuid';
import Input, { getInputErrors } from '../../Form/Input';
import InputBaseLabel from '../../Form/InputBase/InputBaseLabel';
import { Main } from '../../Typography';
import { PARTNERS } from '../../../containers/LocationDetails/PointDetails/SensorDetail/v2/constants';
import { ReactComponent as ExternalLinkIcon } from '../../../assets/images/icon_external_link.svg';
import {
AddSensorsFormFields,
FarmAddonField,
PARTNER,
} from '../../../containers/LocationDetails/PointDetails/SensorDetail/v2/types';
import Input, { getInputErrors } from '../Form/Input';
import InputBaseLabel from '../Form/InputBase/InputBaseLabel';
import { Main } from '../Typography';
import { PARTNERS } from '../../containers/AddSensors/constants';
import { ReactComponent as ExternalLinkIcon } from '../../assets/images/icon_external_link.svg';
import { AddSensorsFormFields, FarmAddonField, PARTNER } from '../../containers/AddSensors/types';
import styles from './styles.module.scss';
import { AddonPartner } from '../../../types';
import { AddonPartner } from '../../types';
import { createSensorsUrl } from '../../util/siteMapConstants';

type PartnersProps = {
hasActiveConnection: Record<AddonPartner, boolean>;
Expand Down Expand Up @@ -89,8 +86,7 @@ const Partners = ({ hasActiveConnection }: PartnersProps) => {
<span>{t('common:MANAGE_ENTITY', { entity: 'ESCI' })}</span>
</Link>
</div>
{/* {'TODO: LF-4696'} */}
<Link className={styles.toSensorSetupButton} to="/TODO">
<Link className={styles.toSensorSetupButton} to={createSensorsUrl(PARTNERS.ESCI.id)}>
<ExternalLinkIcon />
<span>{t('SENSOR.ESCI.SEE_ENSEMBLE_SENSOR_LIST')}</span>
</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* GNU General Public License for more details, see <https://www.gnu.org/licenses/>.
*/

@import '../../../assets/mixin.scss';
@import '../../assets/mixin.scss';

.wrapper {
padding: 34px 32px 0 32px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import { useTheme } from '@mui/styles';
import { useMediaQuery } from '@mui/material';
import { useTranslation } from 'react-i18next';
import styles from './styles.module.scss';
import { IconLink, Main } from '../../../Typography';
import { Main } from '../../../Typography';
import { InlineWarning as InlineRemoveWarning, RemoveLink } from '../../../Expandable/InlineRemove';
import Icon from '../../../Icons';
import TextButton from '../../../Form/Button/TextButton';
import { ReactComponent as TrashIcon } from '../../../../assets/images/animals/trash_icon_new.svg';
import { AnimalTypeIconKey } from '../../../Icons/icons';

type AnimalFormHeaderItemProps = {
Expand Down Expand Up @@ -125,34 +124,10 @@ const RemoveComponent = ({
return (
<div className={clsx(styles.remove, isExpanded && showRemove && isRemoving && styles.spanAll)}>
{showRemove && isExpanded && !isRemoving && (
<IconLink
className={styles.removeLink}
onClick={initiateRemoval}
icon={<TrashIcon />}
isIconClickable
underlined={false}
>
{t('common:REMOVE')}
</IconLink>
<RemoveLink onClick={initiateRemoval} className={styles.removeLink} />
)}
{isExpanded && showRemove && isRemoving && (
<div className={clsx(styles.inlineRemoveWarning)}>
<div className={styles.inlineIconText}>
<Icon iconName={'TRASH'} className={styles.trashIcon} />
<Main className={styles.inlineRemoveText}>{t('ADD_ANIMAL.REMOVE_CONFIRM')}</Main>
</div>
<div className={styles.inlineButtonContainer}>
<TextButton className={clsx(styles.inlineButton, styles.yesButton)} onClick={onRemove}>
{t('common:YES')}
</TextButton>
<TextButton
className={clsx(styles.inlineButton, styles.noButton)}
onClick={cancelRemoval}
>
{t('common:NO')}
</TextButton>
</div>
</div>
<InlineRemoveWarning onRemove={onRemove} onCancel={cancelRemoval} />
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,80 +131,7 @@
}
}

.removeLink,
.inlineRemoveWarning,
.inlineButtonContainer,
.inlineIconText {
display: flex;
align-items: center;
}

// IconLink
.removeLink {
span {
color: var(--Colors-Neutral-Neutral-900);
font-size: 14px;
padding-inline: 4px 16px;
}

@include xs-breakpoint {
flex-direction: column;
padding: 4px;

span {
padding-inline: 0px;
}
}
}

.inlineRemoveWarning {
justify-content: space-between;
gap: 20px;

padding: 8px;
border-radius: 4px;
background: #fff3f2;

.trashIcon {
@include svgColorFill(var(--Colors-Accent---singles-Red-dark));
background-color: transparent;
}
}

.inlineIconText,
.inlineRemoveText {
// Truncate remove confirmation
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}

.inlineRemoveText {
color: var(--Colors-Accent---singles-Red-dark);
font-size: 14px;
}

.inlineButtonContainer {
gap: 16px;

@include xs-breakpoint {
gap: 8px;
}
}

.inlineButton {
padding: 4px 8px;
border-radius: 4px;
font-weight: 700;
line-height: 20px;
}

.yesButton {
background: var(--Colors-Accent---singles-Red-full);
color: var(--Colors-Accent---singles-Red-light);
}

.noButton {
background: #ffc1bf;
color: var(--Colors-Accent---singles-Red-dark);
padding-inline: 4px 16px;
}
69 changes: 69 additions & 0 deletions packages/webapp/src/components/Expandable/InlineRemove.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2025 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 <https://www.gnu.org/licenses/>.
*/

import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import TextButton from '../Form/Button/TextButton';
import { IconLink, Main } from '../Typography';
import Icon from '../Icons';
import { ReactComponent as TrashIcon } from '../../assets/images/animals/trash_icon_new.svg';
import styles from './styles.module.scss';

export interface InlineWarningProps {
onRemove?: (e: React.MouseEvent) => void;
onCancel?: (e: React.MouseEvent) => void;
}

export const InlineWarning = ({ onRemove, onCancel }: InlineWarningProps) => {
const { t } = useTranslation();

return (
<div className={clsx(styles.inlineRemoveWarning)}>
<div className={styles.inlineIconText}>
<Icon iconName={'TRASH'} className={styles.trashIcon} />
<Main className={styles.inlineRemoveText}>{t('ADD_ANIMAL.REMOVE_CONFIRM')}</Main>
</div>
<div className={styles.inlineButtonContainer}>
<TextButton className={clsx(styles.inlineButton, styles.yesButton)} onClick={onRemove}>
{t('common:YES')}
</TextButton>
<TextButton className={clsx(styles.inlineButton, styles.noButton)} onClick={onCancel}>
{t('common:NO')}
</TextButton>
</div>
</div>
);
};

interface RemoveLinkProps {
onClick: (e: React.MouseEvent) => void;
className?: string;
}

export const RemoveLink = ({ onClick, className }: RemoveLinkProps) => {
const { t } = useTranslation();

return (
<IconLink
className={clsx(styles.removeLink, className)}
onClick={onClick}
icon={<TrashIcon />}
isIconClickable
underlined={false}
>
{t('common:REMOVE')}
</IconLink>
);
};
41 changes: 3 additions & 38 deletions packages/webapp/src/components/Expandable/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@
*/

import { ReactNode, useState } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { FaCheck } from 'react-icons/fa';
import TextButton from '../Form/Button/TextButton';
import { IconLink, Main } from '../Typography';
import Icon from '../Icons';
import { ReactComponent as TrashIcon } from '../../assets/images/animals/trash_icon_new.svg';
import { InlineWarning as InlineRemoveWarning, RemoveLink } from './InlineRemove';
import { ReactComponent as CircledCheckIcon } from '../../assets/images/check-circle.svg';
import { ReactComponent as WarningIcon } from '../../assets/images/warning.svg';
import styles from './styles.module.scss';
Expand Down Expand Up @@ -68,41 +64,10 @@ const MainContent = ({

if (isExpanded && onRemove) {
if (isRemoving) {
return (
<div className={clsx(styles.inlineRemoveWarning)}>
<div className={styles.inlineIconText}>
<Icon iconName={'TRASH'} className={styles.trashIcon} />
<Main className={styles.inlineRemoveText}>{t('ADD_ANIMAL.REMOVE_CONFIRM')}</Main>
</div>
<div className={styles.inlineButtonContainer}>
<TextButton
className={clsx(styles.inlineButton, styles.yesButton)}
onClick={onRemove}
>
{t('common:YES')}
</TextButton>
<TextButton
className={clsx(styles.inlineButton, styles.noButton)}
onClick={cancelRemoval}
>
{t('common:NO')}
</TextButton>
</div>
</div>
);
return <InlineRemoveWarning onRemove={onRemove} onCancel={cancelRemoval} />;
}

return (
<IconLink
className={styles.removeLink}
onClick={initiateRemoval}
icon={<TrashIcon />}
isIconClickable
underlined={false}
>
{t('common:REMOVE')}
</IconLink>
);
return <RemoveLink onClick={initiateRemoval} />;
}

if (errorCount) {
Expand Down
Loading

0 comments on commit 0741c93

Please # to comment.