From 5512569e39b0709090bf9bac06b99f72c2108eb4 Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Thu, 21 Jul 2022 19:50:11 -0300 Subject: [PATCH 1/7] Connected Remove Safes dialog --- src/i18n/en.json | 4 + .../RemoveSafeDialog/RemoveSafeDialog.tsx | 69 +++--- .../RemoveSafeDialog/RemoveSafeDialogForm.tsx | 9 +- .../Dialogs/RemoveSafeDialog/SafeListItem.tsx | 21 +- .../Dialogs/RemoveSafeDialog/types.ts | 7 - src/modules/dashboard/sagas/actions/index.ts | 2 + .../sagas/actions/removeExistingSafes.ts | 221 ++++++++++++++++++ src/redux/actionTypes.ts | 3 + src/redux/types/actions/colonyActions.ts | 18 ++ 9 files changed, 290 insertions(+), 64 deletions(-) delete mode 100644 src/modules/dashboard/components/Dialogs/RemoveSafeDialog/types.ts create mode 100644 src/modules/dashboard/sagas/actions/removeExistingSafes.ts diff --git a/src/i18n/en.json b/src/i18n/en.json index 680033be57f..e2ff49802f6 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -244,6 +244,10 @@ "transaction.group.addExistingSafe.description": "Add an existing Safe to this Colony", "transaction.ColonyClient.addExistingSafe.title": "Add Existing Safe", "transaction.ColonyClient.addExistingSafe.description": "Add an existing Safe to this Colony", + "transaction.group.removeExistingSafes.title": "Remove Existing Safes", + "transaction.group.removeExistingSafes.description": "Remove existing Safes from this Colony", + "transaction.ColonyClient.removeExistingSafes.title": "Remove Existing Safes", + "transaction.ColonyClient.removeExistingSafes.description": "Remove existing Safes from this Colony", "message.generic.title": "Generic Message", "message.generic.description": "This needs your wallet's signature", diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx index 13f36d70623..3af1fd00045 100644 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx @@ -1,54 +1,19 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { FormikProps } from 'formik'; +import { useHistory } from 'react-router'; import Dialog, { DialogProps, ActionDialogProps } from '~core/Dialog'; import { ActionForm } from '~core/Fields'; import { Address } from '~types/index'; -// import { Colony } from '~data/index'; import { ActionTypes } from '~redux/index'; import { WizardDialogType } from '~utils/hooks'; +import { pipe, withMeta, mapPayload } from '~utils/actions'; -import { Safe } from './types'; import DialogForm from './RemoveSafeDialogForm'; const displayName = 'dashboard.RemoveSafeDialog'; -// Mock data for testing -const safes: Safe[] = [ - { - name: 'All Saints', - chain: `Gnosis Chain`, - address: '0x3a157280ca91bB49dAe3D1619C55Da7F9D4438c2', - }, - // { - // name: '', - // chain: `Mainnet` - // address: '0x4a157280ca91bB49dAe3D1619C55Da7F9D4438c3', - // }, - // { - // name: 'Big safe', - // chain: `Mainnet` - // address: '0x5a157280ca91bB49dAe3D1619C55Da7F9D4438c2', - // }, - // { - // name: `Just a test with a very very long name, - // hang on its even longer!!!!!!!!`, - // chain: `Mainnet` - // address: '0x6a157280ca91bB49dAe3D1619C55Da7F9D4438c3', - // }, - // { - // name: 'blalabalabal', - // chain: `Mainnet` - // address: '0x7a157280ca91bB49dAe3D1619C55Da7F9D4438c2', - // }, - // { - // name: 'final test', - // chain: `Mainnet` - // address: '0x8a157280ca91bB49dAe3D1619C55Da7F9D4438c3', - // }, -]; - export interface FormValues { safeList: Address[]; } @@ -64,17 +29,35 @@ const RemoveSafeDialog = ({ prevStep, colony, }: Props) => { + const history = useHistory(); + const { safes } = colony; + + const transform = useCallback( + pipe( + mapPayload(({ safeList, annotation: annotationMessage }) => { + return { + colonyName: colony.colonyName, + colonyAddress: colony.colonyAddress, + safeAddresses: safeList, + annotationMessage, + }; + }), + withMeta({ history }), + ), + [], + ); + return ( {(formValues: FormikProps) => { return ( diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialogForm.tsx b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialogForm.tsx index cc988334474..71659c11dee 100644 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialogForm.tsx +++ b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialogForm.tsx @@ -7,13 +7,12 @@ import DialogSection from '~core/Dialog/DialogSection'; import Heading from '~core/Heading'; import { ActionDialogProps } from '~core/Dialog'; -import { useLoggedInUser } from '~data/index'; +import { ColonySafe, useLoggedInUser } from '~data/index'; import { useTransformer } from '~utils/hooks'; import { getAllUserRoles } from '~modules/transformers'; import { canEnterRecoveryMode } from '~modules/users/checks'; import SafeListItem from './SafeListItem'; -import { Safe } from './types'; import { FormValues } from './RemoveSafeDialog'; import styles from './RemoveSafeDialogForm.css'; @@ -34,7 +33,7 @@ const MSG = defineMessages({ }); interface Props extends Omit { - safeList: Safe[]; + safeList: ColonySafe[]; } const RemoveSafeDialogForm = ({ @@ -77,9 +76,9 @@ const RemoveSafeDialogForm = ({
{safeList.map((item) => ( ))}
diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx index f9743ab2939..336fb937c4c 100644 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx +++ b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx @@ -1,11 +1,12 @@ import React from 'react'; import { defineMessages } from 'react-intl'; +import { GNOSIS_SAFE_NETWORKS } from '~constants'; import Avatar from '~core/Avatar'; import { Checkbox } from '~core/Fields'; import MaskedAddress from '~core/MaskedAddress'; import InvisibleCopyableAddress from '~core/InvisibleCopyableAddress'; -import { Safe } from './types'; +import { ColonySafe } from '~data/index'; import styles from './SafeListItem.css'; @@ -17,11 +18,14 @@ const MSG = defineMessages({ }); interface Props { - safe: Safe; + safe: ColonySafe; isChecked: boolean; } const SafeListItem = ({ safe, isChecked }: Props) => { + const safeNetwork = GNOSIS_SAFE_NETWORKS.find( + (network) => network.chainId === Number(safe.chainId), + ); return (
{ - {`${safe.name} (${safe.chain})`} + {`${safe.safeName} (${safeNetwork?.name || 'Unknown'})`}
- +
diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/types.ts b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/types.ts deleted file mode 100644 index 6c60df10d50..00000000000 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { Address } from '~types/index'; - -export interface Safe { - name: string; - chain: string; - address: Address; -} diff --git a/src/modules/dashboard/sagas/actions/index.ts b/src/modules/dashboard/sagas/actions/index.ts index b8653530b40..47bf1e6581f 100644 --- a/src/modules/dashboard/sagas/actions/index.ts +++ b/src/modules/dashboard/sagas/actions/index.ts @@ -12,6 +12,7 @@ import unlockTokenActionSaga from './unlockToken'; import enterRecoveryActionSaga from './enterRecovery'; import manageReputationActionSaga from './manageReputation'; import addExistingSafeSaga from './addExistingSafe'; +import removeExistingSafesSaga from './removeExistingSafes'; export default function* actionsSagas() { yield all([ @@ -23,6 +24,7 @@ export default function* actionsSagas() { call(editDomainActionSaga), call(editColonyActionSaga), call(addExistingSafeSaga), + call(removeExistingSafesSaga), call(managePermissionsActionSaga), call(unlockTokenActionSaga), call(enterRecoveryActionSaga), diff --git a/src/modules/dashboard/sagas/actions/removeExistingSafes.ts b/src/modules/dashboard/sagas/actions/removeExistingSafes.ts new file mode 100644 index 00000000000..acc5bf15869 --- /dev/null +++ b/src/modules/dashboard/sagas/actions/removeExistingSafes.ts @@ -0,0 +1,221 @@ +import { call, fork, put, takeEvery } from 'redux-saga/effects'; +import { ClientType } from '@colony/colony-js'; +import isEmpty from 'lodash/isEmpty'; + +import { ContextModule, TEMP_getContext } from '~context/index'; +import { + ColonyFromNameDocument, + ColonyFromNameQuery, + ColonyFromNameQueryVariables, + SubgraphColonyDocument, + SubgraphColonyQuery, + SubgraphColonyQueryVariables, +} from '~data/index'; +import { Action, ActionTypes, AllActions } from '~redux/index'; +import { putError, takeFrom, routeRedirect } from '~utils/saga/effects'; + +import { uploadIfpsAnnotation } from '../utils'; +import { + createTransaction, + createTransactionChannels, + getTxChannel, +} from '../../../core/sagas'; +import { ipfsUpload } from '../../../core/sagas/ipfs'; +import { + transactionReady, + transactionPending, + transactionAddParams, +} from '../../../core/actionCreators'; + +function* removeExistingSafesAction({ + payload: { colonyName, colonyAddress, safeAddresses, annotationMessage }, + meta: { id: metaId, history }, + meta, +}: Action) { + let txChannel; + try { + const apolloClient = TEMP_getContext(ContextModule.ApolloClient); + const ipfsWithFallback = TEMP_getContext(ContextModule.IPFSWithFallback); + + if (isEmpty(safeAddresses)) { + throw new Error('A list with safe addresses is required to remove safes'); + } + + txChannel = yield call(getTxChannel, metaId); + const batchKey = 'removeExistingSafes'; + const { + removeExistingSafesAction: removeExistingSafes, + annotateRemoveExistingSafesAction: annotateRemoveExistingSafes, + } = yield createTransactionChannels(metaId, [ + 'removeExistingSafesAction', + 'annotateRemoveExistingSafesAction', + ]); + + const createGroupTransaction = ({ id, index }, config) => + fork(createTransaction, id, { + ...config, + group: { + key: batchKey, + id: metaId, + index, + }, + }); + + yield createGroupTransaction(removeExistingSafes, { + context: ClientType.ColonyClient, + methodName: 'editColony', + identifier: colonyAddress, + params: [], + ready: false, + }); + + if (annotationMessage) { + yield createGroupTransaction(annotateRemoveExistingSafes, { + context: ClientType.ColonyClient, + methodName: 'annotateTransaction', + identifier: colonyAddress, + params: [], + ready: false, + }); + } + + yield takeFrom( + removeExistingSafes.channel, + ActionTypes.TRANSACTION_CREATED, + ); + if (annotationMessage) { + yield takeFrom( + annotateRemoveExistingSafes.channel, + ActionTypes.TRANSACTION_CREATED, + ); + } + + yield put(transactionPending(removeExistingSafes.id)); + + /* + * Fetch colony data from the subgraph + * And destructure the metadata hash. + */ + + const { + data: { + colony: { metadata: currentMetadataIPFSHash }, + }, + } = yield apolloClient.query< + SubgraphColonyQuery, + SubgraphColonyQueryVariables + >({ + query: SubgraphColonyDocument, + variables: { + address: colonyAddress.toLowerCase(), + }, + fetchPolicy: 'network-only', + }); + + const currentMetadata = yield call( + ipfsWithFallback.getString, + currentMetadataIPFSHash, + ); + + const colonyMetadata = JSON.parse(currentMetadata); + + const updatedColonySafes = colonyMetadata.colonySafes.filter((safe) => + safeAddresses.find((safeAddress) => safeAddress !== safe.contractAddress), + ); + const updatedColonyMetadata = { + ...colonyMetadata, + colonySafes: updatedColonySafes, + }; + + /* + * Upload updated metadata object to IPFS + */ + + const updatedColonyMetadataIpfsHash = yield call( + ipfsUpload, + JSON.stringify(updatedColonyMetadata), + ); + + yield put( + transactionAddParams(removeExistingSafes.id, [ + (updatedColonyMetadataIpfsHash as unknown) as string, + ]), + ); + + yield put(transactionReady(removeExistingSafes.id)); + + const { + payload: { hash: txHash }, + } = yield takeFrom( + removeExistingSafes.channel, + ActionTypes.TRANSACTION_HASH_RECEIVED, + ); + + yield takeFrom( + removeExistingSafes.channel, + ActionTypes.TRANSACTION_SUCCEEDED, + ); + + if (annotationMessage) { + yield put(transactionPending(annotateRemoveExistingSafes.id)); + + /* + * Upload annotationMessage to IPFS + */ + const annotationMessageIpfsHash = yield call( + uploadIfpsAnnotation, + annotationMessage, + ); + + yield put( + transactionAddParams(annotateRemoveExistingSafes.id, [ + txHash, + annotationMessageIpfsHash, + ]), + ); + + yield put(transactionReady(annotateRemoveExistingSafes.id)); + + yield takeFrom( + annotateRemoveExistingSafes.channel, + ActionTypes.TRANSACTION_SUCCEEDED, + ); + } + + /* + * Update the colony object cache + */ + yield apolloClient.query( + { + query: ColonyFromNameDocument, + variables: { name: colonyName || '', address: colonyAddress }, + fetchPolicy: 'network-only', + }, + ); + + yield put({ + type: ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS, + meta, + }); + + if (colonyName) { + yield routeRedirect(`/colony/${colonyName}/tx/${txHash}`, history); + } + } catch (error) { + return yield putError( + ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR, + error, + meta, + ); + } finally { + txChannel.close(); + } + return null; +} + +export default function* addExistingSafeSaga() { + yield takeEvery( + ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES, + removeExistingSafesAction, + ); +} diff --git a/src/redux/actionTypes.ts b/src/redux/actionTypes.ts index b16ca6e232a..18c64620103 100644 --- a/src/redux/actionTypes.ts +++ b/src/redux/actionTypes.ts @@ -45,6 +45,9 @@ export enum ActionTypes { COLONY_ACTION_DOMAIN_EDIT = 'COLONY_ACTION_DOMAIN_EDIT', COLONY_ACTION_DOMAIN_EDIT_ERROR = 'COLONY_ACTION_DOMAIN_EDIT_ERROR', COLONY_ACTION_DOMAIN_EDIT_SUCCESS = 'COLONY_ACTION_DOMAIN_EDIT_SUCCESS', + COLONY_ACTION_REMOVE_EXISTING_SAFES = 'COLONY_ACTION_REMOVE_EXISTING_SAFES', + COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR = 'COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR', + COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS = 'COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS', /* * @NOTE These are generic actions use for placeholders * They are not, and should not be wired to any dispatch action diff --git a/src/redux/types/actions/colonyActions.ts b/src/redux/types/actions/colonyActions.ts index 3b3b1bc5a52..82f5d03b7d6 100644 --- a/src/redux/types/actions/colonyActions.ts +++ b/src/redux/types/actions/colonyActions.ts @@ -272,4 +272,22 @@ export type ColonyActionsActionTypes = | ActionTypeWithMeta< ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS, MetaWithHistory + > + | UniqueActionType< + ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES, + { + colonyName: string; + colonyAddress: Address; + safeAddresses: Address[]; + annotationMessage?: string; + }, + MetaWithHistory + > + | ErrorActionType< + ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR, + object + > + | ActionTypeWithMeta< + ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS, + MetaWithHistory >; From f186f17061f147a371d2661a82825cbf15279f03 Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Thu, 21 Jul 2022 20:00:23 -0300 Subject: [PATCH 2/7] Added permission validation to adding/removing safes actions in the UAC --- .../ColonyHomeActions/ColonyHomeActions.tsx | 19 --------- .../ManageGnosisSafeDialog.tsx | 42 +++++++++++++++++-- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/src/modules/dashboard/components/ColonyHomeActions/ColonyHomeActions.tsx b/src/modules/dashboard/components/ColonyHomeActions/ColonyHomeActions.tsx index ba2077eeba0..4f5daaa18cc 100644 --- a/src/modules/dashboard/components/ColonyHomeActions/ColonyHomeActions.tsx +++ b/src/modules/dashboard/components/ColonyHomeActions/ColonyHomeActions.tsx @@ -228,7 +228,6 @@ const ColonyHomeActions = ({ colony, ethDomainId }: Props) => { colony, }, }, - // @todo - ready to be implemented in another PR. { component: AddExistingSafeDialog, props: { @@ -236,15 +235,6 @@ const ColonyHomeActions = ({ colony, ethDomainId }: Props) => { colony, }, }, - // { - // component: RemoveSafeDialog, - // props: { - // prevStep: 'dashboard.RemoveSafeDialog', - // colony, - // isVotingExtensionEnabled, - // ethDomainId, - // }, - // }, { component: GnosisControlSafeDialog, props: { @@ -260,15 +250,6 @@ const ColonyHomeActions = ({ colony, ethDomainId }: Props) => { colony, }, }, - // { - // component: ControlSafeDialog, - // props: { - // prevStep: 'dashboard.ManageGnosisSafeDialog', - // colony, - // isVotingExtensionEnabled, - // ethDomainId, - // }, - // }, { component: PermissionManagementDialog, diff --git a/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx b/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx index 9819ee55078..7ae882b5ec3 100644 --- a/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx @@ -1,10 +1,13 @@ +import { ColonyRole } from '@colony/colony-js'; import React from 'react'; -import { defineMessages } from 'react-intl'; +import { defineMessages, useIntl } from 'react-intl'; import { DialogProps, ActionDialogProps } from '~core/Dialog'; import IndexModal from '~core/IndexModal'; - -import { WizardDialogType } from '~utils/hooks'; +import { useLoggedInUser } from '~data/index'; +import { getAllUserRoles } from '~modules/transformers'; +import { userHasRole } from '~modules/users/checks'; +import { useTransformer, WizardDialogType } from '~utils/hooks'; const MSG = defineMessages({ dialogHeader: { @@ -36,6 +39,11 @@ const MSG = defineMessages({ id: 'dashboard.ManageGnosisSafeDialog.controlSafeDescription', defaultMessage: 'Get your colony’s Gnosis Safe to do stuff.', }, + permissionText: { + id: 'dashboard.ManageReputationDialog.permissionsText', + defaultMessage: `You must have the {permission} permissions in the + relevant teams, in order to take this action`, + }, }); interface CustomWizardDialogProps extends ActionDialogProps { @@ -50,6 +58,7 @@ type Props = DialogProps & WizardDialogType & CustomWizardDialogProps; const displayName = 'dashboard.ManageGnosisSafeDialog'; const ManageGnosisSafeDialog = ({ + colony, cancel, close, callStep, @@ -58,6 +67,15 @@ const ManageGnosisSafeDialog = ({ nextStepRemoveSafe, nextStepControlSafe, }: Props) => { + const { walletAddress, username, ethereal } = useLoggedInUser(); + const { formatMessage } = useIntl(); + const allUserRoles = useTransformer(getAllUserRoles, [colony, walletAddress]); + + const hasRegisteredProfile = !!username && !ethereal; + const canManageGnosisSafes = + (hasRegisteredProfile && + userHasRole(allUserRoles, ColonyRole.Administration)) || + userHasRole(allUserRoles, ColonyRole.Funding); const items = [ { title: MSG.addExistingSafeTitle, @@ -65,6 +83,15 @@ const ManageGnosisSafeDialog = ({ icon: 'plus-heavy', dataTest: 'gnosisAddExistingItem', onClick: () => callStep(nextStepAddExistingSafe), + permissionRequired: !canManageGnosisSafes, + permissionInfoText: MSG.permissionText, + permissionInfoTextValues: { + permission: `${formatMessage({ + id: `role.${ColonyRole.Administration}`, + }).toLowerCase()} and ${formatMessage({ + id: `role.${ColonyRole.Funding}`, + }).toLowerCase()}`, + }, }, { title: MSG.removeSafeTitle, @@ -72,6 +99,15 @@ const ManageGnosisSafeDialog = ({ icon: 'trash-can', dataTest: 'gnosisRemoveSafeItem', onClick: () => callStep(nextStepRemoveSafe), + permissionRequired: !canManageGnosisSafes, + permissionInfoText: MSG.permissionText, + permissionInfoTextValues: { + permission: `${formatMessage({ + id: `role.${ColonyRole.Administration}`, + }).toLowerCase()} and ${formatMessage({ + id: `role.${ColonyRole.Funding}`, + }).toLowerCase()}`, + }, }, { title: MSG.controlSafeTitle, From 9a86e5f9215e3e76a4654efe7dc1a2c96807dca6 Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Mon, 25 Jul 2022 19:08:44 -0300 Subject: [PATCH 3/7] Fixed MSG havng wring id in ManageGnosisSafeDialog --- .../Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx b/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx index 7ae882b5ec3..f72e7dca05e 100644 --- a/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/ManageGnosisSafeDialog/ManageGnosisSafeDialog.tsx @@ -32,7 +32,7 @@ const MSG = defineMessages({ defaultMessage: 'Remove a Gnosis Safe you previously added to your Colony.', }, controlSafeTitle: { - id: 'dashboard.ManageReputationDialog.controlSafeTitle', + id: 'dashboard.ManageGnosisSafeDialog.controlSafeTitle', defaultMessage: 'Control Safe', }, controlSafeDescription: { @@ -40,7 +40,7 @@ const MSG = defineMessages({ defaultMessage: 'Get your colony’s Gnosis Safe to do stuff.', }, permissionText: { - id: 'dashboard.ManageReputationDialog.permissionsText', + id: 'dashboard.ManageGnosisSafeDialog.permissionsText', defaultMessage: `You must have the {permission} permissions in the relevant teams, in order to take this action`, }, From 5ae1893e3aacbfc03f1fef794781a5c44498ab1b Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Tue, 26 Jul 2022 20:22:40 -0300 Subject: [PATCH 4/7] Fixed safe filter function in removeExistingSafes --- .../dashboard/sagas/actions/removeExistingSafes.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/dashboard/sagas/actions/removeExistingSafes.ts b/src/modules/dashboard/sagas/actions/removeExistingSafes.ts index acc5bf15869..8b005ce4344 100644 --- a/src/modules/dashboard/sagas/actions/removeExistingSafes.ts +++ b/src/modules/dashboard/sagas/actions/removeExistingSafes.ts @@ -7,6 +7,7 @@ import { ColonyFromNameDocument, ColonyFromNameQuery, ColonyFromNameQueryVariables, + ColonySafe, SubgraphColonyDocument, SubgraphColonyQuery, SubgraphColonyQueryVariables, @@ -119,8 +120,11 @@ function* removeExistingSafesAction({ const colonyMetadata = JSON.parse(currentMetadata); - const updatedColonySafes = colonyMetadata.colonySafes.filter((safe) => - safeAddresses.find((safeAddress) => safeAddress !== safe.contractAddress), + const updatedColonySafes = colonyMetadata.colonySafes.filter( + (safe: ColonySafe) => + !safeAddresses.some( + (safeAddress) => safeAddress === safe.contractAddress, + ), ); const updatedColonyMetadata = { ...colonyMetadata, From 88bb1b68d3b36f3c0ae0d04c60b9a1cb7ce7627f Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Thu, 4 Aug 2022 16:12:37 -0300 Subject: [PATCH 5/7] Fixed tooltip placement in SafeListItem --- .../InvisibleCopyableAddress/InvisibleCopyableAddress.tsx | 6 +++++- .../components/Dialogs/RemoveSafeDialog/SafeListItem.tsx | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/core/components/InvisibleCopyableAddress/InvisibleCopyableAddress.tsx b/src/modules/core/components/InvisibleCopyableAddress/InvisibleCopyableAddress.tsx index badd05e10a4..e7cffdcfc6b 100644 --- a/src/modules/core/components/InvisibleCopyableAddress/InvisibleCopyableAddress.tsx +++ b/src/modules/core/components/InvisibleCopyableAddress/InvisibleCopyableAddress.tsx @@ -5,6 +5,7 @@ import { MessageDescriptor, useIntl, } from 'react-intl'; +import { Placement } from '@popperjs/core'; import copyToClipboard from 'copy-to-clipboard'; import { Address } from '~types/index'; @@ -19,6 +20,8 @@ interface Props { address: Address; /** Text which will display in tooltip when hovering on address */ copyMessage?: MessageDescriptor; + /** Determines the position of the tooltip's text */ + tooltipPlacement?: Placement; } const MSG = defineMessages({ @@ -41,6 +44,7 @@ const InvisibleCopyableAddress = ({ children, address, copyMessage, + tooltipPlacement = 'right', }: Props) => { const [copied, setCopied] = useState(false); const { formatMessage } = useIntl(); @@ -64,7 +68,7 @@ const InvisibleCopyableAddress = ({ formatMessage(MSG.copyMessage); return ( {
From a8bf6e3a48b753d58fea8760c9658dee1369723e Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Thu, 4 Aug 2022 17:32:30 -0300 Subject: [PATCH 6/7] Combined removeExistingSafes and addExistingSafe into manageExistingSafes --- .../AddExistingSafeDialog.tsx | 16 +- .../RemoveSafeDialog/RemoveSafeDialog.tsx | 7 +- .../sagas/actions/addExistingSafe.ts | 234 ------------------ src/modules/dashboard/sagas/actions/index.ts | 6 +- ...xistingSafes.ts => manageExistingSafes.ts} | 91 ++++--- src/redux/actionTypes.ts | 9 +- src/redux/types/actions/colonyActions.ts | 24 +- 7 files changed, 78 insertions(+), 309 deletions(-) delete mode 100644 src/modules/dashboard/sagas/actions/addExistingSafe.ts rename src/modules/dashboard/sagas/actions/{removeExistingSafes.ts => manageExistingSafes.ts} (67%) diff --git a/src/modules/dashboard/components/Dialogs/AddExistingSafeDialog/AddExistingSafeDialog.tsx b/src/modules/dashboard/components/Dialogs/AddExistingSafeDialog/AddExistingSafeDialog.tsx index 27faf5c8379..fe3fdb1ede2 100644 --- a/src/modules/dashboard/components/Dialogs/AddExistingSafeDialog/AddExistingSafeDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/AddExistingSafeDialog/AddExistingSafeDialog.tsx @@ -61,9 +61,13 @@ const AddExistingSafeDialog = ({ return { colonyName, colonyAddress, - chainId, - safeName, - contractAddress, + safeAddresses: [ + { + chainId, + safeName, + contractAddress, + }, + ], annotationMessage, }; }, @@ -82,9 +86,9 @@ const AddExistingSafeDialog = ({ contractAddress: undefined, }} validationSchema={validationSchema} - submit={ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE} - error={ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_ERROR} - success={ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS} + submit={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES} + error={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR} + success={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS} transform={transform} onSuccess={close} > diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx index 3af1fd00045..379b32ee2c2 100644 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx +++ b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/RemoveSafeDialog.tsx @@ -40,6 +40,7 @@ const RemoveSafeDialog = ({ colonyAddress: colony.colonyAddress, safeAddresses: safeList, annotationMessage, + isRemovingSafes: true, }; }), withMeta({ history }), @@ -53,9 +54,9 @@ const RemoveSafeDialog = ({ // if there's only 1 safe then that safe is already checked. safeList: safes.length === 1 ? [safes[0].contractAddress] : [], }} - submit={ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES} - error={ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR} - success={ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS} + submit={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES} + error={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR} + success={ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS} onSuccess={close} transform={transform} > diff --git a/src/modules/dashboard/sagas/actions/addExistingSafe.ts b/src/modules/dashboard/sagas/actions/addExistingSafe.ts deleted file mode 100644 index a6df64c93fd..00000000000 --- a/src/modules/dashboard/sagas/actions/addExistingSafe.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { call, fork, put, takeEvery } from 'redux-saga/effects'; -import { ClientType } from '@colony/colony-js'; - -import { ContextModule, TEMP_getContext } from '~context/index'; -import { - ColonyFromNameDocument, - ColonyFromNameQuery, - ColonyFromNameQueryVariables, - SubgraphColonyDocument, - SubgraphColonyQuery, - SubgraphColonyQueryVariables, -} from '~data/index'; -import { Action, ActionTypes, AllActions } from '~redux/index'; -import { putError, takeFrom, routeRedirect } from '~utils/saga/effects'; - -import { uploadIfpsAnnotation } from '../utils'; -import { - createTransaction, - createTransactionChannels, - getTxChannel, -} from '../../../core/sagas'; -import { ipfsUpload } from '../../../core/sagas/ipfs'; -import { - transactionReady, - transactionPending, - transactionAddParams, -} from '../../../core/actionCreators'; - -function* addExistingSafeAction({ - payload: { - colonyName, - colonyAddress, - chainId, - safeName, - contractAddress, - annotationMessage, - }, - meta: { id: metaId, history }, - meta, -}: Action) { - let txChannel; - try { - const apolloClient = TEMP_getContext(ContextModule.ApolloClient); - const ipfsWithFallback = TEMP_getContext(ContextModule.IPFSWithFallback); - - if (!contractAddress) { - throw new Error('A Safe contract address is required.'); - } - - txChannel = yield call(getTxChannel, metaId); - const batchKey = 'addExistingSafe'; - const { - addExistingSafeAction: addExistingSafe, - annotateAddExistingSafeAction: annotateAddExistingSafe, - } = yield createTransactionChannels(metaId, [ - 'addExistingSafeAction', - 'annotateAddExistingSafeAction', - ]); - - const createGroupTransaction = ({ id, index }, config) => - fork(createTransaction, id, { - ...config, - group: { - key: batchKey, - id: metaId, - index, - }, - }); - - yield createGroupTransaction(addExistingSafe, { - context: ClientType.ColonyClient, - methodName: 'editColony', - identifier: colonyAddress, - params: [], - ready: false, - }); - - if (annotationMessage) { - yield createGroupTransaction(annotateAddExistingSafe, { - context: ClientType.ColonyClient, - methodName: 'annotateTransaction', - identifier: colonyAddress, - params: [], - ready: false, - }); - } - - yield takeFrom(addExistingSafe.channel, ActionTypes.TRANSACTION_CREATED); - if (annotationMessage) { - yield takeFrom( - annotateAddExistingSafe.channel, - ActionTypes.TRANSACTION_CREATED, - ); - } - - yield put(transactionPending(addExistingSafe.id)); - - /* - * Fetch colony data from the subgraph - * And destructure the metadata hash. - */ - const { - data: { - colony: { metadata: currentMetadataIPFSHash }, - }, - } = yield apolloClient.query< - SubgraphColonyQuery, - SubgraphColonyQueryVariables - >({ - query: SubgraphColonyDocument, - variables: { - address: colonyAddress.toLowerCase(), - }, - fetchPolicy: 'network-only', - }); - - let updatedColonyMetadata: any = {}; - const safeData = { safeName, contractAddress, chainId }; - - /* - * If there isn't metadata in the colony ... - */ - if (!currentMetadataIPFSHash) { - /* - * ... add the safe to a new metadata object. - */ - updatedColonyMetadata = { colonySafes: [safeData] }; - } else { - /* - * ... otherwise, fetch the metadata from IPFS... - */ - const currentMetadata = yield call( - ipfsWithFallback.getString, - currentMetadataIPFSHash, - ); - - const colonyMetadata = JSON.parse(currentMetadata); - const safes = colonyMetadata.colonySafes; - updatedColonyMetadata = { - ...colonyMetadata, - colonySafes: safes - ? [...colonyMetadata.colonySafes, safeData] - : [safeData], - }; - } - - /* - * Upload updated metadata object to IPFS - */ - const updatedColonyMetadataIpfsHash = yield call( - ipfsUpload, - JSON.stringify(updatedColonyMetadata), - ); - - yield put( - transactionAddParams(addExistingSafe.id, [ - (updatedColonyMetadataIpfsHash as unknown) as string, - ]), - ); - - yield put(transactionReady(addExistingSafe.id)); - - const { - payload: { hash: txHash }, - } = yield takeFrom( - addExistingSafe.channel, - ActionTypes.TRANSACTION_HASH_RECEIVED, - ); - - yield takeFrom(addExistingSafe.channel, ActionTypes.TRANSACTION_SUCCEEDED); - - if (annotationMessage) { - yield put(transactionPending(annotateAddExistingSafe.id)); - - /* - * Upload annotationMessage to IPFS - */ - const annotationMessageIpfsHash = yield call( - uploadIfpsAnnotation, - annotationMessage, - ); - - yield put( - transactionAddParams(annotateAddExistingSafe.id, [ - txHash, - annotationMessageIpfsHash, - ]), - ); - - yield put(transactionReady(annotateAddExistingSafe.id)); - - yield takeFrom( - annotateAddExistingSafe.channel, - ActionTypes.TRANSACTION_SUCCEEDED, - ); - } - - /* - * Update the colony object cache - */ - yield apolloClient.query( - { - query: ColonyFromNameDocument, - variables: { name: colonyName || '', address: colonyAddress }, - fetchPolicy: 'network-only', - }, - ); - - yield put({ - type: ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS, - meta, - }); - - if (colonyName) { - yield routeRedirect(`/colony/${colonyName}/tx/${txHash}`, history); - } - } catch (error) { - return yield putError( - ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_ERROR, - error, - meta, - ); - } finally { - txChannel.close(); - } - return null; -} - -export default function* addExistingSafeSaga() { - yield takeEvery( - ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE, - addExistingSafeAction, - ); -} diff --git a/src/modules/dashboard/sagas/actions/index.ts b/src/modules/dashboard/sagas/actions/index.ts index 47bf1e6581f..01b31650f84 100644 --- a/src/modules/dashboard/sagas/actions/index.ts +++ b/src/modules/dashboard/sagas/actions/index.ts @@ -11,8 +11,7 @@ import managePermissionsActionSaga from './managePermissions'; import unlockTokenActionSaga from './unlockToken'; import enterRecoveryActionSaga from './enterRecovery'; import manageReputationActionSaga from './manageReputation'; -import addExistingSafeSaga from './addExistingSafe'; -import removeExistingSafesSaga from './removeExistingSafes'; +import manageExistingSafesSaga from './manageExistingSafes'; export default function* actionsSagas() { yield all([ @@ -23,8 +22,7 @@ export default function* actionsSagas() { call(createDomainActionSaga), call(editDomainActionSaga), call(editColonyActionSaga), - call(addExistingSafeSaga), - call(removeExistingSafesSaga), + call(manageExistingSafesSaga), call(managePermissionsActionSaga), call(unlockTokenActionSaga), call(enterRecoveryActionSaga), diff --git a/src/modules/dashboard/sagas/actions/removeExistingSafes.ts b/src/modules/dashboard/sagas/actions/manageExistingSafes.ts similarity index 67% rename from src/modules/dashboard/sagas/actions/removeExistingSafes.ts rename to src/modules/dashboard/sagas/actions/manageExistingSafes.ts index 8b005ce4344..ce1252baa58 100644 --- a/src/modules/dashboard/sagas/actions/removeExistingSafes.ts +++ b/src/modules/dashboard/sagas/actions/manageExistingSafes.ts @@ -28,28 +28,36 @@ import { transactionAddParams, } from '../../../core/actionCreators'; -function* removeExistingSafesAction({ - payload: { colonyName, colonyAddress, safeAddresses, annotationMessage }, +function* manageExistingSafesAction({ + payload: { + colonyName, + colonyAddress, + safeAddresses, + annotationMessage, + isRemovingSafes, + }, meta: { id: metaId, history }, meta, -}: Action) { +}: Action) { let txChannel; try { const apolloClient = TEMP_getContext(ContextModule.ApolloClient); const ipfsWithFallback = TEMP_getContext(ContextModule.IPFSWithFallback); if (isEmpty(safeAddresses)) { - throw new Error('A list with safe addresses is required to remove safes'); + throw new Error('A list with safe addresses is required to manage safes'); } txChannel = yield call(getTxChannel, metaId); - const batchKey = 'removeExistingSafes'; + const batchKey = !isRemovingSafes + ? 'addExistingSafe' + : 'removeExistingSafes'; const { - removeExistingSafesAction: removeExistingSafes, - annotateRemoveExistingSafesAction: annotateRemoveExistingSafes, + manageExistingSafesAction: manageExistingSafes, + annotateManageExistingSafesAction: annotateManageExistingSafes, } = yield createTransactionChannels(metaId, [ - 'removeExistingSafesAction', - 'annotateRemoveExistingSafesAction', + 'manageExistingSafesAction', + 'annotateManageExistingSafesAction', ]); const createGroupTransaction = ({ id, index }, config) => @@ -62,7 +70,7 @@ function* removeExistingSafesAction({ }, }); - yield createGroupTransaction(removeExistingSafes, { + yield createGroupTransaction(manageExistingSafes, { context: ClientType.ColonyClient, methodName: 'editColony', identifier: colonyAddress, @@ -71,7 +79,7 @@ function* removeExistingSafesAction({ }); if (annotationMessage) { - yield createGroupTransaction(annotateRemoveExistingSafes, { + yield createGroupTransaction(annotateManageExistingSafes, { context: ClientType.ColonyClient, methodName: 'annotateTransaction', identifier: colonyAddress, @@ -81,17 +89,17 @@ function* removeExistingSafesAction({ } yield takeFrom( - removeExistingSafes.channel, + manageExistingSafes.channel, ActionTypes.TRANSACTION_CREATED, ); if (annotationMessage) { yield takeFrom( - annotateRemoveExistingSafes.channel, + annotateManageExistingSafes.channel, ActionTypes.TRANSACTION_CREATED, ); } - yield put(transactionPending(removeExistingSafes.id)); + yield put(transactionPending(manageExistingSafes.id)); /* * Fetch colony data from the subgraph @@ -120,16 +128,27 @@ function* removeExistingSafesAction({ const colonyMetadata = JSON.parse(currentMetadata); - const updatedColonySafes = colonyMetadata.colonySafes.filter( - (safe: ColonySafe) => - !safeAddresses.some( - (safeAddress) => safeAddress === safe.contractAddress, - ), - ); - const updatedColonyMetadata = { - ...colonyMetadata, - colonySafes: updatedColonySafes, - }; + let updatedColonyMetadata: any = {}; + + if (!isRemovingSafes) { + updatedColonyMetadata = { + ...colonyMetadata, + colonySafes: colonyMetadata.colonySafes + ? [...colonyMetadata.colonySafes, ...safeAddresses] + : safeAddresses, + }; + } else { + const updatedColonySafes = colonyMetadata.colonySafes.filter( + (safe: ColonySafe) => + !safeAddresses.some( + (safeAddress) => safeAddress === safe.contractAddress, + ), + ); + updatedColonyMetadata = { + ...colonyMetadata, + colonySafes: updatedColonySafes, + }; + } /* * Upload updated metadata object to IPFS @@ -141,27 +160,27 @@ function* removeExistingSafesAction({ ); yield put( - transactionAddParams(removeExistingSafes.id, [ + transactionAddParams(manageExistingSafes.id, [ (updatedColonyMetadataIpfsHash as unknown) as string, ]), ); - yield put(transactionReady(removeExistingSafes.id)); + yield put(transactionReady(manageExistingSafes.id)); const { payload: { hash: txHash }, } = yield takeFrom( - removeExistingSafes.channel, + manageExistingSafes.channel, ActionTypes.TRANSACTION_HASH_RECEIVED, ); yield takeFrom( - removeExistingSafes.channel, + manageExistingSafes.channel, ActionTypes.TRANSACTION_SUCCEEDED, ); if (annotationMessage) { - yield put(transactionPending(annotateRemoveExistingSafes.id)); + yield put(transactionPending(annotateManageExistingSafes.id)); /* * Upload annotationMessage to IPFS @@ -172,16 +191,16 @@ function* removeExistingSafesAction({ ); yield put( - transactionAddParams(annotateRemoveExistingSafes.id, [ + transactionAddParams(annotateManageExistingSafes.id, [ txHash, annotationMessageIpfsHash, ]), ); - yield put(transactionReady(annotateRemoveExistingSafes.id)); + yield put(transactionReady(annotateManageExistingSafes.id)); yield takeFrom( - annotateRemoveExistingSafes.channel, + annotateManageExistingSafes.channel, ActionTypes.TRANSACTION_SUCCEEDED, ); } @@ -198,7 +217,7 @@ function* removeExistingSafesAction({ ); yield put({ - type: ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS, + type: ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS, meta, }); @@ -207,7 +226,7 @@ function* removeExistingSafesAction({ } } catch (error) { return yield putError( - ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR, + ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR, error, meta, ); @@ -219,7 +238,7 @@ function* removeExistingSafesAction({ export default function* addExistingSafeSaga() { yield takeEvery( - ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES, - removeExistingSafesAction, + ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES, + manageExistingSafesAction, ); } diff --git a/src/redux/actionTypes.ts b/src/redux/actionTypes.ts index 18c64620103..ed8ccaa11da 100644 --- a/src/redux/actionTypes.ts +++ b/src/redux/actionTypes.ts @@ -36,18 +36,15 @@ export enum ActionTypes { /* * Actions */ - COLONY_ACTION_ADD_EXISTING_SAFE = 'COLONY_ACTION_ADD_EXISTING_SAFE', - COLONY_ACTION_ADD_EXISTING_SAFE_ERROR = 'COLONY_ACTION_ADD_EXISTING_SAFE_ERROR', - COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS = 'COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS', COLONY_ACTION_DOMAIN_CREATE = 'COLONY_ACTION_DOMAIN_CREATE', COLONY_ACTION_DOMAIN_CREATE_ERROR = 'COLONY_ACTION_DOMAIN_CREATE_ERROR', COLONY_ACTION_DOMAIN_CREATE_SUCCESS = 'COLONY_ACTION_DOMAIN_CREATE_SUCCESS', COLONY_ACTION_DOMAIN_EDIT = 'COLONY_ACTION_DOMAIN_EDIT', COLONY_ACTION_DOMAIN_EDIT_ERROR = 'COLONY_ACTION_DOMAIN_EDIT_ERROR', COLONY_ACTION_DOMAIN_EDIT_SUCCESS = 'COLONY_ACTION_DOMAIN_EDIT_SUCCESS', - COLONY_ACTION_REMOVE_EXISTING_SAFES = 'COLONY_ACTION_REMOVE_EXISTING_SAFES', - COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR = 'COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR', - COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS = 'COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS', + COLONY_ACTION_MANAGE_EXISTING_SAFES = 'COLONY_ACTION_MANAGE_EXISTING_SAFES', + COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR = 'COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR', + COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS = 'COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS', /* * @NOTE These are generic actions use for placeholders * They are not, and should not be wired to any dispatch action diff --git a/src/redux/types/actions/colonyActions.ts b/src/redux/types/actions/colonyActions.ts index 82f5d03b7d6..b67e2a2f0ef 100644 --- a/src/redux/types/actions/colonyActions.ts +++ b/src/redux/types/actions/colonyActions.ts @@ -257,37 +257,21 @@ export type ColonyActionsActionTypes = MetaWithHistory > | UniqueActionType< - ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE, - { - colonyName: string; - colonyAddress: Address; - chainId: number; - safeName: string; - contractAddress: string; - annotationMessage?: string; - }, - MetaWithHistory - > - | ErrorActionType - | ActionTypeWithMeta< - ActionTypes.COLONY_ACTION_ADD_EXISTING_SAFE_SUCCESS, - MetaWithHistory - > - | UniqueActionType< - ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES, + ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES, { colonyName: string; colonyAddress: Address; safeAddresses: Address[]; annotationMessage?: string; + isRemovingSafes?: boolean; }, MetaWithHistory > | ErrorActionType< - ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_ERROR, + ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_ERROR, object > | ActionTypeWithMeta< - ActionTypes.COLONY_ACTION_REMOVE_EXISTING_SAFES_SUCCESS, + ActionTypes.COLONY_ACTION_MANAGE_EXISTING_SAFES_SUCCESS, MetaWithHistory >; From c749658523bcf02b43c7e61c250a74178d96d1b0 Mon Sep 17 00:00:00 2001 From: ArmandoGraterol Date: Thu, 4 Aug 2022 17:48:49 -0300 Subject: [PATCH 7/7] Added message descriptor to safe name placeholder in SafeListItem --- .../Dialogs/RemoveSafeDialog/SafeListItem.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx index 9f797ae2d57..0258af64900 100644 --- a/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx +++ b/src/modules/dashboard/components/Dialogs/RemoveSafeDialog/SafeListItem.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { defineMessages } from 'react-intl'; +import { defineMessages, useIntl } from 'react-intl'; import { GNOSIS_SAFE_NETWORKS } from '~constants'; import Avatar from '~core/Avatar'; @@ -15,6 +15,10 @@ const MSG = defineMessages({ id: 'dashboard.Dialogs.RemoveSafeDialog.SafeListItem.copyMessage', defaultMessage: 'Click to copy Gnosis Safe address', }, + safeNamePlaceholder: { + id: 'dashboard.Dialogs.RemoveSafeDialog.SafeListItem.safeNamePlaceholder', + defaultMessage: 'Unknown', + }, }); interface Props { @@ -23,6 +27,7 @@ interface Props { } const SafeListItem = ({ safe, isChecked }: Props) => { + const { formatMessage } = useIntl(); const safeNetwork = GNOSIS_SAFE_NETWORKS.find( (network) => network.chainId === Number(safe.chainId), ); @@ -46,7 +51,9 @@ const SafeListItem = ({ safe, isChecked }: Props) => { /> - {`${safe.safeName} (${safeNetwork?.name || 'Unknown'})`} + {`${safe.safeName} (${ + safeNetwork?.name || formatMessage(MSG.safeNamePlaceholder) + })`}