Skip to content

Commit

Permalink
feat: added cancel with reputation
Browse files Browse the repository at this point in the history
fix after rebase

fix: translations, duplicated steps

fix: cancel step

fixes after rebase

fix: auto claim, stepper

Feat: Add willPunishExpenditureStaker field to colony motion

feat: add penalty badge

fix: pending buttons, penalise saga

fix: types

fix: permission badge
  • Loading branch information
CzarekDryl committed Dec 20, 2024
1 parent 9ee0189 commit 0b9ce27
Show file tree
Hide file tree
Showing 41 changed files with 1,158 additions and 153 deletions.
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 @@ -342,7 +342,7 @@ const Motions: FC<MotionsProps> = ({ transactionId }) => {
>
<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
Expand Up @@ -6,8 +6,10 @@ import { defineMessages } from 'react-intl';
import { useAppContext } from '~context/AppContext/AppContext.ts';
import { useColonyContext } from '~context/ColonyContext/ColonyContext.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 { MotionState } from '~utils/colonyMotions.ts';
import { formatText } from '~utils/intl.ts';
Expand Down Expand Up @@ -46,7 +48,7 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
const { onFinalizeSuccessCallback } = useFinalizeSuccessCallback();
const { canInteract } = useAppContext();
const [isPolling, setIsPolling] = useState(false);
const { refetchColony } = useColonyContext();
const { refetchColony, colony } = useColonyContext();
const {
isFinalizable,
transform: finalizePayload,
Expand All @@ -61,6 +63,7 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
claimPayload,
canClaimStakes,
} = useClaimConfig(actionData, startPollingAction, refetchAction);
const { type, expenditure } = actionData;

const isMotionFinalized = actionData.motionData.isFinalized;
const previousIsMotionFinalized = usePrevious(isMotionFinalized);
Expand All @@ -74,11 +77,28 @@ const FinalizeStep: FC<FinalizeStepProps> = ({
!isMotionFailed &&
!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 () => {
startPollingAction(getSafePollingInterval());
setIsPolling(true);
onFinalizeSuccessCallback(actionData);

if (
type === ColonyActionType.CancelExpenditureMotion &&
expenditure?.isStaked
) {
const payload: ReclaimExpenditureStakePayload = {
colonyAddress: colony.colonyAddress,
nativeExpenditureId: expenditure.nativeId,
};

await reclaimExpenditureStake(payload);
}
};

/* Stop polling when mounted / dismounted */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,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);
startPollingAction(getSafePollingInterval());
pollLockedTokenBalance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const RevealStep: FC<RevealStepProps> = ({
stopPollingAction,
transactionId,
rootHash,
isActionCancelled,
}) => {
const { canInteract } = useAppContext();
const [isInformationAccordionOpen, { toggle: toggleInformationAccordion }] =
Expand Down Expand Up @@ -111,6 +112,19 @@ const RevealStep: FC<RevealStepProps> = ({
</>
}
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 @@ -172,7 +186,7 @@ const RevealStep: FC<RevealStepProps> = ({
: '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 @@ -7,4 +7,5 @@ export interface RevealStepProps {
rootHash: string | undefined;
transactionId: string;
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 { motionAction } = useMotionContext();
const [isAccordionOpen, { toggle: toggleAccordion }] = useToggle();
Expand Down Expand Up @@ -134,6 +138,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 @@ -45,6 +45,7 @@ const VotingStep: FC<VotingStepProps> = ({
startPollingAction,
stopPollingAction,
transactionId,
isActionCancelled,
}) => {
const {
currentReputationPercent,
Expand Down Expand Up @@ -112,6 +113,19 @@ const VotingStep: FC<VotingStepProps> = ({
</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 @@ -5,6 +5,7 @@ export interface VotingStepProps {
stopPollingAction: () => void;
actionData: MotionAction;
transactionId: string;
isActionCancelled?: boolean;
}

export interface VotingFormValues {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,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
Original file line number Diff line number Diff line change
@@ -1,77 +1,25 @@
import { isToday, isYesterday } from 'date-fns';
import React, { type FC } from 'react';
import { FormattedDate, defineMessages } from 'react-intl';

import PermissionRow from '~frame/v5/pages/VerifiedPage/partials/PermissionRow/index.ts';
import { getFormattedDateFrom } from '~utils/getFormattedDateFrom.ts';
import { formatText } from '~utils/intl.ts';
import MenuWithStatusText from '~v5/shared/MenuWithStatusText/index.ts';
import { StatusTypes } from '~v5/shared/StatusText/consts.ts';
import StatusText from '~v5/shared/StatusText/StatusText.tsx';
import UserPopover from '~v5/shared/UserPopover/UserPopover.tsx';

import { type ActionWithPermissionsInfoProps } from './types.ts';

const displayName =
'v5.common.CompletedAction.partials.ActionWithPermissionsInfoProps';

const MSG = defineMessages({
todayAt: {
id: `${displayName}.todayAt`,
defaultMessage: 'Today at',
},
yestardayAt: {
id: `${displayName}.yestardayAt`,
defaultMessage: 'Yesterday at',
},
at: {
id: `${displayName}.at`,
defaultMessage: 'at',
},
});

const formatDate = (value: string | undefined) => {
if (!value) {
return undefined;
}

const date = new Date(value);

if (isToday(date)) {
return (
<>
{formatText(MSG.todayAt)}{' '}
<FormattedDate value={date} hour="numeric" minute="numeric" />
</>
);
}
import FormatDate from '../FormatDate/FormatDate.tsx';

if (isYesterday(date)) {
return (
<>
{formatText(MSG.yestardayAt)}{' '}
<FormattedDate value={date} hour="numeric" minute="numeric" />
</>
);
}

return (
<>
{getFormattedDateFrom(value)} {formatText(MSG.at)}{' '}
<FormattedDate value={date} hour="numeric" minute="numeric" />
</>
);
};
import { type ActionWithPermissionsInfoProps } from './types.ts';

const ActionWithPermissionsInfo: FC<ActionWithPermissionsInfoProps> = ({
action,
title,
}) => {
if (!action) {
return null;
}

const { createdAt, initiatorAddress } = action ?? {};
const formattedDate = formatDate(createdAt);

return (
<MenuWithStatusText
Expand All @@ -83,9 +31,10 @@ const ActionWithPermissionsInfo: FC<ActionWithPermissionsInfoProps> = ({
iconSize={16}
iconClassName="text-gray-500"
>
{formatText({
id: 'action.executed.permissions.description',
})}
{title ||
formatText({
id: 'action.executed.permissions.description',
})}
</StatusText>
}
sections={[
Expand Down Expand Up @@ -131,7 +80,9 @@ const ActionWithPermissionsInfo: FC<ActionWithPermissionsInfoProps> = ({
id: 'action.executed.permissions.date',
})}
</span>
<span className="text-sm text-gray-900">{formattedDate}</span>
<span className="text-sm text-gray-900">
<FormatDate value={createdAt} />
</span>
</div>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import { type ExpenditureAction } from '~types/graphql.ts';

export interface ActionWithPermissionsInfoProps {
action?: ExpenditureAction | null;
title?: string;
}
Loading

0 comments on commit 0b9ce27

Please sign in to comment.