From 68a8f7d53952bf7970aa0393a983ac707d4d3442 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 30 Dec 2022 16:15:35 +0100 Subject: [PATCH 01/10] added Stages section --- .../Stages/StageItem/StageItem.css | 51 ++++++ .../Stages/StageItem/StageItem.css.d.ts | 8 + .../Stages/StageItem/StageItem.tsx | 42 +++++ .../Stages/StageItem/index.ts | 1 + .../DAOIncorporation/Stages/Stages.css | 104 ++++++++++++ .../DAOIncorporation/Stages/Stages.css.d.ts | 10 ++ .../DAOIncorporation/Stages/Stages.tsx | 152 ++++++++++++++++++ .../Stages/StagesButton/StagesButton.css | 14 ++ .../Stages/StagesButton/StagesButton.css.d.ts | 3 + .../Stages/StagesButton/StagesButton.tsx | 85 ++++++++++ .../Stages/StagesButton/index.ts | 1 + .../DAOIncorporation/Stages/index.ts | 1 + .../components/IncorporationPage/constants.ts | 1 + 13 files changed, 473 insertions(+) create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/index.ts diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css new file mode 100644 index 0000000000..3bbfbd6273 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css @@ -0,0 +1,51 @@ +.container { + display: flex; + align-items: baseline; + padding: 9px 0; + position: relative; +} + +.dot { + margin-right: 14px; + height: 7px; + width: 7px; + min-width: 7px; + border: 1px solid var(--temp-grey-blue-7); + border-radius: 50%; +} + +.verticalLine { + height: 60%; + position: absolute; + bottom: -7px; + left: 3px; + border-left: 1px solid var(--temp-grey-6); +} + +.activeDot { + border: 1px solid var(--primary); + background-color: var(--primary); +} + +.label { + margin-bottom: 8px; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: var(--dark); + letter-spacing: var(--spacing-medium); +} + +.activeLabel { + color: var(--temp-grey-blue-7); +} + +.description { + font-size: var(--size-tiny); + font-weight: var(--weight-bold); + color: var(--temp-grey-blue-7); + letter-spacing: var(--spacing-medium); +} + +.completedLabel { + color: var(--temp-grey-blue-7); +} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts new file mode 100644 index 0000000000..76c5a5b024 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts @@ -0,0 +1,8 @@ +export const container: string; +export const dot: string; +export const verticalLine: string; +export const activeDot: string; +export const label: string; +export const activeLabel: string; +export const description: string; +export const completedLabel: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx new file mode 100644 index 0000000000..cf9ad5e928 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { FormattedMessage, MessageDescriptor } from 'react-intl'; +import classNames from 'classnames'; + +import styles from './StageItem.css'; + +interface Props { + title?: MessageDescriptor; + description?: MessageDescriptor; + isActive: boolean; + isLast?: boolean; +} +const displayName = 'dashboard.ExpenditurePage.Stages.StageItem'; + +const StageItem = ({ title, description, isActive, isLast }: Props) => { + return ( +
+
+ {!isLast &&
} +
+
+ +
+
+ +
+
+
+ ); +}; + +StageItem.displayName = displayName; + +export default StageItem; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts new file mode 100644 index 0000000000..234df6a6cb --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts @@ -0,0 +1 @@ +export { default } from './StageItem'; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css new file mode 100644 index 0000000000..cb87d68bb6 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css @@ -0,0 +1,104 @@ +@value iconColor: var(--temp-grey-blue-7); + +.mainContainer { + padding-top: 20px; + max-width: 340px; +} + +.stagesText { + display: flex; + align-items: center; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + line-height: 18px; + color: var(--temp-grey-blue-7); +} + +.statusContainer { + display: flex; + justify-content: space-between; + padding: 10px 0; + border-bottom: 1px solid var(--temp-grey-6); +} + +.statusContainer:first-child { + padding-top: 0; +} + +.icon svg { + height: 18px; + width: 18px; + fill: var(--temp-grey-blue-7); +} + +.buttonsContainer { + display: flex; + align-items: center; +} + +.buttonsContainer button:not(:last-of-type) { + margin-right: 30px; +} + +.buttonsContainer button { + &:disabled { + height: 20px; + border: none; + border-radius: 5px; + background-color: var(--colony-light-blue); + font-weight: var(--weight-bold); + color: var(--temp-grey-blue-7); + } + + &:disabled:hover { + background-color: var(--colony-light-blue); + color: var(--temp-grey-blue-7); + cursor: default; + } +} + +.iconButton { + margin-left: 0; + padding: 0; + border: none; + background-color: transparent; +} + +.iconButton i { + display: flex; +} + +.iconButton:hover { + cursor: pointer; +} + +.iconButtonDisabled { + opacity: 0.5; +} + +.iconWrapper { + position: relative; +} + +.iconWrapper:hover { + &::after { + height: 30px; + width: 30px; + position: absolute; + top: 0; + left: 0; + border-radius: 50%; + background-color: var(--action-secondary); + transform: translate(-6px, -6px); + content: ''; + opacity: 0.1; + } +} + +.iconButtonDisabled:hover { + cursor: not-allowed; +} + +.buttonTooltip { + max-width: 192px; +} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts new file mode 100644 index 0000000000..1c668b5f59 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts @@ -0,0 +1,10 @@ +export const iconColor: string; +export const mainContainer: string; +export const stagesText: string; +export const statusContainer: string; +export const icon: string; +export const buttonsContainer: string; +export const iconButton: string; +export const iconButtonDisabled: string; +export const iconWrapper: string; +export const buttonTooltip: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx new file mode 100644 index 0000000000..d07cff6cf7 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx @@ -0,0 +1,152 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; +import copyToClipboard from 'copy-to-clipboard'; +import classNames from 'classnames'; + +import Button from '~core/Button'; +import Icon from '~core/Icon'; +import { Tooltip } from '~core/Popover'; + +import StageItem from './StageItem'; +import StagesButton from './StagesButton'; +import styles from './Stages.css'; +import { StageObject } from '~pages/IncorporationPage/types'; +import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; + +const MSG = defineMessages({ + stages: { + id: 'dashboard.DAOIncorporation.Stages.stages', + defaultMessage: 'Stages', + }, + deleteDraft: { + id: 'dashboard.DAOIncorporation.Stages.deleteDraft', + defaultMessage: 'Delete draft', + }, + tooltipDeleteText: { + id: 'dashboard.DAOIncorporation.Stages.tooltipDeleteText', + defaultMessage: 'Delete', + }, + tooltipShareText: { + id: 'dashboard.DAOIncorporation.Stages.tooltipShareText', + defaultMessage: 'Share URL', + }, +}); + +const displayName = 'dashboard.DAOIncorporation.Stages'; + +export interface Props { + stages: StageObject[]; + activeStageId: StagesEnum; + buttonDisabled?: boolean; + buttonAction?: VoidFunction; +} + +const Stages = ({ + stages, + activeStageId, + buttonDisabled, + buttonAction, +}: Props) => { + const [valueIsCopied, setValueIsCopied] = useState(false); + const userFeedbackTimer = useRef(null); + + const handleClipboardCopy = () => { + copyToClipboard(window.location.href); + setValueIsCopied(true); + userFeedbackTimer.current = setTimeout(() => setValueIsCopied(false), 2000); + }; + + useEffect(() => () => clearTimeout(userFeedbackTimer.current), [ + userFeedbackTimer, + ]); + + const activeIndex = stages.findIndex((stage) => stage.id === activeStageId); + const activeStage = stages.find((stage) => stage.id === activeStageId); + + return ( +
+
+
+ +
+
+ <> + + + + +
+
+ {stages.map(({ id, title, description }, index) => ( + + ))} +
+ ); +}; + +Stages.displayName = displayName; + +export default Stages; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css new file mode 100644 index 0000000000..5f73f896d7 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css @@ -0,0 +1,14 @@ +.button { + composes: themePrimary main from '~core/Button/Button.css'; + padding: 0; + height: 29px; + width: 100px; +} + +.buttonTooltip { + max-width: 192px; +} + +.buttonWithTooltip { + margin-left: 20px; +} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts new file mode 100644 index 0000000000..5941522346 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts @@ -0,0 +1,3 @@ +export const button: string; +export const buttonTooltip: string; +export const buttonWithTooltip: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx new file mode 100644 index 0000000000..0cc9e5c55e --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx @@ -0,0 +1,85 @@ +import React from 'react'; +import { useIntl } from 'react-intl'; + +import Button from '~core/Button'; +import { Tooltip } from '~core/Popover'; +import { Stages } from '~pages/IncorporationPage/constants'; +import { StageObject } from '~pages/IncorporationPage/types'; + +import styles from './StagesButton.css'; + +const displayName = 'dashboard.ExpenditurePage.Stages.StagesButton'; + +interface Props { + activeStage?: StageObject; + buttonDisabled?: boolean; + buttonAction?: VoidFunction; +} + +const StagesButton = ({ activeStage, buttonDisabled, buttonAction }: Props) => { + const { formatMessage } = useIntl(); + const buttonText = + typeof activeStage?.buttonText === 'string' + ? activeStage.buttonText + : activeStage?.buttonText && formatMessage(activeStage.buttonText); + + if (!activeStage) return null; + + if ( + activeStage.id === Stages.Processing || + activeStage.id === Stages.Complete + ) { + return null; + } + + if (activeStage?.buttonTooltip) { + return ( + + + {typeof activeStage.buttonTooltip === 'string' + ? activeStage.buttonTooltip + : formatMessage(activeStage.buttonTooltip)} +
+ } + popperOptions={{ + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 8], + }, + }, + ], + }} + > + + + + ); + } + + return ( + + ); +}; + +StagesButton.displayName = displayName; + +export default StagesButton; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts new file mode 100644 index 0000000000..4085c13edd --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts @@ -0,0 +1 @@ +export { default } from './StagesButton'; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts new file mode 100644 index 0000000000..11bb6dccd3 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts @@ -0,0 +1 @@ +export { default } from './Stages'; diff --git a/src/modules/pages/components/IncorporationPage/constants.ts b/src/modules/pages/components/IncorporationPage/constants.ts index 1db6ec3bc4..742ff625ea 100644 --- a/src/modules/pages/components/IncorporationPage/constants.ts +++ b/src/modules/pages/components/IncorporationPage/constants.ts @@ -144,6 +144,7 @@ export const stages: StageObject[] = [ title: MSG.create, description: MSG.createDesc, buttonText: MSG.createButtonText, + buttonTooltip: MSG.createTooltip, }, { id: Stages.Created, From ce34406cd6e5fe726a475b581134ea74311bd882 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 2 Jan 2023 14:15:19 +0100 Subject: [PATCH 02/10] added validation --- .../Stages/StageItem/StageItem.css | 51 ------ .../Stages/StageItem/StageItem.css.d.ts | 8 - .../Stages/StageItem/StageItem.tsx | 42 ----- .../Stages/StageItem/index.ts | 1 - .../DAOIncorporation/Stages/Stages.css | 104 ------------ .../DAOIncorporation/Stages/Stages.css.d.ts | 10 -- .../DAOIncorporation/Stages/Stages.tsx | 152 ------------------ .../Stages/StagesButton/StagesButton.css | 14 -- .../Stages/StagesButton/StagesButton.css.d.ts | 3 - .../Stages/StagesButton/StagesButton.tsx | 85 ---------- .../Stages/StagesButton/index.ts | 1 - .../DAOIncorporation/Stages/index.ts | 1 - .../Incorporation/Stages/FormStages.tsx | 108 +++++++++++++ .../components/IncorporationPage/constants.ts | 1 - 14 files changed, 108 insertions(+), 473 deletions(-) delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/index.ts create mode 100644 src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css deleted file mode 100644 index 3bbfbd6273..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css +++ /dev/null @@ -1,51 +0,0 @@ -.container { - display: flex; - align-items: baseline; - padding: 9px 0; - position: relative; -} - -.dot { - margin-right: 14px; - height: 7px; - width: 7px; - min-width: 7px; - border: 1px solid var(--temp-grey-blue-7); - border-radius: 50%; -} - -.verticalLine { - height: 60%; - position: absolute; - bottom: -7px; - left: 3px; - border-left: 1px solid var(--temp-grey-6); -} - -.activeDot { - border: 1px solid var(--primary); - background-color: var(--primary); -} - -.label { - margin-bottom: 8px; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: var(--dark); - letter-spacing: var(--spacing-medium); -} - -.activeLabel { - color: var(--temp-grey-blue-7); -} - -.description { - font-size: var(--size-tiny); - font-weight: var(--weight-bold); - color: var(--temp-grey-blue-7); - letter-spacing: var(--spacing-medium); -} - -.completedLabel { - color: var(--temp-grey-blue-7); -} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts deleted file mode 100644 index 76c5a5b024..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.css.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const container: string; -export const dot: string; -export const verticalLine: string; -export const activeDot: string; -export const label: string; -export const activeLabel: string; -export const description: string; -export const completedLabel: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx deleted file mode 100644 index cf9ad5e928..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/StageItem.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import { FormattedMessage, MessageDescriptor } from 'react-intl'; -import classNames from 'classnames'; - -import styles from './StageItem.css'; - -interface Props { - title?: MessageDescriptor; - description?: MessageDescriptor; - isActive: boolean; - isLast?: boolean; -} -const displayName = 'dashboard.ExpenditurePage.Stages.StageItem'; - -const StageItem = ({ title, description, isActive, isLast }: Props) => { - return ( -
-
- {!isLast &&
} -
-
- -
-
- -
-
-
- ); -}; - -StageItem.displayName = displayName; - -export default StageItem; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts deleted file mode 100644 index 234df6a6cb..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StageItem/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './StageItem'; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css deleted file mode 100644 index cb87d68bb6..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css +++ /dev/null @@ -1,104 +0,0 @@ -@value iconColor: var(--temp-grey-blue-7); - -.mainContainer { - padding-top: 20px; - max-width: 340px; -} - -.stagesText { - display: flex; - align-items: center; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - line-height: 18px; - color: var(--temp-grey-blue-7); -} - -.statusContainer { - display: flex; - justify-content: space-between; - padding: 10px 0; - border-bottom: 1px solid var(--temp-grey-6); -} - -.statusContainer:first-child { - padding-top: 0; -} - -.icon svg { - height: 18px; - width: 18px; - fill: var(--temp-grey-blue-7); -} - -.buttonsContainer { - display: flex; - align-items: center; -} - -.buttonsContainer button:not(:last-of-type) { - margin-right: 30px; -} - -.buttonsContainer button { - &:disabled { - height: 20px; - border: none; - border-radius: 5px; - background-color: var(--colony-light-blue); - font-weight: var(--weight-bold); - color: var(--temp-grey-blue-7); - } - - &:disabled:hover { - background-color: var(--colony-light-blue); - color: var(--temp-grey-blue-7); - cursor: default; - } -} - -.iconButton { - margin-left: 0; - padding: 0; - border: none; - background-color: transparent; -} - -.iconButton i { - display: flex; -} - -.iconButton:hover { - cursor: pointer; -} - -.iconButtonDisabled { - opacity: 0.5; -} - -.iconWrapper { - position: relative; -} - -.iconWrapper:hover { - &::after { - height: 30px; - width: 30px; - position: absolute; - top: 0; - left: 0; - border-radius: 50%; - background-color: var(--action-secondary); - transform: translate(-6px, -6px); - content: ''; - opacity: 0.1; - } -} - -.iconButtonDisabled:hover { - cursor: not-allowed; -} - -.buttonTooltip { - max-width: 192px; -} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts deleted file mode 100644 index 1c668b5f59..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const iconColor: string; -export const mainContainer: string; -export const stagesText: string; -export const statusContainer: string; -export const icon: string; -export const buttonsContainer: string; -export const iconButton: string; -export const iconButtonDisabled: string; -export const iconWrapper: string; -export const buttonTooltip: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx deleted file mode 100644 index d07cff6cf7..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/Stages.tsx +++ /dev/null @@ -1,152 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; -import copyToClipboard from 'copy-to-clipboard'; -import classNames from 'classnames'; - -import Button from '~core/Button'; -import Icon from '~core/Icon'; -import { Tooltip } from '~core/Popover'; - -import StageItem from './StageItem'; -import StagesButton from './StagesButton'; -import styles from './Stages.css'; -import { StageObject } from '~pages/IncorporationPage/types'; -import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; - -const MSG = defineMessages({ - stages: { - id: 'dashboard.DAOIncorporation.Stages.stages', - defaultMessage: 'Stages', - }, - deleteDraft: { - id: 'dashboard.DAOIncorporation.Stages.deleteDraft', - defaultMessage: 'Delete draft', - }, - tooltipDeleteText: { - id: 'dashboard.DAOIncorporation.Stages.tooltipDeleteText', - defaultMessage: 'Delete', - }, - tooltipShareText: { - id: 'dashboard.DAOIncorporation.Stages.tooltipShareText', - defaultMessage: 'Share URL', - }, -}); - -const displayName = 'dashboard.DAOIncorporation.Stages'; - -export interface Props { - stages: StageObject[]; - activeStageId: StagesEnum; - buttonDisabled?: boolean; - buttonAction?: VoidFunction; -} - -const Stages = ({ - stages, - activeStageId, - buttonDisabled, - buttonAction, -}: Props) => { - const [valueIsCopied, setValueIsCopied] = useState(false); - const userFeedbackTimer = useRef(null); - - const handleClipboardCopy = () => { - copyToClipboard(window.location.href); - setValueIsCopied(true); - userFeedbackTimer.current = setTimeout(() => setValueIsCopied(false), 2000); - }; - - useEffect(() => () => clearTimeout(userFeedbackTimer.current), [ - userFeedbackTimer, - ]); - - const activeIndex = stages.findIndex((stage) => stage.id === activeStageId); - const activeStage = stages.find((stage) => stage.id === activeStageId); - - return ( -
-
-
- -
-
- <> - - - - -
-
- {stages.map(({ id, title, description }, index) => ( - - ))} -
- ); -}; - -Stages.displayName = displayName; - -export default Stages; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css deleted file mode 100644 index 5f73f896d7..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css +++ /dev/null @@ -1,14 +0,0 @@ -.button { - composes: themePrimary main from '~core/Button/Button.css'; - padding: 0; - height: 29px; - width: 100px; -} - -.buttonTooltip { - max-width: 192px; -} - -.buttonWithTooltip { - margin-left: 20px; -} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts deleted file mode 100644 index 5941522346..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.css.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const button: string; -export const buttonTooltip: string; -export const buttonWithTooltip: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx deleted file mode 100644 index 0cc9e5c55e..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/StagesButton.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React from 'react'; -import { useIntl } from 'react-intl'; - -import Button from '~core/Button'; -import { Tooltip } from '~core/Popover'; -import { Stages } from '~pages/IncorporationPage/constants'; -import { StageObject } from '~pages/IncorporationPage/types'; - -import styles from './StagesButton.css'; - -const displayName = 'dashboard.ExpenditurePage.Stages.StagesButton'; - -interface Props { - activeStage?: StageObject; - buttonDisabled?: boolean; - buttonAction?: VoidFunction; -} - -const StagesButton = ({ activeStage, buttonDisabled, buttonAction }: Props) => { - const { formatMessage } = useIntl(); - const buttonText = - typeof activeStage?.buttonText === 'string' - ? activeStage.buttonText - : activeStage?.buttonText && formatMessage(activeStage.buttonText); - - if (!activeStage) return null; - - if ( - activeStage.id === Stages.Processing || - activeStage.id === Stages.Complete - ) { - return null; - } - - if (activeStage?.buttonTooltip) { - return ( - - - {typeof activeStage.buttonTooltip === 'string' - ? activeStage.buttonTooltip - : formatMessage(activeStage.buttonTooltip)} -
- } - popperOptions={{ - modifiers: [ - { - name: 'offset', - options: { - offset: [0, 8], - }, - }, - ], - }} - > - - - - ); - } - - return ( - - ); -}; - -StagesButton.displayName = displayName; - -export default StagesButton; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts deleted file mode 100644 index 4085c13edd..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/StagesButton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './StagesButton'; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts b/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts deleted file mode 100644 index 11bb6dccd3..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Stages'; diff --git a/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx b/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx new file mode 100644 index 0000000000..7abb9c16fd --- /dev/null +++ b/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx @@ -0,0 +1,108 @@ +import { useFormikContext, setNestedObjectValues, FormikTouched } from 'formik'; +import React, { useCallback, useMemo } from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +import { flattenObject } from '~dashboard/ExpenditurePage/Stages/utils'; +import { FIX_TRIGGER_EVENT_NAME } from '~pages/ExpenditurePage/constants'; +import { StageObject, ValuesType } from '~pages/IncorporationPage/types'; +import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; + +import Stages from './Stages'; +import styles from './Stages.css'; + +const displayName = 'dashboard.Incorporation.Stages.FormStages'; + +const MSG = defineMessages({ + singleErrorMessage: { + id: 'dashboard.Incorporation.Stages.FormStages.singleErrorMessage', + defaultMessage: '{number} required field has an error.', + }, + mulitpleErrorMessage: { + id: 'dashboard.Incorporation.Stages.FormStages.mulitpleErrorMessage', + defaultMessage: '{number} required fields have an error.', + }, + errorMessageAction: { + id: 'dashboard.Incorporation.Stages.FormStages.errorMessageAction', + defaultMessage: 'Fix it!', + }, +}); + +export interface Props { + stages: StageObject[]; + activeStageId: StagesEnum; +} + +const FormStages = ({ stages, activeStageId }: Props) => { + const { values, handleSubmit, validateForm, setTouched, errors: formikErr } = + useFormikContext() || {}; + + const formikErrors = useMemo(() => { + const errorsFlat = flattenObject(formikErr); + return Object.keys(errorsFlat); + }, [formikErr]); + + const handleSaveDraft = useCallback(async () => { + const errors = await validateForm(values); + const errorsLength = Object.keys(errors)?.length; + setTouched(setNestedObjectValues>(errors, true)); + + return !errorsLength && handleSubmit(values as any); + }, [handleSubmit, setTouched, validateForm, values]); + + const handleFixButtonClick = useCallback(() => { + setTouched( + setNestedObjectValues>(formikErr, true), + ); + if (!formikErrors.length) return; + + const firstError = document.getElementsByName(formikErrors[0])?.[0]; + + if (firstError?.tagName.toLowerCase() === 'input') { + (firstError as HTMLElement).focus(); + } else if (firstError?.tagName.toLowerCase() === 'textarea') { + (firstError as HTMLElement).focus(); + } else { + const customEvent = new CustomEvent(FIX_TRIGGER_EVENT_NAME, { + detail: { + name: formikErrors[0], + }, + }); + + window.dispatchEvent(customEvent); + } + }, [setTouched, formikErr, formikErrors]); + + return ( +
+ {!!formikErrors.length && ( +
+

+ 1 + ? { ...MSG.mulitpleErrorMessage } + : { ...MSG.singleErrorMessage })} + values={{ number: formikErrors.length }} + /> +

