Merge branch 'master' into 14100-process-logs-service
authorMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Mon, 3 Sep 2018 08:35:28 +0000 (10:35 +0200)
committerMichal Klobukowski <michal.klobukowski@contractors.roche.com>
Mon, 3 Sep 2018 08:35:28 +0000 (10:35 +0200)
refs #14100

Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski@contractors.roche.com>

16 files changed:
src/components/code-snippet/code-snippet.tsx [new file with mode: 0644]
src/components/default-code-snippet/default-code-snippet.tsx [new file with mode: 0644]
src/components/icon/icon.tsx
src/index.css
src/routes/routes.ts
src/store/context-menu/context-menu-actions.ts
src/store/navigation/navigation-action.ts
src/store/workbench/workbench-actions.ts
src/views-components/context-menu/action-sets/process-action-set.ts
src/views-components/context-menu/context-menu.tsx
src/views/process-log-panel/process-log-code-snippet.tsx [new file with mode: 0644]
src/views/process-log-panel/process-log-form.tsx [new file with mode: 0644]
src/views/process-log-panel/process-log-main-card.tsx [new file with mode: 0644]
src/views/process-log-panel/process-log-panel-root.tsx [new file with mode: 0644]
src/views/process-log-panel/process-log-panel.tsx [new file with mode: 0644]
src/views/workbench/workbench.tsx

diff --git a/src/components/code-snippet/code-snippet.tsx b/src/components/code-snippet/code-snippet.tsx
new file mode 100644 (file)
index 0000000..dda607c
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { StyleRulesCallback, WithStyles, Typography, withStyles, Theme } from '@material-ui/core';
+import { ArvadosTheme } from '~/common/custom-theme';
+
+type CssRules = 'root';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    root: {
+        boxSizing: 'border-box',
+        width: '100%',
+        height: 'auto',
+        maxHeight: '550px',
+        overflow: 'scroll',
+        padding: theme.spacing.unit
+    }
+});
+
+export interface CodeSnippetDataProps {
+    lines: string[];
+}
+
+type CodeSnippetProps = CodeSnippetDataProps & WithStyles<CssRules>;
+
+export const CodeSnippet = withStyles(styles)(
+    ({ classes, lines }: CodeSnippetProps) =>
+        <Typography component="div" className={classes.root}>
+            {
+                lines.map((line: string, index: number) => {
+                    return <Typography key={index} component="div">{line}</Typography>;
+                })
+            }
+        </Typography>
+    );
\ No newline at end of file
diff --git a/src/components/default-code-snippet/default-code-snippet.tsx b/src/components/default-code-snippet/default-code-snippet.tsx
new file mode 100644 (file)
index 0000000..541f390
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
+import { CodeSnippet, CodeSnippetDataProps } from '~/components/code-snippet/code-snippet';
+import grey from '@material-ui/core/colors/grey';
+
+const theme = createMuiTheme({
+    overrides: {
+        MuiTypography: {
+            body1: {
+                color: grey["900"]
+            },
+            root: {
+                backgroundColor: grey["200"]
+            }
+        }
+    },
+    typography: {
+        fontFamily: 'VT323'
+    }
+});
+
+type DefaultCodeSnippet = CodeSnippetDataProps;
+
+export const DefaultCodeSnippet = (props: DefaultCodeSnippet) => 
+    <MuiThemeProvider theme={theme}>
+        <CodeSnippet lines={props.lines} />
+    </MuiThemeProvider>;
\ No newline at end of file
index 0f0442a53ebd1b7be4b485694b45e86e3a99be7a..8bd9e22772c42ea593767f8614882ccac96fe9da 100644 (file)
@@ -4,6 +4,7 @@
 
 import * as React from 'react';
 import AccessTime from '@material-ui/icons/AccessTime';
+import ArrowBack from '@material-ui/icons/ArrowBack';
 import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
 import BubbleChart from '@material-ui/icons/BubbleChart';
 import Cached from '@material-ui/icons/Cached';
@@ -41,6 +42,7 @@ export type IconType = React.SFC<{ className?: string }>;
 
 export const AddFavoriteIcon: IconType = (props) => <StarBorder {...props} />;
 export const AdvancedIcon: IconType = (props) => <SettingsApplications {...props} />;
