Skip to content

Commit 736fa5f

Browse files
Merge pull request #197 from JaneliaSciComp/open-convert-tab-when-navigating-from-jobs-page
feat: open properties panel and convert tab when navigating from jobs page
2 parents 1374a5a + 3c4e62c commit 736fa5f

File tree

6 files changed

+96
-18
lines changed

6 files changed

+96
-18
lines changed

src/components/ui/PropertiesDrawer/PropertiesDrawer.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import toast from 'react-hot-toast';
1111
import { HiOutlineDocument, HiOutlineDuplicate, HiX } from 'react-icons/hi';
1212
import { HiOutlineFolder } from 'react-icons/hi2';
13+
import { useLocation } from 'react-router';
1314

1415
import PermissionsTable from '@/components/ui/PropertiesDrawer/PermissionsTable';
1516
import OverviewTable from '@/components/ui/PropertiesDrawer/OverviewTable';
@@ -80,8 +81,10 @@ export default function PropertiesDrawer({
8081
setShowPermissionsDialog,
8182
setShowConvertFileDialog
8283
}: PropertiesDrawerProps): JSX.Element {
84+
const location = useLocation();
8385
const [showDataLinkDialog, setShowDataLinkDialog] =
8486
React.useState<boolean>(false);
87+
const [activeTab, setActiveTab] = React.useState<string>('overview');
8588

8689
const { fileBrowserState } = useFileBrowserContext();
8790
const { pathPreference, areDataLinksAutomatic } = usePreferencesContext();
@@ -95,6 +98,13 @@ export default function PropertiesDrawer({
9598
handleDeleteDataLink
9699
} = useDataToolLinks(setShowDataLinkDialog);
97100

101+
// Set active tab to 'convert' when navigating from jobs page
102+
React.useEffect(() => {
103+
if (location.state?.openConvertTab) {
104+
setActiveTab('convert');
105+
}
106+
}, [location.state]);
107+
98108
const fullPath = getPreferredPathForDisplay(
99109
pathPreference,
100110
fileBrowserState.currentFileSharePath,
@@ -145,8 +155,9 @@ export default function PropertiesDrawer({
145155
{fileBrowserState.propertiesTarget ? (
146156
<Tabs
147157
className="flex flex-col flex-1 min-h-0 "
148-
defaultValue="overview"
149158
key="file-properties-tabs"
159+
onValueChange={setActiveTab}
160+
value={activeTab}
150161
>
151162
<Tabs.List className="justify-start items-stretch shrink-0 min-w-fit w-full py-2 bg-surface dark:bg-surface-light">
152163
<Tabs.Trigger

src/components/ui/Table/jobsColumns.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Typography } from '@material-tailwind/react';
22
import { type ColumnDef } from '@tanstack/react-table';
3+
import { useNavigate } from 'react-router';
34

45
import { useZoneAndFspMapContext } from '@/contexts/ZonesAndFspMapContext';
56
import { usePreferencesContext } from '@/contexts/PreferencesContext';
@@ -12,10 +13,13 @@ import {
1213
} from '@/utils';
1314
import { FileSharePath } from '@/shared.types';
1415
import { FgStyledLink } from '../widgets/FgLink';
16+
import toast from 'react-hot-toast';
1517

1618
function FilePathCell({ item }: { readonly item: Ticket }) {
1719
const { zonesAndFileSharePathsMap } = useZoneAndFspMapContext();
18-
const { pathPreference } = usePreferencesContext();
20+
const { pathPreference, setLayoutWithPropertiesOpen } =
21+
usePreferencesContext();
22+
const navigate = useNavigate();
1923

2024
const itemFsp = zonesAndFileSharePathsMap[
2125
makeMapKey('fsp', item.fsp_name)
@@ -26,9 +30,24 @@ function FilePathCell({ item }: { readonly item: Ticket }) {
2630
item.path
2731
);
2832

33+
const handleClick = async (e: React.MouseEvent<HTMLAnchorElement>) => {
34+
e.preventDefault();
35+
const result = await setLayoutWithPropertiesOpen();
36+
if (!result.success) {
37+
toast.error(`Error opening properties for file: ${result.error}`);
38+
return;
39+
}
40+
navigate(makeBrowseLink(item.fsp_name, item.path), {
41+
state: { openConvertTab: true }
42+
});
43+
};
44+
2945
return (
3046
<div className="line-clamp-2 max-w-full">
31-
<FgStyledLink to={makeBrowseLink(item.fsp_name, item.path)}>
47+
<FgStyledLink
48+
onClick={handleClick}
49+
to={makeBrowseLink(item.fsp_name, item.path)}
50+
>
3251
{displayPath}
3352
</FgStyledLink>
3453
</div>

src/components/ui/widgets/FgLink.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type StyledLinkProps = {
99
readonly target?: string;
1010
readonly rel?: string;
1111
readonly textSize?: 'default' | 'large' | 'small';
12+
readonly onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
1213
};
1314

1415
export function FgStyledLink({
@@ -17,7 +18,8 @@ export function FgStyledLink({
1718
className = '',
1819
target,
1920
rel,
20-
textSize = 'default'
21+
textSize = 'default',
22+
onClick
2123
}: StyledLinkProps) {
2224
const baseClasses = 'text-primary-light hover:underline focus:underline';
2325
const textClasses = {
@@ -29,6 +31,7 @@ export function FgStyledLink({
2931
return (
3032
<Link
3133
className={`${baseClasses} ${textClasses[textSize]} ${className}`}
34+
onClick={onClick}
3235
rel={rel}
3336
target={target}
3437
to={to}

src/constants/layoutConstants.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Shared constants for layout management between PreferencesContext and useLayoutPrefs
2+
3+
// Name is set by the autosaveId prop in PanelGroup
4+
export const LAYOUT_NAME = 'react-resizable-panels:layout';
5+
6+
// Layout keys for the different panel combinations
7+
// Confusingly, the names are in alphabetical order, but the order of the sizes is set by the order prop
8+
// in the respective Panel components
9+
export const WITH_PROPERTIES_AND_SIDEBAR = 'main,properties,sidebar';
10+
export const ONLY_SIDEBAR = 'main,sidebar';
11+
export const ONLY_PROPERTIES = 'main,properties';
12+
13+
export const DEFAULT_LAYOUT =
14+
'{"main,properties,sidebar":{"expandToSizes":{},"layout":[24,50,26]}}';
15+
export const DEFAULT_LAYOUT_SMALL_SCREENS =
16+
'{"main":{"expandToSizes":{},"layout":[100]}}';

src/contexts/PreferencesContext.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import { useFileBrowserContext } from './FileBrowserContext';
88
import { sendFetchRequest, makeMapKey, HTTPError } from '@/utils';
99
import { createSuccess, handleError, toHttpError } from '@/utils/errorHandling';
1010
import type { Result } from '@/shared.types';
11+
import {
12+
LAYOUT_NAME,
13+
WITH_PROPERTIES_AND_SIDEBAR,
14+
ONLY_PROPERTIES
15+
} from '@/constants/layoutConstants';
1116

1217
export type FolderFavorite = {
1318
type: 'folder';
@@ -53,6 +58,7 @@ type PreferencesContextType = {
5358
recentlyViewedFolders: FolderPreference[];
5459
layout: string;
5560
handleUpdateLayout: (layout: string) => Promise<void>;
61+
setLayoutWithPropertiesOpen: () => Promise<Result<void>>;
5662
loadingRecentlyViewedFolders: boolean;
5763
isLayoutLoadedFromDB: boolean;
5864
handleContextMenuFavorite: () => Promise<Result<boolean>>;
@@ -223,6 +229,34 @@ export const PreferencesProvider = ({
223229
setLayout(layout);
224230
};
225231

232+
const setLayoutWithPropertiesOpen = async (): Promise<Result<void>> => {
233+
try {
234+
// Keep sidebar in new layout if it is currently present
235+
const hasSidebar = layout.includes('sidebar');
236+
237+
const layoutKey = hasSidebar
238+
? WITH_PROPERTIES_AND_SIDEBAR
239+
: ONLY_PROPERTIES;
240+
241+
const layoutSizes = hasSidebar ? [24, 50, 26] : [75, 25];
242+
243+
const newLayout = {
244+
[LAYOUT_NAME]: {
245+
[layoutKey]: {
246+
expandToSizes: {},
247+
layout: layoutSizes
248+
}
249+
}
250+
};
251+
const newLayoutString = JSON.stringify(newLayout);
252+
await savePreferencesToBackend('layout', newLayoutString);
253+
setLayout(newLayoutString);
254+
return createSuccess(undefined);
255+
} catch (error) {
256+
return handleError(error);
257+
}
258+
};
259+
226260
const handlePathPreferenceSubmit = React.useCallback(
227261
async (
228262
localPathPreference: ['linux_path'] | ['windows_path'] | ['mac_path']
@@ -750,6 +784,7 @@ export const PreferencesProvider = ({
750784
recentlyViewedFolders,
751785
layout,
752786
handleUpdateLayout,
787+
setLayoutWithPropertiesOpen,
753788
loadingRecentlyViewedFolders,
754789
isLayoutLoadedFromDB,
755790
handleContextMenuFavorite

src/hooks/useLayoutPrefs.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ import React from 'react';
33
import { usePreferencesContext } from '@/contexts/PreferencesContext';
44
import { useCentralServerHealthContext } from '@/contexts/CentralServerHealthContext';
55
import logger from '@/logger';
6+
import {
7+
LAYOUT_NAME,
8+
WITH_PROPERTIES_AND_SIDEBAR,
9+
ONLY_SIDEBAR,
10+
ONLY_PROPERTIES,
11+
DEFAULT_LAYOUT,
12+
DEFAULT_LAYOUT_SMALL_SCREENS
13+
} from '@/constants/layoutConstants';
614
/**
715
* Custom hook that provides storage interface for react-resizable-panels
816
* with debounced updates to reduce API calls when resizing panels
@@ -12,20 +20,6 @@ import logger from '@/logger';
1220

1321
const DEBOUNCE_MS = 500;
1422

15-
// Name is set by the autosaveId prop in PanelGroup
16-
const LAYOUT_NAME = 'react-resizable-panels:layout';
17-
// Confusingly, the names are in alphabetical order, but the order of the sizes is set by the order prop
18-
// in the respective Panel components
19-
const DEFAULT_LAYOUT =
20-
'{"main,properties,sidebar":{"expandToSizes":{},"layout":[24,50,24]}}';
21-
const DEFAULT_LAYOUT_SMALL_SCREENS =
22-
'{"main":{"expandToSizes":{},"layout":[100]}}';
23-
24-
// Layout keys for the two possible panel combinations
25-
const WITH_PROPERTIES_AND_SIDEBAR = 'main,properties,sidebar';
26-
const ONLY_SIDEBAR = 'main,sidebar';
27-
const ONLY_PROPERTIES = 'main,properties';
28-
2923
export default function useLayoutPrefs() {
3024
const [showPropertiesDrawer, setShowPropertiesDrawer] =
3125
React.useState<boolean>(false);

0 commit comments

Comments
 (0)