import { Resource } from "./resource";
import { TagProperty } from "~/models/tag";
+import { ResourceKind } from '~/models/resource';
export interface LinkResource extends Resource {
headUuid: string;
+ headKind: ResourceKind;
tailUuid: string;
+ tailKind: string;
linkClass: string;
name: string;
properties: TagProperty;
STAR = 'star',
TAG = 'tag',
PERMISSION = 'permission',
+ PRESET = 'preset',
}
const searchResultsMatch = Routes.matchSearchResultsRoute(pathname);
const sharedWithMeMatch = Routes.matchSharedWithMeRoute(pathname);
const runProcessMatch = Routes.matchRunProcessRoute(pathname);
- const virtualMachineMatch = Routes.matchVirtualMachineRoute(pathname);
+ const virtualMachineUserMatch = Routes.matchUserVirtualMachineRoute(pathname);
+ const virtualMachineAdminMatch = Routes.matchAdminVirtualMachineRoute(pathname);
const workflowMatch = Routes.matchWorkflowRoute(pathname);
- const sshKeysMatch = Routes.matchSshKeysRoute(pathname);
+ const sshKeysUserMatch = Routes.matchSshKeysUserRoute(pathname);
+ const sshKeysAdminMatch = Routes.matchSshKeysAdminRoute(pathname);
const keepServicesMatch = Routes.matchKeepServicesRoute(pathname);
const computeNodesMatch = Routes.matchComputeNodesRoute(pathname);
const apiClientAuthorizationsMatch = Routes.matchApiClientAuthorizationsRoute(pathname);
const myAccountMatch = Routes.matchMyAccountRoute(pathname);
const userMatch = Routes.matchUsersRoute(pathname);
+ const linksMatch = Routes.matchLinksRoute(pathname);
if (projectMatch) {
store.dispatch(WorkbenchActions.loadProject(projectMatch.params.id));
store.dispatch(WorkbenchActions.loadWorkflow);
} else if (searchResultsMatch) {
store.dispatch(WorkbenchActions.loadSearchResults);
- } else if (virtualMachineMatch) {
+ } else if (virtualMachineUserMatch) {
store.dispatch(WorkbenchActions.loadVirtualMachines);
- } else if(repositoryMatch) {
+ } else if (virtualMachineAdminMatch) {
+ store.dispatch(WorkbenchActions.loadVirtualMachines);
+ } else if (repositoryMatch) {
store.dispatch(WorkbenchActions.loadRepositories);
- } else if (sshKeysMatch) {
+ } else if (sshKeysUserMatch) {
+ store.dispatch(WorkbenchActions.loadSshKeys);
+ } else if (sshKeysAdminMatch) {
store.dispatch(WorkbenchActions.loadSshKeys);
} else if (keepServicesMatch) {
store.dispatch(WorkbenchActions.loadKeepServices);
store.dispatch(WorkbenchActions.loadMyAccount);
} else if (userMatch) {
store.dispatch(WorkbenchActions.loadUsers);
+ } else if (linksMatch) {
+ store.dispatch(WorkbenchActions.loadLinks);
}
};
REPOSITORIES: '/repositories',
SHARED_WITH_ME: '/shared-with-me',
RUN_PROCESS: '/run-process',
- VIRTUAL_MACHINES: '/virtual-machines',
+ VIRTUAL_MACHINES_ADMIN: '/virtual-machines-admin',
+ VIRTUAL_MACHINES_USER: '/virtual-machines-user',
WORKFLOWS: '/workflows',
SEARCH_RESULTS: '/search-results',
- SSH_KEYS: `/ssh-keys`,
+ SSH_KEYS_ADMIN: `/ssh-keys-admin`,
+ SSH_KEYS_USER: `/ssh-keys-user`,
MY_ACCOUNT: '/my-account',
KEEP_SERVICES: `/keep-services`,
COMPUTE_NODES: `/nodes`,
USERS: '/users',
- API_CLIENT_AUTHORIZATIONS: `/api_client_authorizations`
+ API_CLIENT_AUTHORIZATIONS: `/api_client_authorizations`,
+ LINKS: '/links'
};
export const getResourceUrl = (uuid: string) => {
export const matchSearchResultsRoute = (route: string) =>
matchPath<ResourceRouteParams>(route, { path: Routes.SEARCH_RESULTS });
- export const matchVirtualMachineRoute = (route: string) =>
- matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES });
+ export const matchUserVirtualMachineRoute = (route: string) =>
+ matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_USER });
+
+ export const matchAdminVirtualMachineRoute = (route: string) =>
+ matchPath<ResourceRouteParams>(route, { path: Routes.VIRTUAL_MACHINES_ADMIN });
export const matchRepositoriesRoute = (route: string) =>
matchPath<ResourceRouteParams>(route, { path: Routes.REPOSITORIES });
- export const matchSshKeysRoute = (route: string) =>
- matchPath(route, { path: Routes.SSH_KEYS });
+ export const matchSshKeysUserRoute = (route: string) =>
+ matchPath(route, { path: Routes.SSH_KEYS_USER });
+
+ export const matchSshKeysAdminRoute = (route: string) =>
+ matchPath(route, { path: Routes.SSH_KEYS_ADMIN });
export const matchMyAccountRoute = (route: string) =>
matchPath(route, { path: Routes.MY_ACCOUNT });
export const matchApiClientAuthorizationsRoute = (route: string) =>
matchPath(route, { path: Routes.API_CLIENT_AUTHORIZATIONS });
+
+export const matchLinksRoute = (route: string) =>
+ matchPath(route, { path: Routes.LINKS });
export const navigateToSearchResults = push(Routes.SEARCH_RESULTS);
- export const navigateToVirtualMachines = push(Routes.VIRTUAL_MACHINES);
+ export const navigateToUserVirtualMachines = push(Routes.VIRTUAL_MACHINES_USER);
+
+ export const navigateToAdminVirtualMachines = push(Routes.VIRTUAL_MACHINES_ADMIN);
export const navigateToRepositories = push(Routes.REPOSITORIES);
- export const navigateToSshKeys= push(Routes.SSH_KEYS);
+ export const navigateToSshKeysAdmin= push(Routes.SSH_KEYS_ADMIN);
+
+ export const navigateToSshKeysUser= push(Routes.SSH_KEYS_USER);
export const navigateToMyAccount = push(Routes.MY_ACCOUNT);
export const navigateToUsers = push(Routes.USERS);
export const navigateToApiClientAuthorizations = push(Routes.API_CLIENT_AUTHORIZATIONS);
+
+export const navigateToLinks = push(Routes.LINKS);
--- /dev/null
-import {
- navigateToSshKeysAdmin, navigateToKeepServices, navigateToComputeNodes,
- navigateToApiClientAuthorizations
-} from '~/store/navigation/navigation-action';
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+
+ import * as React from "react";
+ import { MenuItem } from "@material-ui/core";
+ import { User } from "~/models/user";
+ import { DropdownMenu } from "~/components/dropdown-menu/dropdown-menu";
+ import { AdminMenuIcon } from "~/components/icon/icon";
+ import { DispatchProp, connect } from 'react-redux';
+ import { logout } from '~/store/auth/auth-action';
+ import { RootState } from "~/store/store";
+ import { openRepositoriesPanel } from "~/store/repositories/repositories-actions";
- <MenuItem onClick={() => dispatch(navigateToSshKeysAdmin)}>Ssh Keys</MenuItem>
- <MenuItem onClick={() => dispatch(navigateToApiClientAuthorizations)}>Api Tokens</MenuItem>
++import * as NavigationAction from '~/store/navigation/navigation-action';
+ import { openAdminVirtualMachines } from "~/store/virtual-machines/virtual-machines-actions";
+ import { openUserPanel } from "~/store/users/users-actions";
+
+ interface AdminMenuProps {
+ user?: User;
+ }
+
+ const mapStateToProps = (state: RootState): AdminMenuProps => ({
+ user: state.auth.user
+ });
+
+ export const AdminMenu = connect(mapStateToProps)(
+ ({ user, dispatch }: AdminMenuProps & DispatchProp<any>) =>
+ user
+ ? <DropdownMenu
+ icon={<AdminMenuIcon />}
+ id="admin-menu"
+ title="Admin Panel">
+ <MenuItem onClick={() => dispatch(openRepositoriesPanel())}>Repositories</MenuItem>
+ <MenuItem onClick={() => dispatch(openAdminVirtualMachines())}>Virtual Machines</MenuItem>
- <MenuItem onClick={() => dispatch(navigateToComputeNodes)}>Compute Nodes</MenuItem>
- <MenuItem onClick={() => dispatch(navigateToKeepServices)}>Keep Services</MenuItem>
++ <MenuItem onClick={() => dispatch(NavigationAction.navigateToSshKeysAdmin)}>Ssh Keys</MenuItem>
++ <MenuItem onClick={() => dispatch(NavigationAction.navigateToApiClientAuthorizations)}>Api Tokens</MenuItem>
+ <MenuItem onClick={() => dispatch(openUserPanel())}>Users</MenuItem>
++ <MenuItem onClick={() => dispatch(NavigationAction.navigateToComputeNodes)}>Compute Nodes</MenuItem>
++ <MenuItem onClick={() => dispatch(NavigationAction.navigateToKeepServices)}>Keep Services</MenuItem>
++ <MenuItem onClick={() => dispatch(NavigationAction.navigateToLinks)}>Links</MenuItem>
+ <MenuItem onClick={() => dispatch(logout())}>Logout</MenuItem>
+ </DropdownMenu>
+ : null);
const isButtonVisible = ({ router }: RootState) => {
const pathname = router.location ? router.location.pathname : '';
- return !Routes.matchWorkflowRoute(pathname) && !Routes.matchVirtualMachineRoute(pathname) &&
- !Routes.matchRepositoriesRoute(pathname) && !Routes.matchSshKeysRoute(pathname) &&
+ return !Routes.matchWorkflowRoute(pathname) && !Routes.matchUserVirtualMachineRoute(pathname) &&
+ !Routes.matchAdminVirtualMachineRoute(pathname) && !Routes.matchRepositoriesRoute(pathname) &&
+ !Routes.matchSshKeysAdminRoute(pathname) && !Routes.matchSshKeysUserRoute(pathname) &&
!Routes.matchKeepServicesRoute(pathname) && !Routes.matchComputeNodesRoute(pathname) &&
- !Routes.matchApiClientAuthorizationsRoute(pathname) && !Routes.matchUsersRoute(pathname) &&
- !Routes.matchLinksRoute(pathname);
+ !Routes.matchApiClientAuthorizationsRoute(pathname) && !Routes.matchUsersRoute(pathname) &&
- !Routes.matchMyAccountRoute(pathname);
++ !Routes.matchMyAccountRoute(pathname) && !Routes.matchLinksRoute(pathname);
};
export const MainContentBar = connect((state: RootState) => ({
import { SharingDialog } from '~/views-components/sharing-dialog/sharing-dialog';
import { AdvancedTabDialog } from '~/views-components/advanced-tab-dialog/advanced-tab-dialog';
import { ProcessInputDialog } from '~/views-components/process-input-dialog/process-input-dialog';
- import { VirtualMachinePanel } from '~/views/virtual-machine-panel/virtual-machine-panel';
+ import { VirtualMachineUserPanel } from '~/views/virtual-machine-panel/virtual-machine-user-panel';
+ import { VirtualMachineAdminPanel } from '~/views/virtual-machine-panel/virtual-machine-admin-panel';
import { ProjectPropertiesDialog } from '~/views-components/project-properties-dialog/project-properties-dialog';
import { RepositoriesPanel } from '~/views/repositories-panel/repositories-panel';
import { KeepServicePanel } from '~/views/keep-service-panel/keep-service-panel';
import { ComputeNodePanel } from '~/views/compute-node-panel/compute-node-panel';
import { ApiClientAuthorizationPanel } from '~/views/api-client-authorization-panel/api-client-authorization-panel';
+import { LinkPanel } from '~/views/link-panel/link-panel';
import { RepositoriesSampleGitDialog } from '~/views-components/repositories-sample-git-dialog/repositories-sample-git-dialog';
import { RepositoryAttributesDialog } from '~/views-components/repository-attributes-dialog/repository-attributes-dialog';
import { CreateRepositoryDialog } from '~/views-components/dialog-forms/create-repository-dialog';
import { RemoveApiClientAuthorizationDialog } from '~/views-components/api-client-authorizations-dialog/remove-dialog';
import { RemoveComputeNodeDialog } from '~/views-components/compute-nodes-dialog/remove-dialog';
import { RemoveKeepServiceDialog } from '~/views-components/keep-services-dialog/remove-dialog';
+import { RemoveLinkDialog } from '~/views-components/links-dialog/remove-dialog';
import { RemoveSshKeyDialog } from '~/views-components/ssh-keys-dialog/remove-dialog';
import { RemoveVirtualMachineDialog } from '~/views-components/virtual-machines-dialog/remove-dialog';
import { AttributesApiClientAuthorizationDialog } from '~/views-components/api-client-authorizations-dialog/attributes-dialog';
import { AttributesComputeNodeDialog } from '~/views-components/compute-nodes-dialog/attributes-dialog';
import { AttributesKeepServiceDialog } from '~/views-components/keep-services-dialog/attributes-dialog';
+import { AttributesLinkDialog } from '~/views-components/links-dialog/attributes-dialog';
import { AttributesSshKeyDialog } from '~/views-components/ssh-keys-dialog/attributes-dialog';
import { VirtualMachineAttributesDialog } from '~/views-components/virtual-machines-dialog/attributes-dialog';
import { UserPanel } from '~/views/user-panel/user-panel';
<Route path={Routes.RUN_PROCESS} component={RunProcessPanel} />
<Route path={Routes.WORKFLOWS} component={WorkflowPanel} />
<Route path={Routes.SEARCH_RESULTS} component={SearchResultsPanel} />
- <Route path={Routes.VIRTUAL_MACHINES} component={VirtualMachinePanel} />
+ <Route path={Routes.VIRTUAL_MACHINES_USER} component={VirtualMachineUserPanel} />
+ <Route path={Routes.VIRTUAL_MACHINES_ADMIN} component={VirtualMachineAdminPanel} />
<Route path={Routes.REPOSITORIES} component={RepositoriesPanel} />
- <Route path={Routes.SSH_KEYS} component={SshKeyPanel} />
+ <Route path={Routes.SSH_KEYS_USER} component={SshKeyPanel} />
+ <Route path={Routes.SSH_KEYS_ADMIN} component={SshKeyPanel} />
<Route path={Routes.KEEP_SERVICES} component={KeepServicePanel} />
<Route path={Routes.USERS} component={UserPanel} />
<Route path={Routes.COMPUTE_NODES} component={ComputeNodePanel} />
<Route path={Routes.API_CLIENT_AUTHORIZATIONS} component={ApiClientAuthorizationPanel} />
<Route path={Routes.MY_ACCOUNT} component={MyAccountPanel} />
+ <Route path={Routes.LINKS} component={LinkPanel} />
</Switch>
</Grid>
</Grid>
<AttributesApiClientAuthorizationDialog />
<AttributesComputeNodeDialog />
<AttributesKeepServiceDialog />
+ <AttributesLinkDialog />
<AttributesSshKeyDialog />
<ChangeWorkflowDialog />
<ContextMenu />
<RemoveApiClientAuthorizationDialog />
<RemoveComputeNodeDialog />
<RemoveKeepServiceDialog />
+ <RemoveLinkDialog />
<RemoveProcessDialog />
<RemoveRepositoryDialog />
<RemoveSshKeyDialog />