Skip to content

Commit

Permalink
feat: pending update confirmation modal (#1450)
Browse files Browse the repository at this point in the history
* feat: pending update confirmation modal

* feat: reuse confirmation modal in other modals

* refactor: remove duplicated classes

* fix: hide edit update button on non-authored updates

* fix: delete update closing on delete

* feat: change texts when last update

* fix: child descendant from a error
  • Loading branch information
andyesp authored Dec 11, 2023
1 parent 134e0be commit 2c1058b
Show file tree
Hide file tree
Showing 28 changed files with 348 additions and 286 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ GATSBY_BUY_NAME_URL=https://builder.decentraland.org/names
GATSBY_VESTING_DASHBOARD_URL=https://vesting.decentraland.org/%23/

# Snapshot integration
GATSBY_SNAPSHOT_API=https://testnet.snapshot.org/
GATSBY_SNAPSHOT_API=https://testnet.hub.snapshot.org/
GATSBY_SNAPSHOT_URL=https://demo.snapshot.org/
GATSBY_SNAPSHOT_QUERY_ENDPOINT=https://api.thegraph.com/subgraphs/name/snapshot-labs/snapshot
GATSBY_SNAPSHOT_SPACE=daotest.dcl.eth
Expand Down
2 changes: 1 addition & 1 deletion gatsby-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import AuthProvider from 'decentraland-gatsby/dist/context/Auth/AuthProvider'
import FeatureFlagProvider from 'decentraland-gatsby/dist/context/FeatureFlag/FeatureFlagProvider'
import segment from 'decentraland-gatsby/dist/utils/segment/segment'
import Layout from './src/components/Layout/Layout'
import ExternalLinkWarningModal from './src/components/Modal/ExternalLinkWarningModal/ExternalLinkWarningModal'
import ExternalLinkWarningModal from './src/components/Modal/ExternalLinkWarningModal'
import Segment from "decentraland-gatsby/dist/components/Development/Segment"
import { SEGMENT_KEY, SSO_URL } from "./src/constants"
import { flattenMessages } from "./src/utils/intl"
Expand Down
10 changes: 8 additions & 2 deletions src/components/Modal/CalendarAlertModal.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
.CalendarAlertModal__SelectorContainer {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
margin-bottom: 25px;
}

.ui.button.basic.CalendarAlertModal__CancelButton {
color: var(--black-600) !important;
.CalendarAlertModal__NumberSelector {
display: flex;
flex-direction: column;
align-items: center;
}
48 changes: 19 additions & 29 deletions src/components/Modal/CalendarAlertModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { useEffect, useMemo, useState } from 'react'

import { UnitTypeLongPlural } from 'dayjs'
import useTrackContext from 'decentraland-gatsby/dist/context/Track/useTrackContext'
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Close } from 'decentraland-ui/dist/components/Close/Close'
import { Header } from 'decentraland-ui/dist/components/Header/Header'
import { Modal, ModalProps } from 'decentraland-ui/dist/components/Modal/Modal'

import { SegmentEvent } from '../../entities/Events/types'
import { ProposalAttributes } from '../../entities/Proposal/types'
Expand All @@ -16,9 +12,12 @@ import { getGoogleCalendarUrl } from '../../utils/projects'
import NumberSelector from '../ProjectRequest/NumberSelector'

import './CalendarAlertModal.css'
import ConfirmationModal from './ConfirmationModal'

type CalendarAlertModalProps = Omit<ModalProps, 'children'> & {
interface Props {
proposal: Pick<ProposalAttributes, 'id' | 'title' | 'finish_at'>
onClose: () => void
open: boolean
}

const UNITS: UnitTypeLongPlural[] = ['minutes', 'hours', 'days']
Expand All @@ -34,7 +33,7 @@ function getAlertDate(finishAt: ProposalAttributes['finish_at'], value: number,
return alertDate.toDate()
}

function CalendarAlertModal({ proposal, onClose, ...props }: CalendarAlertModalProps) {
function CalendarAlertModal({ proposal, onClose, open }: Props) {
const t = useFormatMessage()
const { finish_at, title, id } = proposal
const [timeValue, setTimeValue] = useState(0)
Expand Down Expand Up @@ -69,13 +68,12 @@ function CalendarAlertModal({ proposal, onClose, ...props }: CalendarAlertModalP
})

return (
<Modal {...props} onClose={handleClose} size="tiny" closeIcon={<Close />}>
<Modal.Content>
<div className="ProposalModal__Title">
<Header>{t('modal.calendar_alert.title')}</Header>
</div>
<ConfirmationModal
title={t('modal.calendar_alert.title')}
description={
<div className="CalendarAlertModal__SelectorContainer">
<NumberSelector
className="CalendarAlertModal__NumberSelector"
value={timeValue}
min={0}
max={MAX_TIME_VALUE}
Expand All @@ -85,24 +83,16 @@ function CalendarAlertModal({ proposal, onClose, ...props }: CalendarAlertModalP
onUnitChange={setUnit}
/>
</div>
<div className="ProposalModal__Actions">
<Button
fluid
primary
disabled={isDisabled}
as="a"
href={alertUrl}
target="_blank"
onClick={trackAddToCalendar}
>
{t('modal.calendar_alert.add_to_calendar')}
</Button>
<Button className="CalendarAlertModal__CancelButton" fluid basic onClick={handleClose}>
{t('modal.calendar_alert.cancel')}
</Button>
</div>
</Modal.Content>
</Modal>
}
isOpen={open}
isDisabled={isDisabled}
onPrimaryClick={trackAddToCalendar}
primaryButtonHref={alertUrl}
onClose={handleClose}
onSecondaryClick={handleClose}
primaryButtonText={t('modal.calendar_alert.add_to_calendar')}
secondaryButtonText={t('modal.calendar_alert.cancel')}
/>
)
}

Expand Down
30 changes: 30 additions & 0 deletions src/components/Modal/ConfirmationModal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@media (min-width: 768px) {
.ConfirmationModal__Container {
margin: 48px 64px 32px 64px !important;
}
}

.ConfirmationModal__Text {
margin-bottom: 26px;
}

.ConfirmationModal__Title {
margin-bottom: 12px !important;
}

.ConfirmationModal__Text,
.ConfirmationModal__Text * {
text-align: center;
white-space: pre-line;
}

.ConfirmationModal__Link {
color: var(--black-800);
pointer-events: none;
cursor: default;
overflow-wrap: break-word;
}

.ConfirmationModal__Actions button:not(:last-child) {
margin-bottom: 15px;
}
67 changes: 67 additions & 0 deletions src/components/Modal/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Close } from 'decentraland-ui/dist/components/Close/Close'
import { Modal } from 'decentraland-ui/dist/components/Modal/Modal'

import Heading from '../Common/Typography/Heading'
import Text from '../Common/Typography/Text'

import './ConfirmationModal.css'

interface Props {
isOpen: boolean
isLoading?: boolean
isDisabled?: boolean
title: string
description: React.ReactNode | string
onClose: () => void
onPrimaryClick: () => void
onSecondaryClick: () => void
primaryButtonHref?: string
primaryButtonText: string
secondaryButtonText: string
}

export default function ConfirmationModal({
isOpen,
isLoading,
isDisabled,
title,
description,
onClose,
onPrimaryClick,
onSecondaryClick,
primaryButtonText,
primaryButtonHref,
secondaryButtonText,
}: Props) {
return (
<Modal open={isOpen} size="tiny" closeIcon={<Close />} onClose={onClose}>
<Modal.Content className="ConfirmationModal__Container">
<div className="ConfirmationModal__Text">
<Heading className="ConfirmationModal__Title" size="xs" weight="semi-bold">
{title}
</Heading>
{typeof description === 'string' ? <Text>{description}</Text> : description}
</div>
<div className="ConfirmationModal__Actions">
<Button
fluid
primary
className="ConfirmationModal__Button"
onClick={onPrimaryClick}
disabled={isLoading || isDisabled}
loading={isLoading}
href={primaryButtonHref}
as={primaryButtonHref ? 'a' : undefined}
target={primaryButtonHref ? '_blank' : undefined}
>
{primaryButtonText}
</Button>
<Button fluid basic className="ConfirmationModal__Button" onClick={onSecondaryClick} disabled={isLoading}>
{secondaryButtonText}
</Button>
</div>
</Modal.Content>
</Modal>
)
}
51 changes: 18 additions & 33 deletions src/components/Modal/DeleteProposalModal/DeleteProposalModal.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,27 @@
import classNames from 'classnames'
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Close } from 'decentraland-ui/dist/components/Close/Close'
import { Header } from 'decentraland-ui/dist/components/Header/Header'
import { Modal, ModalProps } from 'decentraland-ui/dist/components/Modal/Modal'

import useFormatMessage from '../../../hooks/useFormatMessage'
import Text from '../../Common/Typography/Text'
import '../ProposalModal.css'
import ConfirmationModal from '../ConfirmationModal'

export type DeleteProposalModalProps = Omit<ModalProps, 'children'> & {
loading?: boolean
onClickAccept?: (e: React.MouseEvent<unknown>) => void
interface Props {
onClickAccept: () => void
onClose: () => void
open: boolean
loading: boolean
}

export function DeleteProposalModal({ onClickAccept, loading, ...props }: DeleteProposalModalProps) {
export function DeleteProposalModal({ onClickAccept, onClose, open, loading }: Props) {
const t = useFormatMessage()

return (
<Modal
{...props}
size="tiny"
className={classNames('GovernanceActionModal', 'ProposalModal', props.className)}
closeIcon={<Close />}
>
<Modal.Content>
<div className="ProposalModal__Title">
<Header>{t('modal.delete_proposal.title')}</Header>
<Text size="lg">{t('modal.delete_proposal.description')}</Text>
</div>
<div>
<Button fluid primary onClick={onClickAccept} loading={loading}>
{t('modal.delete_proposal.accept')}
</Button>
<Button fluid className="cancel" onClick={props.onClose}>
{t('modal.delete_proposal.reject')}
</Button>
</div>
</Modal.Content>
</Modal>
<ConfirmationModal
isOpen={open}
isLoading={loading}
title={t('modal.delete_proposal.title')}
description={t('modal.delete_proposal.description')}
onPrimaryClick={onClickAccept}
onSecondaryClick={onClose}
onClose={onClose}
primaryButtonText={t('modal.delete_proposal.accept')}
secondaryButtonText={t('modal.delete_proposal.reject')}
/>
)
}
49 changes: 17 additions & 32 deletions src/components/Modal/DeleteUpdateModal/DeleteUpdateModal.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,27 @@
import classNames from 'classnames'
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Close } from 'decentraland-ui/dist/components/Close/Close'
import { Header } from 'decentraland-ui/dist/components/Header/Header'
import { Modal, ModalProps } from 'decentraland-ui/dist/components/Modal/Modal'

import useFormatMessage from '../../../hooks/useFormatMessage'
import Text from '../../Common/Typography/Text'
import '../ProposalModal.css'
import ConfirmationModal from '../ConfirmationModal'

export type DeleteUpdateModal = Omit<ModalProps, 'children'> & {
type Props = {
loading?: boolean
onClickAccept?: (e: React.MouseEvent<unknown>) => void
open: boolean
onClickAccept: () => void
onClose: () => void
}

export function DeleteUpdateModal({ onClickAccept, loading, ...props }: DeleteUpdateModal) {
export function DeleteUpdateModal({ onClickAccept, onClose, loading, open }: Props) {
const t = useFormatMessage()

return (
<Modal
{...props}
size="tiny"
className={classNames('GovernanceActionModal', 'ProposalModal', props.className)}
closeIcon={<Close />}
>
<Modal.Content>
<div className="ProposalModal__Title">
<Header>{t('modal.delete_update.title')}</Header>
<Text size="lg">{t('modal.delete_update.description')}</Text>
</div>
<div>
<Button fluid primary onClick={onClickAccept} loading={loading}>
{t('modal.delete_update.accept')}
</Button>
<Button fluid className="cancel" onClick={props.onClose}>
{t('modal.delete_update.reject')}
</Button>
</div>
</Modal.Content>
</Modal>
<ConfirmationModal
isOpen={open}
isLoading={loading}
title={t('modal.delete_update.title')}
description={t('modal.delete_update.description')}
onPrimaryClick={onClickAccept}
onSecondaryClick={onClose}
onClose={onClose}
primaryButtonText={t('modal.delete_update.accept')}
secondaryButtonText={t('modal.delete_update.reject')}
/>
)
}
Loading

0 comments on commit 2c1058b

Please sign in to comment.