Skip to content

Commit

Permalink
add permissionsModal to snapshotActionMenu
Browse files Browse the repository at this point in the history
  • Loading branch information
kpierre13 committed Sep 27, 2024
1 parent ae9c80d commit 06ed6a6
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 42 deletions.
26 changes: 2 additions & 24 deletions src/pages/workflows/workflow/WorkflowSummary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@ import _ from 'lodash/fp';
import { Fragment, useState } from 'react';
import { div, h, h2, span } from 'react-hyperscript-helpers';
import * as breadcrumbs from 'src/components/breadcrumbs';
import { ButtonPrimary, Link, spinnerOverlay } from 'src/components/common';
import { Link } from 'src/components/common';
import { icon } from 'src/components/icons';
import { MarkdownViewer, newWindowLinkRenderer } from 'src/components/markdown';
import { TooltipCell } from 'src/components/table';
import { Ajax } from 'src/libs/ajax';
import { getConfig } from 'src/libs/config';
import { withErrorReporting } from 'src/libs/error';
import { forwardRefWithName, useCancellation, useStore } from 'src/libs/react-utils';
import { forwardRefWithName, useStore } from 'src/libs/react-utils';
import { snapshotStore } from 'src/libs/state';
import * as Style from 'src/libs/style';
import * as Utils from 'src/libs/utils';
import { WorkflowRightBoxSection } from 'src/pages/workflows/components/WorkflowRightBoxSection';
import { PermissionsModal } from 'src/pages/workflows/workflow/common/PermissionsModal';
import { wrapWorkflows } from 'src/pages/workflows/workflow/WorkflowWrapper';
import { InfoRow } from 'src/workspaces/dashboard/InfoRow';

Expand All @@ -33,17 +30,10 @@ export const BaseWorkflowSummary = () => {
} = useStore(snapshotStore);
const persistenceId = `workflows/${namespace}/${name}/dashboard`;
const [importUrlCopied, setImportUrlCopied] = useState<boolean>();
const [permissionsModalOpen, setPermissionsModalOpen] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const signal: AbortSignal = useCancellation();
const importUrl = `${
getConfig().orchestrationUrlRoot
}/ga4gh/v1/tools/${namespace}:${name}/versions/${snapshotId}/plain-WDL/descriptor`;

const refresh = Utils.withBusyState(setLoading, async () => {
snapshotStore.set(await Ajax(signal).Methods.method(namespace, name, snapshotId).get());
});

return div({ style: { flex: 1, display: 'flex' }, role: 'tabpanel' }, [
div({ style: Style.dashboard.leftBox }, [
synopsis &&
Expand All @@ -52,7 +42,6 @@ export const BaseWorkflowSummary = () => {
div({ style: { fontSize: 16 } }, [synopsis]),
]),
h2({ style: Style.dashboard.header }, ['Documentation']),
h(ButtonPrimary, { onClick: () => setPermissionsModalOpen(true) }),
documentation
? h(MarkdownViewer, { renderers: { link: newWindowLinkRenderer } }, [documentation])
: div({ style: { fontStyle: 'italic' } }, ['No documentation provided']),
Expand Down Expand Up @@ -120,17 +109,6 @@ export const BaseWorkflowSummary = () => {
]
),
]),
permissionsModalOpen &&
h(PermissionsModal, {
snapshotOrNamespace: 'Snapshot',
namespace,
name,
selectedSnapshot: snapshotId,
setPermissionsModalOpen,
refresh,
setLoading,
}),
loading && spinnerOverlay,
]);
};

