Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/15886093 reputation cancel #3322

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions amplify/backend/api/colonycdapp/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -3010,6 +3010,12 @@ type ColonyMotion @model {
the details of tokens and amounts to be funded
"""
expenditureFunding: [ExpenditureFundingItem!]

"""
In case of motions cancelling a staked expenditure, boolean indicating
whether the expenditure staker will be punished by losing their stake
"""
willPunishExpenditureStaker: Boolean
}

type ExpenditureFundingItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import { useAppContext } from '~context/AppContext/AppContext.ts';
import { useColonyContext } from '~context/ColonyContext/ColonyContext.ts';
import { useColonyTriggersContext } from '~context/GlobalTriggersContext/ColonyTriggersContext.ts';
import { ColonyActionType } from '~gql';
import useAsyncFunction from '~hooks/useAsyncFunction.ts';
import usePrevious from '~hooks/usePrevious.ts';
import { ActionTypes } from '~redux/index.ts';
import { type ReclaimExpenditureStakePayload } from '~redux/sagas/expenditures/reclaimExpenditureStake.ts';
import { ActionForm } from '~shared/Fields/index.ts';
import { getMotionAssociatedActionId } from '~utils/actions.ts';
import { MotionState } from '~utils/colonyMotions.ts';
import { formatText } from '~utils/intl.ts';
import { useFinalizeSuccessCallback } from '~v5/common/ActionSidebar/partials/hooks.ts';
Expand Down Expand Up @@ -46,9 +49,7 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
const { canInteract } = useAppContext();

const [isPolling, setIsPolling] = useState(false);

const { refetchColony } = useColonyContext();

const { refetchColony, colony } = useColonyContext();
const {
isFinalizable,
transform: finalizePayload,
Expand All @@ -65,7 +66,7 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
canClaimStakes,
} = useClaimConfig({ action, motionData });

const { type: actionType } = action;
const { type: actionType, expenditure } = action;

const {
isFinalized: isMotionFinalized,
Expand All @@ -85,10 +86,31 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
isMotionFinalized ||
isMotionFailedNotFinalizable ||
(isMotionAgreement && !isClaimed);
const reclaimExpenditureStake = useAsyncFunction({
submit: ActionTypes.RECLAIM_EXPENDITURE_STAKE,
error: ActionTypes.RECLAIM_EXPENDITURE_STAKE_ERROR,
success: ActionTypes.RECLAIM_EXPENDITURE_STAKE_SUCCESS,
});

const handleSuccess = () => {
const handleSuccess = async () => {
setIsPolling(true);
onFinalizeSuccessCallback(action);

const associatedActionId = getMotionAssociatedActionId(action);

if (
actionType === ColonyActionType.CancelExpenditureMotion &&
!motionData.willPunishExpenditureStaker &&
expenditure?.isStaked
) {
const payload: ReclaimExpenditureStakePayload = {
colonyAddress: colony.colonyAddress,
nativeExpenditureId: expenditure.nativeId,
associatedActionId,
};

await reclaimExpenditureStake(payload);
}
};

/* Update colony object when motion gets finalized or is agreement. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export const useClaimConfig = ({
const buttonTextId = isClaimed ? 'button.claimed' : 'button.claim';
const remainingStakesNumber = remainingStakes.length;
const canClaimStakes = userTotalStake ? !userTotalStake.isZero() : false;
const handleClaimSuccess = () => {
const handleClaimSuccess = async () => {
setIsClaimed(true);
pollLockedTokenBalance();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ import { type RevealStepProps } from './types.ts';
const displayName =
'v5.common.ActionSidebar.partials.motions.MotionSimplePayment.steps.RevealStep';

const RevealStep: FC<RevealStepProps> = ({ action, motionState }) => {
const RevealStep: FC<RevealStepProps> = ({
action,
motionState,
isActionCancelled,
}) => {
const { transactionHash, rootHash } = action;
const { canInteract } = useAppContext();
const [isInformationAccordionOpen, { toggle: toggleInformationAccordion }] =
Expand Down Expand Up @@ -103,6 +107,19 @@ const RevealStep: FC<RevealStepProps> = ({ action, motionState }) => {
</>
}
sections={[
...(isActionCancelled
? [
{
key: '3',
content: (
<p className="text-sm">
{formatText({ id: 'motion.cancelled' })}
</p>
),
className: 'bg-negative-100 text-negative-400 !py-3',
},
]
: []),
{
key: '1',
content: (
Expand Down Expand Up @@ -164,7 +181,7 @@ const RevealStep: FC<RevealStepProps> = ({ action, motionState }) => {
: 'motion.revealStep.buttonShow',
})}
isOpen={isInformationAccordionOpen}
onToggle={toggleInformationAccordion}
onToggle={() => toggleInformationAccordion()}
className={clsx(
`
[&_.accordion-toggler]:text-sm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { type ICompletedMotionAction } from '~v5/common/ActionSidebar/partials/M
export interface RevealStepProps
extends Pick<ICompletedMotionAction, 'action'> {
motionState?: number;
isActionCancelled?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ import { type StakingStepProps } from './types.ts';
const displayName =
'v5.common.ActionSidebar.partials.motions.MotionSimplePayment.steps.StakingStep';

const StakingStep: FC<StakingStepProps> = ({ className, isActive }) => {
const StakingStep: FC<StakingStepProps> = ({
className,
isActive,
isActionCancelled,
}) => {
const { canInteract } = useAppContext();
const { action, motionData } = useMotionContext();
const [isAccordionOpen, { toggle: toggleAccordion }] = useToggle();
Expand Down Expand Up @@ -139,6 +143,19 @@ const StakingStep: FC<StakingStepProps> = ({ className, isActive }) => {
},
]
: []),
...(isActionCancelled
? [
{
key: '3',
content: (
<p className="text-sm">
{formatText({ id: 'motion.cancelled' })}
</p>
),
className: 'bg-negative-100 text-negative-400 !py-3',
},
]
: []),
{
key: '2',
content: (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface StakingStepProps {
className?: string;
isActive?: boolean;
isActionCancelled?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,11 @@ const MSG = defineMessages({
},
});

const VotingStep: FC<ICompletedMotionAction> = ({ action, motionData }) => {
const VotingStep: FC<ICompletedMotionAction> = ({
action,
motionData,
isActionCancelled,
}) => {
const {
currentReputationPercent,
currentUserVote,
Expand Down Expand Up @@ -116,6 +120,19 @@ const VotingStep: FC<ICompletedMotionAction> = ({ action, motionData }) => {
</div>
}
sections={[
...(isActionCancelled
? [
{
key: '1',
content: (
<p className="text-sm">
{formatText({ id: 'motion.cancelled' })}
</p>
),
className: 'bg-negative-100 text-negative-400 !py-3',
},
]
: []),
{
key: VotingStepSections.Vote,
content: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ const Motions: FC<ICompletedMotionAction> = ({ action, motionData }) => {
<MotionProvider action={action} motionData={motionData}>
<Stepper<Steps>
activeStepKey={activeStepKey}
setActiveStepKey={setActiveStepKey}
setActiveStepKey={(key: Steps) => setActiveStepKey(key)}
items={items}
/>
</MotionProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { type ColonyAction } from '~types/graphql.ts';

export interface RevealStepProps {
startPollingAction: (pollingInterval: number) => void;
stopPollingAction: () => void;
actionData: ColonyAction | undefined | null;
rootHash: string | undefined;
transactionId: string;
motionState?: number;
isActionCancelled?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { type ICompletedAction } from '~v5/common/CompletedAction/types.ts';

export interface ICompletedMotionAction extends ICompletedAction {
motionData: NonNullable<ICompletedAction['action']['motionData']>;
isActionCancelled?: boolean;
}

export enum CustomStep {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const MultiSigWidget: FC<MultiSigWidgetProps> = ({
<Stepper<MultiSigState>
items={items}
activeStepKey={activeStepKey}
setActiveStepKey={setActiveStepKey}
setActiveStepKey={(key: MultiSigState) => setActiveStepKey(key)}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import { type MeatBallMenuItem } from '~v5/shared/MeatBallMenu/types.ts';

import CompletedExpenditureContent from '../CompletedExpenditureContent/CompletedExpenditureContent.tsx';

import CancelModal from './partials/CancelModal/CancelModal.tsx';
import PaymentBuilderTable from './partials/PaymentBuilderTable/PaymentBuilderTable.tsx';
import { ExpenditureStep } from './partials/PaymentBuilderWidget/types.ts';
import { getExpenditureStep } from './partials/PaymentBuilderWidget/utils.ts';
Expand Down Expand Up @@ -76,18 +75,17 @@ const PaymentBuilder = ({ action }: PaymentBuilderProps) => {
const { initiatorUser, transactionHash, fromDomain, annotation } = action;
const allTokens = useGetAllTokens();

const { expenditure, loadingExpenditure, refetchExpenditure } =
useGetExpenditureData(action.expenditureId);
const { expenditure, loadingExpenditure } = useGetExpenditureData(
action.expenditureId,
);
const expenditureStep = getExpenditureStep(expenditure);
const { user: recipient } = useUserByAddress(
expenditure?.slots?.[0]?.recipientAddress || '',
);
const {
expectedExpenditureType,
setExpectedExpenditureType,
isCancelModalOpen,
toggleOnCancelModal,
toggleOffCancelModal,
} = usePaymentBuilderContext();

useEffect(() => {
Expand Down Expand Up @@ -214,12 +212,6 @@ const PaymentBuilder = ({ action }: PaymentBuilderProps) => {
isLoading={!expenditure.metadata?.stages?.length}
isPaymentStep={expenditureStep === ExpenditureStep.Payment}
/>
<CancelModal
isOpen={isCancelModalOpen}
expenditure={expenditure}
onClose={toggleOffCancelModal}
refetchExpenditure={refetchExpenditure}
/>
</>
);
}
Expand Down Expand Up @@ -268,12 +260,6 @@ const PaymentBuilder = ({ action }: PaymentBuilderProps) => {
finalizedTimestamp={finalizedAt}
expectedNumberOfPayouts={expectedNumberOfPayouts}
/>
<CancelModal
isOpen={isCancelModalOpen}
expenditure={expenditure}
onClose={toggleOffCancelModal}
refetchExpenditure={refetchExpenditure}
/>
</>
);
};
Expand Down
Loading