Skip to content

Commit 7b1e35c

Browse files
committed
Add menu item to duplicate tab
1 parent 22a0779 commit 7b1e35c

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

packages/compass-components/src/components/workspace-tabs/tab.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ export type WorkspaceTabCoreProps = {
193193
isSelected: boolean;
194194
isDragging: boolean;
195195
onSelect: () => void;
196+
onDuplicate: () => void;
196197
onClose: () => void;
197198
onCloseAllOthers: () => void;
198199
tabContentId: string;
@@ -209,6 +210,7 @@ function Tab({
209210
isSelected,
210211
isDragging,
211212
onSelect,
213+
onDuplicate,
212214
onClose,
213215
onCloseAllOthers,
214216
tabContentId,
@@ -238,8 +240,11 @@ function Tab({
238240
}, [tabTheme, darkMode]);
239241

240242
const contextMenuRef = useContextMenuItems(
241-
() => [{ label: 'Close all other tabs', onAction: onCloseAllOthers }],
242-
[onCloseAllOthers]
243+
() => [
244+
{ label: 'Close all other tabs', onAction: onCloseAllOthers },
245+
{ label: 'Duplicate', onAction: onDuplicate },
246+
],
247+
[onCloseAllOthers, onDuplicate]
243248
);
244249

245250
const mergedRef = useMergeRefs([setNodeRef, contextMenuRef]);

packages/compass-components/src/components/workspace-tabs/workspace-tabs.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ type SortableItemProps = {
150150
selectedTabIndex: number;
151151
activeId: UniqueIdentifier | null;
152152
onSelect: (tabIndex: number) => void;
153+
onDuplicate: (tabIndex: number) => void;
153154
onClose: (tabIndex: number) => void;
154155
onCloseAllOthers: (tabIndex: number) => void;
155156
};
@@ -159,6 +160,7 @@ type SortableListProps = {
159160
selectedTabIndex: number;
160161
onMove: (oldTabIndex: number, newTabIndex: number) => void;
161162
onSelect: (tabIndex: number) => void;
163+
onDuplicate: (tabIndex: number) => void;
162164
onClose: (tabIndex: number) => void;
163165
onCloseAllOthers: (tabIndex: number) => void;
164166
};
@@ -169,6 +171,7 @@ type WorkspaceTabsProps = {
169171
onSelectTab: (tabIndex: number) => void;
170172
onSelectNextTab: () => void;
171173
onSelectPrevTab: () => void;
174+
onDuplicateTab: (tabIndex: number) => void;
172175
onCloseTab: (tabIndex: number) => void;
173176
onCloseAllOtherTabs: (tabIndex: number) => void;
174177
onMoveTab: (oldTabIndex: number, newTabIndex: number) => void;
@@ -212,6 +215,7 @@ const SortableList = ({
212215
onMove,
213216
onSelect,
214217
selectedTabIndex,
218+
onDuplicate,
215219
onClose,
216220
onCloseAllOthers,
217221
}: SortableListProps) => {
@@ -270,6 +274,7 @@ const SortableList = ({
270274
tab={tab}
271275
activeId={activeId}
272276
onSelect={onSelect}
277+
onDuplicate={onDuplicate}
273278
onClose={onClose}
274279
onCloseAllOthers={onCloseAllOthers}
275280
selectedTabIndex={selectedTabIndex}
@@ -287,13 +292,18 @@ const SortableItem = ({
287292
selectedTabIndex,
288293
activeId,
289294
onSelect,
295+
onDuplicate,
290296
onClose,
291297
onCloseAllOthers,
292298
}: SortableItemProps) => {
293299
const onTabSelected = useCallback(() => {
294300
onSelect(index);
295301
}, [onSelect, index]);
296302

303+
const onTabDuplicated = useCallback(() => {
304+
onDuplicate(index);
305+
}, [onDuplicate, index]);
306+
297307
const onTabClosed = useCallback(() => {
298308
onClose(index);
299309
}, [onClose, index]);
@@ -314,6 +324,7 @@ const SortableItem = ({
314324
isDragging,
315325
tabContentId: tabId,
316326
onSelect: onTabSelected,
327+
onDuplicate: onTabDuplicated,
317328
onClose: onTabClosed,
318329
onCloseAllOthers: onAllOthersTabsClosed,
319330
});
@@ -322,6 +333,7 @@ const SortableItem = ({
322333
function WorkspaceTabs({
323334
['aria-label']: ariaLabel,
324335
onCreateNewTab,
336+
onDuplicateTab,
325337
onCloseTab,
326338
onCloseAllOtherTabs,
327339
onMoveTab,
@@ -420,6 +432,7 @@ function WorkspaceTabs({
420432
tabs={tabs}
421433
onMove={onMoveTab}
422434
onSelect={onSelectTab}
435+
onDuplicate={onDuplicateTab}
423436
onClose={onCloseTab}
424437
onCloseAllOthers={onCloseAllOtherTabs}
425438
selectedTabIndex={selectedTabIndex}

packages/compass-workspaces/src/components/workspaces.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
moveTab,
2222
openFallbackWorkspace,
2323
openTabFromCurrent,
24+
duplicateTab,
2425
selectNextTab,
2526
selectPrevTab,
2627
selectTab,
@@ -76,6 +77,7 @@ type CompassWorkspacesProps = {
7677
onSelectPrevTab(): void;
7778
onMoveTab(from: number, to: number): void;
7879
onCreateTab(defaultTab?: OpenWorkspaceOptions | null): void;
80+
onDuplicateTab(at: number): void;
7981
onCloseTab(at: number): void;
8082
onCloseAllOtherTabs(at: number): void;
8183
onNamespaceNotFound(
@@ -95,6 +97,7 @@ const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
9597
onSelectPrevTab,
9698
onMoveTab,
9799
onCreateTab,
100+
onDuplicateTab,
98101
onCloseTab,
99102
onCloseAllOtherTabs,
100103
onNamespaceNotFound,
@@ -205,6 +208,7 @@ const CompassWorkspaces: React.FunctionComponent<CompassWorkspacesProps> = ({
205208
onSelectPrevTab={onSelectPrevTab}
206209
onMoveTab={onMoveTab}
207210
onCreateNewTab={onCreateNewTab}
211+
onDuplicateTab={onDuplicateTab}
208212
onCloseTab={onCloseTab}
209213
onCloseAllOtherTabs={onCloseAllOtherTabs}
210214
tabs={workspaceTabs}
@@ -238,6 +242,7 @@ export default connect(
238242
onSelectPrevTab: selectPrevTab,
239243
onMoveTab: moveTab,
240244
onCreateTab: openTabFromCurrent,
245+
onDuplicateTab: duplicateTab,
241246
onCloseTab: closeTab,
242247
onCloseAllOtherTabs: closeAllOtherTabs,
243248
onNamespaceNotFound: openFallbackWorkspace,

packages/compass-workspaces/src/stores/workspaces.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export enum WorkspacesActions {
5555
SelectNextTab = 'compass-workspaces/SelectNextTab',
5656
MoveTab = 'compass-workspaces/MoveTab',
5757
OpenTabFromCurrentActive = 'compass-workspaces/OpenTabFromCurrentActive',
58+
DuplicateTab = 'compass-workspaces/DuplicateTab',
5859
CloseTab = 'compass-workspaces/CloseTab',
5960
CloseAllOtherTabs = 'compass-workspaces/CloseAllOtherTabs',
6061
CollectionRenamed = 'compass-workspaces/CollectionRenamed',
@@ -401,6 +402,20 @@ const reducer: Reducer<WorkspacesState, Action> = (
401402
};
402403
}
403404

405+
if (isAction<DuplicateTabAction>(action, WorkspacesActions.DuplicateTab)) {
406+
const tabsBefore = state.tabs.slice(0, action.atIndex);
407+
const targetTab = state.tabs[action.atIndex];
408+
const tabsAfter = state.tabs.slice(action.atIndex + 1);
409+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
410+
const { id: _id, ...tabProps } = targetTab;
411+
const newTab = getInitialTabState(tabProps);
412+
return {
413+
...state,
414+
tabs: [...tabsBefore, targetTab, newTab, ...tabsAfter],
415+
activeTabId: newTab.id,
416+
};
417+
}
418+
404419
if (isAction<SelectTabAction>(action, WorkspacesActions.SelectTab)) {
405420
if (state.tabs[action.atIndex]?.id === state.activeTabId) {
406421
return state;
@@ -858,6 +873,18 @@ export const openTabFromCurrent = (
858873
};
859874
};
860875

876+
type DuplicateTabAction = {
877+
type: WorkspacesActions.DuplicateTab;
878+
atIndex: number;
879+
};
880+
881+
export const duplicateTab = (atIndex: number): DuplicateTabAction => {
882+
return {
883+
type: WorkspacesActions.DuplicateTab,
884+
atIndex,
885+
};
886+
};
887+
861888
async function confirmClosingTabs() {
862889
return await showConfirmation({
863890
title: 'Are you sure you want to close the tab?',

0 commit comments

Comments
 (0)