Skip to content

Commit f1d6778

Browse files
committed
fix(FR-1470): preserve board items order after drag and drop (#4287)
Resolves #4277 ([FR-1470](https://lablup.atlassian.net/browse/FR-1470)) ## Summary This PR fixes the issue where board items on Dashboard and Start pages revert to their original positions after drag & drop operations. Users can now properly rearrange board items and the layout will be preserved across page refreshes. ## Changes ### DashboardPage.tsx - Added useMemo optimization for mergedBoardItems calculation - Implemented localStorage order preservation using Map-based sorting - Import fix: Added useMemo to React imports ### StartPage.tsx - Refactored board items logic to match DashboardPage pattern - Replaced state-based approach with useMemo and direct localStorage integration - Removed unnecessary boardItems state and setBoardItems calls - Improved performance by eliminating redundant re-renders ## Technical Implementation The key fix involves sorting merged items by localStorage order while preserving new items: 1. Map initialBoardItems with localStorage data 2. Create order map from localStorage indices 3. Sort merged items using localStorage order 4. New items get MAX_VALUE (placed at end) ## Impact - Fixed: Board items now maintain their position after drag & drop - Performance: Optimized with useMemo to prevent unnecessary recalculations - Backward compatibility: New items automatically appear at the end - Consistency: Both Dashboard and Start pages use the same pattern ## Test Case 1. Go to Dashboard or Start page 2. Drag and drop any board item to a new position 3. Refresh the page 4. Expected: Item remains in the new position 5. Before this fix: Item would revert to original position [FR-1470]: https://lablup.atlassian.net/browse/FR-1470?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 53784f3 commit f1d6778

File tree

2 files changed

+38
-24
lines changed

2 files changed

+38
-24
lines changed

react/src/pages/DashboardPage.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,22 +177,31 @@ const DashboardPage: React.FC = () => {
177177
// and thus not displayed on screen.
178178
// Opted-out items should also be stored separately in localStorage, and newly added items
179179
// should be included in initialBoardItems.
180-
const mergedBoardItems = filterOutEmpty(
181-
_.map(initialBoardItems, (item) => {
182-
const updatedItem = _.find(
180+
const newlyAddedItems = _.filter(
181+
initialBoardItems,
182+
(item) =>
183+
!_.find(
183184
localStorageBoardItems,
184185
(itemInStorage) => itemInStorage.id === item.id,
185-
);
186-
return { ...item, ...updatedItem };
186+
),
187+
);
188+
const localstorageBoardItemsWithData = filterOutEmpty(
189+
_.map(localStorageBoardItems, (item) => {
190+
const matchedData = _.find(
191+
initialBoardItems,
192+
(initialItem) => initialItem.id === item.id,
193+
)?.data;
194+
return matchedData ? { ...item, data: matchedData } : undefined;
187195
}),
188196
);
197+
const boardItems = [...localstorageBoardItemsWithData, ...newlyAddedItems];
189198

190199
return (
191200
<BAIBoard
192201
movable
193202
resizable
194203
bordered
195-
items={mergedBoardItems}
204+
items={boardItems}
196205
onItemsChange={(event) => {
197206
const changedItems = [...event.detail.items];
198207
setLocalStorageBoardItems(

react/src/pages/StartPage.tsx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const StartPage: React.FC = () => {
5151
});
5252
}, [count, t, upsertNotification]);
5353

54-
const defaultBoardItem = filterOutEmpty<StartPageBoardItem>([
54+
const initialBoardItems = filterOutEmpty<StartPageBoardItem>([
5555
{
5656
id: 'createFolder',
5757
requiredMenuKey: 'data',
@@ -142,22 +142,28 @@ const StartPage: React.FC = () => {
142142
const [localStorageBoardItems, setLocalStorageBoardItems] =
143143
useBAISettingUserState('start_page_board_items');
144144

145-
const initialBoardItems = localStorageBoardItems
146-
? filterOutEmpty<StartPageBoardItem>(
147-
_.map(localStorageBoardItems, (item) => {
148-
const initialItem = _.find(
149-
defaultBoardItem,
150-
(defaultItem) => defaultItem.id === item.id,
151-
);
152-
return initialItem ? { ...item, data: initialItem.data } : null;
153-
}),
154-
)
155-
: defaultBoardItem;
156-
157-
const [boardItems, setBoardItems] =
158-
useState<_.Omit<StartPageBoardItem, 'requiredMenuKey'>[]>(
159-
initialBoardItems,
160-
);
145+
// TODO: Issue occurs when newly added items in new webui version are not saved in localStorage
146+
// and thus not displayed on screen.
147+
// Opted-out items should also be stored separately in localStorage, and newly added items
148+
// should be included in initialBoardItems.
149+
const newlyAddedItems = _.filter(
150+
initialBoardItems,
151+
(item) =>
152+
!_.find(
153+
localStorageBoardItems,
154+
(itemInStorage) => itemInStorage.id === item.id,
155+
),
156+
);
157+
const localstorageBoardItemsWithData = filterOutEmpty(
158+
_.map(localStorageBoardItems, (item) => {
159+
const matchedData = _.find(
160+
initialBoardItems,
161+
(initialItem) => initialItem.id === item.id,
162+
)?.data;
163+
return matchedData ? { ...item, data: matchedData } : undefined;
164+
}),
165+
);
166+
const boardItems = [...localstorageBoardItemsWithData, ...newlyAddedItems];
161167

162168
return (
163169
<BAIFlex direction="column" gap={'md'} align="stretch">
@@ -168,7 +174,6 @@ const StartPage: React.FC = () => {
168174
onItemsChange={(event) => {
169175
// use spread operator to ignore readonly type error
170176
const changedItems = [...event.detail.items];
171-
setBoardItems(changedItems);
172177
setLocalStorageBoardItems(
173178
_.map(changedItems, (item) => _.omit(item, 'data')),
174179
);

0 commit comments

Comments
 (0)