diff options
Diffstat (limited to 'workflow-designer-ui/src/main')
39 files changed, 387 insertions, 97 deletions
diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/_components.scss b/workflow-designer-ui/src/main/frontend/resources/scss/_components.scss index 93c75bf5..3baac0b0 100644 --- a/workflow-designer-ui/src/main/frontend/resources/scss/_components.scss +++ b/workflow-designer-ui/src/main/frontend/resources/scss/_components.scss @@ -9,3 +9,4 @@ @import 'components/tree'; @import 'components/customModal'; @import 'components/scrollbars'; +@import 'components/archiveLabel';
\ No newline at end of file diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/components/_archiveLabel.scss b/workflow-designer-ui/src/main/frontend/resources/scss/components/_archiveLabel.scss new file mode 100644 index 00000000..a3fa8479 --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/resources/scss/components/_archiveLabel.scss @@ -0,0 +1,10 @@ +.archive-label { + @include body-3; + color: $white; + background-color: $dark-purple; + margin-left: 20px; + border-radius: 3px; + padding: 1px 10px; + align-self: center; + text-transform: none; +}
\ No newline at end of file diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/components/_versionController.scss b/workflow-designer-ui/src/main/frontend/resources/scss/components/_versionController.scss index 4fa8d841..7bf784e4 100644 --- a/workflow-designer-ui/src/main/frontend/resources/scss/components/_versionController.scss +++ b/workflow-designer-ui/src/main/frontend/resources/scss/components/_versionController.scss @@ -33,6 +33,8 @@ } .version-status-container { + display: flex; + align-items: center; .version-selector-more-versions { @include body-1-emphasis; color: $blue; diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/features/_catalog.scss b/workflow-designer-ui/src/main/frontend/resources/scss/features/_catalog.scss index ea5bba28..c5c32030 100644 --- a/workflow-designer-ui/src/main/frontend/resources/scss/features/_catalog.scss +++ b/workflow-designer-ui/src/main/frontend/resources/scss/features/_catalog.scss @@ -1,18 +1,26 @@ .wf-catalog { overflow: auto; background-color: $light-silver; - display: grid; grid-template-rows: 35px 1fr; height: 100vh; padding-bottom: 20px; .header { align-items: center; display: flex; - justify-content: flex-end; + justify-content: space-between; background-color: $silver; margin-bottom: 2px; @include box-shadow(0px 1px 3px 0 rgba(0, 0, 0, 0.2)); - padding: 8px 60px 0 60px; + padding: 8px 60px 0 0px; + .wf-status-select { + + display: grid; + width: 200px; + height: 34px; + margin-top: -8px; + background-color: $light-silver; + color: $blue; + } &__search { height: 25px; } diff --git a/workflow-designer-ui/src/main/frontend/resources/scss/features/_overview.scss b/workflow-designer-ui/src/main/frontend/resources/scss/features/_overview.scss index e299fa3d..c1c371fd 100644 --- a/workflow-designer-ui/src/main/frontend/resources/scss/features/_overview.scss +++ b/workflow-designer-ui/src/main/frontend/resources/scss/features/_overview.scss @@ -64,6 +64,7 @@ color: $blue; justify-content: space-between; .title { + display: flex; @include heading-1; text-transform: uppercase; } @@ -80,6 +81,18 @@ height: 16px; } } + .restore-btn { + margin-left: 20px; + } + .archive-btn { + margin-left: 20px; + fill: $gray; + &:hover { + fill: $blue; + color: $light-blue; + cursor: pointer; + } + } } @mixin version-page-box-shadow() { diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js index 867aeebd..3a8fae37 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/Catalog.js @@ -32,8 +32,8 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - handleFetchWorkflow: (sort, offset, searchNameFilter) => - dispatch(fetchWorkflow(sort, offset, searchNameFilter)), + handleFetchWorkflow: ({ sort, offset, searchNameFilter, status }) => + dispatch(fetchWorkflow({ sort, offset, searchNameFilter, status })), clearWorkflow: () => dispatch(clearWorkflowAction), showNewWorkflowModal: () => dispatch( diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx b/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx index 3f002523..73ef6548 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/CatalogView.jsx @@ -40,26 +40,49 @@ class CatalogView extends Component { const { handleFetchWorkflow, - catalog: { sort, searchNameFilter } + catalog: { sort, status, searchNameFilter } } = this.props; const payload = { ...sort }; + payload[NAME] = payload[NAME] === ASC ? DESC : ASC; - handleFetchWorkflow(payload, undefined, searchNameFilter); + handleFetchWorkflow({ + sort: payload, + searchNameFilter, + status + }); }; + handleStatusChange = value => { + const { + handleFetchWorkflow, + searchNameFilter, + catalog: { sort } + } = this.props; + handleFetchWorkflow({ + sort, + searchNameFilter, + status: value + }); + }; handleScroll = () => { const { catalog: { paging: { offset }, sort, + status, searchNameFilter }, handleFetchWorkflow } = this.props; - handleFetchWorkflow(sort, offset, searchNameFilter); + handleFetchWorkflow({ + sort, + offset, + searchNameFilter, + status + }); }; goToOverviewPage = id => { @@ -86,6 +109,7 @@ class CatalogView extends Component { sort, paging: { hasMore, total }, items, + status, searchNameFilter } = catalog; const alphabeticalOrder = sort[NAME]; @@ -93,6 +117,8 @@ class CatalogView extends Component { return ( <div className="wf-catalog"> <Header + status={status} + statusChange={this.handleStatusChange} searchChange={this.searchChange} searchValue={searchNameFilter} /> diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogActions-test.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogActions-test.js index e37307f7..bd2b0006 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogActions-test.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogActions-test.js @@ -23,18 +23,20 @@ import { NAME, ASC } from 'features/catalog/catalogConstants'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; import { fetchWorkflow, updateWorkflow } from 'features/catalog/catalogActions'; describe('Catalog Actions', () => { it('should have `fetchWorkflow` action', () => { const sort = { [NAME]: ASC }; const offset = 0; - - expect(fetchWorkflow(sort, offset)).toEqual({ + const status = WORKFLOW_STATUS.ACTIVE; + expect(fetchWorkflow({ sort, offset, status })).toEqual({ type: FETCH_WORKFLOW, payload: { sort, limit: LIMIT, + status, offset } }); diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogReducer-test.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogReducer-test.js index b31aa2ea..406e2d52 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogReducer-test.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogReducer-test.js @@ -19,6 +19,7 @@ import { NAME, ASC, DESC } from 'features/catalog/catalogConstants'; import catalogReducer, { initialState } from 'features/catalog/catalogReducer'; import { updateWorkflow } from 'features/catalog/catalogActions'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; describe('Catalog Reducer', () => { const state = { @@ -29,6 +30,7 @@ describe('Catalog Reducer', () => { hasMore: false, total: 2 }, + status: WORKFLOW_STATUS.ACTIVE, sort: { [NAME]: ASC }, @@ -106,5 +108,4 @@ describe('Catalog Reducer', () => { expect.arrayContaining([...dataPayload.items, ...state.items]) ); }); - }); diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js index 99a56508..d3e9bda2 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/__tests__/catalogSagas-test.js @@ -25,6 +25,7 @@ import { LIMIT, SEARCH_CHANGED } from 'features/catalog/catalogConstants'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; import catalogApi from '../catalogApi'; import { fetchWorkflow, updateWorkflow } from 'features/catalog/catalogActions'; import catalogSaga, { @@ -51,6 +52,7 @@ describe('Catalog Sagas', () => { const sort = { [NAME]: DESC }; + const status = WORKFLOW_STATUS.ACTIVE; const offset = 0; const searchNameFilter = undefined; const data = { @@ -61,6 +63,7 @@ describe('Catalog Sagas', () => { hasMore: false, total: 2 }, + status: WORKFLOW_STATUS.ACTIVE, searchNameFilter: 'w', items: [ { @@ -88,18 +91,19 @@ describe('Catalog Sagas', () => { dispatch: action => dispatched.push(action) }, fetchWorkflowSaga, - fetchWorkflow(sort, offset) + fetchWorkflow({ sort, offset, status }) ).done; expect(dispatched).toEqual( expect.arrayContaining([updateWorkflow({ sort, ...data })]) ); - expect(catalogApi.getWorkflows).toBeCalledWith( + expect(catalogApi.getWorkflows).toBeCalledWith({ sort, - LIMIT, - offset + LIMIT, + status, + limit: LIMIT, + offset: offset + LIMIT, searchNameFilter - ); + }); }); }); diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js index f2cb0435..81c22848 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogActions.js @@ -33,11 +33,12 @@ export const { export const fetchWorkflow = createAction( FETCH_WORKFLOW, - (sort, offset, searchNameFilter) => ({ + ({ sort, offset, searchNameFilter, status }) => ({ sort, limit: LIMIT, offset, - searchNameFilter + searchNameFilter, + status }) ); diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js index f5c9e218..b15f3d8e 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogApi.js @@ -25,11 +25,12 @@ function baseUrl() { } const Api = { - getWorkflows: (sort, limit, offset, searchNameFilter) => { + getWorkflows: ({ sort, limit, offset, searchNameFilter, status }) => { const queryParams = { sort: Object.keys(sort).map(key => `${key}:${sort[key]}`), limit, - offset + offset, + archiving: status }; if (searchNameFilter) queryParams.searchNameFilter = searchNameFilter; const queryString = qs.stringify(queryParams, { diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogReducer.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogReducer.js index e5f887b6..18507c21 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogReducer.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogReducer.js @@ -14,9 +14,13 @@ * limitations under the License. */ -import { NAME, ASC, UPDATE_WORKFLOW } from 'features/catalog/catalogConstants'; -import { SEARCH_CHANGED } from './catalogConstants'; - +import { + NAME, + ASC, + UPDATE_WORKFLOW, + SEARCH_CHANGED +} from 'features/catalog/catalogConstants'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; export const initialState = { paging: { hasMore: true, @@ -24,7 +28,8 @@ export const initialState = { }, sort: { [NAME]: ASC - } + }, + status: WORKFLOW_STATUS.ACTIVE }; const catalogReducer = (state = initialState, action) => { diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js index f1770560..dd77bc97 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/catalogSagas.js @@ -28,16 +28,16 @@ import { const noOp = () => {}; export function* fetchWorkflowSaga({ payload }) { - const { sort, limit, offset, searchNameFilter } = payload; + const { sort, limit, offset, searchNameFilter, status } = payload; try { - const data = yield call( - catalogApi.getWorkflows, + const data = yield call(catalogApi.getWorkflows, { sort, - LIMIT, - offset === undefined ? 0 : offset + limit, - searchNameFilter - ); - yield put(updateWorkflow({ sort, ...data })); + limit: LIMIT, + offset: offset === undefined ? 0 : offset + limit, + searchNameFilter, + status + }); + yield put(updateWorkflow({ sort, status, ...data })); } catch (e) { noOp(); } diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/views/Header.jsx b/workflow-designer-ui/src/main/frontend/src/features/catalog/views/Header.jsx index 864a512c..b70c0a50 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/catalog/views/Header.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/views/Header.jsx @@ -16,11 +16,12 @@ import React from 'react'; import PropTypes from 'prop-types'; - import SearchInput from 'shared/searchInput/SearchInput'; +import StatusSelect from './StatusSelector'; -const Header = ({ searchChange, searchValue }) => ( +const Header = ({ searchChange, searchValue, statusChange, status }) => ( <div className="header"> + <StatusSelect status={status} onChange={statusChange} /> <div className="header__search"> <SearchInput dataTestId="wf-catalog-search" @@ -33,7 +34,9 @@ const Header = ({ searchChange, searchValue }) => ( Header.propTypes = { searchChange: PropTypes.func, - searchValue: PropTypes.string + searchValue: PropTypes.string, + statusChange: PropTypes.func, + status: PropTypes.string }; Header.defaultProps = { diff --git a/workflow-designer-ui/src/main/frontend/src/features/catalog/views/StatusSelector.js b/workflow-designer-ui/src/main/frontend/src/features/catalog/views/StatusSelector.js new file mode 100644 index 00000000..5b77bd5d --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/src/features/catalog/views/StatusSelector.js @@ -0,0 +1,24 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; + +const StatusSelect = ({ status, onChange }) => ( + <select + className="wf-status-select" + value={status} + data-test-id="status-select" + onChange={e => onChange(e.target.value)}> + {Object.keys(WORKFLOW_STATUS).map((type, i) => ( + <option key={`type.${i}`} value={WORKFLOW_STATUS[type]}> + {type} + </option> + ))} + </select> +); + +StatusSelect.propTypes = { + status: PropTypes.string, + onChange: PropTypes.func +}; + +export default StatusSelect; diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js b/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js index b91cedaa..97697c70 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/composition/Composition.js @@ -24,6 +24,8 @@ import { activitiesSelector } from 'features/activities/activitiesSelectors'; import { getInputOutputForComposition } from 'features/version/inputOutput/inputOutputSelectors'; import { getVersionInfo } from 'features/version/general/generalSelectors'; import { getIsCertified } from 'features/version/general/generalSelectors'; +import { isWorkflowArchive } from 'features/workflow/workflowSelectors'; + function mapStateToProps(state) { return { composition: getComposition(state), @@ -32,7 +34,7 @@ function mapStateToProps(state) { activities: activitiesSelector(state), inputOutput: getInputOutputForComposition(state), errors: getErrors(state), - isReadOnly: getIsCertified(state) + isReadOnly: getIsCertified(state) || isWorkflowArchive(state) }; } diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/general/General.js b/workflow-designer-ui/src/main/frontend/src/features/version/general/General.js index f1ba7705..ecf84750 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/general/General.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/general/General.js @@ -22,10 +22,10 @@ import { getIsCertified } from 'features/version/general/generalSelectors'; import { workflowVersionDetailsChangedAction } from 'features/version/versionConstants'; - +import { isWorkflowArchive } from 'features/workflow/workflowSelectors'; const mapStateToProps = state => ({ versionInfo: getVersionInfo(state), - isCertified: getIsCertified(state) + isReadOnly: getIsCertified(state) || isWorkflowArchive(state) }); const mapDispatchToProps = dispatch => ({ diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/general/GeneralView.js b/workflow-designer-ui/src/main/frontend/src/features/version/general/GeneralView.js index bd69bfdf..e069ffb0 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/general/GeneralView.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/general/GeneralView.js @@ -21,7 +21,7 @@ import { I18n } from 'react-redux-i18n'; import Description from 'shared/components/Description'; import { VersionInfo, LabeledValue } from 'shared/components/VersionInfo'; -const GeneralView = ({ onDataChange, versionInfo, isCertified }) => { +const GeneralView = ({ onDataChange, versionInfo, isReadOnly }) => { const modifiedValue = I18n.l(versionInfo.modificationTime, { dateFormat: 'date.short' }); @@ -35,7 +35,7 @@ const GeneralView = ({ onDataChange, versionInfo, isCertified }) => { <Description description={versionInfo.description} onDataChange={onDataChange} - disabled={isCertified} + disabled={isReadOnly} /> <VersionInfo> <LabeledValue @@ -55,7 +55,7 @@ const GeneralView = ({ onDataChange, versionInfo, isCertified }) => { GeneralView.propTypes = { onDataChange: PropTypes.func, versionInfo: PropTypes.object, - isCertified: PropTypes.bool + isReadOnly: PropTypes.bool }; export default GeneralView; diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutput.js b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutput.js index 94f2f227..c9cd5756 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutput.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutput.js @@ -39,7 +39,7 @@ import { changeMandatory, remove } from 'features/version/inputOutput/inputOutputActions'; - +import { isWorkflowArchive } from 'features/workflow/workflowSelectors'; import InputOutputView from 'features/version/inputOutput/InputOutputView'; const mapStateToProps = state => ({ @@ -48,7 +48,7 @@ const mapStateToProps = state => ({ dataRows: getDataRows(state), types: getTypes(state), error: getError(state), - isCertified: getIsCertified(state) + isReadOnly: getIsCertified(state) || isWorkflowArchive(state) }); const mapDispatchToProps = dispatch => ({ diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutputView.jsx b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutputView.jsx index 4dea49d4..fae81444 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutputView.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/InputOutputView.jsx @@ -147,7 +147,7 @@ class InputOutputView extends React.Component { }; render() { - const { isShowInputs, search, handleAdd, isCertified } = this.props; + const { isShowInputs, search, handleAdd, isReadOnly } = this.props; const addLabel = isShowInputs ? I18n.t('workflow.inputOutput.addInput') @@ -180,7 +180,7 @@ class InputOutputView extends React.Component { </div> <div className={cn('input-output__add', { - disabled: isCertified + disabled: isReadOnly })} data-test-id="wf-input-output-add" onClick={handleAdd}> @@ -195,7 +195,7 @@ class InputOutputView extends React.Component { </div> <div className="input-output__table"> <TableHead /> - <TableBody isCertified={isCertified}> + <TableBody isReadOnly={isReadOnly}> <Scrollbars className="scrollbars"> {dataRowsView} </Scrollbars> @@ -218,7 +218,7 @@ InputOutputView.propTypes = { ), types: PropTypes.array, error: PropTypes.object, - isCertified: PropTypes.bool, + isReadOnly: PropTypes.bool, handleChangeError: PropTypes.func, handleShowInputs: PropTypes.func, handleShowOutputs: PropTypes.func, diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/views/TableBody.jsx b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/views/TableBody.jsx index a85bcfb6..ed11bbc5 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/views/TableBody.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/version/inputOutput/views/TableBody.jsx @@ -29,12 +29,12 @@ class TableBody extends React.Component { }; render() { - const { isCertified, children } = this.props; + const { isReadOnly, children } = this.props; return ( <div className={cn('input-output__table__tbody', { - disabled: isCertified + disabled: isReadOnly })}> {children} </div> @@ -43,7 +43,7 @@ class TableBody extends React.Component { } TableBody.propTypes = { - isCertified: PropTypes.bool, + isReadOnly: PropTypes.bool, children: PropTypes.node }; diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionController.js b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionController.js index 5c334337..8f9c9d7d 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionController.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionController.js @@ -21,6 +21,7 @@ import { getVersions, getSortedVersions } from 'features/workflow/overview/overviewSelectors'; +import { isWorkflowArchive } from 'features/workflow/workflowSelectors'; import { getWorkflowId, getWorkflowName @@ -42,6 +43,7 @@ function mapStateToProps(state) { savedParams: getSavedObjParams(state), hasErrors: getIOErrors(state) || getCompositionHasErrors(state), isCertifyDisable: getIsCertified(state), + isArchive: isWorkflowArchive(state), currentWorkflowVersion: state.currentVersion.general }; } diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionControllerView.jsx b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionControllerView.jsx index 88157e99..cdaf9aeb 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionControllerView.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/VersionControllerView.jsx @@ -37,7 +37,8 @@ export default class VersionControllerView extends Component { certifyVersion: PropTypes.func, changeVersion: PropTypes.func, isCertifyDisable: PropTypes.bool, - hasErrors: PropTypes.bool + hasErrors: PropTypes.bool, + isArchive: PropTypes.bool }; constructor(props) { @@ -96,8 +97,10 @@ export default class VersionControllerView extends Component { workflowName, versionsList, hasErrors, - isCertifyDisable + isCertifyDisable, + isArchive } = this.props; + const isReadonly = isCertifyDisable || hasErrors || isArchive; return ( <div className="version-controller-bar"> <WorkflowTitle workflowName={workflowName} /> @@ -107,11 +110,12 @@ export default class VersionControllerView extends Component { viewableVersions={versionsList} onOverviewClick={this.routeToOverview} onVersionSelectChange={this.versionChangeCallback} + isArchive={isArchive} /> <ActionButtons - saveDisabled={isCertifyDisable || hasErrors} + saveDisabled={isReadonly} onSaveClick={this.sendSaveParamsToServer} - certifyDisabled={isCertifyDisable || hasErrors} + certifyDisabled={isReadonly} onCertifyClick={this.certifyVersion} onUndoClick={this.undoClickCallback} /> diff --git a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/views/VersionsContainer.js b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/views/VersionsContainer.js index 374e565a..c84ab31d 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/version/versionController/views/VersionsContainer.js +++ b/workflow-designer-ui/src/main/frontend/src/features/version/versionController/views/VersionsContainer.js @@ -17,13 +17,15 @@ import React from 'react'; import VersionSelect from 'features/version/versionController/views/VersionSelect'; import { I18n } from 'react-redux-i18n'; import PropTypes from 'prop-types'; +import ArchiveLabel from 'shared/archiveLabel/ArchiveLabel'; const VersionContainer = props => { - let { + const { currentWorkflowVersion, viewableVersions, onOverviewClick, - onVersionSelectChange + onVersionSelectChange, + isArchive } = props; return ( @@ -41,6 +43,7 @@ const VersionContainer = props => { onClick={onOverviewClick}> {I18n.t('workflow.overview.viewOverview')} </span> + {isArchive && <ArchiveLabel />} </div> </div> ); @@ -50,7 +53,8 @@ VersionContainer.propTypes = { currentWorkflowVersion: PropTypes.object, viewableVersions: PropTypes.arrayOf(Object), onOverviewClick: PropTypes.func, - onVersionSelectChange: PropTypes.func + onVersionSelectChange: PropTypes.func, + isArchive: PropTypes.bool }; export default VersionContainer; diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/Overview.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/Overview.js index 0cce3e5c..993879a4 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/Overview.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/Overview.js @@ -21,9 +21,12 @@ import { getWorkflowData, getAllIsVersionsCertifies } from 'features/workflow/overview/overviewSelectors'; +import { isWorkflowArchive } from 'features/workflow/workflowSelectors'; import { getVersionsAction, - updateWorkflowAction + updateWorkflowAction, + archiveWorkflowAction, + restoreWorkflowAction } from 'features/workflow/overview/overviewConstansts'; import { NEW_VERSION_MODAL } from 'shared/modal/modalWrapperComponents'; import { showCustomModalAction } from 'shared/modal/modalWrapperActions'; @@ -34,7 +37,8 @@ function mapStateToProps(state) { versions: getSortedVersions(state), selectedVersion: getSelectedVersionId(state), workflow: getWorkflowData(state), - isVersionsCertifies: getAllIsVersionsCertifies(state) + isVersionsCertifies: getAllIsVersionsCertifies(state), + isArchive: isWorkflowArchive(state) }; } @@ -49,7 +53,9 @@ function mapDispatchToProps(dispatch) { }) ), workflowInputChange: payload => dispatch(inputChangeAction(payload)), - updateWorkflow: payload => dispatch(updateWorkflowAction(payload)) + updateWorkflow: payload => dispatch(updateWorkflowAction(payload)), + archiveWorkflow: payload => dispatch(archiveWorkflowAction(payload)), + restoreWorkflow: payload => dispatch(restoreWorkflowAction(payload)) }; } diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/OverviewView.jsx b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/OverviewView.jsx index f87dbfa5..0b88a846 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/OverviewView.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/OverviewView.jsx @@ -34,7 +34,10 @@ class OverviewView extends Component { location: PropTypes.object, match: PropTypes.object, updateWorkflow: PropTypes.func, - workflowInputChange: PropTypes.func + workflowInputChange: PropTypes.func, + archiveWorkflow: PropTypes.func, + restoreWorkflow: PropTypes.func, + isArchive: PropTypes.bool }; constructor(props) { @@ -70,14 +73,23 @@ class OverviewView extends Component { const { workflowInputChange } = this.props; workflowInputChange({ ...payload }); }; + onArchiveWorkflow = () => { + const { archiveWorkflow, workflow, history } = this.props; + archiveWorkflow({ id: workflow.id, history }); + }; + onRestoreWorkflow = () => { + const { restoreWorkflow, workflow, history } = this.props; + restoreWorkflow({ id: workflow.id, history }); + }; render() { const { versions, selectedVersion, workflow, isVersionsCertifies, - history + history, + isArchive } = this.props; const nodeVersions = versions.map(version => ({ id: version.id, @@ -87,9 +99,16 @@ class OverviewView extends Component { return ( <div className="overview-page"> - <WorkflowHeader history={history} name={workflow.name} /> + <WorkflowHeader + isArchive={isArchive} + archiveWorkflow={this.onArchiveWorkflow} + restoreWorkflow={this.onRestoreWorkflow} + history={history} + name={workflow.name} + /> <div className="overview-content"> <WorkflowDetails + isArchive={isArchive} name={workflow.name} description={workflow.description} modified={workflow.modified} diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/__tests__/__snapshots__/OverviewView_snapshot-test.js.snap b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/__tests__/__snapshots__/OverviewView_snapshot-test.js.snap index 381ec4b8..d870bedb 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/__tests__/__snapshots__/OverviewView_snapshot-test.js.snap +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/__tests__/__snapshots__/OverviewView_snapshot-test.js.snap @@ -15,18 +15,33 @@ exports[`OverviewView Snapshot renders correctly 1`] = ` title </div> <div - className="svg-icon-wrapper go-catalog-btn clickable right" - disabled={undefined} - onClick={[Function]} + className="header-buttons" > - <test-file-stub - className="svg-icon __back" - /> - <span - className="svg-icon-label " + <div + className="svg-icon-wrapper go-catalog-btn clickable right" + disabled={undefined} + onClick={[Function]} + > + <test-file-stub + className="svg-icon __back" + /> + <span + className="svg-icon-label " + > + backBtnLabel + </span> + </div> + <div + className="svg-icon-wrapper archive-btn clickable bottom" + disabled={undefined} + onClick={[Function]} + title="Archive workflow" > - backBtnLabel - </span> + <test-file-stub + className="svg-icon __archiveBox" + /> + + </div> </div> </div> <div diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewApi.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewApi.js index b7910bc1..d48c214b 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewApi.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewApi.js @@ -35,6 +35,11 @@ const Api = { name, description }); + }, + archiveRestoreWorkflow: ({ id, type }) => { + return RestfulAPIUtil.post(`${baseUrl()}${id}/archiving`, { + status: type + }); } }; diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewConstansts.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewConstansts.js index c90685c8..17bd2fd2 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewConstansts.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewConstansts.js @@ -15,10 +15,13 @@ */ import { createAction } from 'redux-actions'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; export const FETCH_VERSION_LIST = 'overview/FETCH_VERSION_LIST'; export const GET_OVERVIEW = 'overview/GET_OVERVIEW'; export const UPDATE_WORKFLOW = 'overview/UPDATE_WORKFLOW'; +export const ARCHIVE_WORKFLOW = 'overview/ARCHIVE_WORKFLOW'; +export const RESTORE_WORKFLOW = 'overview/RESTORE_WORKFLOW'; export const versionListFetchAction = payload => ({ type: FETCH_VERSION_LIST, @@ -34,3 +37,19 @@ export const updateWorkflowAction = createAction( UPDATE_WORKFLOW, payload => payload ); + +export const archiveWorkflowAction = payload => ({ + type: ARCHIVE_WORKFLOW, + payload: { + ...payload, + type: WORKFLOW_STATUS.ARCHIVE + } +}); + +export const restoreWorkflowAction = payload => ({ + type: RESTORE_WORKFLOW, + payload: { + ...payload, + type: WORKFLOW_STATUS.ACTIVE + } +}); diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSagas.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSagas.js index 6df38a4e..f2b4cf17 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSagas.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSagas.js @@ -13,17 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { call, takeEvery, put } from 'redux-saga/effects'; +import { call, takeEvery, put, select } from 'redux-saga/effects'; import { genericNetworkErrorAction } from 'wfapp/appConstants'; import overviewApi from 'features/workflow/overview/overviewApi'; import { versionListFetchAction, GET_OVERVIEW, - UPDATE_WORKFLOW + UPDATE_WORKFLOW, + ARCHIVE_WORKFLOW, + RESTORE_WORKFLOW } from 'features/workflow/overview/overviewConstansts'; import { setWorkflowAction } from 'features/workflow/workflowConstants'; import { notificationActions } from 'shared/notifications/notificationsActions'; +import { fetchWorkflow } from 'features/catalog/catalogActions'; +import { WORKFLOW_STATUS } from 'features/workflow/workflowConstants'; export function* getOverview(action) { try { @@ -50,7 +54,31 @@ export function* updateWorkflow(action) { } } +export function* archiveRestoreWorkflow(action) { + try { + const { history, ...data } = action.payload; + yield call(overviewApi.archiveRestoreWorkflow, data); + const { + catalog: { sort }, + searchNameFilter = '' + } = yield select(); + + yield put( + fetchWorkflow({ + sort, + searchNameFilter, + status: WORKFLOW_STATUS.ACTIVE + }) + ); + history.push('/'); + } catch (e) { + yield put(genericNetworkErrorAction(e)); + } +} + export function* watchOverview() { yield takeEvery(GET_OVERVIEW, getOverview); yield takeEvery(UPDATE_WORKFLOW, updateWorkflow); + yield takeEvery(ARCHIVE_WORKFLOW, archiveRestoreWorkflow); + yield takeEvery(RESTORE_WORKFLOW, archiveRestoreWorkflow); } diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSelectors.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSelectors.js index cc1f7ff5..d6bb1915 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSelectors.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/overviewSelectors.js @@ -32,7 +32,6 @@ export const getWorkflowModificationTime = state => state && state.workflow.data.modificationTime; export const getWorkflowId = state => state && state.workflow.data.id; - export const getAllIsVersionsCertifies = createSelector( getSortedVersions, versions => diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowDetails.jsx b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowDetails.jsx index 5afa8d99..de638a15 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowDetails.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowDetails.jsx @@ -28,7 +28,12 @@ class WorkflowDetails extends Component { }; render() { - const { name, description, workflowDetailsChanged } = this.props; + const { + name, + description, + workflowDetailsChanged, + isArchive + } = this.props; return ( <div className="workflow-details"> <form onSubmit={this.handleSubmitForm}> @@ -41,11 +46,12 @@ class WorkflowDetails extends Component { disabled /> <Description + disabled={isArchive} description={description} onDataChange={workflowDetailsChanged} /> <div className="save-description"> - <Button btnType="primary"> + <Button disabled={isArchive} btnType="primary"> {I18n.t('buttons.saveBtn')} </Button> </div> @@ -62,7 +68,8 @@ WorkflowDetails.propTypes = { description: PropTypes.string, defaultDescription: PropTypes.string, updateWorkflow: PropTypes.func, - workflowDetailsChanged: PropTypes.func + workflowDetailsChanged: PropTypes.func, + isArchive: PropTypes.bool }; export default WorkflowDetails; diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowHeader.jsx b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowHeader.jsx index f5bfc3db..3175cbba 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowHeader.jsx +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/overview/views/WorkflowHeader.jsx @@ -17,42 +17,91 @@ import React from 'react'; import PropTypes from 'prop-types'; import { I18n } from 'react-redux-i18n'; import SVGIcon from 'sdc-ui/lib/react/SVGIcon'; +import Button from 'sdc-ui/lib/react/Button'; +import ArchiveLabel from 'shared/archiveLabel/ArchiveLabel'; -const BackBtn = ({ history }) => ( - <SVGIcon - onClick={() => history.push('/')} - label={I18n.t('workflow.overview.backBtnLabel')} - className="go-catalog-btn" - labelPosition="right" - name="back" - /> +const Buttons = ({ history, archiveWorkflow, restoreWorkflow, isArchive }) => ( + <div className="header-buttons"> + <SVGIcon + onClick={() => history.push('/')} + label={I18n.t('workflow.overview.backBtnLabel')} + className="go-catalog-btn" + labelPosition="right" + name="back" + /> + <ArchiveBtn + isArchive={isArchive} + restoreWorkflow={restoreWorkflow} + archiveWorkflow={archiveWorkflow} + /> + </div> ); -BackBtn.propTypes = { - history: PropTypes.object +Buttons.propTypes = { + history: PropTypes.object, + archiveWorkflow: PropTypes.func, + isArchive: PropTypes.bool, + restoreWorkflow: PropTypes.func }; -const Title = ({ name }) => ( +const Title = ({ name, isArchive }) => ( <div className="title"> {name} - {I18n.t('workflow.overview.title')} + {isArchive && <ArchiveLabel />} </div> ); Title.propTypes = { - name: PropTypes.string + name: PropTypes.string, + isArchive: PropTypes.bool +}; + +const ArchiveBtn = ({ isArchive, archiveWorkflow, restoreWorkflow }) => { + return !isArchive ? ( + <SVGIcon + onClick={archiveWorkflow} + title="Archive workflow" + className="archive-btn" + name="archiveBox" + /> + ) : ( + <Button className="restore-btn" onClick={restoreWorkflow}> + RESTORE + </Button> + ); +}; +ArchiveBtn.propTypes = { + status: PropTypes.string, + archiveWorkflow: PropTypes.func, + restoreWorkflow: PropTypes.func, + isArchive: PropTypes.bool }; -const WorkflowHeader = ({ name, history }) => { +const WorkflowHeader = ({ + name, + history, + archiveWorkflow, + restoreWorkflow, + isArchive +}) => { return ( <div className="overview-header"> - <Title name={name} /> - <BackBtn history={history} /> + <Title isArchive={isArchive} name={name} /> + <Buttons + restoreWorkflow={restoreWorkflow} + archiveWorkflow={archiveWorkflow} + isArchive={isArchive} + history={history} + /> </div> ); }; WorkflowHeader.propTypes = { name: PropTypes.string, - history: PropTypes.object + history: PropTypes.object, + archiveWorkflow: PropTypes.func, + restoreWorkflow: PropTypes.func, + isArchive: PropTypes.bool }; export default WorkflowHeader; diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowConstants.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowConstants.js index cedcafe2..a9f4aa51 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowConstants.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowConstants.js @@ -15,6 +15,11 @@ */ import { createAction } from 'redux-actions'; +export const WORKFLOW_STATUS = { + ACTIVE: 'ACTIVE', + ARCHIVE: 'ARCHIVED' +}; + export const CLEAR_WORKFLOW_DATA = 'workflow/CLEAR_WORKFLOW_DATA'; export const SET_WORKFLOW = 'workflow/SET_WORKFLOW'; diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowReducer.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowReducer.js index c0b0557d..70d6e5be 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowReducer.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowReducer.js @@ -37,6 +37,11 @@ function workflowReducer(state = {}, action) { return { ...action.payload }; + //TODO change it when BE is done + // return { + // ...action.payload, + // status: 'archive' + // }; case VALIDATION_ERROR: return { ...state, diff --git a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowSelectors.js b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowSelectors.js index bef67c2f..e03bfbf0 100644 --- a/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowSelectors.js +++ b/workflow-designer-ui/src/main/frontend/src/features/workflow/workflowSelectors.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import { WORKFLOW_STATUS } from './workflowConstants'; export const getWorkflowName = state => state && state.workflow.data.name && state.workflow.data.name; export const getTrimWorkflowName = state => @@ -21,3 +21,14 @@ export const getTrimWorkflowName = state => export const getWorkflowId = state => state && state.workflow.data.id; export const getWorkflowDescription = state => state && state.workflow.data.description; +export const getWorkflowStatus = state => + state && + state.workflow && + state.workflow.data && + state.workflow.data.status; +export const isWorkflowArchive = state => + state && + state.workflow && + state.workflow.data && + state.workflow.data.status && + state.workflow.data.status === WORKFLOW_STATUS.ARCHIVE; diff --git a/workflow-designer-ui/src/main/frontend/src/i18n/languages.json b/workflow-designer-ui/src/main/frontend/src/i18n/languages.json index 42f2475e..6b839375 100644 --- a/workflow-designer-ui/src/main/frontend/src/i18n/languages.json +++ b/workflow-designer-ui/src/main/frontend/src/i18n/languages.json @@ -46,7 +46,8 @@ "newVersion": "Create New Version", "title": "Overview", "lastEdited": "Last Edited On", - "backBtnLabel": "WORKFLOW CATALOG" + "backBtnLabel": "WORKFLOW CATALOG", + "archived": "Archived" }, "inputOutput": { "name": "Name", diff --git a/workflow-designer-ui/src/main/frontend/src/shared/archiveLabel/ArchiveLabel.js b/workflow-designer-ui/src/main/frontend/src/shared/archiveLabel/ArchiveLabel.js new file mode 100644 index 00000000..45b39090 --- /dev/null +++ b/workflow-designer-ui/src/main/frontend/src/shared/archiveLabel/ArchiveLabel.js @@ -0,0 +1,8 @@ +import React from 'react'; +import { I18n } from 'react-redux-i18n'; + +const ArchiveLabel = () => ( + <div className="archive-label">{I18n.t('workflow.overview.archived')}</div> +); + +export default ArchiveLabel; |