From: Pawel Kowalczyk Date: Mon, 3 Dec 2018 12:32:53 +0000 (+0100) Subject: conflicts X-Git-Tag: 1.4.0~97^2~2 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/cc72c29b709759a4498ad232e3f0374e857c7a62 conflicts Feature #14498 Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk --- cc72c29b709759a4498ad232e3f0374e857c7a62 diff --cc src/index.tsx index 3ff8088c,79525a8a..d8385967 --- a/src/index.tsx +++ b/src/index.tsx @@@ -50,8 -50,8 +50,9 @@@ import HTML5Backend from 'react-dnd-htm import { initAdvanceFormProjectsTree } from '~/store/search-bar/search-bar-actions'; import { repositoryActionSet } from '~/views-components/context-menu/action-sets/repository-action-set'; import { sshKeyActionSet } from '~/views-components/context-menu/action-sets/ssh-key-action-set'; + import { keepServiceActionSet } from '~/views-components/context-menu/action-sets/keep-service-action-set'; import { loadVocabulary } from '~/store/vocabulary/vocabulary-actions'; +import { virtualMachineActionSet } from '~/views-components/context-menu/action-sets/virtual-machine-action-set'; console.log(`Starting arvados [${getBuildInfo()}]`); @@@ -70,7 -70,7 +71,8 @@@ addMenuActionSet(ContextMenuKind.PROCES addMenuActionSet(ContextMenuKind.TRASH, trashActionSet); addMenuActionSet(ContextMenuKind.REPOSITORY, repositoryActionSet); addMenuActionSet(ContextMenuKind.SSH_KEY, sshKeyActionSet); +addMenuActionSet(ContextMenuKind.VIRTUAL_MACHINE, virtualMachineActionSet); + addMenuActionSet(ContextMenuKind.KEEP_SERVICE, keepServiceActionSet); fetchConfig() .then(({ config, apiHost }) => { diff --cc src/store/advanced-tab/advanced-tab.ts index fd68eb4b,c48011d2..d9dabe5c --- a/src/store/advanced-tab/advanced-tab.ts +++ b/src/store/advanced-tab/advanced-tab.ts @@@ -16,10 -16,7 +16,11 @@@ import { ServiceRepository } from '~/se import { FilterBuilder } from '~/services/api/filter-builder'; import { RepositoryResource } from '~/models/repositories'; import { SshKeyResource } from '~/models/ssh-key'; +import { VirtualMachinesResource } from '~/models/virtual-machines'; +import { UserResource } from '~/models/user'; +import { ListResults } from '~/services/common-service/common-resource-service'; +import { LinkResource } from '~/models/link'; + import { KeepServiceResource } from '~/models/keep-services'; export const ADVANCED_TAB_DIALOG = 'advancedTabDialog'; @@@ -62,21 -59,15 +63,27 @@@ enum SshKeyData CREATED_AT = 'created_at' } +enum VirtualMachineData { + VIRTUAL_MACHINE = 'virtual_machine', + CREATED_AT = 'created_at' +} + +enum ResourcePrefix { + REPOSITORIES = 'repositories', + AUTORIZED_KEYS = 'authorized_keys', - VIRTUAL_MACHINES = 'virtual_machines' ++ VIRTUAL_MACHINES = 'virtual_machines', ++ KEEP_SERVICES = 'keep_services' +} + - type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | VirtualMachineData; + enum KeepServiceData { + KEEP_SERVICE = 'keep_services', + CREATED_AT = 'created_at' + } + -type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | KeepServiceData; -type AdvanceResourcePrefix = GroupContentsResourcePrefix | 'repositories' | 'authorized_keys' | 'keep_services'; ++type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | VirtualMachineData | KeepServiceData; +type AdvanceResourcePrefix = GroupContentsResourcePrefix | ResourcePrefix; -export const openAdvancedTabDialog = (uuid: string, index?: number) => +export const openAdvancedTabDialog = (uuid: string) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { const kind = extractUuidKind(uuid); switch (kind) { @@@ -141,35 -92,15 +148,50 @@@ dispatch(initAdvancedTabDialog(advanceDataRepository)); break; case ResourceKind.SSH_KEY: - const dataSshKey = getState().auth.sshKeys[index!]; - const advanceDataSshKey: AdvancedTabDialogData = advancedTabData(uuid, '', '', sshKeyApiResponse, dataSshKey, SshKeyData.SSH_KEY, 'authorized_keys', SshKeyData.CREATED_AT, dataSshKey.createdAt); + const dataSshKey = getState().auth.sshKeys.find(it => it.uuid === uuid); + const advanceDataSshKey: AdvancedTabDialogData = advancedTabData({ + uuid, + metadata: '', + user: '', + apiResponseKind: sshKeyApiResponse, + data: dataSshKey, + resourceKind: SshKeyData.SSH_KEY, + resourcePrefix: ResourcePrefix.AUTORIZED_KEYS, + resourceKindProperty: SshKeyData.CREATED_AT, + property: dataSshKey!.createdAt + }); dispatch(initAdvancedTabDialog(advanceDataSshKey)); break; + case ResourceKind.VIRTUAL_MACHINE: + const dataVirtualMachine = getState().virtualMachines.virtualMachines.items.find(it => it.uuid === uuid); + const advanceDataVirtualMachine: AdvancedTabDialogData = advancedTabData({ + uuid, + metadata: '', + user: '', + apiResponseKind: virtualMachineApiResponse, + data: dataVirtualMachine, + resourceKind: VirtualMachineData.VIRTUAL_MACHINE, + resourcePrefix: ResourcePrefix.VIRTUAL_MACHINES, + resourceKindProperty: VirtualMachineData.CREATED_AT, + property: dataVirtualMachine.createdAt + }); + dispatch(initAdvancedTabDialog(advanceDataVirtualMachine)); + break; + case ResourceKind.KEEP_SERVICE: - const dataKeepService = getState().keepServices[index!]; - const advanceDataKeepService: AdvancedTabDialogData = advancedTabData(uuid, '', '', keepServiceApiResponse, dataKeepService, KeepServiceData.KEEP_SERVICE, 'keep_services', KeepServiceData.CREATED_AT, dataKeepService.createdAt); ++ const dataKeepService = getState().keepServices.find(it => it.uuid === uuid); ++ const advanceDataKeepService: AdvancedTabDialogData = advancedTabData({ ++ uuid, ++ metadata: '', ++ user: '', ++ apiResponseKind: keepServiceApiResponse, ++ data: dataKeepService, ++ resourceKind: KeepServiceData.KEEP_SERVICE, ++ resourcePrefix: ResourcePrefix.KEEP_SERVICES, ++ resourceKindProperty: KeepServiceData.CREATED_AT, ++ property: dataKeepService!.createdAt ++ }); + dispatch(initAdvancedTabDialog(advanceDataKeepService)); + break; default: dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Could not open advanced tab for this resource.", hideDuration: 2000, kind: SnackbarKind.ERROR })); } @@@ -377,14 -306,22 +399,36 @@@ const sshKeyApiResponse = (apiResponse return response; }; +const virtualMachineApiResponse = (apiResponse: VirtualMachinesResource) => { + const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, hostname } = apiResponse; - const response = `"uuid": "${uuid}", ++ const response = `"hostname": ${stringify(hostname)}, ++"uuid": "${uuid}", +"owner_uuid": "${ownerUuid}", +"modified_by_client_uuid": ${stringify(modifiedByClientUuid)}, +"modified_by_user_uuid": ${stringify(modifiedByUserUuid)}, +"modified_at": ${stringify(modifiedAt)}, - "hostname": ${stringify(hostname)}, ++"modified_at": ${stringify(modifiedAt)}, +"created_at": "${createdAt}"`; ++ ++ return response; ++}; ++ + const keepServiceApiResponse = (apiResponse: KeepServiceResource) => { + const { + uuid, readOnly, serviceHost, servicePort, serviceSslFlag, serviceType, + ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid + } = apiResponse; + const response = `"uuid": "${uuid}", + "owner_uuid": "${ownerUuid}", + "modified_by_client_uuid": ${stringify(modifiedByClientUuid)}, + "modified_by_user_uuid": ${stringify(modifiedByUserUuid)}, + "modified_at": ${stringify(modifiedAt)}, + "service_host": "${serviceHost}", + "service_port": "${servicePort}", + "service_ssl_flag": "${stringify(serviceSslFlag)}", + "service_type": "${serviceType}", + "created_at": "${createdAt}", + "read_only": "${stringify(readOnly)}"`; + return response; }; diff --cc src/store/context-menu/context-menu-actions.ts index 1412d958,2c533d66..d56a3fb5 --- a/src/store/context-menu/context-menu-actions.ts +++ b/src/store/context-menu/context-menu-actions.ts @@@ -15,7 -15,7 +15,8 @@@ import { extractUuidKind, ResourceKind import { Process } from '~/store/processes/process'; import { RepositoryResource } from '~/models/repositories'; import { SshKeyResource } from '~/models/ssh-key'; +import { VirtualMachinesResource } from '~/models/virtual-machines'; + import { KeepServiceResource } from '~/models/keep-services'; export const contextMenuActions = unionize({ OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(), @@@ -96,6 -88,18 +98,17 @@@ export const openSshKeyContextMenu = (e })); }; -export const openKeepServiceContextMenu = (event: React.MouseEvent, index: number, keepService: KeepServiceResource) => ++export const openKeepServiceContextMenu = (event: React.MouseEvent, keepService: KeepServiceResource) => + (dispatch: Dispatch) => { + dispatch(openContextMenu(event, { + name: '', + uuid: keepService.uuid, + ownerUuid: keepService.ownerUuid, + kind: ResourceKind.KEEP_SERVICE, - menuKind: ContextMenuKind.KEEP_SERVICE, - index ++ menuKind: ContextMenuKind.KEEP_SERVICE + })); + }; + export const openRootProjectContextMenu = (event: React.MouseEvent, projectUuid: string) => (dispatch: Dispatch, getState: () => RootState) => { const res = getResource(projectUuid)(getState().resources); diff --cc src/store/keep-services/keep-services-actions.ts index 00000000,1de6802e..54a7c3fe mode 000000,100644..100644 --- a/src/store/keep-services/keep-services-actions.ts +++ b/src/store/keep-services/keep-services-actions.ts @@@ -1,0 -1,71 +1,71 @@@ + // Copyright (C) The Arvados Authors. All rights reserved. + // + // SPDX-License-Identifier: AGPL-3.0 + + import { Dispatch } from "redux"; + import { unionize, ofType, UnionOf } from "~/common/unionize"; + import { RootState } from '~/store/store'; + import { setBreadcrumbs } from '~/store/breadcrumbs/breadcrumbs-actions'; + import { ServiceRepository } from "~/services/services"; + import { KeepServiceResource } from '~/models/keep-services'; + import { dialogActions } from '~/store/dialog/dialog-actions'; + import { snackbarActions } from '~/store/snackbar/snackbar-actions'; + import { navigateToRootProject } from '~/store/navigation/navigation-action'; + + export const keepServicesActions = unionize({ + SET_KEEP_SERVICES: ofType(), + REMOVE_KEEP_SERVICE: ofType() + }); + + export type KeepServicesActions = UnionOf; + + export const KEEP_SERVICE_REMOVE_DIALOG = 'keepServiceRemoveDialog'; + export const KEEP_SERVICE_ATTRIBUTES_DIALOG = 'keepServiceAttributesDialog'; + + export const loadKeepServicesPanel = () => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const user = getState().auth.user; + if(user && user.isAdmin) { + try { + dispatch(setBreadcrumbs([{ label: 'Keep Services' }])); + const response = await services.keepService.list(); + dispatch(keepServicesActions.SET_KEEP_SERVICES(response.items)); + } catch (e) { + return; + } + } else { + dispatch(navigateToRootProject); + dispatch(snackbarActions.OPEN_SNACKBAR({ message: "You don't have permissions to view this page", hideDuration: 2000 })); + } + }; + -export const openKeepServiceAttributesDialog = (index: number) => ++export const openKeepServiceAttributesDialog = (uuid: string) => + (dispatch: Dispatch, getState: () => RootState) => { - const keepService = getState().keepServices[index]; ++ const keepService = getState().keepServices.find(it => it.uuid === uuid); + dispatch(dialogActions.OPEN_DIALOG({ id: KEEP_SERVICE_ATTRIBUTES_DIALOG, data: { keepService } })); + }; + + export const openKeepServiceRemoveDialog = (uuid: string) => + (dispatch: Dispatch, getState: () => RootState) => { + dispatch(dialogActions.OPEN_DIALOG({ + id: KEEP_SERVICE_REMOVE_DIALOG, + data: { + title: 'Remove keep service', + text: 'Are you sure you want to remove this keep service?', + confirmButtonLabel: 'Remove', + uuid + } + })); + }; + + export const removeKeepService = (uuid: string) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removing ...' })); + try { + await services.keepService.delete(uuid); + dispatch(keepServicesActions.REMOVE_KEEP_SERVICE(uuid)); + dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Keep service has been successfully removed.', hideDuration: 2000 })); + } catch (e) { + return; + } + }; diff --cc src/views-components/context-menu/action-sets/keep-service-action-set.ts index 00000000,5d27e4e9..807a3abf mode 000000,100644..100644 --- a/src/views-components/context-menu/action-sets/keep-service-action-set.ts +++ b/src/views-components/context-menu/action-sets/keep-service-action-set.ts @@@ -1,0 -1,28 +1,28 @@@ + // Copyright (C) The Arvados Authors. All rights reserved. + // + // SPDX-License-Identifier: AGPL-3.0 + + import { openKeepServiceAttributesDialog, openKeepServiceRemoveDialog } from '~/store/keep-services/keep-services-actions'; + import { openAdvancedTabDialog } from '~/store/advanced-tab/advanced-tab'; + import { ContextMenuActionSet } from "~/views-components/context-menu/context-menu-action-set"; + import { AdvancedIcon, RemoveIcon, AttributesIcon } from "~/components/icon/icon"; + + export const keepServiceActionSet: ContextMenuActionSet = [[{ + name: "Attributes", + icon: AttributesIcon, - execute: (dispatch, { index }) => { - dispatch(openKeepServiceAttributesDialog(index!)); ++ execute: (dispatch, { uuid }) => { ++ dispatch(openKeepServiceAttributesDialog(uuid)); + } + }, { + name: "Advanced", + icon: AdvancedIcon, - execute: (dispatch, { uuid, index }) => { - dispatch(openAdvancedTabDialog(uuid, index)); ++ execute: (dispatch, { uuid }) => { ++ dispatch(openAdvancedTabDialog(uuid)); + } + }, { + name: "Remove", + icon: RemoveIcon, + execute: (dispatch, { uuid }) => { + dispatch(openKeepServiceRemoveDialog(uuid)); + } + }]]; diff --cc src/views-components/context-menu/context-menu.tsx index d08798f7,211881ca..5f321bfe --- a/src/views-components/context-menu/context-menu.tsx +++ b/src/views-components/context-menu/context-menu.tsx @@@ -71,5 -71,5 +71,6 @@@ export enum ContextMenuKind PROCESS_LOGS = "ProcessLogs", REPOSITORY = "Repository", SSH_KEY = "SshKey", - VIRTUAL_MACHINE = "VirtualMachine" ++ VIRTUAL_MACHINE = "VirtualMachine", + KEEP_SERVICE = "KeepService" } diff --cc src/views/keep-service-panel/keep-service-panel-root.tsx index 00000000,57193d35..8c266b61 mode 000000,100644..100644 --- a/src/views/keep-service-panel/keep-service-panel-root.tsx +++ b/src/views/keep-service-panel/keep-service-panel-root.tsx @@@ -1,0 -1,87 +1,87 @@@ + // Copyright (C) The Arvados Authors. All rights reserved. + // + // SPDX-License-Identifier: AGPL-3.0 + + import * as React from 'react'; + import { StyleRulesCallback, WithStyles, withStyles, Card, CardContent, Button, Typography, Grid, Table, TableHead, TableRow, TableCell, TableBody, Tooltip, IconButton, Checkbox } from '@material-ui/core'; + import { ArvadosTheme } from '~/common/custom-theme'; + import { MoreOptionsIcon } from '~/components/icon/icon'; + import { KeepServiceResource } from '~/models/keep-services'; + + type CssRules = 'root' | 'tableRow'; + + const styles: StyleRulesCallback = (theme: ArvadosTheme) => ({ + root: { + width: '100%', + overflow: 'auto' + }, + tableRow: { + '& td, th': { + whiteSpace: 'nowrap' + } + } + }); + + export interface KeepServicePanelRootActionProps { - openRowOptions: (event: React.MouseEvent, index: number, keepService: KeepServiceResource) => void; ++ openRowOptions: (event: React.MouseEvent, keepService: KeepServiceResource) => void; + } + + export interface KeepServicePanelRootDataProps { + keepServices: KeepServiceResource[]; + hasKeepSerices: boolean; + } + + type KeepServicePanelRootProps = KeepServicePanelRootActionProps & KeepServicePanelRootDataProps & WithStyles; + + export const KeepServicePanelRoot = withStyles(styles)( + ({ classes, hasKeepSerices, keepServices, openRowOptions }: KeepServicePanelRootProps) => + + + {hasKeepSerices && + + + + + UUID + Read only + Service host + Service port + Service SSL flag + Service type + + + + + {keepServices.map((keepService, index) => + + {keepService.uuid} + + + + {keepService.serviceHost} + {keepService.servicePort} + + + + {keepService.serviceType} + + - openRowOptions(event, index, keepService)}> ++ openRowOptions(event, keepService)}> + + + + + )} + +
+
+
} +
+
+ ); diff --cc src/views/keep-service-panel/keep-service-panel.tsx index 00000000,2c6323b0..a11cee0b mode 000000,100644..100644 --- a/src/views/keep-service-panel/keep-service-panel.tsx +++ b/src/views/keep-service-panel/keep-service-panel.tsx @@@ -1,0 -1,29 +1,29 @@@ + // Copyright (C) The Arvados Authors. All rights reserved. + // + // SPDX-License-Identifier: AGPL-3.0 + + import { RootState } from '~/store/store'; + import { Dispatch } from 'redux'; + import { connect } from 'react-redux'; + import { } from '~/store/keep-services/keep-services-actions'; + import { + KeepServicePanelRoot, + KeepServicePanelRootDataProps, + KeepServicePanelRootActionProps + } from '~/views/keep-service-panel/keep-service-panel-root'; + import { openKeepServiceContextMenu } from '~/store/context-menu/context-menu-actions'; + + const mapStateToProps = (state: RootState): KeepServicePanelRootDataProps => { + return { + keepServices: state.keepServices, + hasKeepSerices: state.keepServices.length > 0 + }; + }; + + const mapDispatchToProps = (dispatch: Dispatch): KeepServicePanelRootActionProps => ({ - openRowOptions: (event, index, keepService) => { - dispatch(openKeepServiceContextMenu(event, index, keepService)); ++ openRowOptions: (event, keepService) => { ++ dispatch(openKeepServiceContextMenu(event, keepService)); + } + }); + + export const KeepServicePanel = connect(mapStateToProps, mapDispatchToProps)(KeepServicePanelRoot); diff --cc src/views/workbench/workbench.tsx index 3fc514af,dd4f802c..2d17fad9 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@@ -57,10 -58,10 +58,12 @@@ import { CreateRepositoryDialog } from import { RemoveRepositoryDialog } from '~/views-components/repository-remove-dialog/repository-remove-dialog'; import { CreateSshKeyDialog } from '~/views-components/dialog-forms/create-ssh-key-dialog'; import { PublicKeyDialog } from '~/views-components/ssh-keys-dialog/public-key-dialog'; + import { RemoveKeepServiceDialog } from '~/views-components/keep-services-dialog/remove-dialog'; import { RemoveSshKeyDialog } from '~/views-components/ssh-keys-dialog/remove-dialog'; + import { AttributesKeepServiceDialog } from '~/views-components/keep-services-dialog/attributes-dialog'; import { AttributesSshKeyDialog } from '~/views-components/ssh-keys-dialog/attributes-dialog'; +import { VirtualMachineAttributesDialog } from '~/views-components/virtual-machines-dialog/attributes-dialog'; +import { RemoveVirtualMachineDialog } from '~/views-components/virtual-machines-dialog/remove-dialog'; type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';