Merge branch 'master' of git.curoverse.com:arvados-workbench2 into 14512_admin_links
authorJanicki Artur <artur.janicki@contractors.roche.com>
Wed, 12 Dec 2018 09:55:10 +0000 (10:55 +0100)
committerJanicki Artur <artur.janicki@contractors.roche.com>
Wed, 12 Dec 2018 09:55:10 +0000 (10:55 +0100)
refs #2
14512

Arvados-DCO-1.1-Signed-off-by: Janicki Artur <artur.janicki@contractors.roche.com>

1  2 
src/models/link.ts
src/routes/route-change-handlers.ts
src/routes/routes.ts
src/store/navigation/navigation-action.ts
src/views-components/main-app-bar/admin-menu.tsx
src/views-components/main-content-bar/main-content-bar.tsx
src/views/workbench/workbench.tsx

diff --combined src/models/link.ts
index acaf13955d2ad2e9f0b2138894939568709ab7df,c9e085be49ac34e535c34e73abae9d0d63ee13cf..d931f7f21898b394b2b2efb73349838e533532a8
@@@ -4,13 -4,10 +4,13 @@@
  
  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;
@@@ -20,4 -17,5 +20,5 @@@ export enum LinkClass 
      STAR = 'star',
      TAG = 'tag',
      PERMISSION = 'permission',
+     PRESET = 'preset',
  }
index 34b488def282b3224a22183766a3f91708eadaf8,4ea0925cdb7d320eec36977ccc9d985de9e85660..c4b0fc7d5d5486f8be4fc30896a5296407c90ed2
@@@ -26,15 -26,16 +26,17 @@@ const handleLocationChange = (store: Ro
      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);
@@@ -74,7 -79,5 +80,7 @@@
          store.dispatch(WorkbenchActions.loadMyAccount);
      } else if (userMatch) {
          store.dispatch(WorkbenchActions.loadUsers);
 +    } else if (linksMatch) {
 +        store.dispatch(WorkbenchActions.loadLinks);
      }
  };
diff --combined src/routes/routes.ts
index 8286e10ea23551a59daffb6258dfe3e97a276b55,f447975b12da7d97e2e84d77a1813e8f5ec80056..05f6663fe3c2bbb8021423249e5e045263ab3be7
@@@ -19,16 -19,17 +19,18 @@@ export const Routes = 
      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) => {
@@@ -86,14 -87,20 +88,20 @@@ export const matchWorkflowRoute = (rout
  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 });
@@@ -109,6 -116,3 +117,6 @@@ export const matchComputeNodesRoute = (
  
  export const matchApiClientAuthorizationsRoute = (route: string) =>
      matchPath(route, { path: Routes.API_CLIENT_AUTHORIZATIONS });
 +
 +export const matchLinksRoute = (route: string) =>
 +    matchPath(route, { path: Routes.LINKS });
index 0221fa9cc7c9b4a209393d6c6300cd4925608151,66fba9cf16d231c7f5d7b3866419c2cf05c96109..cbd983a68fe4bce3f6676068f44b59ccc3786b29
@@@ -62,11 -62,15 +62,15 @@@ export const navigateToRunProcess = pus
  
  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);
  
@@@ -77,5 -81,3 +81,5 @@@ export const navigateToComputeNodes = p
  export const navigateToUsers = push(Routes.USERS);
  
  export const navigateToApiClientAuthorizations = push(Routes.API_CLIENT_AUTHORIZATIONS);
 +
 +export const navigateToLinks = push(Routes.LINKS);
index 0000000000000000000000000000000000000000,40ba91616e4675ddce7622b68d2168da8bcc6fdc..88aafbae61ef3c821d90b513389a772c4b0e41da
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,45 +1,43 @@@
 -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);
index 03362178075c75be95fb7fcbbf6e51fc90d80cea,92592193a97c67ba7b467162a5e28650ed7617fa..3806b5245a75b0e58acfe4d6c4aba4247acdb434
@@@ -18,11 -18,12 +18,12 @@@ interface MainContentBarProps 
  
  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) => ({
index 8181cdf9c47d714b30a18777c1a5999faf6236dc,0e9c5d0f08dc2e0d141af3f4074a165542d12b6e..025540e22ed89c6bab5ecd1a9dee6ddc11281a94
@@@ -49,13 -49,13 +49,14 @@@ import { MyAccountPanel } from '~/views
  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';
@@@ -65,13 -65,11 +66,13 @@@ import { PublicKeyDialog } from '~/view
  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';
@@@ -147,15 -145,16 +148,17 @@@ export const WorkbenchPanel 
                                  <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 />