From 7a654dcff83cc875ff148660a0dc39ee61f07efb Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 30 Dec 2022 16:15:35 +0100 Subject: [PATCH 01/15] 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 311d840016..ddaae0e2e3 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 21a3f4728b9334b40759cca37d4baee1c544ee47 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 2 Jan 2023 14:15:19 +0100 Subject: [PATCH 02/15] 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 ddaae0e2e3..311d840016 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 97dfd674ff8ecd662df6713fe0d6bea062eb8708 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 23 Jan 2023 11:05:36 +0100 Subject: [PATCH 03/15] 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 842f3cfab3123be68a54a49e6b8115807ac7a465 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Tue, 3 Jan 2023 12:47:51 +0100 Subject: [PATCH 04/15] [wip]locked sidebar form --- .../LockedIncorporationForm.css | 113 +++++++++++++++ .../LockedIncorporationForm.css.d.ts | 13 ++ .../LockedIncorporationForm.tsx | 131 ++++++++++++++++++ .../LockedIncorporationForm/index.ts | 1 + .../LockedProtectors/LockedProtectors.css | 47 +++++++ .../LockedProtectors.css.d.ts | 10 ++ .../LockedProtectors/LockedProtectors.tsx | 101 ++++++++++++++ .../LockedProtectors/index.ts | 1 + .../IncorporationPage/IncorporationPage.tsx | 2 + 9 files changed, 419 insertions(+) create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css new file mode 100644 index 0000000000..825f2e246a --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css @@ -0,0 +1,113 @@ +@value paddingTop: 46px; +@value lockedPaddingTop: 75px; +@value paddingRightLeftBottom: 54px; + +.container { + padding: paddingTop paddingRightLeftBottom paddingRightLeftBottom; +} + +.costRow { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; +} + +.cost { + display: flex; + align-items: center; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); + letter-spacing: var(--spacing-medium); +} + +.cost i { + margin-right: 8px; +} + +.labelWrapper { + display: flex; + align-items: center; + justify-content: flex-start; +} + +.labelWrapper label { + margin-right: 8px; + width: auto; +} + +.labelWrapper > div { + max-width: 250px; +} + +.nameInputs { + padding: 12px 0 0 0; +} + +.nameInputs input { + height: 44px; + font-size: var(--size-normal); + font-weight: var(--weight-bold); + color: var(--dark); + letter-spacing: var(--spacing-normal); +} + +.nameInputs > div:not(:first-child) { + margin-bottom: 12px; +} + +.nameInputs label { + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); +} + +.namesWrapper { + /* border: 1px solid red */ +} + +.namesWrapper label { + flex: 1; + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); + letter-spacing: var(--spacing-medium); +} + +.description { + /* border: 1px solid red */ +} + +.descriptionWrapper { + display: flex; + align-items: baseline; +} + +.descriptionWrapper label { + flex: 1; + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); + letter-spacing: var(--spacing-medium); +} + +.descriptionWrapper > div { + flex: 2.5; + font-size: var(--size-normal); + font-weight: var(--weight-bold); + text-align: right; + color: color-mod(var(--dark) alpha(85%)); + letter-spacing: 0.1px; +} + +.title { + margin-bottom: 16px; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); + letter-spacing: var(--spacing-medium); +} + +.label { + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); + letter-spacing: var(--spacing-medium); +} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts new file mode 100644 index 0000000000..ac2d41545d --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts @@ -0,0 +1,13 @@ +export const paddingTop: string; +export const lockedPaddingTop: string; +export const paddingRightLeftBottom: string; +export const container: string; +export const costRow: string; +export const cost: string; +export const labelWrapper: string; +export const nameInputs: string; +export const namesWrapper: string; +export const description: string; +export const descriptionWrapper: string; +export const title: string; +export const label: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx new file mode 100644 index 0000000000..f5c6001ebe --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx @@ -0,0 +1,131 @@ +import React from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +import { FormSection, InputLabel, SelectHorizontal, Form } from '~core/Fields'; +import { Colony } from '~data/index'; +import Icon from '~core/Icon'; +import { ValuesType } from '~pages/IncorporationPage/types'; + +import LockedProtectors from '../LockedProtectors'; + +import styles from './LockedIncorporationForm.css'; + +export const MSG = defineMessages({ + incorporation: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.incorporation`, + defaultMessage: 'Incorporation', + }, + initialCost: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.initialCost`, + defaultMessage: 'Initial cost', + }, + ongoingCost: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.ongoingCost`, + defaultMessage: 'Ongoing cost', + }, + cost: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.cost`, + defaultMessage: '{icon} {amount} {currency}', + }, + nameLabel: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.nameLabel`, + defaultMessage: 'Corporation name', + }, + descriptionLabel: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.descriptionLabel`, + defaultMessage: 'DAO Purpose', + }, +}); + +const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm`; + +export interface Props { + sidebarRef: HTMLElement | null; + colony: Colony; + formValues: ValuesType; +} + +const LockedIncorporationForm = ({ sidebarRef }: Props) => { + return ( +
+ +
+ +
+
+ +
+
+ +
+
+ , + amount: '5,300', + currency: 'USDC', + }} + /> +
+
+
+ +
+
+ +
+
+ , + amount: '3,800 / year', + currency: 'USDC', + }} + /> +
+
+
+ +
+ {/* */} +
{}}> + + +
+
+ +
+ +
+ WallStreetBets is on a mission to deploy decentralized satellites in + our skies. +
+
+
+ +
+ ); +}; + +LockedIncorporationForm.displayName = displayName; + +export default LockedIncorporationForm; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts new file mode 100644 index 0000000000..836476fa94 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts @@ -0,0 +1 @@ +export { default } from './LockedIncorporationForm'; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css new file mode 100644 index 0000000000..5c898c4e6a --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css @@ -0,0 +1,47 @@ +.wrapper { + /* border: 1px solid red */ +} + +.protectorsLabelWrapper { + /* border: 1px solid red */ +} + +.label { + /* border: 1px solid red */ +} + +.userAvatarContainer { + /* border: 1px solid red */ +} + +.userName { + /* border: 1px solid red */ +} + +.row { + display: flex; +} + +.row label { + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); +} + +.signing { + /* border: 1px solid red */ +} + +.labelWrapper { + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); +} + +.signOptionWrapper { + /* border: 1px solid red */ +} + +.signOptionLabel { + /* border: 1px solid red */ +} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts new file mode 100644 index 0000000000..dc35015ce0 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts @@ -0,0 +1,10 @@ +export const wrapper: string; +export const protectorsLabelWrapper: string; +export const label: string; +export const userAvatarContainer: string; +export const userName: string; +export const row: string; +export const signing: string; +export const labelWrapper: string; +export const signOptionWrapper: string; +export const signOptionLabel: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx new file mode 100644 index 0000000000..1f106508bb --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +import { FormSection, InputLabel } from '~core/Fields'; +import QuestionMarkTooltip from '~core/QuestionMarkTooltip'; +import { Colony } from '~data/index'; + +import styles from './LockedProtectors.css'; +import { ValuesType } from '~pages/IncorporationPage/types'; + +export const MSG = defineMessages({ + protectors: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.protectors`, + defaultMessage: 'Protectors', + }, + protectorsTooltip: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.protectorsTooltip`, + defaultMessage: `A Protector's role in a DAO legal corporation is to ratify the decisions of the DAO. Their purpose is to act on behalf of the DAO and handle legal the required administration. Learn more`, + }, + unverified: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.unverified`, + defaultMessage: 'Unverified', + }, + verified: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.verified`, + defaultMessage: 'Verified', + }, + mainContact: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.mainContact`, + defaultMessage: 'Main contact', + }, + signing: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.signing`, + defaultMessage: 'Signing', + }, + mainContactTooltip: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.mainContactTooltip`, + defaultMessage: `The main contact is required during the incorporation process and is also required to use their delivery address details for the registration.`, + }, + signOptionTooltip: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.signOptionTooltip`, + defaultMessage: `Decide the requirements as to how many Protectors are required to sign legal documents to enact the decisions of a DAO.`, + }, +}); + +const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors`; + +export interface Props { + protectors: ValuesType['protectors']; + colony: Colony; +} + +const LockedProtectors = () => { + return ( + <> + +
+
+
+ +
+ +
+
+
+ + {/* {protectors?.map((protector) => { + return ( +
+ +
+ +
+
+ )})} */} +
+ +
+ + {/*
+ +
+ +
+
*/} +
+
+
+
+ + +
+
All need to sign
+
+ + ); +}; + +LockedProtectors.displayName = displayName; + +export default LockedProtectors; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts new file mode 100644 index 0000000000..2c15a2c788 --- /dev/null +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts @@ -0,0 +1 @@ +export { default } from './LockedProtectors'; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index e5475565aa..5964a27307 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -23,6 +23,8 @@ import { } from './constants'; import { ValuesType } from './types'; import styles from './IncorporationPage.css'; +import { ValuesType } from './types'; +import LockedIncorporationForm from '~dashboard/DAOIncorporation/IncorporationForm/LockedIncorporationForm'; const displayName = 'pages.IncorporationPage'; From 5ee96fea877d2f5dd9b212cadd028f1ac4faed71 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Thu, 5 Jan 2023 12:24:08 +0100 Subject: [PATCH 05/15] added locked sidebar --- .../LockedIncorporationForm.css | 48 ++++++--- .../LockedIncorporationForm.css.d.ts | 5 +- .../LockedIncorporationForm.tsx | 43 ++++---- .../LockedProtectors/LockedProtectors.css | 68 ++++++++++--- .../LockedProtectors.css.d.ts | 4 +- .../LockedProtectors/LockedProtectors.tsx | 99 ++++++++++++++----- .../IncorporationForm/constants.ts | 9 ++ 7 files changed, 196 insertions(+), 80 deletions(-) create mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css index 825f2e246a..85f0a651fc 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css @@ -2,6 +2,16 @@ @value lockedPaddingTop: 75px; @value paddingRightLeftBottom: 54px; +@keyframes slideDown { + 0% { + max-height: 0; + } + + 100% { + max-height: 180px; + } +} + .container { padding: paddingTop paddingRightLeftBottom paddingRightLeftBottom; } @@ -63,23 +73,10 @@ color: color-mod(var(--dark) alpha(85%)); } -.namesWrapper { - /* border: 1px solid red */ -} - -.namesWrapper label { - flex: 1; - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.description { - /* border: 1px solid red */ -} - .descriptionWrapper { display: flex; align-items: baseline; + padding: 12px 0; } .descriptionWrapper label { @@ -88,7 +85,7 @@ letter-spacing: var(--spacing-medium); } -.descriptionWrapper > div { +.description { flex: 2.5; font-size: var(--size-normal); font-weight: var(--weight-bold); @@ -111,3 +108,24 @@ color: color-mod(var(--temp-grey-blue-7) alpha(85%)); letter-spacing: var(--spacing-medium); } + +.namesWrapper label { + flex: 1; + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); + letter-spacing: var(--spacing-medium); +} + +.namesWrapper ul { + position: static; + overflow: hidden; + animation-name: slideDown; + animation-duration: 250ms; +} + +.namesWrapper span { + font-size: var(--size-smallish); +} + +.namesWrapper li:hover { + background-color: transparent; +} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts index ac2d41545d..ef5111b4ae 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts @@ -6,8 +6,9 @@ export const costRow: string; export const cost: string; export const labelWrapper: string; export const nameInputs: string; -export const namesWrapper: string; -export const description: string; export const descriptionWrapper: string; +export const description: string; export const title: string; export const label: string; +export const namesWrapper: string; +export const slideDown: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx index f5c6001ebe..7c965323a8 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx @@ -1,8 +1,7 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { defineMessages, FormattedMessage } from 'react-intl'; import { FormSection, InputLabel, SelectHorizontal, Form } from '~core/Fields'; -import { Colony } from '~data/index'; import Icon from '~core/Icon'; import { ValuesType } from '~pages/IncorporationPage/types'; @@ -40,12 +39,19 @@ export const MSG = defineMessages({ const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm`; export interface Props { - sidebarRef: HTMLElement | null; - colony: Colony; formValues: ValuesType; } -const LockedIncorporationForm = ({ sidebarRef }: Props) => { +const LockedIncorporationForm = ({ formValues }: Props) => { + const alternativeNames = useMemo( + () => + formValues.alternativeNames.map((name) => ({ + label: name, + value: name, + })), + [formValues.alternativeNames], + ); + return (
@@ -88,9 +94,9 @@ const LockedIncorporationForm = ({ sidebarRef }: Props) => {
-
- {/* */} -
{}}> + {/* A form is used here because the SelectHorizontal component must be wrapped in a Formik form. It doesn't send data anywhere. */} + {}}> +
{ theme: 'alt', width: 'content', }} - options={[ - { label: 'WallStreetBets', value: 'WallStreetBets' }, - { label: 'WallStreetBets2', value: 'WallStreetBets' }, - ]} - scrollContainer={sidebarRef} - placement="bottom" - withDropdownElement - optionSizeLarge + renderActiveOption={() => <>{formValues.name}} + options={alternativeNames} autoHeight unselectable /> - -
+
+
-
- WallStreetBets is on a mission to deploy decentralized satellites in - our skies. -
+
{formValues.purpose}
- +
); }; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css index 5c898c4e6a..508476d5b6 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css @@ -1,47 +1,91 @@ .wrapper { - /* border: 1px solid red */ + margin-top: 32px; } .protectorsLabelWrapper { - /* border: 1px solid red */ + display: flex; + align-items: center; +} + +.protectorsLabelWrapper span { + display: inline-block; + height: 16px; } .label { - /* border: 1px solid red */ + margin-right: 8px; + font-size: var(--size-smallish); + font-weight: var(--weight-bold); + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); } .userAvatarContainer { - /* border: 1px solid red */ + display: flex; + align-items: center; } .userName { - /* border: 1px solid red */ + margin-left: 8px; } .row { display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 0; } .row label { font-size: var(--size-smallish); font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); } -.signing { - /* border: 1px solid red */ +.row > span { + display: flex; + justify-content: center; + align-items: center; + height: 20px; + width: 94px; + border-radius: 5px; +} + +.mainContactRow { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; } .labelWrapper { + display: flex; font-size: var(--size-smallish); font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); + color: color-mod(var(--temp-grey-blue-7) alpha(85%)); +} + +.labelWrapper > span { + margin-left: 8px; +} + +.labelWrapper > div { + max-width: 250px; +} + +.protectorsLabelWrapper > div { + max-width: 250px; } .signOptionWrapper { - /* border: 1px solid red */ + display: flex; + align-items: baseline; + justify-content: space-between; + padding: 9px 0; } -.signOptionLabel { - /* border: 1px solid red */ +.signing { + font-size: var(--size-normal); + font-weight: var(--weight-bold); + color: color-mod(var(--dark) alpha(85%)); + letter-spacing: var(--spacing-medium); } diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts index dc35015ce0..e3c52d6de2 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts @@ -4,7 +4,7 @@ export const label: string; export const userAvatarContainer: string; export const userName: string; export const row: string; -export const signing: string; +export const mainContactRow: string; export const labelWrapper: string; export const signOptionWrapper: string; -export const signOptionLabel: string; +export const signing: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx index 1f106508bb..34275d4f53 100644 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx +++ b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx @@ -1,12 +1,16 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { defineMessages, FormattedMessage } from 'react-intl'; import { FormSection, InputLabel } from '~core/Fields'; import QuestionMarkTooltip from '~core/QuestionMarkTooltip'; -import { Colony } from '~data/index'; +import { ValuesType } from '~pages/IncorporationPage/types'; +import UserAvatar from '~core/UserAvatar'; +import UserMention from '~core/UserMention'; +import Tag from '~core/Tag'; + +import { SignOption, VerificationStatus } from '../constants'; import styles from './LockedProtectors.css'; -import { ValuesType } from '~pages/IncorporationPage/types'; export const MSG = defineMessages({ protectors: { @@ -41,19 +45,32 @@ export const MSG = defineMessages({ id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.signOptionTooltip`, defaultMessage: `Decide the requirements as to how many Protectors are required to sign legal documents to enact the decisions of a DAO.`, }, + individual: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.individual`, + defaultMessage: 'Individual signing', + }, + multiple: { + id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.multiple`, + defaultMessage: 'All need to sign', + }, }); const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors`; export interface Props { - protectors: ValuesType['protectors']; - colony: Colony; + formValues: ValuesType; } -const LockedProtectors = () => { +const LockedProtectors = ({ formValues }: Props) => { + const signLabel = useMemo(() => { + return formValues.signOption === SignOption.Individual + ? MSG.individual + : MSG.multiple; + }, [formValues]); + return ( <> - +
@@ -64,34 +81,64 @@ const LockedProtectors = () => {
- {/* {protectors?.map((protector) => { + {formValues.protectors?.map((protector) => { + const { profile } = protector || {}; + const { walletAddress, username, displayName: userDispalyName } = + profile || {}; + return ( -
- -
- +
+ + {protector.verified + ? VerificationStatus.Verified + : VerificationStatus.Unverified} + +
+ +
+ +
+
-
- )})} */} + ); + })} -
- - {/*
- +
+
+ + +
+
+
- +
-
*/} +
-
-
- - + +
+
+ + +
+
+ +
-
All need to sign
-
+ ); }; 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', +} From e8d167981153960a69db1978342cf79d73263a3a Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 13 Jan 2023 13:14:21 +0100 Subject: [PATCH 06/15] renamed to Incorporation --- .../LockedIncorporationForm.css | 131 ---------------- .../LockedIncorporationForm.css.d.ts | 14 -- .../LockedIncorporationForm.tsx | 128 --------------- .../LockedIncorporationForm/index.ts | 1 - .../LockedProtectors/LockedProtectors.css | 91 ----------- .../LockedProtectors.css.d.ts | 10 -- .../LockedProtectors/LockedProtectors.tsx | 148 ------------------ .../LockedProtectors/index.ts | 1 - .../IncorporationForm/constants.ts | 9 -- .../IncorporationPage/IncorporationPage.tsx | 2 +- 10 files changed, 1 insertion(+), 534 deletions(-) delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts delete mode 100644 src/modules/dashboard/components/DAOIncorporation/IncorporationForm/constants.ts diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css deleted file mode 100644 index 85f0a651fc..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css +++ /dev/null @@ -1,131 +0,0 @@ -@value paddingTop: 46px; -@value lockedPaddingTop: 75px; -@value paddingRightLeftBottom: 54px; - -@keyframes slideDown { - 0% { - max-height: 0; - } - - 100% { - max-height: 180px; - } -} - -.container { - padding: paddingTop paddingRightLeftBottom paddingRightLeftBottom; -} - -.costRow { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 0; -} - -.cost { - display: flex; - align-items: center; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.cost i { - margin-right: 8px; -} - -.labelWrapper { - display: flex; - align-items: center; - justify-content: flex-start; -} - -.labelWrapper label { - margin-right: 8px; - width: auto; -} - -.labelWrapper > div { - max-width: 250px; -} - -.nameInputs { - padding: 12px 0 0 0; -} - -.nameInputs input { - height: 44px; - font-size: var(--size-normal); - font-weight: var(--weight-bold); - color: var(--dark); - letter-spacing: var(--spacing-normal); -} - -.nameInputs > div:not(:first-child) { - margin-bottom: 12px; -} - -.nameInputs label { - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); -} - -.descriptionWrapper { - display: flex; - align-items: baseline; - padding: 12px 0; -} - -.descriptionWrapper label { - flex: 1; - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.description { - flex: 2.5; - font-size: var(--size-normal); - font-weight: var(--weight-bold); - text-align: right; - color: color-mod(var(--dark) alpha(85%)); - letter-spacing: 0.1px; -} - -.title { - margin-bottom: 16px; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.label { - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.namesWrapper label { - flex: 1; - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); - letter-spacing: var(--spacing-medium); -} - -.namesWrapper ul { - position: static; - overflow: hidden; - animation-name: slideDown; - animation-duration: 250ms; -} - -.namesWrapper span { - font-size: var(--size-smallish); -} - -.namesWrapper li:hover { - background-color: transparent; -} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts deleted file mode 100644 index ef5111b4ae..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.css.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const paddingTop: string; -export const lockedPaddingTop: string; -export const paddingRightLeftBottom: string; -export const container: string; -export const costRow: string; -export const cost: string; -export const labelWrapper: string; -export const nameInputs: string; -export const descriptionWrapper: string; -export const description: string; -export const title: string; -export const label: string; -export const namesWrapper: string; -export const slideDown: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx deleted file mode 100644 index 7c965323a8..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import React, { useMemo } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; - -import { FormSection, InputLabel, SelectHorizontal, Form } from '~core/Fields'; -import Icon from '~core/Icon'; -import { ValuesType } from '~pages/IncorporationPage/types'; - -import LockedProtectors from '../LockedProtectors'; - -import styles from './LockedIncorporationForm.css'; - -export const MSG = defineMessages({ - incorporation: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.incorporation`, - defaultMessage: 'Incorporation', - }, - initialCost: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.initialCost`, - defaultMessage: 'Initial cost', - }, - ongoingCost: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.ongoingCost`, - defaultMessage: 'Ongoing cost', - }, - cost: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.cost`, - defaultMessage: '{icon} {amount} {currency}', - }, - nameLabel: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.nameLabel`, - defaultMessage: 'Corporation name', - }, - descriptionLabel: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm.descriptionLabel`, - defaultMessage: 'DAO Purpose', - }, -}); - -const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedIncorporationForm`; - -export interface Props { - formValues: ValuesType; -} - -const LockedIncorporationForm = ({ formValues }: Props) => { - const alternativeNames = useMemo( - () => - formValues.alternativeNames.map((name) => ({ - label: name, - value: name, - })), - [formValues.alternativeNames], - ); - - return ( -
- -
- -
-
- -
-
- -
-
- , - amount: '5,300', - currency: 'USDC', - }} - /> -
-
-
- -
-
- -
-
- , - amount: '3,800 / year', - currency: 'USDC', - }} - /> -
-
-
- - {/* A form is used here because the SelectHorizontal component must be wrapped in a Formik form. It doesn't send data anywhere. */} -
{}}> -
- <>{formValues.name}} - options={alternativeNames} - autoHeight - unselectable - /> -
-
-
- -
- -
{formValues.purpose}
-
-
- -
- ); -}; - -LockedIncorporationForm.displayName = displayName; - -export default LockedIncorporationForm; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts deleted file mode 100644 index 836476fa94..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedIncorporationForm/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './LockedIncorporationForm'; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css deleted file mode 100644 index 508476d5b6..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css +++ /dev/null @@ -1,91 +0,0 @@ -.wrapper { - margin-top: 32px; -} - -.protectorsLabelWrapper { - display: flex; - align-items: center; -} - -.protectorsLabelWrapper span { - display: inline-block; - height: 16px; -} - -.label { - margin-right: 8px; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); -} - -.userAvatarContainer { - display: flex; - align-items: center; -} - -.userName { - margin-left: 8px; -} - -.row { - display: flex; - justify-content: space-between; - align-items: center; - padding: 12px 0; -} - -.row label { - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); -} - -.row > span { - display: flex; - justify-content: center; - align-items: center; - height: 20px; - width: 94px; - border-radius: 5px; -} - -.mainContactRow { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 0; -} - -.labelWrapper { - display: flex; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); -} - -.labelWrapper > span { - margin-left: 8px; -} - -.labelWrapper > div { - max-width: 250px; -} - -.protectorsLabelWrapper > div { - max-width: 250px; -} - -.signOptionWrapper { - display: flex; - align-items: baseline; - justify-content: space-between; - padding: 9px 0; -} - -.signing { - font-size: var(--size-normal); - font-weight: var(--weight-bold); - color: color-mod(var(--dark) alpha(85%)); - letter-spacing: var(--spacing-medium); -} diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts deleted file mode 100644 index e3c52d6de2..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.css.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const wrapper: string; -export const protectorsLabelWrapper: string; -export const label: string; -export const userAvatarContainer: string; -export const userName: string; -export const row: string; -export const mainContactRow: string; -export const labelWrapper: string; -export const signOptionWrapper: string; -export const signing: string; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx deleted file mode 100644 index 34275d4f53..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/LockedProtectors.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import React, { useMemo } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; - -import { FormSection, InputLabel } from '~core/Fields'; -import QuestionMarkTooltip from '~core/QuestionMarkTooltip'; -import { ValuesType } from '~pages/IncorporationPage/types'; -import UserAvatar from '~core/UserAvatar'; -import UserMention from '~core/UserMention'; -import Tag from '~core/Tag'; - -import { SignOption, VerificationStatus } from '../constants'; - -import styles from './LockedProtectors.css'; - -export const MSG = defineMessages({ - protectors: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.protectors`, - defaultMessage: 'Protectors', - }, - protectorsTooltip: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.protectorsTooltip`, - defaultMessage: `A Protector's role in a DAO legal corporation is to ratify the decisions of the DAO. Their purpose is to act on behalf of the DAO and handle legal the required administration. Learn more`, - }, - unverified: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.unverified`, - defaultMessage: 'Unverified', - }, - verified: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.verified`, - defaultMessage: 'Verified', - }, - mainContact: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.mainContact`, - defaultMessage: 'Main contact', - }, - signing: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.signing`, - defaultMessage: 'Signing', - }, - mainContactTooltip: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.mainContactTooltip`, - defaultMessage: `The main contact is required during the incorporation process and is also required to use their delivery address details for the registration.`, - }, - signOptionTooltip: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.signOptionTooltip`, - defaultMessage: `Decide the requirements as to how many Protectors are required to sign legal documents to enact the decisions of a DAO.`, - }, - individual: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.individual`, - defaultMessage: 'Individual signing', - }, - multiple: { - id: `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors.multiple`, - defaultMessage: 'All need to sign', - }, -}); - -const displayName = `dashboard.DAOIncorporation.IncorporationForm.LockedProtectors`; - -export interface Props { - formValues: ValuesType; -} - -const LockedProtectors = ({ formValues }: Props) => { - const signLabel = useMemo(() => { - return formValues.signOption === SignOption.Individual - ? MSG.individual - : MSG.multiple; - }, [formValues]); - - return ( - <> - -
-
-
- -
- -
-
-
- - {formValues.protectors?.map((protector) => { - const { profile } = protector || {}; - const { walletAddress, username, displayName: userDispalyName } = - profile || {}; - - return ( -
- - {protector.verified - ? VerificationStatus.Verified - : VerificationStatus.Unverified} - -
- -
- -
-
-
- ); - })} -
- -
-
- - -
-
- -
- -
-
-
-
- -
-
- - -
-
- -
-
-
- - ); -}; - -LockedProtectors.displayName = displayName; - -export default LockedProtectors; diff --git a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts b/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts deleted file mode 100644 index 2c15a2c788..0000000000 --- a/src/modules/dashboard/components/DAOIncorporation/IncorporationForm/LockedProtectors/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './LockedProtectors'; 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/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index 5964a27307..b9b3c5b17c 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -24,7 +24,7 @@ import { import { ValuesType } from './types'; import styles from './IncorporationPage.css'; import { ValuesType } from './types'; -import LockedIncorporationForm from '~dashboard/DAOIncorporation/IncorporationForm/LockedIncorporationForm'; +import LockedIncorporationForm from '~dashboard/Incorporation/IncorporationForm/LockedIncorporationForm'; const displayName = 'pages.IncorporationPage'; From d66637312de8a0fdacd08fdeba72875e05ed1ccb Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 23 Jan 2023 09:39:25 +0100 Subject: [PATCH 07/15] 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 4e441354a61d63f2d3e9102caf523e067d13962b Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 2 Jan 2023 14:15:19 +0100 Subject: [PATCH 08/15] 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 76413a45dddf87b0e888c06f1c92db576b17f748 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Thu, 5 Jan 2023 12:24:08 +0100 Subject: [PATCH 09/15] 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 2bdb82f4450da6b0c62489d91674d5e258b52b5e Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 13 Jan 2023 13:14:21 +0100 Subject: [PATCH 10/15] 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 c0f294d2a4ac2b15a01dec07beee134f03acc294 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Thu, 19 Jan 2023 14:22:17 +0100 Subject: [PATCH 11/15] added edition in the locked state --- .../ChangedMultipleUsers.css | 29 +++ .../ChangedMultipleUsers.css.d.ts | 4 + .../ChangedMultipleUsers.tsx | 106 ++++++++ .../ChangedMultipleUsers/index.ts | 1 + .../ChangedValues/ChangedValues.css | 47 ++++ .../ChangedValues/ChangedValues.css.d.ts | 6 + .../ChangedValues/ChangedValues.tsx | 106 ++++++++ .../ChangedValues/index.ts | 1 + .../EditIncorporationDialog.tsx | 101 ++++++++ .../EditIncorporationDialogForm.css | 98 ++++++++ .../EditIncorporationDialogForm.css.d.ts | 13 + .../EditIncorporationDialogForm.tsx | 234 ++++++++++++++++++ .../NewRecipient/NewRecipient.css | 23 ++ .../NewRecipient/NewRecipient.css.d.ts | 3 + .../NewRecipient/NewRecipient.tsx | 57 +++++ .../NewRecipient/index.ts | 1 + .../Dialogs/EditIncorporationDialog/index.ts | 1 + .../Dialogs/EditIncorporationDialog/types.ts | 9 + .../EditButtons/EditButtons.tsx | 10 +- .../LockedIncorporationForm.tsx | 4 +- .../Protectors/Protectors.css | 4 + .../Protectors/Protectors.css.d.ts | 3 + .../Protectors/Protectors.tsx | 110 ++++---- .../IncorporationPage/IncorporationPage.tsx | 158 +++++++++--- .../components/IncorporationPage/utils.ts | 153 ++++++++++++ 25 files changed, 1193 insertions(+), 89 deletions(-) create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css.d.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.tsx create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/index.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css.d.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.tsx create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/index.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css.d.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/NewRecipient/NewRecipient.css create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/NewRecipient/NewRecipient.css.d.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/NewRecipient/NewRecipient.tsx create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/NewRecipient/index.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/index.ts create mode 100644 src/modules/dashboard/components/Dialogs/EditIncorporationDialog/types.ts create mode 100644 src/modules/pages/components/IncorporationPage/utils.ts diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css new file mode 100644 index 0000000000..924d929cfc --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css @@ -0,0 +1,29 @@ +.row { + display: grid; + align-items: center; + height: 44px; + border-bottom: 1px solid color-mod(var(--temp-grey-blue-7) alpha(15%)); + font-size: var(--size-normal); + font-weight: var(--weight-normal); + line-height: 18px; + color: var(--temp-grey-blue-7); + grid-template-columns: 4.5fr 1fr 4.5fr; +} + +.arrowIcon { + height: 16px; + width: 16px; + color: color-mod(var(--dark) alpha(65%)); + justify-self: center; +} + +.right { + color: var(--dark); + justify-self: end; +} + +.left { + max-width: 90%; + overflow: hidden; + justify-self: start; +} diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css.d.ts b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css.d.ts new file mode 100644 index 0000000000..042b10cffe --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.css.d.ts @@ -0,0 +1,4 @@ +export const row: string; +export const arrowIcon: string; +export const right: string; +export const left: string; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.tsx new file mode 100644 index 0000000000..0406ef27a4 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/ChangedMultipleUsers.tsx @@ -0,0 +1,106 @@ +import React, { Fragment, useCallback } from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +import Icon from '~core/Icon'; +import { Colony } from '~data/index'; +import { ValuesType } from '~pages/IncorporationPage/types'; + +import NewRecipient from '../NewRecipient'; +import { NewValueType } from '../types'; + +import styles from './ChangedMultipleUsers.css'; + +export const MSG = defineMessages({ + discard: { + id: 'dashboard.EditIncorporationDialog.ChangedMultipleUsers.discard', + defaultMessage: 'Discard', + }, + changeRecipient: { + id: `dashboard.EditIncorporationDialog.ChangedMultipleUsers.changeRecipient`, + defaultMessage: 'Change Recipient', + }, + removed: { + id: `dashboard.EditIncorporationDialog.ChangedMultipleUsers.removed`, + defaultMessage: 'Removed protector', + }, + added: { + id: `dashboard.EditIncorporationDialog.ChangedMultipleUsers.added`, + defaultMessage: 'Added protector', + }, +}); + +const displayName = 'dashboard.EditIncorporationDialog.ChangedMultipleUsers'; + +interface Props { + newValues?: NewValueType[]; + colony: Colony; + oldValues: ValuesType; +} + +const ChangedMultipleUsers = ({ newValues, oldValues }: Props) => { + const renderUserChange = useCallback((newUser, oldUser) => { + if (newUser.removed) { + return ( +
+ + + + + +
+ ); + } + + if (newUser.created) { + return ( +
+ + + + + +
+ ); + } + + return ( +
+
+ +
+ +
+ +
+
+ ); + }, []); + + if (!Array.isArray(newValues) || !Array.isArray) { + return null; + } + + return ( + <> + {newValues?.map((newValue) => ( + + {Array.isArray(newValue.value) && + newValue.value?.map((changeItem) => { + const oldItem = oldValues[newValue.key]?.find( + (item) => item?.key === changeItem?.key, + ); + return ( + + {renderUserChange(changeItem, oldItem)} + + ); + })} + + ))} + + ); +}; + +ChangedMultipleUsers.displayName = displayName; + +export default ChangedMultipleUsers; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/index.ts b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/index.ts new file mode 100644 index 0000000000..469ae206ee --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedMultipleUsers/index.ts @@ -0,0 +1 @@ +export { default } from './ChangedMultipleUsers'; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css new file mode 100644 index 0000000000..1a5859c6b3 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css @@ -0,0 +1,47 @@ +.teamWrapper { + display: flex; + align-items: center; +} + +.teamWrapper > div { + margin-right: 4px; +} + +.row { + display: grid; + align-items: center; + height: 44px; + border-bottom: 1px solid color-mod(var(--temp-grey-blue-7) alpha(15%)); + font-size: var(--size-normal); + font-weight: var(--weight-normal); + line-height: 18px; + color: var(--temp-grey-blue-7); + grid-template-columns: 4.5fr 1fr 4.5fr; + grid-template-rows: auto; + letter-spacing: 0.1px; +} + +.smallerPadding { + padding: 4px 0; +} + +.arrowIcon { + height: 16px; + width: 16px; + color: color-mod(var(--dark) alpha(65%)); + justify-self: center; +} + +.left { + max-width: 90%; + overflow: hidden; + justify-self: start; +} + +.right { + max-width: 90%; + overflow: hidden; + text-align: right; + color: var(--dark); + justify-self: end; +} diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css.d.ts b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css.d.ts new file mode 100644 index 0000000000..180d42ed57 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.css.d.ts @@ -0,0 +1,6 @@ +export const teamWrapper: string; +export const row: string; +export const smallerPadding: string; +export const arrowIcon: string; +export const left: string; +export const right: string; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.tsx new file mode 100644 index 0000000000..d6bc0d30c2 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/ChangedValues.tsx @@ -0,0 +1,106 @@ +import React, { useCallback } from 'react'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { isEmpty } from 'lodash'; +import classNames from 'classnames'; + +import Icon from '~core/Icon'; +import { SignOption } from '~dashboard/Incorporation/IncorporationForm/constants'; +import { ValuesType } from '~pages/IncorporationPage/types'; +import { multiLineTextEllipsis } from '~utils/strings'; + +import NewRecipient from '../NewRecipient'; + +import styles from './ChangedValues.css'; + +export const MSG = defineMessages({ + none: { + id: 'dashboard.EditIncorporationDialog.ChangedValues.none', + defaultMessage: 'None', + }, + individual: { + id: 'dashboard.EditIncorporationDialog.ChangedValues.individual', + defaultMessage: 'Individual signing', + }, + multiple: { + id: 'dashboard.EditIncorporationDialog.ChangedValues.multiple', + defaultMessage: 'All have to sign', + }, +}); + +const displayName = 'dashboard.EditIncorporationDialog.ChangedValues'; + +export type ValueOf = T[keyof T]; +interface Props { + newValues?: { + key: string; + value?: ValueOf; + id: string; + }[]; + oldValues: ValuesType; +} + +const ChangedValues = ({ newValues, oldValues }: Props) => { + const { formatMessage } = useIntl(); + + const renderChange = useCallback( + (change: any, key: string, newVallue: boolean) => { + switch (key) { + case 'name': + case 'alternativeName1': + case 'alternativeName2': + case 'purpose': { + return ( + multiLineTextEllipsis(change, newVallue ? 40 : 20) || + formatMessage(MSG.none) + ); + } + case 'protectors': { + return ; + } + case 'mainContact': { + return ; + } + case 'signOption': { + return change === SignOption.Individual ? ( + + ) : ( + + ); + } + default: + return null; + } + }, + [formatMessage], + ); + + if (!newValues || isEmpty(newValues)) { + return null; + } + + return ( + <> + {newValues.map(({ key, value }) => { + const oldValue = oldValues[key]; + + return ( +
+
+ {renderChange(oldValue, key, false)} +
+ +
{renderChange(value, key, true)}
+
+ ); + })} + + ); +}; + +ChangedValues.displayName = displayName; + +export default ChangedValues; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/index.ts b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/index.ts new file mode 100644 index 0000000000..6adc4412c6 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/ChangedValues/index.ts @@ -0,0 +1 @@ +export { default } from './ChangedValues'; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx new file mode 100644 index 0000000000..7c0d4cd249 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx @@ -0,0 +1,101 @@ +import React, { useCallback, useState } from 'react'; +import * as yup from 'yup'; +import { FormikProps } from 'formik'; + +import { ActionForm } from '~core/Fields'; +import Dialog from '~core/Dialog'; +import { Colony } from '~data/index'; +import { ActionTypes } from '~redux/actionTypes'; +import { ValuesType } from '~pages/IncorporationPage/types'; + +import EditIncorporationDialogForm from './EditIncorporationDialogForm'; + +const displayName = 'dashboard.EditIncorporationDialog'; + +export const validationSchema = yup.object().shape({ + forceAction: yup.bool(), + annotationMessage: yup.string(), +}); + +export interface FormValuesType { + forceAction: boolean; + annotationMessage?: string; +} + +interface Props { + onSubmitClick: ( + values: Partial | undefined, + wasForced: boolean, + ) => void; + onCancelClick: VoidFunction; + close: () => void; + isVotingExtensionEnabled: boolean; + colony: Colony; + newValues?: Partial; + oldValues: ValuesType; +} + +const EditIncorporationDialog = ({ + close, + onSubmitClick, + onCancelClick, + isVotingExtensionEnabled, + colony, + newValues, + oldValues, +}: Props) => { + const [isForce, setIsForce] = useState(false); + + const discardChange = useCallback(() => { + close(); + onCancelClick?.(); + }, [close, onCancelClick]); + + const getFormAction = useCallback( + (actionType: 'SUBMIT' | 'ERROR' | 'SUCCESS') => { + const actionEnd = actionType === 'SUBMIT' ? '' : `_${actionType}`; + + return isVotingExtensionEnabled && !isForce + ? ActionTypes[`COLONY_ACTION_GENERIC${actionEnd}`] + : ActionTypes[`COLONY_ACTION_GENERIC${actionEnd}`]; + }, + [isVotingExtensionEnabled, isForce], + ); + + return ( + + {(formValues: FormikProps) => { + if (formValues.values.forceAction !== isForce) { + setIsForce(formValues.values.forceAction); + } + return ( + + + + ); + }} + + ); +}; + +EditIncorporationDialog.displayName = displayName; + +export default EditIncorporationDialog; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css new file mode 100644 index 0000000000..f66a80094f --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css @@ -0,0 +1,98 @@ +@value submitButtonWidth: 160px; + +.title { + display: flex; + justify-content: space-between; + align-items: center; + padding: 9px 0 22px; + width: 100%; + font-size: var(--size-medium-l); + font-weight: var(--weight-bold); + color: var(--dark); +} + +.withoutPadding { + padding: 0; +} + +.forceRow { + display: flex; + justify-content: space-between; + align-items: baseline; + padding-top: 16px; + white-space: nowrap; +} + +.contentWrapper { + padding: 16px 20px 54px; +} + +.descriptionWrapper { + font-size: var(--size-normal); + letter-spacing: 0.1px; +} + +.noChanges { + font-weight: var(--weight-bold); + color: var(--pink); +} + +.annotationsWrapper { + margin-bottom: 11px; +} + +.toggleContainer span div { + margin-left: 0; +} + +/* this selector is for tooltip wrapper */ +.toggleContainer > div > div:last-child { + max-width: 250px; + white-space: normal; +} + +.toggleContainer > div > div:first-of-type { + margin-right: 11px; + height: 16px; +} + +.toggleContainer label { + margin-bottom: 0; +} + +.toggleContainer i { + transform: translate(0, -1px); +} + +.link { + font-weight: 600; + color: var(--action-secondary); +} + +.link:hover { + color: var(--action-secondary); +} + +.buttonWrappper { + display: flex; + justify-content: flex-end; + width: 100%; +} + +.discard { + composes: main from '~core/Button/Button.css'; + padding: 0; + height: auto; + font-size: var(--size-smallish); + font-weight: 600; + color: var(--action-secondary); +} + +.subheader { + display: flex; + justify-content: space-between; + margin-bottom: 4px; + padding: 6px 0; + font-weight: var(--weight-bold); + color: var(--dark); +} diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css.d.ts b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css.d.ts new file mode 100644 index 0000000000..e8cbc474c2 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.css.d.ts @@ -0,0 +1,13 @@ +export const submitButtonWidth: string; +export const title: string; +export const withoutPadding: string; +export const forceRow: string; +export const contentWrapper: string; +export const descriptionWrapper: string; +export const noChanges: string; +export const annotationsWrapper: string; +export const toggleContainer: string; +export const link: string; +export const buttonWrappper: string; +export const discard: string; +export const subheader: string; diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx new file mode 100644 index 0000000000..8ba7a71078 --- /dev/null +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx @@ -0,0 +1,234 @@ +import React, { useMemo } from 'react'; +import { defineMessages, FormattedMessage } from 'react-intl'; +import classNames from 'classnames'; +import { FormikProps } from 'formik'; +import { nanoid } from 'nanoid'; +import { isEmpty } from 'lodash'; + +import { Annotations, FormSection, Toggle } from '~core/Fields'; +import { DialogSection } from '~core/Dialog'; +import MotionDomainSelect from '~dashboard/MotionDomainSelect'; +import Heading from '~core/Heading'; +import Button from '~core/Button'; +import { Colony } from '~data/index'; +import { ValuesType } from '~pages/IncorporationPage/types'; + +import { FormValuesType } from './EditIncorporationDialog'; +import ChangedValues from './ChangedValues'; +import ChangedMultipleUsers from './ChangedMultipleUsers'; +import styles from './EditIncorporationDialogForm.css'; + +export const MSG = defineMessages({ + header: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.header`, + defaultMessage: 'Create a Motion to change application', + }, + descriptionText: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.descriptionText`, + defaultMessage: `You are proposing a change to the corporation details, this requires collective approval via a Motion.`, + }, + descriptionLabel: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.descriptionLabel`, + defaultMessage: `Explain why you're changing the application (optional)`, + }, + cancelText: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.cancelText`, + defaultMessage: 'Back', + }, + confirmText: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.confirmText`, + defaultMessage: 'Create Motion', + }, + noChanges: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.noChanges`, + defaultMessage: 'No values have been changed!', + }, + from: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.ChangedValues.from`, + defaultMessage: '1. Application changes', + }, + to: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.ChangedValues.to`, + defaultMessage: 'Change to', + }, + discard: { + id: 'dashboard.EditIncorporationDialog.EditIncorporationDialogForm.discard', + defaultMessage: 'Discard', + }, +}); + +const displayName = `dashboard.EditIncorporationDialog.EditIncorporationDialogForm`; + +interface Props { + close: () => void; + colony: Colony; + confirmedValues?: Partial; + oldValues: ValuesType; + discardChange: VoidFunction; + onSubmitClick: ( + values: Partial | undefined, + wasForced: boolean, + ) => void; + isVotingExtensionEnabled: boolean; +} + +const EditIncorporationDialogForm = ({ + close, + colony, + confirmedValues, + oldValues, + discardChange, + onSubmitClick, + isVotingExtensionEnabled, + isSubmitting, + handleSubmit, + values, +}: Props & FormikProps) => { + const noChanges = + (confirmedValues && isEmpty(confirmedValues)) || + (confirmedValues && + Object.values(confirmedValues).every((value) => !value)); + + const confirmedValuesWithIds = useMemo(() => { + if (!confirmedValues || isEmpty(confirmedValues)) { + return []; + } + + return Object.entries(confirmedValues).map(([key, value]) => { + return { + key, + value, + id: nanoid(), + }; + }); + }, [confirmedValues]); + + const newData = useMemo(() => { + const newValues = confirmedValuesWithIds.filter( + (newValue) => !Array.isArray(newValue.value), + ); + const newMultiple = confirmedValuesWithIds.filter((newValue) => { + return Array.isArray(newValue.value); + }); + + return { + newValues, + newMultiple, + }; + }, [confirmedValuesWithIds]); + + return ( + <> + +
+ + {isVotingExtensionEnabled && ( +
+ +
+ )} +
+ + + +
+ +
+
+
+ {!confirmedValues || noChanges ? ( +
+ +
+ ) : ( + <> + +
+ + + + + + +
+
+ + +
+
+ + )} +
+ +
+ +
+
+ + + {handleEditCancel && ( + + )}
- {shouldShowMainContact && mainContactData && ( - -
-
- - -
-
-
- + {shouldShowMainContact && mainContactData && ( + +
+
+ + +
+
+
+ + {error && typeof error === 'object' && touched && ( +
{formatMessage(error)}
+ )} +
+ setMainContact(undefined)} + title={MSG.deleteIconTitle} />
- setMainContact(undefined)} - title={MSG.deleteIconTitle} - />
-
- - )} - {shouldShowMainContact && ( -
-
- - -
-
+ + )} + {shouldShowMainContact && ( +
+
+ + +
- - -
-
+ /> - - + />
-
- )} + )} +
); }; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index b9b3c5b17c..57bdff1ade 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -1,17 +1,24 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; import { useParams } from 'react-router'; -import { Formik } from 'formik'; +import { Formik, FormikErrors } from 'formik'; +import { defineMessages, FormattedMessage } from 'react-intl'; import classNames from 'classnames'; import { useColonyFromNameQuery } from '~data/generated'; import { getMainClasses } from '~utils/css'; import { SpinnerLoader } from '~core/Preloaders'; import IncorporationForm from '~dashboard/Incorporation/IncorporationForm'; -import Stages, { FormStages } from '~dashboard/ExpenditurePage/Stages'; +import Stages, { FormStages } from '~dashboard/Incorporation/Stages'; import LockedIncorporationForm from '~dashboard/Incorporation/IncorporationForm/LockedIncorporationForm'; -import VerificationBanner from '~dashboard/Incorporation/VerificationBanner'; -import IncorporationPaymentDialog from '~dashboard/Dialogs/IncorporationPaymentDialog'; import { useDialog } from '~core/Dialog'; +import EditButtons from '~dashboard/ExpenditurePage/EditButtons/EditButtons'; +import EditIncorporationDialog from '~dashboard/Dialogs/EditIncorporationDialog'; +import Tag from '~core/Tag'; +import { + MotionStatus, + MotionType, +} from '~dashboard/ExpenditurePage/Stages/constants'; +import { Motion } from '~pages/ExpenditurePage/types'; import { initialValues, @@ -21,10 +28,21 @@ import { formValuesMock, userMock, } from './constants'; +import { findDifferences, updateValues } from './utils'; import { ValuesType } from './types'; import styles from './IncorporationPage.css'; -import { ValuesType } from './types'; -import LockedIncorporationForm from '~dashboard/Incorporation/IncorporationForm/LockedIncorporationForm'; +import VerificationBanner from '~dashboard/Incorporation/VerificationBanner'; + +const MSG = defineMessages({ + editMode: { + id: 'pages.IncorporationPage.editMode', + defaultMessage: `Edit mode. Changes require motion to pass.`, + }, + title: { + id: 'pages.IncorporationPage.editMode', + defaultMessage: 'Incorporate this DAO', + }, +}); const displayName = 'pages.IncorporationPage'; @@ -41,12 +59,21 @@ const IncorporationPage = () => { const [isFormEditable, setFormEditable] = useState(false); const [formValues, setFormValues] = useState(formValuesMock); const [shouldValidate, setShouldValidate] = useState(false); - const [activeStageId, setActiveStageId] = useState(StagesEnum.Payment); + const [activeStageId, setActiveStageId] = useState(StagesEnum.Draft); + const [inEditMode, setInEditMode] = useState(false); + const oldValues = useRef(); const sidebarRef = useRef(null); const notVerified = true; // temporary valule const openPayDialog = useDialog(IncorporationPaymentDialog); + const [motion, setMotion] = useState(); + + const openEditIncorporationDialog = useDialog(EditIncorporationDialog); + + const { data: colonyData, loading } = useColonyFromNameQuery({ + variables: { name: colonyName, address: '' }, + }); const handleSubmit = useCallback((values) => { setFormValues(values); @@ -94,16 +121,83 @@ const IncorporationPage = () => { } }, [shouldValidate]); + const handleConfirmEition = useCallback( + (confirmedValues: Partial | undefined, isForced: boolean) => { + setInEditMode(false); + setFormEditable(false); + + if (isForced) { + const data = updateValues(formValues, confirmedValues); + // call to backend to set new values goes here, setting state is temorary + setFormValues(data); + } else { + setMotion({ type: MotionType.Edit, status: MotionStatus.Pending }); + // setTimeout is temporary, it should be replaced with call to api + setTimeout(() => { + const data = updateValues(formValues, confirmedValues); + setMotion({ type: MotionType.Edit, status: MotionStatus.Passed }); + setFormValues(data); + }, 3000); + } + }, + [formValues], + ); + + const handleEditLockedForm = useCallback(() => { + setInEditMode(true); + setFormEditable(true); + oldValues.current = formValues; + }, [formValues]); + + const handleEditCancel = useCallback(() => { + setInEditMode(false); + setFormEditable(false); + }, []); + + const handleEditSubmit = useCallback( + async ( + values: ValuesType, + validateForm: (values?: ValuesType) => Promise>, + ) => { + setInEditMode(true); + setFormEditable(true); + const errors = await validateForm(values); + const hasErrors = Object.keys(errors)?.length; + + const differentValues = findDifferences(values, oldValues.current); + + return ( + !hasErrors && + colonyData && + oldValues.current && + openEditIncorporationDialog({ + onSubmitClick: handleConfirmEition, + onCancelClick: handleEditCancel, + isVotingExtensionEnabled: true, + colony: colonyData?.processedColony, + newValues: differentValues, + oldValues: oldValues.current, + }) + ); + }, + [ + colonyData, + handleConfirmEition, + handleEditCancel, + openEditIncorporationDialog, + ], + ); + return isFormEditable ? ( - {() => ( + {({ values, validateForm }) => (
) : ( colonyData && ( - + <> + {inEditMode && ( +
+ + + +
+ )} + + ) )}
-
- {colonyData && ( - ({ - ...stage, - id: stage.id.toString(), - label: stage.title, - buttonAction, - }))} - setActiveStageId={setActiveStageId} - colony={colonyData.processedColony} - setFormValues={setFormValues} - handleCancelExpenditure={() => {}} +
+ +
+ {inEditMode ? ( + + handleEditSubmit(values, validateForm) + } /> + ) : ( + )}
@@ -154,6 +253,7 @@ const IncorporationPage = () => { formValues && ( ) @@ -167,7 +267,9 @@ const IncorporationPage = () => { {/* user passed to VerifiactionBanner is a mock */} {notVerified && }
-
+
+ +
{colonyData && ( { + const allKeys = uniq([ + ...newArray?.map((val) => val.key), + ...oldArray?.map((val) => val.key), + ]); + + const changes = allKeys + .map((key) => { + const newValueById = newArray?.find((val) => val.key === key); + const oldValueById = oldArray?.find((val) => val.key === key); + + if (!newValueById && oldValueById) { + // value has been removed, so we set removed field to true + return { key, removed: true }; + } + + if (newValueById && !oldValueById) { + // value has been added, so we set created field to true + return { ...newValueById, created: true }; + } + + if (typeof newValueById === 'object') { + const change = Object.entries(newValueById).reduce( + (acc, [currKey, currVal]) => { + // we don't want to check if 'isExpanded', 'id', etc. have been changed + if (skip.includes(currKey)) { + return acc; + } + + if (!isEqual(currVal, oldValueById[currKey])) { + return { ...acc, ...{ [currKey]: currVal } }; + } + + return acc; + }, + {}, + ); + + return isEmpty(change) ? undefined : { key, ...change }; + } + + if (!isEqual(newValueById, oldValueById)) { + return newValueById; + } + + return undefined; + }) + .filter((change) => !!change); + + return changes; +}; + +export const findDifferences = ( + newValues: Record, + oldValues?: Record, +) => { + if (!oldValues) { + return undefined; + } + + const allKeys = uniq([...Object.keys(newValues), ...Object.keys(oldValues)]); + const differentValues = allKeys?.reduce((result, key) => { + if (key === 'id') { + return result; + } + + const oldValue = oldValues[key]; + const newValue = newValues[key]; + + if (Array.isArray(newValue)) { + const changes = checkArray(newValue, oldValue); + + return changes.length > 0 ? { ...result, ...{ [key]: changes } } : result; + } + + if (typeof newValue === 'object' && typeof oldValue === 'object') { + const change = Object.entries(newValue).reduce( + (acc, [currKey, currVal]) => { + if (!isEqual(currVal, oldValue[currKey])) { + return { ...acc, ...{ [currKey]: currVal } }; + } + + return acc; + }, + {}, + ); + return { ...result, ...(!isEmpty(change) && { [key]: change }) }; + } + + if (!isEqual(oldValue, newValue)) { + return { ...result, [key]: newValue }; + } + + return result; + }, {}); + + return differentValues; +}; + +export const updateValues = (values, confirmedValues) => { + let newProtectors: Protector | undefined; + + if ('protectors' in confirmedValues) { + const changedUsers = values.protectors?.filter((user) => + confirmedValues.protectors.find((confUser) => confUser.key === user.key), + ); + + const sameUsers = values.protectors?.filter((user) => + confirmedValues.protectors.every((confUser) => confUser.key !== user.key), + ); + + const newUsers = confirmedValues.protectors?.filter( + (value) => value.created, + ); + + newProtectors = [ + ...sameUsers, + ...changedUsers.map((user) => { + const newValue = confirmedValues.protectors.find( + (item) => item.key === user.key, + ); + + return { + ...user, + ...newValue, + isChanged: true, + }; + }), + ...newUsers.map((user) => ({ + ...user, + created: undefined, + isChanged: true, + })), + ].filter((rec) => !rec.removed) as any; + } + + const newValues = merge({}, values, confirmedValues); + + return { + ...newValues, + ...('mainContact' in confirmedValues && { + mainContact: confirmedValues.mainContact, + }), + ...('protectors' in confirmedValues && { + protectors: newProtectors, + }), + }; +}; From bf3f7a05f574c6e909e9816004015efd6ec0f6fb Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 27 Jan 2023 07:45:33 +0100 Subject: [PATCH 12/15] added view for owner --- .../EditIncorporationDialog.tsx | 3 + .../EditIncorporationDialogForm.tsx | 60 +++++++++++-------- .../IncorporationPage/IncorporationPage.tsx | 27 +++++++-- .../components/IncorporationPage/constants.ts | 17 ++++++ .../components/IncorporationPage/types.ts | 12 +++- 5 files changed, 87 insertions(+), 32 deletions(-) diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx index 7c0d4cd249..b0662177f6 100644 --- a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialog.tsx @@ -33,6 +33,7 @@ interface Props { colony: Colony; newValues?: Partial; oldValues: ValuesType; + isOwner: boolean; } const EditIncorporationDialog = ({ @@ -43,6 +44,7 @@ const EditIncorporationDialog = ({ colony, newValues, oldValues, + isOwner, }: Props) => { const [isForce, setIsForce] = useState(false); @@ -86,6 +88,7 @@ const EditIncorporationDialog = ({ oldValues, onSubmitClick, isVotingExtensionEnabled, + isOwner, ...formValues, }} /> diff --git a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx index 8ba7a71078..9501c32204 100644 --- a/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx +++ b/src/modules/dashboard/components/Dialogs/EditIncorporationDialog/EditIncorporationDialogForm.tsx @@ -39,6 +39,10 @@ export const MSG = defineMessages({ id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.confirmText`, defaultMessage: 'Create Motion', }, + ownerConfirmText: { + id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.ownerConfirmText`, + defaultMessage: 'Confirm', + }, noChanges: { id: `dashboard.EditIncorporationDialog.EditIncorporationDialogForm.noChanges`, defaultMessage: 'No values have been changed!', @@ -70,6 +74,7 @@ interface Props { wasForced: boolean, ) => void; isVotingExtensionEnabled: boolean; + isOwner: boolean; } const EditIncorporationDialogForm = ({ @@ -80,6 +85,7 @@ const EditIncorporationDialogForm = ({ discardChange, onSubmitClick, isVotingExtensionEnabled, + isOwner, isSubmitting, handleSubmit, values, @@ -120,32 +126,34 @@ const EditIncorporationDialogForm = ({ return ( <> -
- - {isVotingExtensionEnabled && ( -
- + + {isVotingExtensionEnabled && ( +
+ -
- )} -
+ ], + strategy: 'fixed', + }} + /> +
+ )} +
+ )} { handleSubmit(e as any); onSubmitClick(confirmedValues, values.forceAction); diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index 57bdff1ade..7972afa8aa 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -19,6 +19,7 @@ import { MotionType, } from '~dashboard/ExpenditurePage/Stages/constants'; import { Motion } from '~pages/ExpenditurePage/types'; +import { useLoggedInUser } from '~data/helpers'; import { initialValues, @@ -27,6 +28,7 @@ import { Stages as StagesEnum, formValuesMock, userMock, + ownerMock, } from './constants'; import { findDifferences, updateValues } from './utils'; import { ValuesType } from './types'; @@ -75,8 +77,16 @@ const IncorporationPage = () => { variables: { name: colonyName, address: '' }, }); + const { walletAddress } = useLoggedInUser(); + + const isOwner = useMemo( + () => formValues?.owner?.walletAddress === walletAddress, + [formValues, walletAddress], + ); + const handleSubmit = useCallback((values) => { - setFormValues(values); + // we temporarily store the mock owner in the formValues + setFormValues({ ...values, owner: ownerMock }); setFormEditable(false); setActiveStageId(StagesEnum.Created); }, []); @@ -126,21 +136,26 @@ const IncorporationPage = () => { setInEditMode(false); setFormEditable(false); + const data = updateValues(formValues, confirmedValues); + + if (isOwner) { + setFormValues(data); + return; + } + if (isForced) { - const data = updateValues(formValues, confirmedValues); // call to backend to set new values goes here, setting state is temorary setFormValues(data); } else { setMotion({ type: MotionType.Edit, status: MotionStatus.Pending }); // setTimeout is temporary, it should be replaced with call to api setTimeout(() => { - const data = updateValues(formValues, confirmedValues); setMotion({ type: MotionType.Edit, status: MotionStatus.Passed }); setFormValues(data); }, 3000); } }, - [formValues], + [formValues, isOwner], ); const handleEditLockedForm = useCallback(() => { @@ -177,6 +192,7 @@ const IncorporationPage = () => { colony: colonyData?.processedColony, newValues: differentValues, oldValues: oldValues.current, + isOwner, }) ); }, @@ -184,6 +200,7 @@ const IncorporationPage = () => { colonyData, handleConfirmEition, handleEditCancel, + isOwner, openEditIncorporationDialog, ], ); @@ -207,7 +224,7 @@ const IncorporationPage = () => { ) : ( colonyData && ( <> - {inEditMode && ( + {inEditMode && !isOwner && (
diff --git a/src/modules/pages/components/IncorporationPage/constants.ts b/src/modules/pages/components/IncorporationPage/constants.ts index 311d840016..678d2adc68 100644 --- a/src/modules/pages/components/IncorporationPage/constants.ts +++ b/src/modules/pages/components/IncorporationPage/constants.ts @@ -3,6 +3,7 @@ import { defineMessages } from 'react-intl'; import * as yup from 'yup'; import { SignOption } from '~dashboard/Incorporation/IncorporationForm/constants'; +import { UserProfile } from '~data/index'; import { StageObject, ValuesType } from './types'; @@ -212,3 +213,19 @@ export const userMock = { walletAddress: '0xb77D57F4959eAfA0339424b83FcFaf9c15407461', }, }; + +export const ownerMock: Pick< + UserProfile, + | 'displayName' + | 'avatarHash' + | 'walletAddress' + | 'username' + | 'bio' + | 'location' + | 'website' +> = { + avatarHash: null, + displayName: null, + username: 'ajarosik', + walletAddress: '0xb77D57F4959eAfA0339424b83FcFaf9c15407461', +}; diff --git a/src/modules/pages/components/IncorporationPage/types.ts b/src/modules/pages/components/IncorporationPage/types.ts index bcbe4a5b88..b9b4800963 100644 --- a/src/modules/pages/components/IncorporationPage/types.ts +++ b/src/modules/pages/components/IncorporationPage/types.ts @@ -4,7 +4,7 @@ import { SignOption, VerificationStatus, } from '~dashboard/Incorporation/IncorporationForm/constants'; -import { AnyUser } from '~data/index'; +import { AnyUser, UserProfile } from '~data/index'; import { Stages } from './constants'; @@ -23,6 +23,16 @@ export interface ValuesType { protectors?: Protector[]; mainContact?: AnyUser; signOption: SignOption; + owner?: Pick< + UserProfile, + | 'displayName' + | 'avatarHash' + | 'walletAddress' + | 'username' + | 'bio' + | 'location' + | 'website' + >; } export interface StageObject { From 2a553032fae95a768265d369629f42fb6c187275 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 27 Jan 2023 11:22:04 +0100 Subject: [PATCH 13/15] fixed errors --- .../Protectors/Protectors.css | 29 ++++++++++++------- .../Protectors/Protectors.css.d.ts | 2 ++ .../Protectors/Protectors.tsx | 11 ++++--- .../IncorporationPage/IncorporationPage.css | 23 +++++++++++++-- .../IncorporationPage.css.d.ts | 1 + .../IncorporationPage/IncorporationPage.tsx | 1 - 6 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css index 1045550a11..1fde09a4f8 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css @@ -1,5 +1,5 @@ .wrapper { - margin: 18px 0 14px; + margin: 8px 0 16px; } .labelWrapper { @@ -42,27 +42,36 @@ .mainContactWrapper { display: flex; justify-content: space-between; - padding: 11px 0 14px; - padding-bottom: 0; - font-size: var(--size-smallish); - font-weight: var(--weight-bold); - color: color-mod(var(--temp-grey-blue-7) alpha(85%)); + font-size: var(--size-tiny); + white-space: nowrap; + color: var(--danger); + letter-spacing: var(--spacing-medium); } .mainContactWrapper label { margin-right: 0; } +.selectWrapper { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.error { + font-size: var(--size-tiny); + font-weight: var(--weight-bold); + white-space: nowrap; + color: var(--danger); + letter-spacing: var(--spacing-medium); +} + .deleteIcon { height: 20px; width: 20px; fill: var(--pink); } -.deleteIcon:hover { - cursor: pointer; -} - .circlePlusIcon { display: flex; height: 30px; diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts index 9d845b4b6c..06f60df12b 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts @@ -4,6 +4,8 @@ export const additionalPaddign: string; export const protectorsLabelWrapper: string; export const label: string; export const mainContactWrapper: string; +export const selectWrapper: string; +export const error: string; export const deleteIcon: string; export const circlePlusIcon: string; export const signOptionWrapper: string; diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index 6454557936..eebfcdeba7 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo } from 'react'; -import { defineMessages, FormattedMessage } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { FieldArray, useField } from 'formik'; import classNames from 'classnames'; import { isEmpty } from 'lodash'; @@ -71,9 +71,12 @@ export interface Props { const Protectors = ({ colony, sidebarRef }: Props) => { const [, { value: protectors }] = useField('protectors'); const [, { value: signOption }] = useField('signOption'); - const [, { value: mainContact }, { setValue: setMainContact }] = useField( - 'mainContact', - ); + const [ + , + { value: mainContact, error, touched }, + { setValue: setMainContact }, + ] = useField('mainContact'); + const { formatMessage } = useIntl(); const { data: colonyMembers, loading } = useMembersSubscription({ variables: { colonyAddress: colony.colonyAddress || '' }, diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.css b/src/modules/pages/components/IncorporationPage/IncorporationPage.css index 7984904f8f..2235b5f6b1 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.css +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.css @@ -51,6 +51,25 @@ min-height: calc(100vh - navBarHeight); } -.smallerPadding { - padding: 36px 100px 80px 25px; +.tagWrapper { + margin-bottom: -30px; + padding: 34px 54px 0; +} + +.tagWrapper > span { + height: 21px; + width: 100%; + border-radius: 12px; + background-color: var(--temp-grey-blue-7); + text-align: center; + color: white; + letter-spacing: var(--spacing-medium); +} + +.titleCommentsContainer { + min-width: 458px; + font-size: var(--size-medium-l); + font-weight: var(--weight-bold); + color: var(--dark); + letter-spacing: var(--spacing-medium); } diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts b/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts index cee612a0b9..02d6e0fffe 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts @@ -8,3 +8,4 @@ export const spinnerContainer: string; export const mainContainer: string; export const mainContent: string; export const smallerPadding: string; +export const tagWrapper: string; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index 7972afa8aa..ee9cae501c 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -8,7 +8,6 @@ import { useColonyFromNameQuery } from '~data/generated'; import { getMainClasses } from '~utils/css'; import { SpinnerLoader } from '~core/Preloaders'; import IncorporationForm from '~dashboard/Incorporation/IncorporationForm'; -import Stages, { FormStages } from '~dashboard/Incorporation/Stages'; import LockedIncorporationForm from '~dashboard/Incorporation/IncorporationForm/LockedIncorporationForm'; import { useDialog } from '~core/Dialog'; import EditButtons from '~dashboard/ExpenditurePage/EditButtons/EditButtons'; From 2943a333744a43110f361f1f62f00bda9b4f6f58 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Fri, 27 Jan 2023 11:24:55 +0100 Subject: [PATCH 14/15] removed unused import --- .../LockedIncorporationForm/LockedIncorporationForm.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx index 333b882b5a..f029e649d1 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/LockedIncorporationForm/LockedIncorporationForm.tsx @@ -50,7 +50,11 @@ export interface Props { activeStageId: Stages; } -const LockedIncorporationForm = ({ formValues, activeStageId, editForm }: Props) => { +const LockedIncorporationForm = ({ + formValues, + activeStageId, + editForm, +}: Props) => { const { alternativeName1: altName1, alternativeName2: altName2 } = formValues; const alternativeNames = useMemo( () => [ From 6972c32f0bd32ead81fb54c1bb0a8c217079e366 Mon Sep 17 00:00:00 2001 From: Agnieszka Jarosik Date: Mon, 13 Mar 2023 14:40:38 +0100 Subject: [PATCH 15/15] fixed types --- .../ExpenditurePage/Stages/Stages.css | 4 + .../ExpenditurePage/Stages/Stages.css.d.ts | 1 + .../ExpenditurePage/Stages/Stages.tsx | 6 +- .../Protectors/Protectors.css.d.ts | 2 - .../Protectors/Protectors.tsx | 112 ++++++++++-------- .../Incorporation/Stages/FormStages.tsx | 106 ----------------- .../IncorporationPage/IncorporationPage.css | 9 +- .../IncorporationPage.css.d.ts | 2 +- .../IncorporationPage/IncorporationPage.tsx | 36 ++++-- 9 files changed, 103 insertions(+), 175 deletions(-) delete mode 100644 src/modules/dashboard/components/Incorporation/Stages/FormStages.tsx diff --git a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css index 9312437576..c48372edf6 100644 --- a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css +++ b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css @@ -143,3 +143,7 @@ border-radius: 12px; text-align: center; } + +.paddingSmall { + padding-top: 0; +} diff --git a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css.d.ts b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css.d.ts index 282c186dd2..62118fac97 100644 --- a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css.d.ts +++ b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.css.d.ts @@ -16,3 +16,4 @@ export const buttonTooltip: string; export const cancelIcon: string; export const claimed: string; export const tagStagesWrapper: string; +export const paddingSmall: string; diff --git a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.tsx b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.tsx index 00d6b8c77f..7eb73c4e79 100644 --- a/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.tsx +++ b/src/modules/dashboard/components/ExpenditurePage/Stages/Stages.tsx @@ -142,7 +142,11 @@ const Stages = ({ status !== Status.Cancelled; return ( -
+
{claimFundsVisible && formValues && ( <> {formValues.expenditure === ExpenditureTypes.Advanced ? ( diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts index 06f60df12b..fc540a64e2 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.css.d.ts @@ -13,5 +13,3 @@ export const additionalText: string; export const additionalMargin: string; export const radioWrapper: string; export const selected: string; -export const mianContactWrapper: string; -export const fadeIn: string; diff --git a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx index eebfcdeba7..796dddaa00 100644 --- a/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx +++ b/src/modules/dashboard/components/Incorporation/IncorporationForm/Protectors/Protectors.tsx @@ -15,7 +15,6 @@ import { supRenderAvatar } from '~dashboard/ExpenditurePage/Recipient/Recipient' import { Protector } from '~pages/IncorporationPage/types'; import Button from '~core/Button'; import Link from '~core/Link'; -import { Protector } from '~pages/IncorporationPage/types'; import SingleUserPicker from '../SingleUserPicker'; import { SignOption } from '../constants'; @@ -181,71 +180,82 @@ const Protectors = ({ colony, sidebarRef }: Props) => { />
-
- {shouldShowMainContact && mainContactData && ( - -
-
- - -
-
-
- - {error && typeof error === 'object' && touched && ( -
{formatMessage(error)}
- )} -
- setMainContact(undefined)} - title={MSG.deleteIconTitle} - /> -
-
-
- )} - {shouldShowMainContact && ( -
+ {shouldShowMainContact && mainContactData && ( + +
- - + +
+
+
+ + {error && typeof error === 'object' && touched && ( +
{formatMessage(error)}
+ )} +
+ setMainContact(undefined)} + title={MSG.deleteIconTitle} + /> +
+
+
+ )} + {shouldShowMainContact && ( +
+
+ + +
+
+ elementOnly + > + + +
+
+ elementOnly + > + +
- )} -
+
+ )} ); }; 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.css b/src/modules/pages/components/IncorporationPage/IncorporationPage.css index 2235b5f6b1..22120812e4 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.css +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.css @@ -7,10 +7,6 @@ height: 100%; } -.titleCommentsContainer { - min-width: 458px; -} - .sidebar { height: 600px; min-height: calc(100vh - navBarHeight); @@ -36,6 +32,7 @@ } .mainContainer { + padding: 52px 100px 70px 25px; padding-bottom: 50px; height: 600px; min-height: 100%; @@ -51,6 +48,10 @@ min-height: calc(100vh - navBarHeight); } +.smallerPadding { + padding: 36px 100px 80px 25px; +} + .tagWrapper { margin-bottom: -30px; padding: 34px 54px 0; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts b/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts index 02d6e0fffe..b4fd056764 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.css.d.ts @@ -1,7 +1,6 @@ export const sidebarWidth: string; export const navBarHeight: string; export const main: string; -export const titleCommentsContainer: string; export const sidebar: string; export const wrapper: string; export const spinnerContainer: string; @@ -9,3 +8,4 @@ export const mainContainer: string; export const mainContent: string; export const smallerPadding: string; export const tagWrapper: string; +export const titleCommentsContainer: string; diff --git a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx index ee9cae501c..2f759ea1d9 100644 --- a/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx +++ b/src/modules/pages/components/IncorporationPage/IncorporationPage.tsx @@ -19,6 +19,9 @@ import { } from '~dashboard/ExpenditurePage/Stages/constants'; import { Motion } from '~pages/ExpenditurePage/types'; import { useLoggedInUser } from '~data/helpers'; +import VerificationBanner from '~dashboard/Incorporation/VerificationBanner'; +import IncorporationPaymentDialog from '~dashboard/Dialogs/IncorporationPaymentDialog'; +import Stages, { FormStages } from '~dashboard/ExpenditurePage/Stages'; import { initialValues, @@ -32,7 +35,6 @@ import { import { findDifferences, updateValues } from './utils'; import { ValuesType } from './types'; import styles from './IncorporationPage.css'; -import VerificationBanner from '~dashboard/Incorporation/VerificationBanner'; const MSG = defineMessages({ editMode: { @@ -60,7 +62,7 @@ const IncorporationPage = () => { const [isFormEditable, setFormEditable] = useState(false); const [formValues, setFormValues] = useState(formValuesMock); const [shouldValidate, setShouldValidate] = useState(false); - const [activeStageId, setActiveStageId] = useState(StagesEnum.Draft); + const [activeStageId, setActiveStageId] = useState(StagesEnum.Created); const [inEditMode, setInEditMode] = useState(false); const oldValues = useRef(); const sidebarRef = useRef(null); @@ -68,14 +70,10 @@ const IncorporationPage = () => { const notVerified = true; // temporary valule const openPayDialog = useDialog(IncorporationPaymentDialog); - const [motion, setMotion] = useState(); + const [, setMotion] = useState(); const openEditIncorporationDialog = useDialog(EditIncorporationDialog); - const { data: colonyData, loading } = useColonyFromNameQuery({ - variables: { name: colonyName, address: '' }, - }); - const { walletAddress } = useLoggedInUser(); const isOwner = useMemo( @@ -248,9 +246,24 @@ const IncorporationPage = () => { handleEditSubmit={() => handleEditSubmit(values, validateForm) } + handleEditCancel={handleEditCancel} /> ) : ( - + colonyData && ( + ({ + ...stage, + id: stage.id.toString(), + label: stage.title, + buttonAction, + }))} + setActiveStageId={setActiveStageId} + colony={colonyData.processedColony} + setFormValues={setFormValues} + handleCancelExpenditure={() => {}} + /> + ) )}
@@ -277,11 +290,14 @@ const IncorporationPage = () => {
{/* user passed to VerifiactionBanner is a mock */} - {notVerified && } + {notVerified && activeStageId === StagesEnum.Created && ( + + )}