Skip to content

Commit e7196e5

Browse files
committed
fix: editing
1 parent 8ff7435 commit e7196e5

File tree

9 files changed

+180
-55
lines changed

9 files changed

+180
-55
lines changed

src/components/v5/common/CompletedAction/partials/EditModeModal/EditModeModal.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,18 @@ const MSG = defineMessages({
6868
interface EditModeModalProps extends ModalProps {
6969
expenditure: Expenditure;
7070
editValues: ExpenditurePayoutFieldValue[] | undefined;
71+
errorMessage?: string;
7172
}
7273

73-
interface EditModeModalContentProps {
74+
interface EditModeModalContentProps
75+
extends Pick<EditModeModalProps, 'errorMessage'> {
7476
onClose: () => void;
7577
}
7678

77-
const EditModeModalContent: FC<EditModeModalContentProps> = ({ onClose }) => {
79+
const EditModeModalContent: FC<EditModeModalContentProps> = ({
80+
onClose,
81+
errorMessage,
82+
}) => {
7883
const [showMore, { toggle: toggleShowMore }] = useToggle();
7984
const { colony } = useColonyContext();
8085
const { user } = useAppContext();
@@ -147,6 +152,11 @@ const EditModeModalContent: FC<EditModeModalContentProps> = ({ onClose }) => {
147152
})}
148153
</div>
149154
)}
155+
{errorMessage && (
156+
<div className="mt-4 rounded-[.25rem] border border-negative-300 bg-negative-100 p-[1.125rem] text-sm font-medium text-negative-400">
157+
{errorMessage}
158+
</div>
159+
)}
150160
</div>
151161
<div className="mt-auto flex flex-col-reverse items-center justify-between gap-3 sm:flex-row">
152162
<Button mode="primaryOutline" isFullSize onClick={onClose}>
@@ -165,7 +175,12 @@ const EditModeModalContent: FC<EditModeModalContentProps> = ({ onClose }) => {
165175
}
166176
/>
167177
) : (
168-
<Button mode="primarySolid" isFullSize type="submit">
178+
<Button
179+
mode="primarySolid"
180+
isFullSize
181+
type="submit"
182+
disabled={!!errorMessage}
183+
>
169184
{formatText(MSG.confirmMessage)}
170185
</Button>
171186
)}
@@ -180,6 +195,7 @@ const EditModeModal: FC<EditModeModalProps> = ({
180195
onClose,
181196
expenditure,
182197
editValues,
198+
errorMessage,
183199
...rest
184200
}) => {
185201
const { colony } = useColonyContext();
@@ -249,7 +265,7 @@ const EditModeModal: FC<EditModeModalProps> = ({
249265
validationSchema={validationSchema}
250266
defaultValues={{ decisionMethod: {} }}
251267
>
252-
<EditModeModalContent onClose={onClose} />
268+
<EditModeModalContent onClose={onClose} errorMessage={errorMessage} />
253269
</Form>
254270
</Modal>
255271
);

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/EditStep/EditStep.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import EditRequests from './partials/EditRequests/EditRequests.tsx';
1111

1212
interface EditStepProps {
1313
actions: ExpenditureAction[];
14+
isEditMode?: boolean;
1415
}
1516

16-
const EditStep: FC<EditStepProps> = ({ actions }) => {
17+
const EditStep: FC<EditStepProps> = ({ actions, isEditMode }) => {
1718
const { selectedEditingAction } = usePaymentBuilderContext();
1819

1920
const { motionData: selectedEditingMotion } = selectedEditingAction ?? {};
@@ -31,7 +32,12 @@ const EditStep: FC<EditStepProps> = ({ actions }) => {
3132

3233
return (
3334
<div className="flex flex-col gap-2">
34-
{actions && <EditRequests editingActions={sortedEditingActions} />}
35+
{actions && (
36+
<EditRequests
37+
editingActions={sortedEditingActions}
38+
isEditMode={isEditMode}
39+
/>
40+
)}
3541
{selectedEditingMotion && (
3642
<MotionBox transactionId={selectedEditingMotion.transactionHash} />
3743
)}

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/EditStep/partials/EditRequests/EditRequestItem.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ import useCountChanges from './hooks.ts';
1212

1313
interface EditingRequestItemProps {
1414
action: ExpenditureAction;
15+
disabled?: boolean;
1516
}
1617

17-
const EditRequestItem: FC<EditingRequestItemProps> = ({ action }) => {
18+
const EditRequestItem: FC<EditingRequestItemProps> = ({ action, disabled }) => {
1819
const { transactionHash, expenditureSlotChanges } = action;
1920
const { motionState, loadingAction } = useGetColonyAction(transactionHash);
2021
const changesCount = useCountChanges(
@@ -37,12 +38,13 @@ const EditRequestItem: FC<EditingRequestItemProps> = ({ action }) => {
3738
'group flex w-full items-center justify-between outline-none transition-all',
3839
{
3940
'text-blue-400': isSelected,
40-
'text-gray-600': !isSelected,
41+
'text-gray-600': !isSelected || disabled,
4142
},
4243
)}
4344
onClick={() => {
4445
setSelectedEditingAction(action);
4546
}}
47+
disabled={disabled}
4648
>
4749
<span
4850
className={clsx('text-sm', {

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/EditStep/partials/EditRequests/EditRequests.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ import EditRequestItem from './EditRequestItem.tsx';
88

99
interface EditRequestsProps {
1010
editingActions: ExpenditureAction[];
11+
isEditMode?: boolean;
1112
}
1213

13-
const EditRequests: FC<EditRequestsProps> = ({ editingActions }) => {
14+
const EditRequests: FC<EditRequestsProps> = ({
15+
editingActions,
16+
isEditMode,
17+
}) => {
1418
return (
1519
<MenuContainer
1620
className="w-full overflow-hidden p-[1.125rem]"
@@ -24,7 +28,7 @@ const EditRequests: FC<EditRequestsProps> = ({ editingActions }) => {
2428
<ul className="max-h-[6.25rem] overflow-y-auto overflow-x-hidden">
2529
{editingActions.map((action) => (
2630
<li className="mb-2 w-full last:mb-0" key={action.transactionHash}>
27-
<EditRequestItem action={action} />
31+
<EditRequestItem action={action} disabled={isEditMode} />
2832
</li>
2933
))}
3034
</ul>

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/PaymentBuilderTable/PaymentBuilderTable.tsx

Lines changed: 109 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import {
2828
type PaymentBuilderTableModel,
2929
type PaymentBuilderTableProps,
3030
} from './types.ts';
31-
import { getChangedSlots } from './utils.ts';
3231

3332
const displayName = 'v5.common.ActionsContent.partials.PaymentBuilderTable';
3433

@@ -225,10 +224,14 @@ const useGetPaymentBuilderColumns = ({
225224
);
226225
};
227226

228-
const useRenderSubComponent = () => {
229-
return ({ row }: { row: Row<PaymentBuilderTableModel> }) => (
230-
<EditContent actionRow={row} />
231-
);
227+
const useRenderSubComponent = (
228+
setIsExpanded: (id: number, isExpanded: boolean) => void,
229+
) => {
230+
return ({ row }: { row: Row<PaymentBuilderTableModel> }) => {
231+
setIsExpanded(row.original.id, row.getIsExpanded());
232+
233+
return <EditContent actionRow={row} />;
234+
};
232235
};
233236

234237
const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
@@ -243,6 +246,7 @@ const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
243246
colony: { expendituresGlobalClaimDelay },
244247
} = useColonyContext();
245248
const { selectedEditingAction, currentStep } = usePaymentBuilderContext();
249+
const [allRowsChanged, setAllRowsChanged] = useState(false);
246250
const { expenditureSlotChanges } = selectedEditingAction || {};
247251
const isEditStepActive =
248252
!!selectedEditingAction && currentStep?.startsWith(ExpenditureStep.Edit);
@@ -300,62 +304,93 @@ const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
300304
return [...populatedItems, ...placeholderItems];
301305
}, [expendituresGlobalClaimDelay, items, expectedNumberOfPayouts]);
302306

303-
const dataWithChanges = useMemo(() => {
307+
const newDataWithChanges = useMemo(() => {
304308
if (!expenditureSlotChanges) {
305309
return data.sort((a, b) => a.id - b.id);
306310
}
307-
308311
const { newSlots, oldSlots } = expenditureSlotChanges;
309312

310-
const changedSlots = getChangedSlots(newSlots, oldSlots);
311-
const changedData = data
312-
.filter((item) => changedSlots.map((slot) => slot.id).includes(item.id))
313-
.map((item) => {
314-
const newSlot = newSlots.find((slot) => slot.id === item.id);
315-
const oldSlot = oldSlots.find((slot) => slot.id === item.id);
313+
const unchangedSlots: PaymentBuilderTableModel[] = [];
314+
const changedSlots: PaymentBuilderTableModel[] = [];
316315

317-
return {
318-
...item,
319-
newValues: newSlot,
320-
oldValues: oldSlot,
321-
};
322-
})
323-
.sort((a, b) => a.id - b.id);
316+
newSlots.forEach((newSlot) => {
317+
const found = oldSlots.some(
318+
(oldSlot) => JSON.stringify(oldSlot) === JSON.stringify(newSlot),
319+
);
324320

325-
const unchangedData = data
326-
.filter((item) => !changedSlots.map((slot) => slot.id).includes(item.id))
327-
.sort((a, b) => a.id - b.id);
321+
const newItemSlot = newSlots.find((slot) => slot.id === newSlot.id);
322+
const oldItemSlot = oldSlots.find((slot) => slot.id === newSlot.id);
323+
324+
if (found) {
325+
unchangedSlots.push({
326+
amount: newSlot.payouts?.[0].amount ?? '0',
327+
claimDelay: newSlot?.claimDelay ?? '0',
328+
id: newSlot.id,
329+
isClaimed: newSlot.payouts?.[0].isClaimed ?? false,
330+
isLoading: false,
331+
recipient: newSlot?.recipientAddress ?? '',
332+
tokenAddress: newSlot.payouts?.[0].tokenAddress ?? '',
333+
});
334+
} else {
335+
changedSlots.push({
336+
amount: newSlot.payouts?.[0].amount ?? '0',
337+
claimDelay: newSlot.claimDelay ?? '',
338+
id: newSlot.id,
339+
isClaimed: newSlot.payouts?.[0].isClaimed ?? false,
340+
isLoading: false,
341+
newValues: newItemSlot,
342+
oldValues: oldItemSlot,
343+
recipient: newSlot.recipientAddress ?? '',
344+
tokenAddress: newSlot.payouts?.[0].tokenAddress ?? '',
345+
});
346+
}
347+
});
328348

329-
return [...changedData, ...unchangedData];
330-
}, [data, expenditureSlotChanges]);
349+
return [
350+
...changedSlots,
351+
...unchangedSlots.filter((item) => item.amount !== '0'),
352+
];
353+
}, [expenditureSlotChanges, data]);
331354

332-
const filteredData = dataWithChanges.filter((item) =>
355+
const filteredData = newDataWithChanges.filter((item) =>
333356
BigNumber.from(item.amount).gt(0),
334357
);
335358

336-
const dataToShow = isEditStepActive ? dataWithChanges : filteredData;
359+
const dataToShow = isEditStepActive ? newDataWithChanges : filteredData;
337360

338361
const columns = useGetPaymentBuilderColumns({
339-
data: dataWithChanges,
362+
data: newDataWithChanges,
340363
status,
341364
slots: items,
342365
finalizedTimestamp,
343366
expectedNumberOfPayouts,
344367
});
345368

346-
const renderSubComponent = useRenderSubComponent();
369+
const [expandedRowsIds, setExpandedRowsIds] = useState<Array<number>>([]);
370+
371+
const renderSubComponent = useRenderSubComponent((id, isExpanded) => {
372+
if (isExpanded && !expandedRowsIds.includes(id)) {
373+
setExpandedRowsIds([...expandedRowsIds, id]);
374+
}
375+
if (!isExpanded && expandedRowsIds.includes(id)) {
376+
setExpandedRowsIds(expandedRowsIds.filter((item) => item !== id));
377+
}
378+
});
347379
const tableRef = React.useRef<HTMLDivElement | null>(null);
348380

349381
useEffect(() => {
350382
const tableRefCurrent = tableRef.current;
351383

352384
if (isEditStepActive && tableRefCurrent) {
353385
const tableRows = tableRefCurrent.querySelectorAll('tbody > tr');
354-
const changedItemsCount = dataWithChanges.filter(
386+
const tableBodys = tableRefCurrent.querySelectorAll('tbody');
387+
388+
const changedItemsCount = newDataWithChanges.filter(
355389
(item) => item.newValues,
356390
).length;
357-
const lastChangedTableRow = tableRows[changedItemsCount - 1];
358-
const hasAllRowsChanged = changedItemsCount === dataWithChanges.length;
391+
const lastChangedTableRow =
392+
tableRows[changedItemsCount + expandedRowsIds.length - 1];
393+
const hasAllRowsChanged = changedItemsCount === newDataWithChanges.length;
359394
const rowsBeforeLastChanged = Array.from(tableRows).slice(
360395
0,
361396
changedItemsCount - 1,
@@ -367,6 +402,27 @@ const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
367402
});
368403
}
369404

405+
const editedRowsLength = changedItemsCount + expandedRowsIds.length;
406+
setAllRowsChanged(hasAllRowsChanged);
407+
408+
if (isTablet) {
409+
tableBodys.forEach((tbody, index) => {
410+
if (index < changedItemsCount) {
411+
tbody.classList.add('tablet-edited');
412+
} else {
413+
tbody.classList.remove('tablet-edited');
414+
}
415+
});
416+
} else {
417+
tableRows.forEach((row, index) => {
418+
if (index < editedRowsLength) {
419+
row.classList.add('edited');
420+
} else {
421+
row.classList.remove('edited');
422+
}
423+
});
424+
}
425+
370426
if (lastChangedTableRow) {
371427
lastChangedTableRow.classList.add('last-edited-row');
372428
if (hasAllRowsChanged) {
@@ -413,13 +469,19 @@ const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
413469
observers.forEach((observer) => observer.disconnect());
414470

415471
tableRows.forEach((row) => {
416-
row.classList.remove('previous-row', 'last-edited-row', 'last-row');
472+
row.classList.remove(
473+
'previous-row',
474+
'last-edited-row',
475+
'last-row',
476+
'edited',
477+
'tablet-edited',
478+
);
417479
});
418480
};
419481
}
420482

421483
return () => {};
422-
}, [isEditStepActive, dataWithChanges]);
484+
}, [isEditStepActive, newDataWithChanges, expandedRowsIds, isTablet]);
423485

424486
return (
425487
<div className="mt-7" ref={tableRef}>
@@ -440,13 +502,21 @@ const PaymentBuilderTable: FC<PaymentBuilderTableProps> = ({
440502
)}
441503
<Table<PaymentBuilderTableModel>
442504
className={clsx(
443-
'[&_tbody]:relative [&_tfoot>tr>td]:border-gray-200 [&_tfoot>tr>td]:py-2 md:[&_tfoot>tr>td]:border-t',
444505
{
445-
'[&_tfoot>tr>td:empty]:hidden [&_th]:w-[6.25rem]': isTablet,
446-
'[&_table]:table-auto lg:[&_table]:table-fixed [&_tbody_td]:h-[54px] [&_td:first-child]:pl-4 [&_td]:pr-4 [&_tfoot_td:first-child]:pl-4 [&_tfoot_td:not(:first-child)]:pl-0 [&_th:first-child]:pl-4 [&_th:not(:first-child)]:pl-0 [&_th]:pr-4':
506+
'[&_tbody>tr>td]:px-[18px] [&_tbody>tr>td]:py-[10px] [&_tr.edited:last-child>td:last-child]:before:h-[calc(100%-5px)] [&_tr.edited:not(:last-child)>td:first-child]:relative [&_tr.edited:not(:last-child)>td:first-child]:after:absolute [&_tr.edited:not(:last-child)>td:first-child]:after:left-0 [&_tr.edited:not(:last-child)>td:first-child]:after:top-0 [&_tr.edited:not(:last-child)>td:first-child]:after:h-[calc(100%+1px)] [&_tr.edited:not(:last-child)>td:first-child]:after:w-[1px] [&_tr.edited:not(:last-child)>td:first-child]:after:translate-x-[-1px] [&_tr.edited:not(:last-child)>td:first-child]:after:rounded-none [&_tr.edited:not(:last-child)>td:first-child]:after:bg-blue-400 [&_tr.edited>td:last-child]:relative [&_tr.edited>td:last-child]:before:absolute [&_tr.edited>td:last-child]:before:right-0 [&_tr.edited>td:last-child]:before:top-0 [&_tr.edited>td:last-child]:before:h-[calc(100%+1px)] [&_tr.edited>td:last-child]:before:w-[1px] [&_tr.edited>td:last-child]:before:translate-x-[1px] [&_tr.edited>td:last-child]:before:bg-blue-400':
447507
!isTablet,
448-
'[&_thead]:relative [&_thead]:after:absolute [&_thead]:after:-left-px [&_thead]:after:-right-px [&_thead]:after:-top-px [&_thead]:after:bottom-0 [&_thead]:after:rounded-t-lg [&_thead]:after:border [&_thead]:after:border-blue-400 [&_tr.last-edited-row.expanded-below+tr_td:first-child]:after:border-l [&_tr.last-edited-row.expanded-below+tr_td:last-child]:after:border-r [&_tr.last-edited-row.expanded-below+tr_td]:after:border-b [&_tr.last-edited-row.expanded-below_td:first-child]:after:rounded-bl-none [&_tr.last-edited-row.expanded-below_td:last-child]:after:rounded-br-none [&_tr.last-edited-row.expanded-below_td]:after:border-b-0 [&_tr.last-edited-row_td:first-child]:after:border-l [&_tr.last-edited-row_td:last-child]:after:border-r [&_tr.last-edited-row_td]:after:border-b [&_tr.last-edited-row_td]:after:border-blue-400 [&_tr.last-row.expanded-below+tr_td:first-child]:after:rounded-bl-lg [&_tr.last-row.expanded-below+tr_td:last-child]:after:rounded-br-lg [&_tr.last-row_td:first-child]:after:rounded-bl-lg [&_tr.last-row_td:last-child]:after:rounded-br-lg [&_tr.previous-row.expanded-below+tr_td:first-child]:after:border-l [&_tr.previous-row.expanded-below+tr_td:last-child]:after:border-r [&_tr.previous-row_td:first-child]:after:border-l [&_tr.previous-row_td:last-child]:after:border-r [&_tr_td>div]:relative [&_tr_td]:after:absolute [&_tr_td]:after:-inset-px [&_tr_td]:after:border-blue-400 [&_tr_td]:sm:relative [&_tr_td_*]:z-[1]':
449-
isEditStepActive,
508+
},
509+
{
510+
'[&_thead]:relative [&_thead]:after:absolute [&_thead]:after:-left-px [&_thead]:after:-right-px [&_thead]:after:-top-px [&_thead]:after:bottom-0 [&_thead]:after:rounded-t-lg [&_thead]:after:border-b [&_thead]:after:border-blue-400':
511+
!isTablet && isEditStepActive,
512+
},
513+
{
514+
'[&_tr.edited:last-child>td]:after:border-b-1 [&_tr.edited:last-child>td:first-child]:after:border-l-1 [&_tr.edited:last-child>td:first-child]:after:h-full [&_tr.edited:last-child>td:not(:first-child)]:after:border-l-0 [&_tr.edited:last-child>td]:relative [&_tr.edited:last-child>td]:after:absolute [&_tr.edited:last-child>td]:after:bottom-0 [&_tr.edited:last-child>td]:after:right-0 [&_tr.edited:last-child>td]:after:h-[17px] [&_tr.edited:last-child>td]:after:w-[calc(100%+2px)] [&_tr.edited:last-child>td]:after:translate-x-[1px] [&_tr.edited:last-child>td]:after:border [&_tr.edited:last-child>td]:after:border-r-0 [&_tr.edited:last-child>td]:after:border-t-0 [&_tr.edited:last-child>td]:after:border-blue-400 [&_tr.edited>td:first-child]:after:rounded-bl-lg [&_tr.edited>td:last-child]:after:rounded-r-lg':
515+
!isTablet && allRowsChanged,
516+
},
517+
{
518+
'[&_tr.last-edited-row>td]:border-b-1 [&_tr.last-edited-row>td]:border [&_tr.last-edited-row>td]:border-l-0 [&_tr.last-edited-row>td]:border-r-0 [&_tr.last-edited-row>td]:border-t-0 [&_tr.last-edited-row>td]:border-blue-400':
519+
!isTablet && !allRowsChanged,
450520
},
451521
)}
452522
rows={{

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/PaymentBuilderTable/partials/EditContent/EditContent.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ const EditContent: FC<EditContentProps> = ({ actionRow }) => {
121121
const isMotion = !!selectedEditingAction?.motionData;
122122

123123
useEffect(() => {
124-
if (!currentStep?.startsWith(ExpenditureStep.Edit)) {
124+
if (!currentStep?.startsWith(ExpenditureStep.Edit) || !newValues) {
125125
toggleExpanded();
126126
}
127-
}, [currentStep, toggleExpanded]);
127+
}, [currentStep, toggleExpanded, newValues]);
128128

129129
const changes: Changes = {};
130130

src/components/v5/common/CompletedAction/partials/PaymentBuilder/partials/PaymentBuilderWidget/PaymentBuilderWidget.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ const PaymentBuilderWidget: FC<PaymentBuilderWidgetProps> = ({ action }) => {
249249
heading: {
250250
label: formatText({ id: 'expenditure.editStage.label' }),
251251
},
252-
content: expenditure ? <EditStep actions={actions} /> : null,
252+
content: expenditure ? (
253+
<EditStep actions={actions} isEditMode={isEditMode} />
254+
) : null,
253255
};
254256
};
255257

0 commit comments

Comments
 (0)