import { SearchInput } from '../search-input/search-input';
import { ArvadosTheme } from "~/common/custom-theme";
-type CssRules = 'searchBox' | "toolbar" | "root";
+type CssRules = 'searchBox' | "toolbar" | "footer" | "root";
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
searchBox: {
toolbar: {
paddingTop: theme.spacing.unit * 2
},
+ footer: {
+ overflow: 'auto'
+ },
root: {
height: '100%'
}
working={working}
defaultView={dataTableDefaultView}
/>
- <Toolbar>
+ <Toolbar className={classes.footer}>
<Grid container justify="flex-end">
<TablePagination
count={itemsAvailable}
// SPDX-License-Identifier: AGPL-3.0
import * as React from 'react';
-import { IconButton, Paper, StyleRulesCallback, withStyles, WithStyles, Tooltip } from '@material-ui/core';
+import {
+ IconButton,
+ Paper,
+ StyleRulesCallback,
+ withStyles,
+ WithStyles,
+ Tooltip,
+ InputAdornment, Input
+} from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
-type CssRules = 'container' | 'input' | 'button';
+type CssRules = 'container' | 'input';
const styles: StyleRulesCallback<CssRules> = theme => {
return {
input: {
border: 'none',
borderRadius: theme.spacing.unit / 4,
- boxSizing: 'border-box',
- padding: theme.spacing.unit,
- paddingRight: theme.spacing.unit * 4,
- width: '100%',
- },
- button: {
- position: 'absolute',
- top: theme.spacing.unit / 2,
- right: theme.spacing.unit / 2,
- width: theme.spacing.unit * 3,
- height: theme.spacing.unit * 3
+ padding: `${theme.spacing.unit / 2}px ${theme.spacing.unit}px`
}
};
};
const { classes } = this.props;
return <Paper className={classes.container}>
<form onSubmit={this.handleSubmit}>
- <input
+ <Input
className={classes.input}
onChange={this.handleChange}
placeholder="Search"
value={this.state.value}
- />
- <Tooltip title='Search'>
- <IconButton className={classes.button}>
- <SearchIcon />
- </IconButton>
- </Tooltip>
+ fullWidth={true}
+ disableUnderline={true}
+ endAdornment={
+ <InputAdornment position="end">
+ <Tooltip title='Search'>
+ <IconButton>
+ <SearchIcon />
+ </IconButton>
+ </Tooltip>
+ </InputAdornment>
+ }/>
</form>
</Paper>;
}
import { unionize, ofType, UnionOf } from '~/common/unionize';
export const collectionPanelActions = unionize({
+ SET_COLLECTION: ofType<CollectionResource>(),
LOAD_COLLECTION: ofType<{ uuid: string }>(),
LOAD_COLLECTION_SUCCESS: ofType<{ item: CollectionResource }>()
});
return collection;
};
-export const createCollectionTag = (data: TagProperty) =>
+export const createCollectionTag = (data: TagProperty) =>
async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
const item = getState().collectionPanel.item;
const uuid = item ? item.uuid : '';
export const collectionPanelReducer = (state: CollectionPanelState = initialState, action: CollectionPanelAction) =>
collectionPanelActions.match(action, {
default: () => state,
+ SET_COLLECTION: (item) => ({ ...state, item }),
LOAD_COLLECTION_SUCCESS: ({ item }) => ({ ...state, item }),
});
SET_CURRENT_STEP: ofType<number>(),
SET_WORKFLOWS: ofType<WorkflowResource[]>(),
SET_SELECTED_WORKFLOW: ofType<WorkflowResource>(),
+ SEARCH_WORKFLOWS: ofType<string>()
});
export interface RunProcessSecondStepDataFormProps {
Object.keys(inputs).reduce((normalizedInputs, key) => ({
...normalizedInputs,
[key.split('/').slice(1).join('/')]: inputs[key],
- }), {});
\ No newline at end of file
+ }), {});
+export const searchWorkflows = (term: string) => runProcessPanelActions.SEARCH_WORKFLOWS(term);
processOwnerUuid: string;
currentStep: number;
workflows: WorkflowResource[];
+ searchWorkflows: WorkflowResource[];
selectedWorkflow: WorkflowResource | undefined;
inputs: CommandInputParameter[];
}
workflows: [],
selectedWorkflow: undefined,
inputs: [],
+ searchWorkflows: [],
};
export const runProcessPanelReducer = (state = initialState, action: RunProcessPanelAction): RunProcessPanel =>
runProcessPanelActions.match(action, {
SET_PROCESS_OWNER_UUID: processOwnerUuid => ({ ...state, processOwnerUuid }),
SET_CURRENT_STEP: currentStep => ({ ...state, currentStep }),
- SET_WORKFLOWS: workflows => ({ ...state, workflows }),
SET_SELECTED_WORKFLOW: selectedWorkflow => ({
...state,
selectedWorkflow,
inputs: getWorkflowInputs(parseWorkflowDefinition(selectedWorkflow)) || [],
}),
+ SET_WORKFLOWS: workflows => ({ ...state, workflows, searchWorkflows: workflows }),
+ SEARCH_WORKFLOWS: term => ({ ...state, searchWorkflows: state.workflows.filter(workflow => workflow.name.includes(term)) }),
default: () => state
});
\ No newline at end of file
import { unionize, ofType, UnionOf, MatchCases } from '~/common/unionize';
import { loadRunProcessPanel } from '~/store/run-process-panel/run-process-panel-actions';
import { loadCollectionFiles } from '~/store/collection-panel/collection-panel-files/collection-panel-files-actions';
+import { collectionPanelActions } from "~/store/collection-panel/collection-panel-action";
+import { CollectionResource } from "~/models/collection";
export const WORKBENCH_LOADING_SCREEN = 'workbenchLoadingScreen';
const match = await loadGroupContentsResource({ uuid, userUuid, services });
match({
OWNED: async collection => {
+ dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
dispatch(updateResources([collection]));
await dispatch(activateSidePanelTreeItem(collection.ownerUuid));
dispatch(setSidePanelBreadcrumbs(collection.ownerUuid));
dispatch(loadCollectionFiles(collection.uuid));
},
SHARED: collection => {
+ dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
dispatch(updateResources([collection]));
dispatch<any>(setSharedWithMeBreadcrumbs(collection.ownerUuid));
dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.SHARED_WITH_ME));
dispatch(loadCollectionFiles(collection.uuid));
},
TRASHED: collection => {
+ dispatch(collectionPanelActions.SET_COLLECTION(collection as CollectionResource));
dispatch(updateResources([collection]));
dispatch(setTrashBreadcrumbs(''));
dispatch(activateSidePanelTreeItem(SidePanelTreeCategory.TRASH));
import { WorkflowResource } from '~/models/workflow';
import { WorkflowIcon } from '~/components/icon/icon';
import { WorkflowDetailsCard } from '../workflow-panel/workflow-description-card';
+import { SearchInput } from '~/components/search-input/search-input';
-type CssRules = 'rightGrid' | 'list' | 'listItem' | 'itemSelected' | 'listItemText' | 'listItemIcon';
+type CssRules = 'root' | 'searchGrid' | 'workflowDetailsGrid' | 'list' | 'listItem' | 'itemSelected' | 'listItemText' | 'listItemIcon';
const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
- rightGrid: {
+ root: {
+ alignSelf: 'flex-start'
+ },
+ searchGrid: {
+ marginBottom: theme.spacing.unit * 2
+ },
+ workflowDetailsGrid: {
borderLeft: `1px solid ${theme.palette.grey["300"]}`
},
list: {
}
export interface RunProcessFirstStepActionProps {
+ onSearch: (term: string) => void;
onSetStep: (step: number) => void;
onSetWorkflow: (workflow: WorkflowResource) => void;
}
type RunProcessFirstStepProps = RunProcessFirstStepDataProps & RunProcessFirstStepActionProps & WithStyles<CssRules>;
export const RunProcessFirstStep = withStyles(styles)(
- ({ onSetStep, onSetWorkflow, workflows, selectedWorkflow, classes }: RunProcessFirstStepProps) =>
+ ({ onSearch, onSetStep, onSetWorkflow, workflows, selectedWorkflow, classes }: RunProcessFirstStepProps) =>
<Grid container spacing={16}>
- <Grid container item xs={6}>
- <Grid item xs={12}>
- {/* TODO: add filters */}
+ <Grid container item xs={6} className={classes.root}>
+ <Grid item xs={12} className={classes.searchGrid}>
+ <SearchInput value='' onSearch={onSearch} />
</Grid>
<Grid item xs={12}>
<List className={classes.list}>
</List>
</Grid>
</Grid>
- <Grid item xs={6} className={classes.rightGrid}>
+ <Grid item xs={6} className={classes.workflowDetailsGrid}>
<WorkflowDetailsCard workflow={selectedWorkflow}/>
</Grid>
<Grid item xs={12}>
type RunProcessPanelRootProps = RunProcessPanelRootDataProps & RunProcessPanelRootActionProps;
-export const RunProcessPanelRoot = ({ runProcess, currentStep, onSetStep, onSetWorkflow, workflows, selectedWorkflow }: RunProcessPanelRootProps) =>
+export const RunProcessPanelRoot = ({ runProcess, currentStep, onSearch, onSetStep, onSetWorkflow, workflows, selectedWorkflow }: RunProcessPanelRootProps) =>
<Stepper activeStep={currentStep} orientation="vertical" elevation={2}>
<Step>
<StepLabel>Choose a workflow</StepLabel>
<RunProcessFirstStep
workflows={workflows}
selectedWorkflow={selectedWorkflow}
- onSetStep={onSetStep}
+ onSearch={onSearch}
+ onSetStep={onSetStep}
onSetWorkflow={onSetWorkflow} />
</StepContent>
</Step>
import { connect } from 'react-redux';
import { RootState } from '~/store/store';
import { RunProcessPanelRootDataProps, RunProcessPanelRootActionProps, RunProcessPanelRoot } from '~/views/run-process-panel/run-process-panel-root';
-import { goToStep, setWorkflow, runProcess } from '~/store/run-process-panel/run-process-panel-actions';
+import { goToStep, setWorkflow, runProcess, searchWorkflows } from '~/store/run-process-panel/run-process-panel-actions';
import { WorkflowResource } from '~/models/workflow';
const mapStateToProps = ({ runProcessPanel }: RootState): RunProcessPanelRootDataProps => {
return {
- workflows: runProcessPanel.workflows,
+ workflows: runProcessPanel.searchWorkflows,
currentStep: runProcessPanel.currentStep,
selectedWorkflow: runProcessPanel.selectedWorkflow
};
},
runProcess: () => {
dispatch<any>(runProcess);
+ },
+ onSearch: (term: string) => {
+ dispatch<any>(searchWorkflows(term));
}
});