});
});
});
+
+ it('can delete a workflow', function() {
+ cy.createResource(activeUser.token, "workflows", {workflow: {name: "Test wf"}})
+ .then(function(workflowResource) {
+ cy.loginAs(activeUser);
+ cy.goToPath(`/projects/${activeUser.user.uuid}`);
+ cy.get('[data-cy=project-panel] table tbody').contains(workflowResource.name).rightclick();
+ cy.get('[data-cy=context-menu]').contains('Delete Workflow').click();
+ cy.get('[data-cy=project-panel] table tbody').should('not.contain', workflowResource.name);
+ });
+ });
+
+ it('cannot delete readonly workflow', function() {
+ cy.createProject({
+ owningUser: adminUser,
+ targetUser: activeUser,
+ projectName: 'mySharedReadonlyProject',
+ canWrite: false,
+ });
+ cy.getAll('@mySharedReadonlyProject')
+ .then(function ([mySharedReadonlyProject]) {
+ cy.createResource(adminUser.token, "workflows", {workflow: {name: "Test wf", owner_uuid: mySharedReadonlyProject.uuid}})
+ .then(function(workflowResource) {
+ cy.loginAs(activeUser);
+ cy.goToPath(`/shared-with-me`);
+ cy.contains("mySharedReadonlyProject").click();
+ cy.get('[data-cy=project-panel] table tbody').contains(workflowResource.name).rightclick();
+ cy.get('[data-cy=context-menu]').should("not.contain", 'Delete Workflow');
+ });
+ });
+ });
});
const containerLogFolderPrefix = 'log for container ';
-// Clean up on a 'before' hook to allow post-mortem analysis on individual tests.
-beforeEach(function () {
+// Clean up anything that was created. You can temporarily add
+// 'return' to the top if you need the resources to hang around to
+// debug a specific test.
+afterEach(function () {
if (createdResources.length === 0) {
return;
}
- cy.log(`Cleaning ${createdResources.length} previously created resource(s)`);
+ cy.log(`Cleaning ${createdResources.length} previously created resource(s).`);
createdResources.forEach(function({suffix, uuid}) {
// Don't fail when a resource isn't already there, some objects may have
// been removed, directly or indirectly, from the test that created them.
import { loadFileViewersConfig } from 'store/file-viewers/file-viewers-actions';
import { filterGroupAdminActionSet, frozenAdminActionSet, projectAdminActionSet } from 'views-components/context-menu/action-sets/project-admin-action-set';
import { permissionEditActionSet } from 'views-components/context-menu/action-sets/permission-edit-action-set';
-import { workflowActionSet } from 'views-components/context-menu/action-sets/workflow-action-set';
+import { workflowActionSet, readOnlyWorkflowActionSet } from 'views-components/context-menu/action-sets/workflow-action-set';
import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
import { openNotFoundDialog } from './store/not-found-panel/not-found-panel-action';
import { storeRedirects } from './common/redirect-to';
addMenuActionSet(ContextMenuKind.FROZEN_PROJECT_ADMIN, frozenAdminActionSet);
addMenuActionSet(ContextMenuKind.FILTER_GROUP_ADMIN, filterGroupAdminActionSet);
addMenuActionSet(ContextMenuKind.PERMISSION_EDIT, permissionEditActionSet);
+addMenuActionSet(ContextMenuKind.READONLY_WORKFLOW, readOnlyWorkflowActionSet);
addMenuActionSet(ContextMenuKind.WORKFLOW, workflowActionSet);
addMenuActionSet(ContextMenuKind.SEARCH_RESULTS, searchResultsActionSet);
case ResourceKind.LINK:
return ContextMenuKind.LINK;
case ResourceKind.WORKFLOW:
- return ContextMenuKind.WORKFLOW;
+ return isEditable ? ContextMenuKind.WORKFLOW : ContextMenuKind.READONLY_WORKFLOW;
default:
return;
}
export type ResourcesState = { [key: string]: Resource };
-export const getResourceWithEditableStatus = <T extends EditableResource & GroupResource>(id: string, userUuid?: string) =>
+export const getResourceWithEditableStatus = <T extends GroupResource & EditableResource>(id: string, userUuid?: string) =>
(state: ResourcesState): T | undefined => {
if (state[id] === undefined) { return; }
- const resource = JSON.parse(JSON.stringify(state[id] as T));
+ const resource = JSON.parse(JSON.stringify(state[id])) as T;
if (resource) {
- resource.isEditable = resource.canWrite;
-
- if (!resource.isEditable && state[resource.ownerUuid]) {
- const resourceOwner = JSON.parse(JSON.stringify(state[resource.ownerUuid] as T));
- resource.isEditable = resourceOwner.canWrite;
+ if (resource.canWrite === undefined) {
+ resource.isEditable = (state[resource.ownerUuid] as GroupResource)?.canWrite;
+ } else {
+ resource.isEditable = resource.canWrite;
}
}
import { bindDataExplorerActions } from 'store/data-explorer/data-explorer-action';
import { propertiesActions } from 'store/properties/properties-actions';
import { getProperty } from 'store/properties/properties';
-import { navigateToRunProcess } from 'store/navigation/navigation-action';
+import { navigateToRunProcess, navigateTo } from 'store/navigation/navigation-action';
import {
goToStep,
runProcessPanelActions,
loadPresets,
getWorkflowRunnerSettings
} from 'store/run-process-panel/run-process-panel-actions';
-import { snackbarActions } from 'store/snackbar/snackbar-actions';
+import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
import { initialize } from 'redux-form';
import { RUN_PROCESS_BASIC_FORM } from 'views/run-process-panel/run-process-basic-form';
import { RUN_PROCESS_INPUTS_FORM } from 'views/run-process-panel/run-process-inputs-form';
const workflow = workflows.find(workflow => workflow.uuid === uuid);
return workflow || undefined;
};
+
+export const deleteWorkflow = (workflowUuid: string, ownerUuid: string) =>
+ async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+ dispatch<any>(navigateTo(ownerUuid));
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removing ...', kind: SnackbarKind.INFO }));
+ await services.workflowService.delete(workflowUuid);
+ dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removed.', hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
+ };
// SPDX-License-Identifier: AGPL-3.0
import { ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
-import { openRunProcess } from "store/workflow-panel/workflow-panel-actions";
+import { openRunProcess, deleteWorkflow } from "store/workflow-panel/workflow-panel-actions";
import {
DetailsIcon,
AdvancedIcon,
OpenIcon,
Link,
- StartIcon
+ StartIcon,
+ TrashIcon
} from "components/icon/icon";
import { copyToClipboardAction, openInNewTabAction } from "store/open-in-new-tab/open-in-new-tab.actions";
import { toggleDetailsPanel } from 'store/details-panel/details-panel-action';
import { openAdvancedTabDialog } from "store/advanced-tab/advanced-tab";
-export const workflowActionSet: ContextMenuActionSet = [[
+export const readOnlyWorkflowActionSet: ContextMenuActionSet = [[
{
icon: OpenIcon,
name: "Open in new tab",
execute: (dispatch, resource) => {
dispatch<any>(openRunProcess(resource.uuid, resource.ownerUuid, resource.name));
}
+ }
+]];
+
+export const workflowActionSet: ContextMenuActionSet = [[
+ ...readOnlyWorkflowActionSet[0],
+ {
+ icon: TrashIcon,
+ name: "Delete Workflow",
+ execute: (dispatch, resource) => {
+ dispatch<any>(deleteWorkflow(resource.uuid, resource.ownerUuid));
+ }
},
]];
PERMISSION_EDIT = "PermissionEdit",
LINK = "Link",
WORKFLOW = "Workflow",
+ READONLY_WORKFLOW = "ReadOnlyWorkflow",
SEARCH_RESULTS = "SearchResults"
}