+export const BackIcon: IconType = (props) => <ArrowBack {...props} />;
 export const CustomizeTableIcon: IconType = (props) => <Menu {...props} />;
 export const CopyIcon: IconType = (props) => <ContentCopy {...props} />;
 export const CollectionIcon: IconType = (props) => <LibraryBooks {...props} />;
index abbd2b21270f17a5b5948580a96ae78e5b6ecb4a..0172d68bcc5c9385ebdbf29d7a06a7022ef08c96 100644 (file)
@@ -1,7 +1,7 @@
 body {
     margin: 0;
     padding: 0;
-    font-family: sans-serif;
+    font-family: 'Roboto', "Helvetica", "Arial", sans-serif;
     width: 100vw;
     height: 100vh;
 }
index 20dd1359b34b626f66ab3b0de959e85a2c28b38f..6901d8755588acb9d5f1600f30cca934ca05566c 100644 (file)
@@ -8,7 +8,7 @@ import { matchPath } from 'react-router';
 import { ResourceKind, RESOURCE_UUID_PATTERN, extractUuidKind } from '~/models/resource';
 import { getProjectUrl } from '../models/project';
 import { getCollectionUrl } from '~/models/collection';
-import { loadProject, loadFavorites, loadCollection } from '~/store/workbench/workbench-actions';
+import { loadProject, loadFavorites, loadCollection, loadProcessLog } from '~/store/workbench/workbench-actions';
 import { loadProcess } from '~/store/processes/processes-actions';
 
 export const Routes = {
@@ -18,6 +18,7 @@ export const Routes = {
     COLLECTIONS: `/collections/:id(${RESOURCE_UUID_PATTERN})`,
     PROCESSES: `/processes/:id(${RESOURCE_UUID_PATTERN})`,
     FAVORITES: '/favorites',
+    PROCESS_LOGS: `/process-logs/:id(${RESOURCE_UUID_PATTERN})`
 };
 
 export const getResourceUrl = (uuid: string) => {
@@ -34,6 +35,8 @@ export const getResourceUrl = (uuid: string) => {
 
 export const getProcessUrl = (uuid: string) => `/processes/${uuid}`;
 
+export const getProcessLogUrl = (uuid: string) => `/process-logs/${uuid}`;
+
 export const addRouteChangeHandlers = (history: History, store: RootStore) => {
     const handler = handleLocationChange(store);
     handler(history.location);
@@ -59,12 +62,16 @@ export const matchCollectionRoute = (route: string) =>
 export const matchProcessRoute = (route: string) =>
     matchPath<ResourceRouteParams>(route, { path: Routes.PROCESSES });
 
+export const matchProcessLogRoute = (route: string) =>
+    matchPath<ResourceRouteParams>(route, { path: Routes.PROCESS_LOGS });
 
 const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
     const projectMatch = matchProjectRoute(pathname);
     const collectionMatch = matchCollectionRoute(pathname);
     const favoriteMatch = matchFavoritesRoute(pathname);
     const processMatch = matchProcessRoute(pathname);
+    const processLogMatch = matchProcessLogRoute(pathname);
+    
     if (projectMatch) {
         store.dispatch(loadProject(projectMatch.params.id));
     } else if (collectionMatch) {
@@ -73,5 +80,7 @@ const handleLocationChange = (store: RootStore) => ({ pathname }: Location) => {
         store.dispatch(loadFavorites());
     } else if (processMatch) {
         store.dispatch(loadProcess(processMatch.params.id));
+    } else if (processLogMatch) {
+        store.dispatch(loadProcessLog(processLogMatch.params.id));
     }
 };
index cf66a53d2361587823219d3d698cfa2572fd07d5..3440a3053dad930dd1db230e0b52e9100e690935 100644 (file)
@@ -12,6 +12,7 @@ import { ProjectResource } from '~/models/project';
 import { UserResource } from '../../models/user';
 import { isSidePanelTreeCategory } from '~/store/side-panel-tree/side-panel-tree-actions';
 import { extractUuidKind, ResourceKind } from '~/models/resource';
+import { matchProcessRoute } from '~/routes/routes';
 
 export const contextMenuActions = unionize({
     OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(),
@@ -69,8 +70,15 @@ export const openSidePanelContextMenu = (event: React.MouseEvent<HTMLElement>, i
 
 export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>) =>
     (dispatch: Dispatch, getState: () => RootState) => {
+        const { location } = getState().router;
+        const pathname = location ? location.pathname : '';
+        // ToDo: We get error from matchProcessRoute
+        // const match = matchProcessRoute(pathname); 
+        // console.log('match: ', match);
+        // const uuid = match ? match.params.id : '';
+        const uuid = pathname.split('/').slice(-1)[0];
         const resource = {
-            uuid: '',
+            uuid,
             name: '',
             description: '',
             kind: ContextMenuKind.PROCESS
index 188acf12bd30afc55b838f6d31f279822e0b6628..6298e2511c48d12a77e549e70cc79135a3f24510 100644 (file)
@@ -9,7 +9,7 @@ import { getCollectionUrl } from "~/models/collection";
 import { getProjectUrl } from "~/models/project";
 
 import { SidePanelTreeCategory } from '../side-panel-tree/side-panel-tree-actions';
-import { Routes, getProcessUrl } from '~/routes/routes';
+import { Routes, getProcessUrl, getProcessLogUrl } from '~/routes/routes';
 
 export const navigateTo = (uuid: string) =>
     async (dispatch: Dispatch) => {
@@ -20,7 +20,7 @@ export const navigateTo = (uuid: string) =>
             dispatch<any>(navigateToCollection(uuid));
         } else if (kind === ResourceKind.CONTAINER_REQUEST) {
             dispatch<any>(navigateToProcess(uuid));
-        }
+        } 
         if (uuid === SidePanelTreeCategory.FAVORITES) {
             dispatch<any>(navigateToFavorites);
         }
@@ -33,3 +33,5 @@ export const navigateToProject = compose(push, getProjectUrl);
 export const navigateToCollection = compose(push, getCollectionUrl);
 
 export const navigateToProcess = compose(push, getProcessUrl);
+
+export const navigateToProcessLogs = compose(push, getProcessLogUrl);
\ No newline at end of file
index 3c68c0004519b15a73fca9a9c5553b316e3a68e5..97fe549a639b23e23ffbcad389869d8e4a75bfcf 100644 (file)
@@ -185,6 +185,12 @@ export const loadProcess = (uuid: string) =>
         }
     };
 
+export const loadProcessLog = (uuid: string) =>
+    async (dispatch: Dispatch, getState: () => RootState) => {
+        dispatch<any>(loadProcess(uuid));
+        // ToDo: loadLog();
+    };
+
 export const resourceIsNotLoaded = (uuid: string) =>
     snackbarActions.OPEN_SNACKBAR({
         message: `Resource identified by ${uuid} is not loaded.`
index 5d679f52b04e4e89d845acfe61ecbda504c4dea6..cc4f8e8fd8732eeb7884b12acccf240dcd387499 100644 (file)
@@ -10,6 +10,7 @@ import {
     AdvancedIcon, RemoveIcon, ReRunProcessIcon, LogIcon
 } from "~/components/icon/icon";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
+import { navigateToProcessLogs } from '~/store/navigation/navigation-action';
 
 export const processActionSet: ContextMenuActionSet = [[
     {
@@ -84,7 +85,7 @@ export const processActionSet: ContextMenuActionSet = [[
         icon: LogIcon,
         name: "Log",
         execute: (dispatch, resource) => {
-            // add code
+            dispatch<any>(navigateToProcessLogs(resource.uuid));
         }
     },
     {
index 5d94766c447674170560e45b5392993ef505a977..d92948c84ae27db97540147cee89de4c59e3ba6e 100644 (file)
@@ -64,5 +64,6 @@ export enum ContextMenuKind {
     COLLECTION_FILES_ITEM = "CollectionFilesItem",
     COLLECTION = 'Collection',
     COLLECTION_RESOURCE = 'CollectionResource',
-    PROCESS = "Process"
+    PROCESS = "Process",
+    PROCESS_LOGS = "ProcessLogs"
 }
diff --git a/src/views/process-log-panel/process-log-code-snippet.tsx b/src/views/process-log-panel/process-log-code-snippet.tsx
new file mode 100644 (file)
index 0000000..99388d6
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
+import { CodeSnippet, CodeSnippetDataProps } from '~/components/code-snippet/code-snippet';
+import grey from '@material-ui/core/colors/grey';
+
+const theme = createMuiTheme({
+    overrides: {
+        MuiTypography: {
+            body1: {
+                color: grey["200"]
+            },
+            root: {
+                backgroundColor: '#000'
+            }
+        }
+    },
+    typography: {
+        fontFamily: 'VT323'
+    }
+});
+
+type ProcessLogCodeSnippet = CodeSnippetDataProps;
+
+export const ProcessLogCodeSnippet = (props: ProcessLogCodeSnippet) => 
+    <MuiThemeProvider theme={theme}>
+        <CodeSnippet lines={props.lines} />
+    </MuiThemeProvider>;
\ No newline at end of file
diff --git a/src/views/process-log-panel/process-log-form.tsx b/src/views/process-log-panel/process-log-form.tsx
new file mode 100644 (file)
index 0000000..dfac832
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { withStyles, WithStyles, StyleRulesCallback, FormControl, InputLabel, Select, MenuItem, Input } from '@material-ui/core';
+import { ArvadosTheme } from '~/common/custom-theme';
+import { FilterOption } from './process-log-panel';
+
+type CssRules = 'formControl';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    formControl: {
+        minWidth: 200
+    }
+});
+
+export interface ProcessLogFormDataProps {
+    selectedFilter: FilterOption;
+    filters: FilterOption[];
+}
+
+export interface ProcessLogFormActionProps {
+    onChange: (filter: FilterOption) => void;
+}
+
+type ProcessLogFormProps = ProcessLogFormDataProps & ProcessLogFormActionProps & WithStyles<CssRules>;
+
+export const ProcessLogForm = withStyles(styles)(
+    ({ classes, selectedFilter, onChange, filters }: ProcessLogFormProps) =>
+        <form autoComplete="off">
+            <FormControl className={classes.formControl}>
+                <InputLabel shrink htmlFor="log-label-placeholder">
+                    Log
+                </InputLabel>
+                <Select
+                    value={selectedFilter.value}
+                    onChange={event => onChange}
+                    input={<Input name="eventType" id="log-label-placeholder" />}
+                    name="eventType">
+                    {
+                        filters.map(option =>
+                            <MenuItem key={option.value} value={option.value}>{option.label}</MenuItem>
+                        )
+                    }
+                </Select>
+            </FormControl>
+        </form>
+);
\ No newline at end of file
diff --git a/src/views/process-log-panel/process-log-main-card.tsx b/src/views/process-log-panel/process-log-main-card.tsx
new file mode 100644 (file)
index 0000000..09aaf08
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { Link } from 'react-router-dom';
+import {
+    StyleRulesCallback, WithStyles, withStyles, Card,
+    CardHeader, IconButton, CardContent, Grid, Typography, Tooltip
+} from '@material-ui/core';
+import { Process } from '~/store/processes/process';
+import { ProcessLogCodeSnippet } from '~/views/process-log-panel/process-log-code-snippet';
+import { ProcessLogForm, ProcessLogFormDataProps, ProcessLogFormActionProps } from '~/views/process-log-panel/process-log-form';
+import { MoreOptionsIcon, ProcessIcon } from '~/components/icon/icon';
+import { ArvadosTheme } from '~/common/custom-theme';
+import { CodeSnippetDataProps } from '~/components/code-snippet/code-snippet';
+import { BackIcon } from '~/components/icon/icon';
+
+type CssRules = 'backLink' | 'backIcon' | 'card' | 'title' | 'iconHeader' | 'link';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    backLink: {
+        fontSize: '1rem',
+        fontWeight: 600,
+        display: 'flex',
+        alignItems: 'center',
+        textDecoration: 'none',
+        padding: theme.spacing.unit,
+        color: theme.palette.grey["700"],
+    },
+    backIcon: {
+        marginRight: theme.spacing.unit
+    },
+    card: {
+        width: '100%'
+    },
+    title: {
+        color: theme.palette.grey["700"]
+    },
+    iconHeader: {
+        fontSize: '1.875rem',
+        color: theme.customs.colors.green700
+    },
+    link: {
+        alignSelf: 'flex-end',
+        textAlign: 'right'
+    }
+});
+
+
+interface ProcessLogMainCardDataProps {
+    process: Process;
+}
+
+export type ProcessLogMainCardProps = ProcessLogMainCardDataProps & CodeSnippetDataProps & ProcessLogFormDataProps & ProcessLogFormActionProps;
+
+export const ProcessLogMainCard = withStyles(styles)(
+    ({ classes, process, selectedFilter, filters, onChange, lines }: ProcessLogMainCardProps & WithStyles<CssRules>) => 
+        <Grid item xs={12}>
+            <Link to={`/processes/${process.containerRequest.uuid}`} className={classes.backLink}>
+                <BackIcon className={classes.backIcon}/> Back
+            </Link>
+            <Card className={classes.card}>
+                <CardHeader
+                    avatar={<ProcessIcon className={classes.iconHeader} />}
+                    action={
+                        <div>
+                            <IconButton aria-label="More options">
+                                <MoreOptionsIcon />
+                            </IconButton>
+                        </div>
+                    }
+                    title={
+                        <Tooltip title={process.containerRequest.name}>
+                            <Typography noWrap variant="title" className={classes.title}>
+                                {process.containerRequest.name}
+                            </Typography>
+                        </Tooltip>
+                    }
+                    subheader={process.containerRequest.description} />
+                <CardContent>
+                    <Grid container spacing={24} alignItems='center'>
+                        <Grid item xs={6}>
+                            <ProcessLogForm selectedFilter={selectedFilter} filters={filters} onChange={onChange} />
+                        </Grid>
+                        <Grid item xs={6} className={classes.link}>
+                            <Typography component='div'>
+                                Container log for request {process.containerRequest.uuid}
+                            </Typography>
+                        </Grid>
+                        <Grid item xs={12}>
+                            <ProcessLogCodeSnippet lines={lines}/>
+                        </Grid>
+                    </Grid>
+                </CardContent>
+            </Card>
+        </Grid>
+);
\ No newline at end of file
diff --git a/src/views/process-log-panel/process-log-panel-root.tsx b/src/views/process-log-panel/process-log-panel-root.tsx
new file mode 100644 (file)
index 0000000..0845a41
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { Grid } from '@material-ui/core';
+import { Process } from '~/store/processes/process';
+import { ProcessLogMainCard } from '~/views/process-log-panel/process-log-main-card';
+import { ProcessLogFormDataProps, ProcessLogFormActionProps } from '~/views/process-log-panel/process-log-form';
+import { DefaultView } from '~/components/default-view/default-view';
+import { ProcessIcon } from '~/components/icon/icon';
+import { CodeSnippetDataProps } from '~/components/code-snippet/code-snippet';
+
+export type ProcessLogPanelRootDataProps = {
+    process?: Process;
+} & ProcessLogFormDataProps & CodeSnippetDataProps;
+
+export type ProcessLogPanelRootActionProps = {
+    onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
+} & ProcessLogFormActionProps;
+
+export type ProcessLogPanelRootProps = ProcessLogPanelRootDataProps & ProcessLogPanelRootActionProps;
+
+export const ProcessLogPanelRoot = (props: ProcessLogPanelRootProps) =>
+    props.process
+        ? <Grid container spacing={16}>
+            <ProcessLogMainCard 
+                process={props.process} 
+                {...props} />
+        </Grid> 
+        : <Grid container
+            alignItems='center'
+            justify='center'>
+            <DefaultView
+                icon={ProcessIcon}
+                messages={['Process Log not found']} />
+        </Grid>;
diff --git a/src/views/process-log-panel/process-log-panel.tsx b/src/views/process-log-panel/process-log-panel.tsx
new file mode 100644 (file)
index 0000000..0936d3b
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import * as React from 'react';
+import { RootState } from '~/store/store';
+import { connect } from 'react-redux';
+import { getProcess } from '~/store/processes/process';
+import { Dispatch } from 'redux';
+import { openProcessContextMenu } from '~/store/context-menu/context-menu-actions';
+import { matchProcessLogRoute } from '~/routes/routes';
+import { ProcessLogPanelRootDataProps, ProcessLogPanelRootActionProps, ProcessLogPanelRoot } from './process-log-panel-root';
+
+const SELECT_OPTIONS = [
+    { label: 'Dispatch', value: 'dispatch' },
+    { label: 'Crunch-run', value: 'crunch-run' },
+    { label: 'Crunchstat', value: 'crunchstat' },
+    { label: 'Hoststat', value: 'hoststat' },
+    { label: 'Node-info', value: 'node-info' },
+    { label: 'Arv-mount', value: 'arv-mount' },
+    { label: 'Stdout', value: 'stdout' },
+    { label: 'Stderr', value: 'stderr' }
+];
+
+const lines = ['Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum', 'Lorem Ipsum'];
+
+export interface Log {
+    object_uuid: string;
+    event_at: string;
+    event_type: string;
+    summary: string;
+    properties: any;
+}
+
+export interface FilterOption {
+    label: string;
+    value: string;
+}
+
+const mapStateToProps = ({ router, resources }: RootState): ProcessLogPanelRootDataProps => {
+    const pathname = router.location ? router.location.pathname : '';
+    const match = matchProcessLogRoute(pathname);
+    const uuid = match ? match.params.id : '';
+    return {
+        process: getProcess(uuid)(resources),
+        selectedFilter: SELECT_OPTIONS[0],
+        filters: SELECT_OPTIONS,
+        lines
+    };
+};
+
+const mapDispatchToProps = (dispatch: Dispatch): ProcessLogPanelRootActionProps => ({
+    onContextMenu: (event: React.MouseEvent<HTMLElement>) => {
+        dispatch<any>(openProcessContextMenu(event));
+    },
+    onChange: (filter: FilterOption) => { return; }
+});
+
+export const ProcessLogPanel = connect(mapStateToProps, mapDispatchToProps)(ProcessLogPanelRoot);
index ef5fe215290e4e33dfac8988840d0cb4740ed83d..21396d1d491306106bbe7210709ccd43ab69f2ef 100644 (file)
@@ -27,6 +27,7 @@ import { MultipleFilesRemoveDialog } from '~/views-components/file-remove-dialog
 import { Routes } from '~/routes/routes';
 import { SidePanel } from '~/views-components/side-panel/side-panel';
 import { ProcessPanel } from '~/views/process-panel/process-panel';
+import { ProcessLogPanel } from '~/views/process-log-panel/process-log-panel';
 import { Breadcrumbs } from '~/views-components/breadcrumbs/breadcrumbs';
 import { CreateProjectDialog } from '~/views-components/dialog-forms/create-project-dialog';
 import { CreateCollectionDialog } from '~/views-components/dialog-forms/create-collection-dialog';
@@ -35,7 +36,6 @@ import { UpdateCollectionDialog } from '~/views-components/dialog-forms/update-c
 import { UpdateProjectDialog } from '~/views-components/dialog-forms/update-project-dialog';
 import { MoveProjectDialog } from '~/views-components/dialog-forms/move-project-dialog';
 import { MoveCollectionDialog } from '~/views-components/dialog-forms/move-collection-dialog';
-
 import { FilesUploadCollectionDialog } from '~/views-components/dialog-forms/files-upload-collection-dialog';
 import { PartialCopyCollectionDialog } from '~/views-components/dialog-forms/partial-copy-collection-dialog';
 
@@ -167,6 +167,7 @@ export const Workbench = withStyles(styles)(
                                     <Route path={Routes.COLLECTIONS} component={CollectionPanel} />
                                     <Route path={Routes.FAVORITES} component={FavoritePanel} />
                                     <Route path={Routes.PROCESSES} component={ProcessPanel} />
+                                    <Route path={Routes.PROCESS_LOGS} component={ProcessLogPanel} />
                                 </Switch>
                             </div>
                             {user && <DetailsPanel />}