Expand Down
26 changes: 23 additions & 3 deletions src/pages/workflows/workflow/WorkflowWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useCancellation, useOnMount, useStore, withDisplayName } from 'src/libs
import { getTerraUser, snapshotsListStore, snapshotStore } from 'src/libs/state';
import * as Style from 'src/libs/style';
import * as Utils from 'src/libs/utils';
import { PermissionsModal } from 'src/pages/workflows/workflow/common/PermissionsModal';
import DeleteSnapshotModal from 'src/workflows/modals/DeleteSnapshotModal';
import ExportWorkflowModal from 'src/workflows/modals/ExportWorkflowModal';
import SnapshotActionMenu from 'src/workflows/SnapshotActionMenu';
Expand All @@ -30,13 +31,13 @@ export interface WrapWorkflowOptions {
interface WorkflowWrapperProps extends PropsWithChildren {
namespace: string;
name: string;
snapshotId: string | undefined;
snapshotId: number | undefined;
}

interface WorkflowContainerProps extends PropsWithChildren {
namespace: string;
name: string;
snapshotId: string | undefined;
snapshotId: number | undefined;
tabName: string | undefined;
}

Expand Down Expand Up @@ -101,6 +102,7 @@ export const WorkflowsContainer = (props: WorkflowContainerProps) => {

const [showDeleteModal, setShowDeleteModal] = useState<boolean>(false);
const [busy, setBusy] = useState<boolean>(false);
const [permissionsModalOpen, setPermissionsModalOpen] = useState<boolean>(false);

const snapshot =
cachedSnapshot &&
Expand All @@ -116,6 +118,10 @@ export const WorkflowsContainer = (props: WorkflowContainerProps) => {
_.map(_.toLower, snapshot?.managers)
);

const refresh = Utils.withBusyState(setBusy, async () => {
snapshotStore.set(await Ajax(signal).Methods.method(namespace, name, snapshotId).get());
});

useOnMount(() => {
const loadSnapshot = async () => {
snapshotStore.set(await Ajax(signal).Methods.method(namespace, name, selectedSnapshot).get());
Expand Down Expand Up @@ -192,7 +198,11 @@ export const WorkflowsContainer = (props: WorkflowContainerProps) => {
['Export to Workspace']
),
div({ style: { marginLeft: '1rem', marginRight: '0.5rem' } }, [
h(SnapshotActionMenu, { isSnapshotOwner, onDelete: () => setShowDeleteModal(true) }),
h(SnapshotActionMenu, {
isSnapshotOwner,
onDelete: () => setShowDeleteModal(true),
onEdit: () => setPermissionsModalOpen(true),
}),
]),
]
),
Expand Down Expand Up @@ -233,6 +243,16 @@ export const WorkflowsContainer = (props: WorkflowContainerProps) => {
}),
onDismiss: () => setShowDeleteModal(false),
}),
permissionsModalOpen &&
h(PermissionsModal, {
snapshotOrNamespace: 'Snapshot',
namespace,
name,
selectedSnapshot: snapshotId,
setPermissionsModalOpen,
refresh,
setLoading: () => busy,
}),
busy && spinnerOverlay,
snapshot ? div({ style: { flex: 1, display: 'flex', flexDirection: 'column' } }, [children]) : centeredSpinner(),
]);
Expand Down
2 changes: 1 addition & 1 deletion src/pages/workflows/workflow/common/PermissionsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type WorkflowPermissionsModalProps = {
snapshotOrNamespace: 'Snapshot' | 'Namespace';
namespace: string;
name: string;
selectedSnapshot: number;
selectedSnapshot: number | undefined;
setPermissionsModalOpen: (b: boolean) => void;
refresh: () => void;
setLoading: (b: boolean) => void;
Expand Down
27 changes: 23 additions & 4 deletions src/workflows/SnapshotActionMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import { renderWithAppContexts as render } from 'src/testing/test-utils';
import SnapshotActionMenu from 'src/workflows/SnapshotActionMenu';

const mockOnDelete = jest.fn();
const mockOnEdit = jest.fn();

describe('snapshot action menu', () => {
describe('snapshot action menu delete', () => {
it('renders and enables the menu buttons if you are the snapshot owner', async () => {
// Arrange
const user: UserEvent = userEvent.setup();

// Act
await act(async () => {
render(<SnapshotActionMenu isSnapshotOwner onDelete={mockOnDelete} />);
render(<SnapshotActionMenu isSnapshotOwner onDelete={mockOnDelete} onEdit={mockOnEdit} />);
});

await user.click(screen.getByRole('button', { name: 'Snapshot action menu' }));
Expand All @@ -34,7 +35,7 @@ describe('snapshot action menu', () => {

// Act
await act(async () => {
render(<SnapshotActionMenu isSnapshotOwner={false} onDelete={mockOnDelete} />);
render(<SnapshotActionMenu isSnapshotOwner={false} onDelete={mockOnDelete} onEdit={mockOnEdit} />);
});

await user.click(screen.getByRole('button', { name: 'Snapshot action menu' }));
Expand All @@ -55,7 +56,7 @@ describe('snapshot action menu', () => {

// Act
await act(async () => {
render(<SnapshotActionMenu isSnapshotOwner onDelete={mockOnDelete} />);
render(<SnapshotActionMenu isSnapshotOwner onDelete={mockOnDelete} onEdit={mockOnEdit} />);
});

await user.click(screen.getByRole('button', { name: 'Snapshot action menu' }));
Expand All @@ -66,3 +67,21 @@ describe('snapshot action menu', () => {
expect(mockOnDelete).toHaveBeenCalled();
});
});

describe('snapshot action menu edit permissions', () => {
it('does', async () => {
// Arrange
const user: UserEvent = userEvent.setup();

// Act
await act(async () => {
render(<SnapshotActionMenu isSnapshotOwner onDelete={mockOnDelete} onEdit={mockOnEdit} />);
});

await user.click(screen.getByRole('button', { name: 'Snapshot action menu' }));
await user.click(screen.getByRole('button', { name: 'Edit Permissions' }));

expect(screen.queryByRole('button', { name: 'Edit Permissions' })).not.toBeInTheDocument();
expect(mockOnEdit).toHaveBeenCalled();
});
});
34 changes: 24 additions & 10 deletions src/workflows/SnapshotActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export interface SnapshotActionMenuProps {

/** The action to be performed if the "Delete snapshot" button is pressed. */
onDelete: () => void;

/** The state that controls whether the permissions modal shows on the page */
onEdit: () => void;
}

/**
Expand All @@ -21,20 +24,31 @@ export interface SnapshotActionMenuProps {
* Currently supported actions: delete
*/
const SnapshotActionMenu = (props: SnapshotActionMenuProps): ReactNode => {
const { isSnapshotOwner, onDelete } = props;
const { isSnapshotOwner, onDelete, onEdit } = props;

const notSnapshotOwnerTooltip = 'You must be an owner of this snapshot';

const menuContent = (
<MenuButton
disabled={!isSnapshotOwner}
tooltip={!isSnapshotOwner && notSnapshotOwnerTooltip}
tooltipSide='left'
onClick={onDelete}
>
{makeMenuIcon('trash')}
Delete snapshot
</MenuButton>
<>
<MenuButton
disabled={!isSnapshotOwner}
tooltip={!isSnapshotOwner && notSnapshotOwnerTooltip}
tooltipSide='left'
onClick={onDelete}
>
{makeMenuIcon('trash')}
Delete snapshot
</MenuButton>
<MenuButton
disabled={!isSnapshotOwner}
tooltip={!isSnapshotOwner && notSnapshotOwnerTooltip}
tooltipSide='left'
onClick={onEdit}
>
{makeMenuIcon('cog')}
Edit Permissions
</MenuButton>
</>
);

return (
Expand Down

0 comments on commit 06ed6a6

Please sign in to comment.