From a9647db89837860305fb2725fcfe7e8ffb934aed Mon Sep 17 00:00:00 2001 From: Melisa Anabella Rossi Date: Tue, 7 Nov 2023 22:21:31 -0300 Subject: [PATCH 1/4] fix: add fingerprint calculation --- .../src/components/AssetImage/AssetImage.tsx | 15 +++++- .../components/AssetImage/AssetImage.types.ts | 1 + .../AssetPage/EstateDetail/EstateDetail.tsx | 1 + .../AssetPage/ParcelDetail/ParcelDetail.tsx | 8 ++- .../src/components/Atlas/Atlas.container.ts | 3 +- webapp/src/components/Atlas/Atlas.css | 5 ++ webapp/src/components/Atlas/Atlas.tsx | 15 +++++- webapp/src/components/Atlas/Atlas.types.ts | 4 +- .../components/BidPage/BidModal/BidModal.tsx | 12 +++-- .../BuyPage/BuyNFTModal/BuyNFTModal.tsx | 20 ++++--- .../ErrorBanner/ErrorBanner.module.css | 28 ++++++++++ .../components/ErrorBanner/ErrorBanner.tsx | 17 ++++++ .../ErrorBanner/ErrorBanner.types.ts | 4 ++ webapp/src/components/ErrorBanner/index.ts | 2 + webapp/src/config/env/dev.json | 50 ++++++++--------- webapp/src/modules/nft/estate/utils.ts | 53 ++++++++++++++++++- webapp/src/modules/nft/hooks.ts | 47 +++++++++++++--- webapp/src/modules/tile/actions.ts | 4 +- webapp/src/modules/tile/reducer.ts | 4 ++ webapp/src/modules/tile/sagas.ts | 15 +++--- webapp/src/modules/tile/selectors.ts | 1 + .../src/modules/translation/locales/en.json | 4 ++ .../src/modules/translation/locales/es.json | 3 ++ .../src/modules/translation/locales/zh.json | 3 ++ .../modules/vendor/decentraland/land/api.ts | 14 +++++ 25 files changed, 277 insertions(+), 56 deletions(-) create mode 100644 webapp/src/components/ErrorBanner/ErrorBanner.module.css create mode 100644 webapp/src/components/ErrorBanner/ErrorBanner.tsx create mode 100644 webapp/src/components/ErrorBanner/ErrorBanner.types.ts create mode 100644 webapp/src/components/ErrorBanner/index.ts diff --git a/webapp/src/components/AssetImage/AssetImage.tsx b/webapp/src/components/AssetImage/AssetImage.tsx index 1d2c9dd148..07c5e8d949 100644 --- a/webapp/src/components/AssetImage/AssetImage.tsx +++ b/webapp/src/components/AssetImage/AssetImage.tsx @@ -81,6 +81,7 @@ const AssetImage = (props: Props) => { wearableController, isTryingOn, isPlayingEmote, + showUpdatedDateWarning, onSetIsTryingOn, onSetWearablePreviewController, onPlaySmartWearableVideoShowcase, @@ -186,7 +187,13 @@ const AssetImage = (props: Props) => { setHasSound(sound) }) } - }, [wearableController, asset.category, isDraggable, hasSound, isLoadingWearablePreview]) + }, [ + wearableController, + asset.category, + isDraggable, + hasSound, + isLoadingWearablePreview + ]) const estateSelection = useMemo(() => (estate ? getSelection(estate) : []), [ estate @@ -257,6 +264,9 @@ const AssetImage = (props: Props) => { showForRent={false} showOnSale={false} showOwned={false} + lastUpdated={ + showUpdatedDateWarning ? new Date(asset.updatedAt) : undefined + } > {hasBadges && children} @@ -278,6 +288,9 @@ const AssetImage = (props: Props) => { showOnSale={false} showOwned={false} isEstate + lastUpdated={ + showUpdatedDateWarning ? new Date(asset.updatedAt) : undefined + } > {hasBadges && children} diff --git a/webapp/src/components/AssetImage/AssetImage.types.ts b/webapp/src/components/AssetImage/AssetImage.types.ts index 438f6f604f..ddc18f9d22 100644 --- a/webapp/src/components/AssetImage/AssetImage.types.ts +++ b/webapp/src/components/AssetImage/AssetImage.types.ts @@ -25,6 +25,7 @@ export type Props = { className?: string isDraggable?: boolean withNavigation?: boolean + showUpdatedDateWarning?: boolean hasPopup?: boolean zoom?: number isSmall?: boolean diff --git a/webapp/src/components/AssetPage/EstateDetail/EstateDetail.tsx b/webapp/src/components/AssetPage/EstateDetail/EstateDetail.tsx index 8a216d170c..b86129a928 100644 --- a/webapp/src/components/AssetPage/EstateDetail/EstateDetail.tsx +++ b/webapp/src/components/AssetPage/EstateDetail/EstateDetail.tsx @@ -45,6 +45,7 @@ const EstateDetail = ({ nft, order, rental }: Props) => { isDraggable withNavigation hasPopup + showUpdatedDateWarning /> {estate.size === 0 && (
diff --git a/webapp/src/components/AssetPage/ParcelDetail/ParcelDetail.tsx b/webapp/src/components/AssetPage/ParcelDetail/ParcelDetail.tsx index 304d8c93aa..e4e442423c 100644 --- a/webapp/src/components/AssetPage/ParcelDetail/ParcelDetail.tsx +++ b/webapp/src/components/AssetPage/ParcelDetail/ParcelDetail.tsx @@ -32,7 +32,13 @@ const ParcelDetail = ({ nft, order, rental }: Props) => { asset={nft} rental={rental ?? undefined} assetImage={ - + } showDetails={isLand(nft)} isOnSale={!!nft.activeOrderId} diff --git a/webapp/src/components/Atlas/Atlas.container.ts b/webapp/src/components/Atlas/Atlas.container.ts index 4bc202b70f..edba68c955 100644 --- a/webapp/src/components/Atlas/Atlas.container.ts +++ b/webapp/src/components/Atlas/Atlas.container.ts @@ -1,6 +1,6 @@ import { connect } from 'react-redux' import { push } from 'connected-react-router' -import { getTiles, getTilesByEstateId } from '../../modules/tile/selectors' +import { getLastModifiedDate, getTiles, getTilesByEstateId } from '../../modules/tile/selectors' import { getOnRentNFTsByLessor } from '../../modules/ui/browse/selectors' import { RootState } from '../../modules/reducer' import { getWalletNFTs } from '../../modules/nft/selectors' @@ -19,6 +19,7 @@ const mapState = (state: RootState): MapStateProps => { nfts: getWalletNFTs(state), nftsOnRent, tilesByEstateId: getTilesByEstateId(state), + lastAtlasModifiedDate: getLastModifiedDate(state), getContract: (query: Partial) => getContract(state, query) } } diff --git a/webapp/src/components/Atlas/Atlas.css b/webapp/src/components/Atlas/Atlas.css index 878d3a3832..168747cfd9 100644 --- a/webapp/src/components/Atlas/Atlas.css +++ b/webapp/src/components/Atlas/Atlas.css @@ -29,6 +29,11 @@ outline: 1px solid white; } +.atlas-wrapper .atlas-warning-banner { + position: absolute; + bottom: 0; +} + .atlas-wrapper .atlas-info-button .info-icon { background-image: url('../../images/info.svg'); width: 16px; diff --git a/webapp/src/components/Atlas/Atlas.tsx b/webapp/src/components/Atlas/Atlas.tsx index 7a00a1025d..da79f645f5 100644 --- a/webapp/src/components/Atlas/Atlas.tsx +++ b/webapp/src/components/Atlas/Atlas.tsx @@ -17,6 +17,7 @@ import { VendorName } from '../../modules/vendor' import { NFT } from '../../modules/nft/types' import Popup from './Popup' import './Atlas.css' +import ErrorBanner from '../ErrorBanner' const getCoords = (x: number | string, y: number | string) => `${x},${y}` @@ -35,8 +36,10 @@ const Atlas: React.FC = (props: Props) => { tilesByEstateId, withMapColorsInfo, withZoomControls, + lastAtlasModifiedDate, getContract, - children + children, + lastUpdated } = props const [showPopup, setShowPopup] = useState(false) @@ -375,6 +378,16 @@ const Atlas: React.FC = (props: Props) => { layers={layers} withZoomControls={withZoomControls} /> + {lastAtlasModifiedDate && + lastUpdated && + lastUpdated > lastAtlasModifiedDate ? ( + {text} + })} + /> + ) : null} {hoveredTile ? ( & { showOwned?: boolean withMapColorsInfo?: boolean withZoomControls?: boolean + lastUpdated?: Date + lastAtlasModifiedDate: Date | null getContract: (query: Partial) => ReturnType onNavigate: (path: string) => void children?: React.ReactNode @@ -39,7 +41,7 @@ export type Props = Partial & { export type MapStateProps = Pick< Props, - 'tiles' | 'nfts' | 'nftsOnRent' | 'tilesByEstateId' | 'getContract' + 'tiles' | 'nfts' | 'nftsOnRent' | 'tilesByEstateId' | 'getContract' | 'lastAtlasModifiedDate' > export type MapDispatchProps = Pick export type MapDispatch = Dispatch diff --git a/webapp/src/components/BidPage/BidModal/BidModal.tsx b/webapp/src/components/BidPage/BidModal/BidModal.tsx index 0560cdaef7..b46fd0d76e 100644 --- a/webapp/src/components/BidPage/BidModal/BidModal.tsx +++ b/webapp/src/components/BidPage/BidModal/BidModal.tsx @@ -1,6 +1,6 @@ import React, { useState, useCallback } from 'react' import { ethers } from 'ethers' -import { Contract } from '@dcl/schemas' +import { Contract, NFTCategory } from '@dcl/schemas' import { Header, Form, Field, Button } from 'decentraland-ui' import { t, T } from 'decentraland-dapps/dist/modules/translation/utils' import { withAuthorizedAction } from 'decentraland-dapps/dist/containers' @@ -28,6 +28,7 @@ import { ConfirmInputValueModal } from '../../ConfirmInputValueModal' import { Mana } from '../../Mana' import { Props } from './BidModal.types' import './BidModal.css' +import ErrorBanner from '../../ErrorBanner' const BidModal = (props: Props) => { const { @@ -44,7 +45,7 @@ const BidModal = (props: Props) => { const [price, setPrice] = useState('') const [expiresAt, setExpiresAt] = useState(getDefaultExpirationDate()) - const [fingerprint, isLoading] = useFingerprint(nft) + const [fingerprint, isLoading, contractFingerprint] = useFingerprint(nft) const [showConfirmationModal, setShowConfirmationModal] = useState(false) @@ -106,7 +107,9 @@ const BidModal = (props: Props) => { isInvalidDate || hasInsufficientMANA || isLoading || - isPlacingBid + isPlacingBid || + (!fingerprint && nft.category === NFTCategory.ESTATE) || + contractFingerprint !== fingerprint return ( @@ -161,6 +164,9 @@ const BidModal = (props: Props) => { error={isInvalidDate} message={isInvalidDate ? t('bid_page.invalid_date') : undefined} /> + {contractFingerprint !== fingerprint ? ( + + ) : null}