+ +
+ )} + + +
+ ); +}; + +FormStages.displayName = displayName; + +export default FormStages; diff --git a/src/modules/pages/components/IncorporationPage/constants.ts b/src/modules/pages/components/IncorporationPage/constants.ts index 742ff625ea..1db6ec3bc4 100644 --- a/src/modules/pages/components/IncorporationPage/constants.ts +++ b/src/modules/pages/components/IncorporationPage/constants.ts @@ -144,7 +144,6 @@ export const stages: StageObject[] = [ title: MSG.create, description: MSG.createDesc, buttonText: MSG.createButtonText, - buttonTooltip: MSG.createTooltip, }, { id: Stages.Created, From b03a652c1ef20ed375ec684f9c957ca3b9b63ad4 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 23 Jan 2023 11:05:36 +0100 Subject: [PATCH 03/10] fixed condition, removed unnecessary type --- .../dashboard/components/Incorporation/Stages/FormStages.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx b/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx index 7abb9c16fd..606ef0e586 100644 --- a/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx +++ b/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx @@ -57,9 +57,7 @@ const FormStages = ({ stages, activeStageId }: Props) => { const firstError = document.getElementsByName(formikErrors[0])?.[0]; - if (firstError?.tagName.toLowerCase() === 'input') { - (firstError as HTMLElement).focus(); - } else if (firstError?.tagName.toLowerCase() === 'textarea') { + if (['textarea', 'input'].includes(firstError?.tagName.toLowerCase())) { (firstError as HTMLElement).focus(); } else { const customEvent = new CustomEvent(FIX_TRIGGER_EVENT_NAME, { From ac349cfdfbb57761cbd0bd540e32b1229eb1ad5b Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 23 Jan 2023 09:39:25 +0100 Subject: [PATCH 04/10] fixed type errors --- .../Incorporation/IncorporationForm/Protectors/Protectors.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index 4fa7617d57..2f5e47a80b 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -17,7 +17,6 @@ import Button from '~core/Button'; import Link from '~core/Link'; import SingleUserPicker from '../SingleUserPicker'; -import { SignOption } from '../constants'; import styles from './Protectors.css'; From 7187a9f6f5eb31b79ca3fea019a80ddb92e1b3cf Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 2 Jan 2023 14:15:19 +0100 Subject: [PATCH 05/10] added validation --- .../SingleUserPicker/SingleUserPicker.css | 35 ++++++ .../SingleUserPicker.css.d.ts | 4 + .../SingleUserPicker/SingleUserPicker.tsx | 70 ++++++++++++ .../SingleUserPicker/index.ts | 1 + .../DAOIncorporation/Stages/FormStages.tsx | 108 ++++++++++++++++++ 5 files changed, 218 insertions(+) create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css new file mode 100644 index 0000000000..2c0af7fa16 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css @@ -0,0 +1,35 @@ +.protectorWrapper { + display: flex; + justify-content: space-between; + padding: 11px 0 14px; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); +} + +.selectWrapper { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.protectorError { + font-size: var(--size-tiny); + white-space: nowrap; + color: var(--danger); + letter-spacing: var(--spacing-medium); +} + +.protectorWrapper label { + margin-right: 0; +} + +.deleteIcon { + height: 20px; + width: 20px; + fill: var(--pink); +} + +.deleteIcon:hover { + cursor: pointer; +} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts new file mode 100644 index 0000000000..3119c86cca --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts @@ -0,0 +1,4 @@ +export const protectorWrapper: string; +export const selectWrapper: string; +export const protectorError: string; +export const deleteIcon: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx new file mode 100644 index 0000000000..2fe3fcc6fe --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx @@ -0,0 +1,70 @@ +import React from 'react'; +import { defineMessages, useIntl } from 'react-intl'; +import { FieldArrayRenderProps, useField } from 'formik'; + +import { AnyUser } from '~data/index'; +import Icon from '~core/Icon'; +import UserPickerWithSearch from '~core/UserPickerWithSearch'; +import { Props as UserPickerProps } from '~core/UserPickerWithSearch/UserPickerWithSearch'; + +import styles from './SingleUserPicker.css'; + +export const MSG = defineMessages({ + deleteIconTitle: { + id: `dashboard.DAOIncorporation.IncorporationForm.SingleUserPicker.deleteIconTitle`, + defaultMessage: 'Delete recipient', + }, +}); + +const displayName = + 'dashboard.DAOIncorporation.IncorporationForm.SingleUserPicker'; + +export interface Props extends UserPickerProps { + sidebarRef: HTMLElement | null; + name: string; + onSelected?: (value: AnyUser) => void; + remove: FieldArrayRenderProps['remove']; + index: number; + setMainContact: (value: any, shouldValidate?: boolean | undefined) => void; +} + +const SingleUserPicker = ({ + name, + remove, + index, + setMainContact, + ...rest +}: Props) => { + const [, { error, touched, value }] = useField(name); + const [, { value: mainContact }] = useField('mainContact'); + const { formatMessage } = useIntl(); + + const errorMessage = + error && typeof error === 'object' && formatMessage(error); + + return ( +
+
+ + {errorMessage && touched && ( +
{errorMessage}
+ )} +
+ { + remove(index); + if (value.id === mainContact.id) { + setMainContact(undefined); + } + }} + title={MSG.deleteIconTitle} + /> +
+ ); +}; + +SingleUserPicker.displayName = displayName; + +export default SingleUserPicker; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts new file mode 100644 index 0000000000..4168664eb6 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts @@ -0,0 +1 @@ +export { default } from './SingleUserPicker'; diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx new file mode 100644 index 0000000000..37d9f3673c --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx @@ -0,0 +1,108 @@ +import { useFormikContext, setNestedObjectValues, FormikTouched } from 'formik'; +import React, { useCallback, useMemo } from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +import { flattenObject } from '~dashboard/ExpenditurePage/Stages/utils'; +import { FIX_TRIGGER_EVENT_NAME } from '~pages/ExpenditurePage/constants'; +import { StageObject, ValuesType } from '~pages/IncorporationPage/types'; +import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; + +import Stages from './Stages'; +import styles from './Stages.css'; + +const displayName = 'dashboard.DAOIncorporation.Stages.FormStages'; + +const MSG = defineMessages({ + singleErrorMessage: { + id: 'dashboard.DAOIncorporation.Stages.FormStages.singleErrorMessage', + defaultMessage: '{number} required field has an error.', + }, + mulitpleErrorMessage: { + id: 'dashboard.DAOIncorporation.Stages.FormStages.mulitpleErrorMessage', + defaultMessage: '{number} required fields have an error.', + }, + errorMessageAction: { + id: 'dashboard.DAOIncorporation.Stages.FormStages.errorMessageAction', + defaultMessage: 'Fix it!', + }, +}); + +export interface Props { + stages: StageObject[]; + activeStageId: StagesEnum; +} + +const FormStages = ({ stages, activeStageId }: Props) => { + const { values, handleSubmit, validateForm, setTouched, errors: formikErr } = + useFormikContext() || {}; + + const formikErrors = useMemo(() => { + const errorsFlat = flattenObject(formikErr); + return Object.keys(errorsFlat); + }, [formikErr]); + + const handleSaveDraft = useCallback(async () => { + const errors = await validateForm(values); + const errorsLength = Object.keys(errors)?.length; + setTouched(setNestedObjectValues>(errors, true)); + + return !errorsLength && handleSubmit(values as any); + }, [handleSubmit, setTouched, validateForm, values]); + + const handleFixButtonClick = useCallback(() => { + setTouched( + setNestedObjectValues>(formikErr, true), + ); + if (!formikErrors.length) return; + + const firstError = document.getElementsByName(formikErrors[0])?.[0]; + + if (firstError?.tagName.toLowerCase() === 'input') { + (firstError as HTMLElement).focus(); + } else if (firstError?.tagName.toLowerCase() === 'textarea') { + (firstError as HTMLElement).focus(); + } else { + const customEvent = new CustomEvent(FIX_TRIGGER_EVENT_NAME, { + detail: { + name: formikErrors[0], + }, + }); + + window.dispatchEvent(customEvent); + } + }, [setTouched, formikErr, formikErrors]); + + return ( +
+ {!!formikErrors.length && ( +
+

+ 1 + ? { ...MSG.mulitpleErrorMessage } + : { ...MSG.singleErrorMessage })} + values={{ number: formikErrors.length }} + /> +

+ +
+ )} + + +
+ ); +}; + +FormStages.displayName = displayName; + +export default FormStages; From 5226314171f3c3b0fd4794c840f4ed70f844d193 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Thu, 5 Jan 2023 12:24:08 +0100 Subject: [PATCH 06/10] added locked sidebar --- .../DAOIncorporation/IncorporationForm/constants.ts | 9 +++++++++ .../IncorporationForm/Protectors/Protectors.tsx | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts new file mode 100644 index 0000000000..8d8f7ec174 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts @@ -0,0 +1,9 @@ +export enum SignOption { + Individual = 'Individual', + Multiple = 'Multiple', +} + +export enum VerificationStatus { + Verified = 'Verified', + Unverified = 'Unverified', +} diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index 2f5e47a80b..4fa7617d57 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -17,6 +17,7 @@ import Button from '~core/Button'; import Link from '~core/Link'; import SingleUserPicker from '../SingleUserPicker'; +import { SignOption } from '../constants'; import styles from './Protectors.css'; From 7e90a475e4e752e7ede94c8f16282976f1c429f2 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 13 Jan 2023 13:14:21 +0100 Subject: [PATCH 07/10] renamed to Incorporation --- .../SingleUserPicker/SingleUserPicker.css | 35 ------ .../SingleUserPicker.css.d.ts | 4 - .../SingleUserPicker/SingleUserPicker.tsx | 70 ------------ .../SingleUserPicker/index.ts | 1 - .../IncorporationForm/constants.ts | 9 -- .../DAOIncorporation/Stages/FormStages.tsx | 108 ------------------ 6 files changed, 227 deletions(-) delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css deleted file mode 100644 index 2c0af7fa16..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css +++ /dev/null @@ -1,35 +0,0 @@ -.protectorWrapper { - display: flex; - justify-content: space-between; - padding: 11px 0 14px; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); -} - -.selectWrapper { - display: flex; - justify-content: flex-start; - align-items: center; -} - -.protectorError { - font-size: var(--size-tiny); - white-space: nowrap; - color: var(--danger); - letter-spacing: var(--spacing-medium); -} - -.protectorWrapper label { - margin-right: 0; -} - -.deleteIcon { - height: 20px; - width: 20px; - fill: var(--pink); -} - -.deleteIcon:hover { - cursor: pointer; -} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts deleted file mode 100644 index 3119c86cca..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.css.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const protectorWrapper: string; -export const selectWrapper: string; -export const protectorError: string; -export const deleteIcon: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx deleted file mode 100644 index 2fe3fcc6fe..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/SingleUserPicker.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React from 'react'; -import { defineMessages, useIntl } from 'react-intl'; -import { FieldArrayRenderProps, useField } from 'formik'; - -import { AnyUser } from '~data/index'; -import Icon from '~core/Icon'; -import UserPickerWithSearch from '~core/UserPickerWithSearch'; -import { Props as UserPickerProps } from '~core/UserPickerWithSearch/UserPickerWithSearch'; - -import styles from './SingleUserPicker.css'; - -export const MSG = defineMessages({ - deleteIconTitle: { - id: `dashboard.DAOIncorporation.IncorporationForm.SingleUserPicker.deleteIconTitle`, - defaultMessage: 'Delete recipient', - }, -}); - -const displayName = - 'dashboard.DAOIncorporation.IncorporationForm.SingleUserPicker'; - -export interface Props extends UserPickerProps { - sidebarRef: HTMLElement | null; - name: string; - onSelected?: (value: AnyUser) => void; - remove: FieldArrayRenderProps['remove']; - index: number; - setMainContact: (value: any, shouldValidate?: boolean | undefined) => void; -} - -const SingleUserPicker = ({ - name, - remove, - index, - setMainContact, - ...rest -}: Props) => { - const [, { error, touched, value }] = useField(name); - const [, { value: mainContact }] = useField('mainContact'); - const { formatMessage } = useIntl(); - - const errorMessage = - error && typeof error === 'object' && formatMessage(error); - - return ( -
-
- - {errorMessage && touched && ( -
{errorMessage}
- )} -
- { - remove(index); - if (value.id === mainContact.id) { - setMainContact(undefined); - } - }} - title={MSG.deleteIconTitle} - /> -
- ); -}; - -SingleUserPicker.displayName = displayName; - -export default SingleUserPicker; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts deleted file mode 100644 index 4168664eb6..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/SingleUserPicker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './SingleUserPicker'; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts deleted file mode 100644 index 8d8f7ec174..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts +++ /dev/null @@ -1,9 +0,0 @@ -export enum SignOption { - Individual = 'Individual', - Multiple = 'Multiple', -} - -export enum VerificationStatus { - Verified = 'Verified', - Unverified = 'Unverified', -} diff --git a/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx b/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx deleted file mode 100644 index 37d9f3673c..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/Stages/FormStages.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { useFormikContext, setNestedObjectValues, FormikTouched } from 'formik'; -import React, { useCallback, useMemo } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; - -import { flattenObject } from '~dashboard/ExpenditurePage/Stages/utils'; -import { FIX_TRIGGER_EVENT_NAME } from '~pages/ExpenditurePage/constants'; -import { StageObject, ValuesType } from '~pages/IncorporationPage/types'; -import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; - -import Stages from './Stages'; -import styles from './Stages.css'; - -const displayName = 'dashboard.DAOIncorporation.Stages.FormStages'; - -const MSG = defineMessages({ - singleErrorMessage: { - id: 'dashboard.DAOIncorporation.Stages.FormStages.singleErrorMessage', - defaultMessage: '{number} required field has an error.', - }, - mulitpleErrorMessage: { - id: 'dashboard.DAOIncorporation.Stages.FormStages.mulitpleErrorMessage', - defaultMessage: '{number} required fields have an error.', - }, - errorMessageAction: { - id: 'dashboard.DAOIncorporation.Stages.FormStages.errorMessageAction', - defaultMessage: 'Fix it!', - }, -}); - -export interface Props { - stages: StageObject[]; - activeStageId: StagesEnum; -} - -const FormStages = ({ stages, activeStageId }: Props) => { - const { values, handleSubmit, validateForm, setTouched, errors: formikErr } = - useFormikContext() || {}; - - const formikErrors = useMemo(() => { - const errorsFlat = flattenObject(formikErr); - return Object.keys(errorsFlat); - }, [formikErr]); - - const handleSaveDraft = useCallback(async () => { - const errors = await validateForm(values); - const errorsLength = Object.keys(errors)?.length; - setTouched(setNestedObjectValues>(errors, true)); - - return !errorsLength && handleSubmit(values as any); - }, [handleSubmit, setTouched, validateForm, values]); - - const handleFixButtonClick = useCallback(() => { - setTouched( - setNestedObjectValues>(formikErr, true), - ); - if (!formikErrors.length) return; - - const firstError = document.getElementsByName(formikErrors[0])?.[0]; - - if (firstError?.tagName.toLowerCase() === 'input') { - (firstError as HTMLElement).focus(); - } else if (firstError?.tagName.toLowerCase() === 'textarea') { - (firstError as HTMLElement).focus(); - } else { - const customEvent = new CustomEvent(FIX_TRIGGER_EVENT_NAME, { - detail: { - name: formikErrors[0], - }, - }); - - window.dispatchEvent(customEvent); - } - }, [setTouched, formikErr, formikErrors]); - - return ( -
- {!!formikErrors.length && ( -
-

- 1 - ? { ...MSG.mulitpleErrorMessage } - : { ...MSG.singleErrorMessage })} - values={{ number: formikErrors.length }} - /> -

- -
- )} - - -
- ); -}; - -FormStages.displayName = displayName; - -export default FormStages; From 9b8a673709c80fb51a14e7b6dd71d47131a433e6 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 27 Jan 2023 14:17:10 +0100 Subject: [PATCH 08/10] removed duplicated import --- .../Incorporation/IncorporationForm/Protectors/Protectors.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index 4fa7617d57..2f5e47a80b 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -17,7 +17,6 @@ import Button from '~core/Button'; import Link from '~core/Link'; import SingleUserPicker from '../SingleUserPicker'; -import { SignOption } from '../constants'; import styles from './Protectors.css'; From 831e255355b923386d43022111d3c6cd9dd4ef1c Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 13 Feb 2023 09:04:11 +0100 Subject: [PATCH 09/10] added motion dot --- .../LockedIncorporationForm.tsx | 9 +++- .../LockedProtectors/LockedProtectors.css | 18 +++++++ .../LockedProtectors.css.d.ts | 2 + .../LockedProtectors/LockedProtectors.tsx | 49 ++++++++++++++----- .../IncorporationPage/IncorporationPage.tsx | 7 +++ 5 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx index 212d48dc78..e580e26725 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx @@ -47,9 +47,14 @@ const displayName = `dashboard.Incorporation.IncorporationForm.LockedIncorporati export interface Props { formValues: ValuesType; activeStageId: Stages; + pendingMotion?: boolean; } -const LockedIncorporationForm = ({ formValues, activeStageId }: Props) => { +const LockedIncorporationForm = ({ + formValues, + activeStageId, + pendingMotion, +}: Props) => { const { alternativeName1: altName1, alternativeName2: altName2 } = formValues; const alternativeNames = useMemo( () => [ @@ -136,7 +141,7 @@ const LockedIncorporationForm = ({ formValues, activeStageId }: Props) => {
{formValues.purpose}
- +
); }; diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css index c1f38e1145..e89bbb9648 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css @@ -104,3 +104,21 @@ animation-name: fadeIn; animation-duration: 500ms; } + +.dot { + height: 9px; + width: 9px; + border-radius: 50%; + background-color: var(--golden); +} + +.labelDotWrapper { + display: flex; + align-items: center; + justify-content: space-between; +} + +/* targets toolitp */ +.labelDotWrapper > div:last-of-type { + max-width: 220px; +} diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts index c7955a631f..fc1e41ae79 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts @@ -10,3 +10,5 @@ export const signOptionWrapper: string; export const signing: string; export const mianContactWrapper: string; export const fadeIn: string; +export const dot: string; +export const labelDotWrapper: string; diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx index 58cb25f4b9..4684e70302 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx @@ -8,6 +8,7 @@ import UserAvatar from '~core/UserAvatar'; import UserMention from '~core/UserMention'; import Tag from '~core/Tag'; import Link from '~core/Link'; +import { Tooltip } from '~core/Popover'; import { SignOption, VerificationStatus } from '../constants'; @@ -54,15 +55,20 @@ export const MSG = defineMessages({ id: `dashboard.Incorporation.IncorporationForm.LockedProtectors.multiple`, defaultMessage: 'All need to sign', }, + motionTooltip: { + id: `dashboard.Incorporation.IncorporationForm.LockedProtectors.motionTooltip`, + defaultMessage: `There is an active Motion to change this application.`, + }, }); const displayName = `dashboard.Incorporation.IncorporationForm.LockedProtectors`; export interface Props { formValues: ValuesType; + pendingMotion?: boolean; } -const LockedProtectors = ({ formValues }: Props) => { +const LockedProtectors = ({ formValues, pendingMotion }: Props) => { const signLabel = useMemo(() => { return formValues.signOption === SignOption.Individual ? MSG.individual @@ -73,17 +79,38 @@ const LockedProtectors = ({ formValues }: Props) => { <>
-
-
- +
+
+
+ +
+ {chunks}, // link is a mock, add redirection to the correct page + }} + interactive + />
- {chunks}, // link is a mock, add redirection to the correct page - }} - interactive - /> + {pendingMotion && ( + } + popperOptions={{ + modifiers: [ + { + name: 'offset', + options: { + offset: [-2, 6], + }, + }, + ], + }} + > +
+ + )}
diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index 3bd76343fb..d21aaa22a0 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -169,6 +169,12 @@ const IncorporationPage = () => { ); }, [colonyData, openCancelIncorporationDialog]); + const pendingMotion = useMemo( + () => + motions?.find((motionItem) => motionItem.status === MotionStatus.Pending), + [motions], + ); + return isFormEditable ? ( { ) )} From 976bd652232824ed4830246ec4d2e99a33ff165e Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Thu, 13 Apr 2023 00:03:55 +0200 Subject: [PATCH 10/10] fixed types --- .../Protectors/Protectors.tsx | 1 + .../Incorporation/Stages/FormStages.tsx | 106 ------------------ .../IncorporationPage/IncorporationPage.tsx | 5 +- 3 files changed, 4 insertions(+), 108 deletions(-) delete mode 100644 src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index 2f5e47a80b..4fa7617d57 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -17,6 +17,7 @@ import Button from '~core/Button'; import Link from '~core/Link'; import SingleUserPicker from '../SingleUserPicker'; +import { SignOption } from '../constants'; import styles from './Protectors.css'; diff --git a/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx b/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx deleted file mode 100644 index 606ef0e586..0000000000 --- a/src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import { useFormikContext, setNestedObjectValues, FormikTouched } from 'formik'; -import React, { useCallback, useMemo } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; - -import { flattenObject } from '~dashboard/ExpenditurePage/Stages/utils'; -import { FIX_TRIGGER_EVENT_NAME } from '~pages/ExpenditurePage/constants'; -import { StageObject, ValuesType } from '~pages/IncorporationPage/types'; -import { Stages as StagesEnum } from '~pages/IncorporationPage/constants'; - -import Stages from './Stages'; -import styles from './Stages.css'; - -const displayName = 'dashboard.Incorporation.Stages.FormStages'; - -const MSG = defineMessages({ - singleErrorMessage: { - id: 'dashboard.Incorporation.Stages.FormStages.singleErrorMessage', - defaultMessage: '{number} required field has an error.', - }, - mulitpleErrorMessage: { - id: 'dashboard.Incorporation.Stages.FormStages.mulitpleErrorMessage', - defaultMessage: '{number} required fields have an error.', - }, - errorMessageAction: { - id: 'dashboard.Incorporation.Stages.FormStages.errorMessageAction', - defaultMessage: 'Fix it!', - }, -}); - -export interface Props { - stages: StageObject[]; - activeStageId: StagesEnum; -} - -const FormStages = ({ stages, activeStageId }: Props) => { - const { values, handleSubmit, validateForm, setTouched, errors: formikErr } = - useFormikContext() || {}; - - const formikErrors = useMemo(() => { - const errorsFlat = flattenObject(formikErr); - return Object.keys(errorsFlat); - }, [formikErr]); - - const handleSaveDraft = useCallback(async () => { - const errors = await validateForm(values); - const errorsLength = Object.keys(errors)?.length; - setTouched(setNestedObjectValues>(errors, true)); - - return !errorsLength && handleSubmit(values as any); - }, [handleSubmit, setTouched, validateForm, values]); - - const handleFixButtonClick = useCallback(() => { - setTouched( - setNestedObjectValues>(formikErr, true), - ); - if (!formikErrors.length) return; - - const firstError = document.getElementsByName(formikErrors[0])?.[0]; - - if (['textarea', 'input'].includes(firstError?.tagName.toLowerCase())) { - (firstError as HTMLElement).focus(); - } else { - const customEvent = new CustomEvent(FIX_TRIGGER_EVENT_NAME, { - detail: { - name: formikErrors[0], - }, - }); - - window.dispatchEvent(customEvent); - } - }, [setTouched, formikErr, formikErrors]); - - return ( -
- {!!formikErrors.length && ( -
-

- 1 - ? { ...MSG.mulitpleErrorMessage } - : { ...MSG.singleErrorMessage })} - values={{ number: formikErrors.length }} - /> -

- -
- )} - - -
- ); -}; - -FormStages.displayName = displayName; - -export default FormStages; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index d21aaa22a0..f5cb30bade 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; import { useParams } from 'react-router'; import { Formik } from 'formik'; import classNames from 'classnames'; +import { isEmpty } from 'lodash'; import { useColonyFromNameQuery } from '~data/generated'; import { getMainClasses } from '~utils/css'; @@ -53,7 +54,7 @@ const IncorporationPage = () => { const notVerified = true; // temporary valule const openPayDialog = useDialog(IncorporationPaymentDialog); - const [motion, setMotions] = useState([]); + const [motions, setMotions] = useState([]); const handleSubmit = useCallback((values) => { setFormValues(values); @@ -264,7 +265,7 @@ const IncorporationPage = () => { colony={colonyData?.processedColony} viewFor={ViewFor.INCORPORATION} handleCancel={handleCancelIncorporation} - motion={motion} + motion={motions} /> )}