From 94cdc882009323eb05b480ec21d4bf097a541b8d Mon Sep 17 00:00:00 2001 From: Riccardo Forina Date: Mon, 13 May 2019 11:11:13 +0200 Subject: [PATCH 1/3] remove 99% of the duplicated code for the editor steps resolvers --- .../src/modules/integrations/resolvers.ts | 432 ++++-------------- .../src/modules/integrations/routes.ts | 2 +- 2 files changed, 86 insertions(+), 348 deletions(-) diff --git a/app/ui-react/syndesis/src/modules/integrations/resolvers.ts b/app/ui-react/syndesis/src/modules/integrations/resolvers.ts index 297359acb1c..d295c99faa6 100644 --- a/app/ui-react/syndesis/src/modules/integrations/resolvers.ts +++ b/app/ui-react/syndesis/src/modules/integrations/resolvers.ts @@ -31,7 +31,7 @@ import { IDetailsRouteParams, IDetailsRouteState, } from './pages/detail/interfaces'; -import routes from './routes'; +import routes, { stepRoutes } from './routes'; interface IEditorIndex { flowId: string; @@ -173,155 +173,54 @@ export const configureTemplateStepMapper = ({ }; }; -// TODO: unit test every single one of these resolvers 😫 - -export const listResolver = makeResolverNoParams(routes.list); - -export const manageCicdResolver = makeResolverNoParams(routes.manageCicd.root); - -export const createRootResolver = makeResolverNoParams(routes.create.root); - -export const createStartSelectStepResolver = makeResolverNoParamsWithDefaults< - ISelectConnectionRouteParams, - ISelectConnectionRouteState ->(routes.create.start.selectStep, () => { - const integration = getEmptyIntegration(); +export function makeEditorStepRoutesResolvers( + esr: typeof stepRoutes +): RouteResolver { return { - params: { - flowId: integration.flows![0].id!, - position: '0', + selectStep: makeResolver< + IEditorSelectConnection, + ISelectConnectionRouteParams, + ISelectConnectionRouteState + >(esr.selectStep, configureSelectConnectionMapper), + connection: { + selectAction: makeResolver< + IEditorSelectAction, + ISelectActionRouteParams, + ISelectConnectionRouteState + >(esr.connection.selectAction, configureSelectActionMapper), + configureAction: makeResolver< + IEditorConfigureAction, + IConfigureActionRouteParams, + IConfigureActionRouteState + >(esr.connection.configureAction, configureConfigureActionMapper), + describeData: () => 'describeData', }, - state: { - integration, + apiProvider: { + upload: makeResolverNoParams(esr.apiProvider.upload), + review: () => 'review', + edit: () => 'edit', }, + basicFilter: () => 'basicFilter', + dataMapper: () => 'dataMapper', + template: makeResolver< + IEditorConfigureStep, + ITemplateStepRouteParams, + ITemplateStepRouteState + >(esr.template, configureTemplateStepMapper), + step: makeResolver< + IEditorConfigureStep, + IConfigureStepRouteParams, + IConfigureStepRouteState + >(esr.step, configureConfigureStepMapper), + extension: () => 'extension', }; -}); - -export const createStartSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectActionRouteState ->(routes.create.start.connection.selectAction, configureSelectActionMapper); - -export const createStartConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.create.start.connection.configureAction, - configureConfigureActionMapper -); - -export const createStartConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.create.start.step, configureConfigureStepMapper); - -export const createFinishSelectStepResolver = makeResolver< - IEditorSelectConnection, - ISelectConnectionRouteParams, - ISelectConnectionRouteState ->(routes.create.finish.selectStep, configureSelectConnectionMapper); - -export const createFinishSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectActionRouteState ->(routes.create.finish.connection.selectAction, configureSelectActionMapper); - -export const createFinishConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.create.finish.connection.configureAction, - configureConfigureActionMapper -); - -export const createFinishConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.create.finish.step, configureConfigureStepMapper); - -export const createConfigureIndexResolver = makeResolver< - IEditorIndex, - IBaseRouteParams, - IBaseRouteState ->(routes.create.configure.index, configureIndexMapper); - -export const createConfigureAddStepSelectStepResolver = makeResolver< - IEditorSelectConnection, - ISelectConnectionRouteParams, - ISelectConnectionRouteState ->(routes.create.configure.addStep.selectStep, configureSelectConnectionMapper); - -export const createConfigureAddStepSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectActionRouteState ->( - routes.create.configure.addStep.connection.selectAction, - configureSelectActionMapper -); - -export const createConfigureAddStepConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.create.configure.addStep.connection.configureAction, - configureConfigureActionMapper -); - -export const createConfigureAddStepConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.create.configure.addStep.step, configureConfigureStepMapper); - -export const createConfigureAddStepTemplateStepResolver = makeResolver< - IEditorConfigureStep, - ITemplateStepRouteParams, - ITemplateStepRouteState ->(routes.create.configure.addStep.template, configureTemplateStepMapper); - -export const createConfigureEditStepSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectActionRouteState ->( - routes.create.configure.editStep.connection.selectAction, - configureSelectActionMapper -); - -export const createConfigureEditStepConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.create.configure.editStep.connection.configureAction, - configureConfigureActionMapper -); +} -export const createConfigureEditStepConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.create.configure.editStep.step, configureConfigureStepMapper); +// TODO: unit test every single one of these resolvers 😫 -export const createConfigureEditStepSaveAndPublishResolver = makeResolver< - IEditorIndex, - ISaveIntegrationRouteParams, - ISaveIntegrationRouteState ->(routes.create.configure.saveAndPublish, configureIndexMapper); +export const listResolver = makeResolverNoParams(routes.list); -export const createConfigureEditStepTemplateStepResolver = makeResolver< - IEditorConfigureStep, - ITemplateStepRouteParams, - ITemplateStepRouteState ->(routes.create.configure.editStep.template, configureTemplateStepMapper); +export const manageCicdResolver = makeResolverNoParams(routes.manageCicd.root); export const integrationActivityResolver = makeResolver< { integrationId: string; integration?: IIntegrationOverviewWithDraft }, @@ -349,84 +248,6 @@ export const integrationDetailsResolver = makeResolver< }, })); -export const integrationEditIndexResolver = makeResolver< - IEditorIndex, - IBaseRouteParams, - IBaseRouteState ->(routes.integration.edit.index, configureIndexMapper); - -export const integrationEditAddStepSelectStepResolver = makeResolver< - IEditorSelectConnection, - ISelectConnectionRouteParams, - ISelectConnectionRouteState ->(routes.integration.edit.addStep.selectStep, configureSelectConnectionMapper); - -export const integrationEditAddStepSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectConnectionRouteState ->( - routes.integration.edit.addStep.connection.selectAction, - configureSelectActionMapper -); - -export const integrationEditAddStepConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.integration.edit.addStep.connection.configureAction, - configureConfigureActionMapper -); - -export const integrationEditAddStepConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.integration.edit.addStep.step, configureConfigureStepMapper); - -export const integrationEditAddStepTemplateStepResolver = makeResolver< - IEditorConfigureStep, - ITemplateStepRouteParams, - ITemplateStepRouteState ->(routes.integration.edit.addStep.template, configureTemplateStepMapper); - -export const integrationEditEditStepSelectActionResolver = makeResolver< - IEditorSelectAction, - ISelectActionRouteParams, - ISelectActionRouteState ->( - routes.integration.edit.editStep.connection.selectAction, - configureSelectActionMapper -); - -export const integrationEditEditStepConfigureActionResolver = makeResolver< - IEditorConfigureAction, - IConfigureActionRouteParams, - IConfigureActionRouteState ->( - routes.integration.edit.editStep.connection.configureAction, - configureConfigureActionMapper -); - -export const integrationEditEditStepConfigureStepResolver = makeResolver< - IEditorConfigureStep, - IConfigureStepRouteParams, - IConfigureStepRouteState ->(routes.integration.edit.editStep.step, configureConfigureStepMapper); - -export const integrationEditEditStepTemplateStepResolver = makeResolver< - IEditorConfigureStep, - ITemplateStepRouteParams, - ITemplateStepRouteState ->(routes.integration.edit.editStep.template, configureTemplateStepMapper); - -export const integrationEditSaveAndPublish = makeResolver< - IEditorIndex, - ISaveIntegrationRouteParams, - ISaveIntegrationRouteState ->(routes.integration.edit.saveAndPublish, configureIndexMapper); - export const metricsResolver = makeResolver< { integrationId: string; integration?: IIntegrationOverviewWithDraft }, IDetailsRouteParams, @@ -450,141 +271,58 @@ const resolvers: RouteResolver = { root: manageCicdResolver, }, create: { - root: createRootResolver, + root: makeResolverNoParams(routes.create.root), start: { - selectStep: createStartSelectStepResolver, - connection: { - selectAction: createStartSelectActionResolver, - configureAction: createStartConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams(routes.create.start.apiProvider.upload), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: () => 'template', - step: createStartConfigureStepResolver, - extension: () => 'extension', - }, - finish: { - selectStep: createFinishSelectStepResolver, - connection: { - selectAction: createFinishSelectActionResolver, - configureAction: createFinishConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams(routes.create.finish.apiProvider.upload), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: () => 'template', - step: createFinishConfigureStepResolver, - extension: () => 'extension', + ...makeEditorStepRoutesResolvers(routes.create.start), + selectStep: makeResolverNoParamsWithDefaults< + ISelectConnectionRouteParams, + ISelectConnectionRouteState + >(routes.create.start.selectStep, () => { + const integration = getEmptyIntegration(); + return { + params: { + flowId: integration.flows![0].id!, + position: '0', + }, + state: { + integration, + }, + }; + }), }, + finish: makeEditorStepRoutesResolvers(routes.create.finish), configure: { - root: createRootResolver, - index: createConfigureIndexResolver, - addStep: { - selectStep: createConfigureAddStepSelectStepResolver, - connection: { - selectAction: createConfigureAddStepSelectActionResolver, - configureAction: createConfigureAddStepConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams( - routes.create.configure.addStep.apiProvider.upload - ), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: createConfigureAddStepTemplateStepResolver, - step: createConfigureAddStepConfigureStepResolver, - extension: () => 'extension', - }, - editStep: { - selectStep: () => { - throw new Error('this route should not be used'); - }, - connection: { - selectAction: createConfigureEditStepSelectActionResolver, - configureAction: createConfigureEditStepConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams( - routes.create.configure.editStep.apiProvider.upload - ), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: createConfigureEditStepTemplateStepResolver, - step: createConfigureEditStepConfigureStepResolver, - extension: () => 'extension', - }, - saveAndPublish: createConfigureEditStepSaveAndPublishResolver, + root: makeResolverNoParams(routes.create.configure.root), + index: makeResolver( + routes.create.configure.index, + configureIndexMapper + ), + addStep: makeEditorStepRoutesResolvers(routes.create.configure.addStep), + editStep: makeEditorStepRoutesResolvers(routes.create.configure.editStep), + saveAndPublish: makeResolver< + IEditorIndex, + ISaveIntegrationRouteParams, + ISaveIntegrationRouteState + >(routes.create.configure.saveAndPublish, configureIndexMapper), }, }, integration: { - root: createRootResolver, + root: makeResolverNoParams(routes.integration.root), activity: integrationActivityResolver, details: integrationDetailsResolver, edit: { - root: createRootResolver, - index: integrationEditIndexResolver, - addStep: { - selectStep: integrationEditAddStepSelectStepResolver, - connection: { - selectAction: integrationEditAddStepSelectActionResolver, - configureAction: integrationEditAddStepConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams( - routes.integration.edit.addStep.apiProvider.upload - ), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: integrationEditAddStepTemplateStepResolver, - step: integrationEditAddStepConfigureStepResolver, - extension: () => 'extension', - }, - editStep: { - selectStep: () => { - throw new Error('this route should not be used'); - }, - connection: { - selectAction: integrationEditEditStepSelectActionResolver, - configureAction: integrationEditEditStepConfigureActionResolver, - describeData: () => 'describeData', - }, - apiProvider: { - upload: makeResolverNoParams( - routes.integration.edit.editStep.apiProvider.upload - ), - review: () => 'review', - edit: () => 'edit', - }, - basicFilter: () => 'basicFilter', - dataMapper: () => 'dataMapper', - template: integrationEditEditStepTemplateStepResolver, - step: integrationEditEditStepConfigureStepResolver, - extension: () => 'extension', - }, - saveAndPublish: integrationEditSaveAndPublish, + root: makeResolverNoParams(routes.integration.edit.root), + index: makeResolver( + routes.integration.edit.index, + configureIndexMapper + ), + addStep: makeEditorStepRoutesResolvers(routes.integration.edit.addStep), + editStep: makeEditorStepRoutesResolvers(routes.integration.edit.editStep), + saveAndPublish: makeResolver< + IEditorIndex, + ISaveIntegrationRouteParams, + ISaveIntegrationRouteState + >(routes.integration.edit.saveAndPublish, configureIndexMapper), }, metrics: metricsResolver, }, diff --git a/app/ui-react/syndesis/src/modules/integrations/routes.ts b/app/ui-react/syndesis/src/modules/integrations/routes.ts index a02a36f0afe..19c38ed6cb8 100644 --- a/app/ui-react/syndesis/src/modules/integrations/routes.ts +++ b/app/ui-react/syndesis/src/modules/integrations/routes.ts @@ -1,7 +1,7 @@ /* tslint:disable:object-literal-sort-keys */ import { include } from 'named-urls'; -const stepRoutes = { +export const stepRoutes = { // step 1 selectStep: '', // if selected step is api provider From 768c1e75f8b97a75756c7e752c78e2eb3634cd7d Mon Sep 17 00:00:00 2001 From: Riccardo Forina Date: Mon, 13 May 2019 15:16:45 +0200 Subject: [PATCH 2/3] reduce duplicated code required to setup the editor apps --- .../integrations/IntegrationCreatorApp.tsx | 851 +----------------- .../integrations/IntegrationEditorApp.tsx | 333 +------ .../components/IntegrationDetailSteps.tsx | 4 +- .../components/IntegrationEditorSidebar.tsx | 116 --- .../components/editor/EditorApp.tsx | 351 +++----- .../components/editor/EditorRoutes.tsx | 232 +++++ .../components/editor/EditorSidebar.tsx | 144 +++ .../editor/SelectConnectionPage.tsx | 10 +- .../editor/endpoint/ConfigureActionPage.tsx | 30 +- .../editor/endpoint/SelectActionPage.tsx | 23 +- .../components/editor/interfaces.tsx | 41 + .../editor/step/ConfigureStepPage.tsx | 16 +- .../editor/template/TemplateStepPage.tsx | 12 +- .../integrations/components/editor/utils.ts | 12 +- .../modules/integrations/components/index.ts | 1 - .../src/modules/integrations/resolvers.ts | 5 +- .../src/modules/integrations/routes.ts | 41 +- 17 files changed, 677 insertions(+), 1545 deletions(-) delete mode 100644 app/ui-react/syndesis/src/modules/integrations/components/IntegrationEditorSidebar.tsx create mode 100644 app/ui-react/syndesis/src/modules/integrations/components/editor/EditorRoutes.tsx create mode 100644 app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx diff --git a/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx index 529da47d118..43c2bdefad1 100644 --- a/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx @@ -1,28 +1,11 @@ -/* tslint:disable:object-literal-sort-keys */ -import { getConnectionIcon, getStepIcon } from '@syndesis/api'; -import { - Breadcrumb, - IntegrationFlowStepGeneric, - IntegrationFlowStepWithOverview, - IntegrationVerticalFlow, -} from '@syndesis/ui'; +import { Breadcrumb } from '@syndesis/ui'; import * as React from 'react'; import { Route, Switch } from 'react-router'; import { Link } from 'react-router-dom'; import { WithClosedNavigation } from '../../shared'; -import { IntegrationEditorSidebar } from './components'; import { AddStepPage } from './components/editor/AddStepPage'; -import { ReviewPage } from './components/editor/api-provider/EditPage'; -import { EditPage } from './components/editor/api-provider/ReviewPage'; -import { UploadPage } from './components/editor/api-provider/UploadPage'; import { EditorApp } from './components/editor/EditorApp'; -import { ConfigureActionPage } from './components/editor/endpoint/ConfigureActionPage'; -import { SelectActionPage } from './components/editor/endpoint/SelectActionPage'; import { SaveIntegrationPage } from './components/editor/SaveIntegrationPage'; -import { SelectConnectionPage } from './components/editor/SelectConnectionPage'; -import { ConfigureStepPage } from './components/editor/step/ConfigureStepPage'; -import { TemplateStepPage } from './components/editor/template/TemplateStepPage'; -import { getDataShapeText, toUIStepKind } from './components/editor/utils'; import resolvers from './resolvers'; import routes from './routes'; @@ -77,641 +60,6 @@ const saveIntegrationPage = ( /> ); -const startStepSelectConnectionPage = ( - - resolvers.create.start.connection.selectAction({ - connection, - ...params, - ...state, - }) - } - filterHref={resolvers.create.start.basicFilter} - mapperHref={resolvers.create.start.dataMapper} - templateHref={resolvers.create.start.template} - stepHref={resolvers.create.start.step} - sidebar={() => ( - - {({ expanded }) => ( - <> - } - i18nTitle={'1. Start'} - i18nTooltip={'Start'} - active={true} - showDetails={expanded} - description={'Choose a connection'} - /> - } - i18nTitle={'2. Finish'} - i18nTooltip={'Finish'} - active={false} - showDetails={expanded} - name={'n/a'} - action={'n/a'} - dataType={'n/a'} - /> - - )} - - )} - /> -); - -const startStepSelectActionPage = ( - ( - - {({ expanded }) => ( - <> - - } - i18nTitle={`1. ${connection.name}`} - i18nTooltip={`1. ${connection.name}`} - active={true} - showDetails={expanded} - description={'Choose an action'} - /> - } - i18nTitle={'2. Finish'} - i18nTooltip={'Finish'} - active={false} - showDetails={expanded} - name={'n/a'} - action={'n/a'} - dataType={'n/a'} - /> - - )} - - )} - selectHref={(actionId, p, s) => - resolvers.create.start.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const startStepConfigureActionPage = ( - - resolvers.create.start.connection.selectAction({ ...p, ...s }) - } - cancelHref={resolvers.list} - mode={'adding'} - nextStepHref={(p, s) => - resolvers.create.start.connection.configureAction({ - ...p, - ...s, - }) - } - sidebar={({ connection }) => ( - - {({ expanded }) => ( - <> - - } - i18nTitle={`1. ${connection.connector!.name}`} - i18nTooltip={`1. ${connection.name}`} - active={true} - showDetails={expanded} - description={'Configure the action'} - /> - } - i18nTitle={'2. Finish'} - i18nTooltip={'Finish'} - active={false} - showDetails={expanded} - name={'n/a'} - action={'n/a'} - dataType={'n/a'} - /> - - )} - - )} - postConfigureHref={(integration, params, state) => { - return resolvers.create.finish.selectStep({ - integration, - ...params, - position: '1', - }); - }} - /> -); - -const startStepConfigureStepPage = ( - ( - - {({ expanded }) => { - return ( - <> - - } - i18nTitle={`1. ${step.name}`} - i18nTooltip={`1. ${step.description}`} - active={true} - showDetails={expanded} - description={'Configure the action'} - /> - } - i18nTitle={'2. Finish'} - i18nTooltip={'Finish'} - active={false} - showDetails={expanded} - name={'n/a'} - action={'n/a'} - dataType={'n/a'} - /> - - ); - }} - - )} - postConfigureHref={(integration, params) => - resolvers.create.finish.selectStep({ - integration, - ...params, - }) - } - /> -); - -const finishStepSelectConnectionPage = ( - - resolvers.create.finish.connection.selectAction({ - connection, - ...params, - ...state, - }) - } - filterHref={resolvers.create.finish.basicFilter} - mapperHref={resolvers.create.finish.dataMapper} - templateHref={resolvers.create.finish.template} - stepHref={(step, params, state) => - resolvers.create.finish.step({ - step, - ...params, - ...state, - }) - } - sidebar={({ steps }) => ( - - {({ expanded }) => { - const s = toUIStepKind(steps[0]); - return ( - <> - } - i18nTitle={`1. ${s.name}`} - i18nTooltip={`1. ${s.title}`} - active={false} - showDetails={expanded} - name={s.name} - action={s.action && s.action.name} - dataType={getDataShapeText(s.stepKind!, s.outputDataShape)} - /> - } - i18nTitle={'2. Finish'} - i18nTooltip={'Finish'} - active={true} - showDetails={expanded} - description={'Choose a connection'} - /> - - ); - }} - - )} - /> -); - -const finishStepSelectActionPage = ( - resolvers.create.finish.selectStep({ ...p, ...s })} - sidebar={({ connection, steps }) => ( - - {({ expanded }) => { - const s = toUIStepKind(steps[0]); - return ( - <> - } - i18nTitle={`1. ${s.name}`} - i18nTooltip={`1. ${s.title}`} - active={false} - showDetails={expanded} - name={s.name} - action={s.action && s.action.name} - dataType={getDataShapeText(s.stepKind!, s.outputDataShape)} - /> - - } - i18nTitle={`2. ${connection.connector!.name}`} - i18nTooltip={`2. ${connection.name}`} - active={true} - showDetails={expanded} - description={'Choose an action'} - /> - - ); - }} - - )} - selectHref={(actionId, p, s) => - resolvers.create.finish.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const finishStepConfigureActionPage = ( - - resolvers.create.finish.connection.selectAction({ ...p, ...s }) - } - cancelHref={resolvers.list} - mode={'adding'} - nextStepHref={(p, s) => - resolvers.create.finish.connection.configureAction({ - ...p, - ...s, - }) - } - sidebar={({ connection, steps }) => ( - - {({ expanded }) => { - const s = toUIStepKind(steps[0]); - return ( - <> - } - i18nTitle={`1. ${s.name}`} - i18nTooltip={`1. ${s.title}`} - active={false} - showDetails={expanded} - name={s.name} - action={s.action && s.action.name} - dataType={getDataShapeText(s.stepKind!, s.outputDataShape)} - /> - - } - i18nTitle={`2. ${connection.connector!.name}`} - i18nTooltip={`2. ${connection.name}`} - active={true} - showDetails={expanded} - description={'Configure the action'} - /> - - ); - }} - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const finishStepConfigureStepPage = ( - ( - - {({ expanded }) => { - const s = toUIStepKind(steps[0]); - return ( - <> - } - i18nTitle={`1. ${s.name}`} - i18nTooltip={`1. ${s.title}`} - active={false} - showDetails={expanded} - name={s.name} - action={s.action && s.action.name} - dataType={getDataShapeText(s.stepKind!, s.outputDataShape)} - /> - - } - i18nTitle={`2. ${step.name}`} - i18nTooltip={`2. ${step.description}`} - active={true} - showDetails={expanded} - description={'Configure the action'} - /> - - ); - }} - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const addStepSelectConnectionPage = ( - resolvers.create.configure.index({ ...p, ...s })} - apiProviderHref={resolvers.create.configure.addStep.apiProvider.upload} - connectionHref={(connection, p, s) => - resolvers.create.configure.addStep.connection.selectAction({ - connection, - ...p, - ...s, - }) - } - filterHref={resolvers.create.configure.addStep.basicFilter} - mapperHref={resolvers.create.configure.addStep.dataMapper} - templateHref={(step, params, state) => - resolvers.create.configure.addStep.template({ - step, - ...params, - ...state, - }) - } - stepHref={(step, params, state) => - resolvers.create.configure.addStep.step({ - step, - ...params, - ...state, - }) - } - sidebar={({ steps, activeIndex }) => ( - - )} - /> -); - -const addStepSelectActionPage = ( - resolvers.create.configure.index({ ...p, ...s })} - sidebar={({ connection, steps, activeIndex }) => ( - - } - addI18nTitle={`${activeIndex + 1}. ${connection.connector!.name}`} - addI18nTooltip={`${activeIndex + 1}. ${connection.name}`} - addI18nDescription={'Choose an action'} - /> - )} - selectHref={(actionId, p, s) => - resolvers.create.configure.addStep.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const addStepConfigureActionPage = ( - - resolvers.create.configure.addStep.connection.selectAction({ ...p, ...s }) - } - cancelHref={(p, s) => resolvers.create.configure.index({ ...p, ...s })} - mode={'adding'} - nextStepHref={(p, s) => - resolvers.create.configure.addStep.connection.configureAction({ - ...p, - ...s, - }) - } - sidebar={({ connection, steps, activeIndex }) => ( - - } - addI18nTitle={`${activeIndex + 1}. ${connection.connector!.name}`} - addI18nTooltip={`${activeIndex + 1}. ${connection.name}`} - addI18nDescription={'Configure the action'} - /> - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const addStepConfigureStepPage = ( - resolvers.create.configure.index({ ...p, ...s })} - mode={'adding'} - sidebar={({ step, steps, activeIndex }) => ( - - } - addI18nTitle={`${activeIndex + 1}. ${step.name}`} - addI18nTooltip={`${activeIndex + 1}. ${step.description}`} - addI18nDescription={'Configure the action'} - /> - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const editStepSelectActionPage = ( - resolvers.create.configure.index({ ...p, ...s })} - sidebar={({ steps, activeIndex }) => ( - - )} - selectHref={(actionId, p, s) => - resolvers.create.configure.editStep.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const editStepConfigureActionPage = ( - - resolvers.create.configure.editStep.connection.selectAction({ - ...p, - ...s, - }) - } - cancelHref={(p, s) => resolvers.create.configure.index({ ...p, ...s })} - mode={'editing'} - nextStepHref={(p, s) => - resolvers.create.configure.editStep.connection.configureAction({ - ...p, - ...s, - }) - } - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const editStepConfigureStepPage = ( - resolvers.create.configure.index({ ...p, ...s })} - mode={'editing'} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const addTemplateStepPage = ( - resolvers.create.configure.index({ ...p, ...s })} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const editTemplateStepPage = ( - resolvers.create.configure.index({ ...p, ...s })} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.create.configure.index({ - integration, - ...params, - }) - } - /> -); - -const TODO: React.FunctionComponent = () => <>TODO; - /** * Entry point for the integration creator app. This is shown when an user clicks * the "Create integration" button somewhere in the app. @@ -743,44 +91,16 @@ export const IntegrationCreatorApp: React.FunctionComponent = () => { {/* start step */} , - reviewPath: routes.create.start.apiProvider.review, - reviewChildren: , - editPath: routes.create.start.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.create.start.template, - templateChildren: addTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.create.start.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.create.start.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.create.start.step, - configureChildren: startStepConfigureStepPage, - }} - extension={{ - configurePath: routes.create.start.extension, - configureChildren: TODO, + mode={'adding'} + appStepRoutes={routes.create.start} + appResolvers={resolvers.create.start} + cancelHref={resolvers.list} + postConfigureHref={(integration, params) => { + return resolvers.create.finish.selectStep({ + integration, + ...params, + position: '1', + }); }} /> @@ -788,45 +108,16 @@ export const IntegrationCreatorApp: React.FunctionComponent = () => { {/* finish step */} , - reviewPath: routes.create.finish.apiProvider.review, - reviewChildren: , - editPath: routes.create.finish.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.create.finish.template, - templateChildren: addTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.create.finish.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.create.finish.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.create.finish.step, - configureChildren: finishStepConfigureStepPage, - }} - extension={{ - configurePath: routes.create.finish.extension, - configureChildren: TODO, - }} + mode={'adding'} + appStepRoutes={routes.create.finish} + appResolvers={resolvers.create.finish} + cancelHref={resolvers.list} + postConfigureHref={(integration, params) => + resolvers.create.configure.index({ + integration, + ...params, + }) + } /> @@ -839,92 +130,32 @@ export const IntegrationCreatorApp: React.FunctionComponent = () => { {/* add step */} , - reviewPath: routes.create.configure.addStep.apiProvider.review, - reviewChildren: , - editPath: routes.create.configure.addStep.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.create.configure.addStep.template, - templateChildren: addTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.create.configure.addStep.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.create.configure.addStep.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.create.configure.addStep.step, - configureChildren: addStepConfigureStepPage, - }} - extension={{ - configurePath: routes.create.configure.addStep.extension, - configureChildren: TODO, - }} + mode={'adding'} + appStepRoutes={routes.create.configure.addStep} + appResolvers={resolvers.create.configure.addStep} + cancelHref={resolvers.list} + postConfigureHref={(integration, params) => + resolvers.create.configure.index({ + integration, + ...params, + }) + } /> {/* edit step */} , - reviewPath: routes.create.configure.editStep.apiProvider.review, - reviewChildren: , - editPath: routes.create.configure.editStep.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.create.configure.editStep.template, - templateChildren: editTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.create.configure.editStep.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.create.configure.editStep.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.create.configure.editStep.step, - configureChildren: editStepConfigureStepPage, - }} - extension={{ - configurePath: routes.create.configure.editStep.extension, - configureChildren: TODO, - }} + mode={'editing'} + appStepRoutes={routes.create.configure.editStep} + appResolvers={resolvers.create.configure.editStep} + cancelHref={resolvers.list} + postConfigureHref={(integration, params) => + resolvers.create.configure.index({ + integration, + ...params, + }) + } /> diff --git a/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx index 9024525457b..bad715f1e6a 100644 --- a/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx @@ -1,5 +1,3 @@ -/* tslint:disable:object-literal-sort-keys */ -import { getConnectionIcon } from '@syndesis/api'; import { Integration } from '@syndesis/models'; import { Breadcrumb } from '@syndesis/ui'; import { WithRouteData } from '@syndesis/utils'; @@ -7,18 +5,9 @@ import * as React from 'react'; import { Route, Switch } from 'react-router'; import { Link } from 'react-router-dom'; import { WithClosedNavigation } from '../../shared'; -import { IntegrationEditorSidebar } from './components'; import { AddStepPage } from './components/editor/AddStepPage'; -import { ReviewPage } from './components/editor/api-provider/EditPage'; -import { EditPage } from './components/editor/api-provider/ReviewPage'; -import { UploadPage } from './components/editor/api-provider/UploadPage'; import { EditorApp } from './components/editor/EditorApp'; -import { ConfigureActionPage } from './components/editor/endpoint/ConfigureActionPage'; -import { SelectActionPage } from './components/editor/endpoint/SelectActionPage'; import { SaveIntegrationPage } from './components/editor/SaveIntegrationPage'; -import { SelectConnectionPage } from './components/editor/SelectConnectionPage'; -import { ConfigureStepPage } from './components/editor/step/ConfigureStepPage'; -import { TemplateStepPage } from './components/editor/template/TemplateStepPage'; import resolvers from './resolvers'; import routes from './routes'; @@ -66,45 +55,6 @@ const addStepPage = ( /> ); -const selectConnectionPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - apiProviderHref={(p, s) => ({ pathname: 'todo' })} - connectionHref={(connection, p, s) => - resolvers.integration.edit.addStep.connection.selectAction({ - connection, - ...p, - ...s, - }) - } - filterHref={resolvers.integration.edit.addStep.basicFilter} - mapperHref={resolvers.integration.edit.addStep.dataMapper} - templateHref={(step, params, state) => - resolvers.integration.edit.addStep.template({ - step, - ...params, - ...state, - }) - } - stepHref={(step, params, state) => - resolvers.integration.edit.addStep.step({ - step, - ...params, - ...state, - }) - } - sidebar={({ steps, activeIndex }) => ( - - )} - /> -); - const saveIntegrationPage = ( resolvers.integration.edit.index({ ...p, ...s })} @@ -112,189 +62,10 @@ const saveIntegrationPage = ( /> ); -const addStepSelectActionPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - sidebar={({ connection, steps, activeIndex }) => ( - - } - addI18nTitle={`${activeIndex + 1}. ${connection.name}`} - addI18nTooltip={`${activeIndex + 1}. ${connection.name}`} - addI18nDescription={'Choose an action'} - /> - )} - selectHref={(actionId, p, s) => - resolvers.integration.edit.addStep.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const addStepConfigureActionPage = ( - - resolvers.integration.edit.addStep.connection.selectAction({ ...p, ...s }) - } - cancelHref={(p, s) => resolvers.integration.edit.index({ ...p, ...s })} - nextStepHref={(p, s) => - resolvers.integration.edit.addStep.connection.configureAction({ - ...p, - ...s, - }) - } - mode={'adding'} - sidebar={({ connection, steps, activeIndex }) => ( - - } - addI18nTitle={`${activeIndex + 1}. ${connection.connector!.name}`} - addI18nTooltip={`${activeIndex + 1}. ${connection.name}`} - addI18nDescription={'Configure the action'} - /> - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - -const addStepConfigureStepPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - mode={'adding'} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - -const editStepSelectActionPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - sidebar={({ steps, activeIndex }) => ( - - )} - selectHref={(actionId, p, s) => - resolvers.integration.edit.editStep.connection.configureAction({ - actionId, - ...p, - ...s, - }) - } - /> -); - -const editStepConfigureActionPage = ( - - resolvers.integration.edit.editStep.connection.selectAction({ - ...p, - ...s, - }) - } - cancelHref={(p, s) => resolvers.integration.edit.index({ ...p, ...s })} - mode={'editing'} - nextStepHref={(p, s) => - resolvers.integration.edit.editStep.connection.configureAction({ - ...p, - ...s, - }) - } - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - -const editStepConfigureStepPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - mode={'editing'} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - -const addTemplateStepPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - mode={'adding'} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - -const editTemplateStepPage = ( - resolvers.integration.edit.index({ ...p, ...s })} - mode={'editing'} - sidebar={({ steps, activeIndex }) => ( - - )} - postConfigureHref={(integration, params) => - resolvers.integration.edit.index({ - integration, - ...params, - }) - } - /> -); - export interface IIntegrationEditorAppRouteState { integration: Integration; } -const TODO: React.FunctionComponent = () => <>TODO; - /** * Entry point for the integration editor app. This is shown when an user clicks * on the "Edit" button for any existing integration. @@ -341,96 +112,32 @@ export const IntegrationEditorApp: React.FunctionComponent = () => { {/* add step */} , - reviewPath: - routes.integration.edit.addStep.apiProvider.review, - reviewChildren: , - editPath: routes.integration.edit.addStep.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.integration.edit.addStep.template, - templateChildren: addTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.integration.edit.addStep.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.integration.edit.addStep.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.integration.edit.addStep.step, - configureChildren: addStepConfigureStepPage, - }} - extension={{ - configurePath: routes.integration.edit.addStep.step, - configureChildren: TODO, - }} + mode={'adding'} + appStepRoutes={routes.integration.edit.addStep} + appResolvers={resolvers.integration.edit.addStep} + cancelHref={resolvers.list} + postConfigureHref={(updatedIntegration, params) => + resolvers.integration.edit.index({ + integration: updatedIntegration, + ...params, + }) + } /> {/* edit step */} , - reviewPath: - routes.integration.edit.editStep.apiProvider.review, - reviewChildren: , - editPath: routes.integration.edit.editStep.apiProvider.edit, - editChildren: , - }} - template={{ - templatePath: routes.integration.edit.editStep.template, - templateChildren: editTemplateStepPage, - }} - dataMapper={{ - mapperPath: routes.integration.edit.editStep.dataMapper, - mapperChildren: TODO, - }} - basicFilter={{ - filterPath: routes.integration.edit.editStep.basicFilter, - filterChildren: TODO, - }} - step={{ - configurePath: routes.integration.edit.editStep.step, - configureChildren: editStepConfigureStepPage, - }} - extension={{ - configurePath: routes.integration.edit.editStep.extension, - configureChildren: TODO, - }} + mode={'editing'} + appStepRoutes={routes.integration.edit.editStep} + appResolvers={resolvers.integration.edit.editStep} + cancelHref={resolvers.list} + postConfigureHref={(updatedIntegration, params) => + resolvers.integration.edit.index({ + integration: updatedIntegration, + ...params, + }) + } /> diff --git a/app/ui-react/syndesis/src/modules/integrations/components/IntegrationDetailSteps.tsx b/app/ui-react/syndesis/src/modules/integrations/components/IntegrationDetailSteps.tsx index 7d8713b7e1d..3decea380cd 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/IntegrationDetailSteps.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/IntegrationDetailSteps.tsx @@ -13,7 +13,7 @@ import { import * as React from 'react'; import resolvers from '../../resolvers'; import { IUIStep } from './editor/interfaces'; -import { toUIStepKindCollection } from './editor/utils'; +import { toUIStepCollection } from './editor/utils'; export interface IIntegrationDetailStepsProps { integration: Integration; @@ -29,7 +29,7 @@ export class IntegrationDetailSteps extends React.Component< return ( - {toUIStepKindCollection(steps).map((s: IUIStep, idx: number) => { + {toUIStepCollection(steps).map((s: IUIStep, idx: number) => { const isFirst = idx === 0; const stepUri = s.stepKind === ENDPOINT && !s.metadata[HIDE_FROM_CONNECTION_PAGES] diff --git a/app/ui-react/syndesis/src/modules/integrations/components/IntegrationEditorSidebar.tsx b/app/ui-react/syndesis/src/modules/integrations/components/IntegrationEditorSidebar.tsx deleted file mode 100644 index 9aac92bf635..00000000000 --- a/app/ui-react/syndesis/src/modules/integrations/components/IntegrationEditorSidebar.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { - IntegrationFlowStepGeneric, - IntegrationFlowStepWithOverview, - IntegrationVerticalFlow, -} from '@syndesis/ui'; -import * as React from 'react'; -import { IUIStep } from './editor/interfaces'; -import { getDataShapeText } from './editor/utils'; - -export interface IIntegrationEditorSidebarProps { - /** - * the list of steps to render. - */ - steps: IUIStep[]; - /** - * the zero-based index of a configured step that should be highlighted as - * active. - * This should not be set in conjunction with [addAtIndex]{@link IIntegrationEditorSidebarProps#addAtIndex} - */ - activeIndex?: number; - /** - * the zero-based index where a new step is being added. - * This should not be set in conjunction with [activeIndex]{@link IIntegrationEditorSidebarProps#activeIndex} - */ - addAtIndex?: number; - /** - * the icon to show in the circle of the step that is being added. - */ - addIcon?: any; - /** - * The title of the information table shown for the step that is being added, - * in the extended view. - */ - addI18nTitle?: string; - /** - * The text to show on the tooltip that opens when hovering with the mouse on - * the icon. - */ - addI18nTooltip?: string; - /** - * The description of the information table shown for the step that is being - * added, in the extended view. - */ - addI18nDescription?: string; -} - -/** - * This component shows the steps of an integration in a vertical fashion. It's - * meant to be used as the sidebar of the `IntegrationEditorLayout` component. - * Steps are rendered as circles, showing the step's connection icon. - * - * It offers two visualization, a compact one where just the icons are shown, - * and an expanded one where additional information about the step are shown in - * a table next to the step's circle. - * - * It can also show a step that is being added to the integration by providing - * its position and some information about the configuration step. - * - * @see [steps]{@link IIntegrationEditorSidebarProps#steps} - * @see [activeIndex]{@link IIntegrationEditorSidebarProps#activeIndex} - * @see [addAtIndex]{@link IIntegrationEditorSidebarProps#addAtIndex} - * @see [addIcon]{@link IIntegrationEditorSidebarProps#addIcon} - * @see [addI18nTitle]{@link IIntegrationEditorSidebarProps#addI18nTitle} - * @see [addI18nTooltip]{@link IIntegrationEditorSidebarProps#addI18nTooltip} - * @see [addI18nDescription]{@link IIntegrationEditorSidebarProps#addI18nDescription} - */ -export class IntegrationEditorSidebar extends React.Component< - IIntegrationEditorSidebarProps -> { - public render() { - return ( - - {({ expanded }) => - this.props.steps.map((s, idx) => { - const isActive = idx === this.props.activeIndex; - const hasAddStep = this.props.addAtIndex === idx + 1; - const isAfterActiveAddStep = this.props.addAtIndex! - 1 < idx; - const position = isAfterActiveAddStep ? idx + 2 : idx + 1; - - const activeAddStep = ( - } - i18nTitle={this.props.addI18nTitle!} - i18nTooltip={this.props.addI18nTooltip!} - active={true} - showDetails={expanded} - description={this.props.addI18nDescription!} - /> - ); - return ( - - - } - i18nTitle={`${position}. ${s.name}`} - i18nTooltip={`${position}. ${s.title}`} - active={isActive} - showDetails={expanded} - name={s.name} - action={s.action && s.action.name!} - dataType={ - idx === 0 - ? getDataShapeText(s.stepKind!, s.outputDataShape) - : getDataShapeText(s.stepKind!, s.inputDataShape) - } - /> - {hasAddStep ? activeAddStep : null} - - ); - }) - } - - ); - } -} diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx index 4f376ff6b70..315922b80e2 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx @@ -1,232 +1,167 @@ +/* tslint:disable:object-literal-sort-keys */ +import * as H from '@syndesis/history'; +import { Integration } from '@syndesis/models'; import * as React from 'react'; -import { Route, Switch } from 'react-router'; +import resolvers, { RouteResolver } from '../../resolvers'; import { ReviewPage } from './api-provider/EditPage'; import { EditPage } from './api-provider/ReviewPage'; import { UploadPage } from './api-provider/UploadPage'; +import { EditorRoutes } from './EditorRoutes'; +import { EditorSidebar } from './EditorSidebar'; import { ConfigureActionPage } from './endpoint/ConfigureActionPage'; import { SelectActionPage } from './endpoint/SelectActionPage'; +import { + IConfigureActionRouteParams, + IConfigureActionRouteState, + ISelectConnectionRouteParams, + ISelectConnectionRouteState, + ITemplateStepRouteParams, + ITemplateStepRouteState, + stepRoutes, +} from './interfaces'; +import { SelectConnectionPage } from './SelectConnectionPage'; +import { ConfigureStepPage } from './step/ConfigureStepPage'; import { TemplateStepPage } from './template/TemplateStepPage'; -export interface IEndpointEditorAppProps { - selectActionPath: string; - selectActionChildren: React.ReactElement; - configureActionPath: string; - configureActionChildren: React.ReactElement; - describeDataPath: string; - describeDataChildren: React.ReactNode; -} -export const EndpointEditorApp: React.FunctionComponent< - IEndpointEditorAppProps -> = props => { - return ( - - - - - - ); -}; +const TODO: React.FunctionComponent = () => <>TODO; -export interface IApiProviderAppProps { - uploadPath: string; - uploadChildren: React.ReactElement; - reviewPath: string; - reviewChildren: React.ReactElement; - editPath: string; - editChildren: React.ReactElement; +export interface IEditorApp { + mode: 'adding' | 'editing'; + appStepRoutes: typeof stepRoutes; + appResolvers: RouteResolver; + cancelHref: ( + p: ISelectConnectionRouteParams, + s: ISelectConnectionRouteState + ) => H.LocationDescriptor; + postConfigureHref: ( + integration: Integration, + p: ITemplateStepRouteParams | IConfigureActionRouteParams, + s: ITemplateStepRouteState | IConfigureActionRouteState + ) => H.LocationDescriptorObject; } -export const ApiProviderApp: React.FunctionComponent< - IApiProviderAppProps -> = props => { - return ( - - - - - - ); -}; -export interface ITemplateAppProps { - templatePath: string; - templateChildren: React.ReactElement; -} -export const TemplateApp: React.FunctionComponent< - ITemplateAppProps -> = props => { - return ( - - - +export const EditorApp: React.FunctionComponent = ({ + mode, + appStepRoutes, + appResolvers, + cancelHref, + postConfigureHref, +}) => { + const selectStepChildren = ( + + appResolvers.connection.selectAction({ + connection, + ...params, + ...state, + }) + } + filterHref={appResolvers.basicFilter} + mapperHref={appResolvers.dataMapper} + templateHref={appResolvers.template} + stepHref={(step, params, state) => + resolvers.create.finish.step({ + step, + ...params, + ...state, + }) + } + sidebar={props => } + /> ); -}; -export interface IBasicFilterAppProps { - filterPath: string; - filterChildren: React.ReactNode; -} -export const BasicFilterApp: React.FunctionComponent< - IBasicFilterAppProps -> = props => { - return ( - - - + const selectActionPage = ( + } + selectHref={(actionId, p, s) => + appResolvers.connection.configureAction({ + actionId, + ...p, + ...s, + }) + } + /> ); -}; -export interface IDataMapperAppProps { - mapperPath: string; - mapperChildren: React.ReactNode; -} -export const DataMapperApp: React.FunctionComponent< - IDataMapperAppProps -> = props => { - return ( - - - + const configureActionPage = ( + appResolvers.connection.selectAction({ ...p, ...s })} + cancelHref={resolvers.list} + mode={mode} + nextStepHref={(p, s) => + appResolvers.connection.configureAction({ + ...p, + ...s, + }) + } + sidebar={props => } + postConfigureHref={postConfigureHref} + /> ); -}; -export interface IStepAppProps { - configurePath: string; - configureChildren: React.ReactNode; -} -export const StepApp: React.FunctionComponent = props => { - return ( - - - + const templateStepPage = ( + } + postConfigureHref={postConfigureHref} + /> ); -}; -export interface IExtensionAppProps { - configurePath: string; - configureChildren: React.ReactNode; -} -export const ExtensionApp: React.FunctionComponent< - IExtensionAppProps -> = props => { - return ( - - - + const configureStepPage = ( + } + postConfigureHref={postConfigureHref} + /> ); -}; -export interface IEditorAppProps { - selectStepPath?: string; - selectStepChildren?: React.ReactNode; - endpointEditor: IEndpointEditorAppProps; - apiProvider: IApiProviderAppProps; - template: ITemplateAppProps; - dataMapper: IDataMapperAppProps; - basicFilter: IBasicFilterAppProps; - step: IStepAppProps; - extension: IExtensionAppProps; -} -export const EditorApp: React.FunctionComponent = props => { return ( - - {props.selectStepPath && props.selectStepChildren ? ( - - ) : null} - - - - - - - - - - - - - - - - - - - - - - - + <> + , + reviewPath: appStepRoutes.apiProvider.review, + reviewChildren: , + editPath: appStepRoutes.apiProvider.edit, + editChildren: , + }} + template={{ + templatePath: appStepRoutes.template, + templateChildren: templateStepPage, + }} + dataMapper={{ + mapperPath: appStepRoutes.dataMapper, + mapperChildren: TODO, + }} + basicFilter={{ + filterPath: appStepRoutes.basicFilter, + filterChildren: TODO, + }} + step={{ + configurePath: appStepRoutes.step, + configureChildren: configureStepPage, + }} + extension={{ + configurePath: appStepRoutes.extension, + configureChildren: TODO, + }} + /> + ); }; diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorRoutes.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorRoutes.tsx new file mode 100644 index 00000000000..f37538d09e8 --- /dev/null +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorRoutes.tsx @@ -0,0 +1,232 @@ +import * as React from 'react'; +import { Route, Switch } from 'react-router'; +import { ReviewPage } from './api-provider/EditPage'; +import { EditPage } from './api-provider/ReviewPage'; +import { UploadPage } from './api-provider/UploadPage'; +import { ConfigureActionPage } from './endpoint/ConfigureActionPage'; +import { SelectActionPage } from './endpoint/SelectActionPage'; +import { TemplateStepPage } from './template/TemplateStepPage'; + +export interface IEndpointEditorAppProps { + selectActionPath: string; + selectActionChildren: React.ReactElement; + configureActionPath: string; + configureActionChildren: React.ReactElement; + describeDataPath: string; + describeDataChildren: React.ReactNode; +} +export const EndpointEditorApp: React.FunctionComponent< + IEndpointEditorAppProps +> = props => { + return ( + + + + + + ); +}; + +export interface IApiProviderAppProps { + uploadPath: string; + uploadChildren: React.ReactElement; + reviewPath: string; + reviewChildren: React.ReactElement; + editPath: string; + editChildren: React.ReactElement; +} +export const ApiProviderApp: React.FunctionComponent< + IApiProviderAppProps +> = props => { + return ( + + + + + + ); +}; + +export interface ITemplateAppProps { + templatePath: string; + templateChildren: React.ReactElement; +} +export const TemplateApp: React.FunctionComponent< + ITemplateAppProps +> = props => { + return ( + + + + ); +}; + +export interface IBasicFilterAppProps { + filterPath: string; + filterChildren: React.ReactNode; +} +export const BasicFilterApp: React.FunctionComponent< + IBasicFilterAppProps +> = props => { + return ( + + + + ); +}; + +export interface IDataMapperAppProps { + mapperPath: string; + mapperChildren: React.ReactNode; +} +export const DataMapperApp: React.FunctionComponent< + IDataMapperAppProps +> = props => { + return ( + + + + ); +}; + +export interface IStepAppProps { + configurePath: string; + configureChildren: React.ReactNode; +} +export const StepApp: React.FunctionComponent = props => { + return ( + + + + ); +}; + +export interface IExtensionAppProps { + configurePath: string; + configureChildren: React.ReactNode; +} +export const ExtensionApp: React.FunctionComponent< + IExtensionAppProps +> = props => { + return ( + + + + ); +}; + +export interface IEditorAppProps { + selectStepPath?: string; + selectStepChildren?: React.ReactNode; + endpointEditor: IEndpointEditorAppProps; + apiProvider: IApiProviderAppProps; + template: ITemplateAppProps; + dataMapper: IDataMapperAppProps; + basicFilter: IBasicFilterAppProps; + step: IStepAppProps; + extension: IExtensionAppProps; +} +export const EditorRoutes: React.FunctionComponent = props => { + return ( + + {props.selectStepPath && props.selectStepChildren ? ( + + ) : null} + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx new file mode 100644 index 00000000000..275aed04654 --- /dev/null +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx @@ -0,0 +1,144 @@ +import { Step } from '@syndesis/models'; +import { + IntegrationFlowStepGeneric, + IntegrationFlowStepWithOverview, + IntegrationVerticalFlow, +} from '@syndesis/ui'; +import * as React from 'react'; +import { IUIStep } from './interfaces'; +import { getDataShapeText, toUIStepCollection } from './utils'; + +function makeActiveStep( + position: number, + expanded: boolean, + activeStep?: IUIStep +) { + return activeStep ? ( + + } + i18nTitle={`${position}. ${activeStep.name}`} + i18nTooltip={`${position}. ${activeStep.title}`} + active={true} + showDetails={expanded} + name={ + activeStep.action ? activeStep.action.name : 'Select/configure action' + } + action={activeStep.action && activeStep.action.name} + dataType={getDataShapeText( + activeStep.stepKind!, + activeStep.outputDataShape + )} + /> + ) : ( + } + i18nTitle={`${position}. Finish`} + i18nTooltip={'Finish'} + active={true} + showDetails={expanded} + description={'Choose a connection'} + /> + ); +} + +export interface IEditorSidebarProps { + steps: Step[]; + activeStep?: IUIStep; + activeIndex: number; +} +export const EditorSidebar: React.FunctionComponent = ({ + activeIndex, + activeStep, + steps, +}) => { + const UISteps = toUIStepCollection(steps); + return ( + + {({ expanded }) => { + if (UISteps.length === 0) { + return ( + <> + {makeActiveStep(1, expanded, activeStep)} + } + i18nTitle={'2. Finish'} + i18nTooltip={'Finish'} + active={false} + showDetails={expanded} + description={'Choose a connection'} + /> + + ); + } else if (UISteps.length === 1) { + const startStep = UISteps[0]; + return ( + <> + + } + i18nTitle={`1. ${startStep.name}`} + i18nTooltip={`1. ${startStep.title}`} + showDetails={expanded} + name={startStep.name} + action={startStep.action && startStep.action.name!} + dataType={getDataShapeText( + startStep.stepKind!, + startStep.outputDataShape + )} + /> + {makeActiveStep(2, expanded, activeStep)} + + ); + } else { + return ( + <> + {UISteps.map((s, idx) => { + const isActive = idx === activeIndex; + const hasAddStep = activeIndex === idx + 1; + const isAfterActiveAddStep = activeIndex - 1 < idx; + const position = isAfterActiveAddStep ? idx + 2 : idx + 1; + + return ( + + + } + i18nTitle={`${position}. ${s.name}`} + i18nTooltip={`${position}. ${s.title}`} + active={isActive && !isAfterActiveAddStep} + showDetails={expanded} + name={s.name} + action={s.action && s.action.name!} + dataType={ + idx === 0 + ? getDataShapeText(s.stepKind!, s.outputDataShape) + : getDataShapeText(s.stepKind!, s.inputDataShape) + } + /> + {hasAddStep + ? makeActiveStep(position, expanded, activeStep) + : null} + + ); + })} + + ); + } + }} + + ); +}; diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/SelectConnectionPage.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/SelectConnectionPage.tsx index b8308a491ca..3b6ae02e96b 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/SelectConnectionPage.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/SelectConnectionPage.tsx @@ -13,6 +13,7 @@ import * as React from 'react'; import { Translation } from 'react-i18next'; import { PageTitle } from '../../../../shared'; import { ConnectionsWithToolbar } from '../../../connections/components'; +import { IEditorSidebarProps } from './EditorSidebar'; import { ISelectConnectionRouteParams, ISelectConnectionRouteState, @@ -22,7 +23,7 @@ import { getStepHref, IGetStepHrefs, mergeConnectionsSources, - toUIStepKindCollection, + toUIStepCollection, visibleStepsByPosition, } from './utils'; @@ -31,10 +32,7 @@ export interface ISelectConnectionPageProps extends IGetStepHrefs { p: ISelectConnectionRouteParams, s: ISelectConnectionRouteState ) => H.LocationDescriptor; - sidebar: (props: { - steps: IUIStep[]; - activeIndex: number; - }) => React.ReactNode; + sidebar: (props: IEditorSidebarProps) => React.ReactNode; } /** @@ -69,7 +67,7 @@ export class SelectConnectionPage extends React.Component< } sidebar={this.props.sidebar({ activeIndex: positionAsNumber, - steps: toUIStepKindCollection(integrationSteps), + steps: toUIStepCollection(integrationSteps), })} content={ diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/endpoint/ConfigureActionPage.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/endpoint/ConfigureActionPage.tsx index d9ffc9d6180..06c85661911 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/endpoint/ConfigureActionPage.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/endpoint/ConfigureActionPage.tsx @@ -1,16 +1,20 @@ -import { getSteps, WithIntegrationHelpers } from '@syndesis/api'; +import { + getConnectionIcon, + getSteps, + WithIntegrationHelpers, +} from '@syndesis/api'; import * as H from '@syndesis/history'; -import { Connection, Integration } from '@syndesis/models'; +import { Integration } from '@syndesis/models'; import { IntegrationEditorLayout } from '@syndesis/ui'; import { WithRouteData } from '@syndesis/utils'; import * as React from 'react'; import { PageTitle } from '../../../../../shared'; +import { IEditorSidebarProps } from '../EditorSidebar'; import { IConfigureActionRouteParams, IConfigureActionRouteState, - IUIStep, } from '../interfaces'; -import { toUIStepKindCollection } from '../utils'; +import { toUIStep, toUIStepCollection } from '../utils'; import { IOnUpdatedIntegrationProps, WithConfigurationForm, @@ -30,11 +34,7 @@ export interface IConfigureActionPageProps { p: IConfigureActionRouteParams, s: IConfigureActionRouteState ) => H.LocationDescriptorObject; - sidebar: (props: { - connection: Connection; - steps: IUIStep[]; - activeIndex: number; - }) => React.ReactNode; + sidebar: (props: IEditorSidebarProps) => React.ReactNode; postConfigureHref: ( integration: Integration, p: IConfigureActionRouteParams, @@ -138,10 +138,14 @@ export class ConfigureActionPage extends React.Component< } sidebar={this.props.sidebar({ activeIndex: positionAsNumber, - connection, - steps: toUIStepKindCollection( - getSteps(updatedIntegration || integration, flowId) - ), + activeStep: { + ...toUIStep(connection), + icon: getConnectionIcon( + process.env.PUBLIC_URL, + connection + ), + }, + steps: toUIStepCollection(getSteps(integration, flowId)), })} content={ H.LocationDescriptor; - sidebar: (props: { - steps: IUIStep[]; - activeIndex: number; - connection: IConnectionWithIconFile; - }) => React.ReactNode; + sidebar: (props: IEditorSidebarProps) => React.ReactNode; selectHref: ( actionId: string, p: ISelectActionRouteParams, @@ -71,8 +66,14 @@ export class SelectActionPage extends React.Component { } sidebar={this.props.sidebar({ activeIndex: positionAsNumber, - connection: connection as IConnectionWithIconFile, - steps: toUIStepKindCollection( + activeStep: { + ...toUIStep(connection), + icon: getConnectionIcon( + process.env.PUBLIC_URL, + connection + ), + }, + steps: toUIStepCollection( getSteps(integration, flowId) ), })} diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/interfaces.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/interfaces.tsx index f9390abc959..2134ff3df0c 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/interfaces.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/interfaces.tsx @@ -1,3 +1,4 @@ +/* tslint:disable:object-literal-sort-keys */ import { ConnectionBulletinBoard, ConnectionOverview, @@ -6,6 +7,7 @@ import { Integration, StepKind, } from '@syndesis/models'; +import { include } from 'named-urls'; /** * @param actionId - the ID of the action selected in the previous step. @@ -149,3 +151,42 @@ export interface IUIStep extends StepKind { inputDataShape?: DataShape; outputDataShape?: DataShape; } + +export const stepRoutes = { + // step 1 + selectStep: '', + // if selected step is api provider + apiProvider: include('api-provider', { + upload: '', + review: 'review', + edit: 'edit', + }), + // if selected step kind is data mapper + dataMapper: 'mapper', + // if selected step kind is basic filter + basicFilter: 'filter', + // if selected step kind is template + template: 'template', + // if selected step kind is step + step: 'step', + // if selected step kind is step + extension: 'extension', + // if selected step kind is endpoint + connection: include('connection/:connectionId', { + selectAction: '', + configureAction: ':actionId/:step', + // if 'any' data shape + describeData: 'describe-data/:position/:direction(input|output)', + }), +}; +/** + * Both the integration creator and editor share the same routes when the creator + * reaches the third step in the wizard. This object is to keep them DRY. + */ +export const editorRoutes = include(':flowId', { + index: 'add-step', + addStep: include(':position/add', stepRoutes), + editStep: include(':position/edit', stepRoutes), + saveAndPublish: 'save', + root: '', +}); diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/step/ConfigureStepPage.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/step/ConfigureStepPage.tsx index 3146cdbf424..d2398040198 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/step/ConfigureStepPage.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/step/ConfigureStepPage.tsx @@ -1,16 +1,16 @@ import { getSteps, WithIntegrationHelpers } from '@syndesis/api'; import * as H from '@syndesis/history'; -import { Integration, StepKind } from '@syndesis/models'; +import { Integration } from '@syndesis/models'; import { IntegrationEditorLayout } from '@syndesis/ui'; import { WithRouteData } from '@syndesis/utils'; import * as React from 'react'; import { PageTitle } from '../../../../../shared'; +import { IEditorSidebarProps } from '../EditorSidebar'; import { IConfigureStepRouteParams, IConfigureStepRouteState, - IUIStep, } from '../interfaces'; -import { toUIStepKindCollection } from '../utils'; +import { toUIStep, toUIStepCollection } from '../utils'; import { IOnUpdatedIntegrationProps, WithConfigurationForm, @@ -22,11 +22,7 @@ export interface IConfigureStepPageProps { s: IConfigureStepRouteState ) => H.LocationDescriptor; mode: 'adding' | 'editing'; - sidebar: (props: { - step: StepKind; - steps: IUIStep[]; - activeIndex: number; - }) => React.ReactNode; + sidebar: (props: IEditorSidebarProps) => React.ReactNode; postConfigureHref: ( integration: Integration, p: IConfigureStepRouteParams, @@ -103,8 +99,8 @@ export class ConfigureStepPage extends React.Component< } sidebar={this.props.sidebar({ activeIndex: positionAsNumber, - step, - steps: toUIStepKindCollection( + activeStep: toUIStep(step), + steps: toUIStepCollection( getSteps(updatedIntegration || integration, flowId) ), })} diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/template/TemplateStepPage.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/template/TemplateStepPage.tsx index 4b6d0745bd8..36f46e78414 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/template/TemplateStepPage.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/template/TemplateStepPage.tsx @@ -9,12 +9,12 @@ import { import { WithRouteData } from '@syndesis/utils'; import * as React from 'react'; import { PageTitle } from '../../../../../shared'; +import { IEditorSidebarProps } from '../EditorSidebar'; import { ITemplateStepRouteParams, ITemplateStepRouteState, - IUIStep, } from '../interfaces'; -import { toUIStepKindCollection } from '../utils'; +import { toUIStep, toUIStepCollection } from '../utils'; import { WithTemplater } from './WithTemplater'; export interface ITemplateStepPageProps { @@ -23,10 +23,7 @@ export interface ITemplateStepPageProps { p: ITemplateStepRouteParams, s: ITemplateStepRouteState ) => H.LocationDescriptor; - sidebar: (props: { - steps: IUIStep[]; - activeIndex: number; - }) => React.ReactNode; + sidebar: (props: IEditorSidebarProps) => React.ReactNode; postConfigureHref: ( integration: Integration, p: ITemplateStepRouteParams, @@ -84,7 +81,8 @@ export class TemplateStepPage extends React.Component { } sidebar={this.props.sidebar({ activeIndex: positionAsNumber, - steps: toUIStepKindCollection( + activeStep: toUIStep(step), + steps: toUIStepCollection( getSteps(updatedIntegration || integration, flowId) ), })} diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/utils.ts b/app/ui-react/syndesis/src/modules/integrations/components/editor/utils.ts index 42765f722b1..2b6e644bd4f 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/utils.ts +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/utils.ts @@ -42,7 +42,7 @@ export function getStepKind(step: Step): IUIStep['uiStepKind'] { return step.stepKind; } -export function toUIStepKind(step: Step): IUIStep { +export function toUIStep(step: Step): IUIStep { const uiStepKind = getStepKind(step); const inputDataShape = step.action && @@ -121,8 +121,8 @@ export function toUIStepKind(step: Step): IUIStep { } } -export function toUIStepKindCollection(steps: Step[]): IUIStep[] { - return steps.map(toUIStepKind); +export function toUIStepCollection(steps: Step[]): IUIStep[] { + return steps.map(toUIStep); } export function getDataShapeText(stepKind: string, dataShape?: DataShape) { @@ -193,7 +193,7 @@ export function mergeConnectionsSources( ): IUIStep[] { return [ ...connections.map(connection => - toUIStepKind({ + toUIStep({ connection, name: connection.name, stepKind: ENDPOINT, @@ -216,7 +216,7 @@ export function mergeConnectionsSources( } if (a.actionType === 'step') { extentionsByAction.push( - toUIStepKind({ + toUIStep({ action: a, configuredProperties: undefined, description: a.description || '', @@ -235,7 +235,7 @@ export function mergeConnectionsSources( }, [] as IUIStep[] ), - ...steps.map(s => toUIStepKind(s)), + ...steps.map(s => toUIStep(s)), ] .filter(s => !!s.uiStepKind) // this should never happen .sort((a, b) => a.name.localeCompare(b.name)); diff --git a/app/ui-react/syndesis/src/modules/integrations/components/index.ts b/app/ui-react/syndesis/src/modules/integrations/components/index.ts index e2ff6f363bc..510c4c480fe 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/index.ts +++ b/app/ui-react/syndesis/src/modules/integrations/components/index.ts @@ -3,6 +3,5 @@ export * from './IntegrationCreatorBreadcrumbs'; export * from './IntegrationDetailHeader'; export * from './IntegrationDetailSteps'; export * from './IntegrationEditorBreadcrumbs'; -export * from './IntegrationEditorSidebar'; export * from './IntegrationEditorStepAdder'; export * from './WithIntegrationActions'; diff --git a/app/ui-react/syndesis/src/modules/integrations/resolvers.ts b/app/ui-react/syndesis/src/modules/integrations/resolvers.ts index d295c99faa6..6d49fbb97fd 100644 --- a/app/ui-react/syndesis/src/modules/integrations/resolvers.ts +++ b/app/ui-react/syndesis/src/modules/integrations/resolvers.ts @@ -26,12 +26,13 @@ import { ISelectConnectionRouteState, ITemplateStepRouteParams, ITemplateStepRouteState, + stepRoutes, } from './components/editor/interfaces'; import { IDetailsRouteParams, IDetailsRouteState, } from './pages/detail/interfaces'; -import routes, { stepRoutes } from './routes'; +import routes from './routes'; interface IEditorIndex { flowId: string; @@ -261,7 +262,7 @@ export const metricsResolver = makeResolver< }, })); -type RouteResolver = { +export type RouteResolver = { [K in keyof T]: T[K] extends string ? any : RouteResolver }; diff --git a/app/ui-react/syndesis/src/modules/integrations/routes.ts b/app/ui-react/syndesis/src/modules/integrations/routes.ts index 19c38ed6cb8..ed7e5684236 100644 --- a/app/ui-react/syndesis/src/modules/integrations/routes.ts +++ b/app/ui-react/syndesis/src/modules/integrations/routes.ts @@ -1,45 +1,6 @@ /* tslint:disable:object-literal-sort-keys */ import { include } from 'named-urls'; - -export const stepRoutes = { - // step 1 - selectStep: '', - // if selected step is api provider - apiProvider: include('api-provider', { - upload: '', - review: 'review', - edit: 'edit', - }), - // if selected step kind is data mapper - dataMapper: 'mapper', - // if selected step kind is basic filter - basicFilter: 'filter', - // if selected step kind is template - template: 'template', - // if selected step kind is step - step: 'step', - // if selected step kind is step - extension: 'extension', - // if selected step kind is endpoint - connection: include('connection/:connectionId', { - selectAction: '', - configureAction: ':actionId/:step', - // if 'any' data shape - describeData: 'describe-data/:position/:direction(input|output)', - }), -}; - -/** - * Both the integration creator and editor share the same routes when the creator - * reaches the third step in the wizard. This object is to keep them DRY. - */ -const editorRoutes = include(':flowId', { - index: 'add-step', - addStep: include(':position/add', stepRoutes), - editStep: include(':position/edit', stepRoutes), - saveAndPublish: 'save', - root: '', -}); +import { editorRoutes, stepRoutes } from './components/editor/interfaces'; export default include('/integrations', { list: '', From 93ed6c5b9a412e114486d46aecf78adf211e1fbd Mon Sep 17 00:00:00 2001 From: Riccardo Forina Date: Mon, 13 May 2019 16:04:32 +0200 Subject: [PATCH 3/3] properly wire the cancel buttons, and fix the sidebar bugs --- .../integrations/IntegrationCreatorApp.tsx | 14 ++++- .../integrations/IntegrationEditorApp.tsx | 14 ++++- .../components/editor/EditorApp.tsx | 34 +++++++++---- .../components/editor/EditorSidebar.tsx | 51 ++++++++++++++----- 4 files changed, 86 insertions(+), 27 deletions(-) diff --git a/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx index 43c2bdefad1..3ee1f07b69f 100644 --- a/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/IntegrationCreatorApp.tsx @@ -133,7 +133,12 @@ export const IntegrationCreatorApp: React.FunctionComponent = () => { mode={'adding'} appStepRoutes={routes.create.configure.addStep} appResolvers={resolvers.create.configure.addStep} - cancelHref={resolvers.list} + cancelHref={(params, state) => + resolvers.create.configure.index({ + ...params, + ...state, + }) + } postConfigureHref={(integration, params) => resolvers.create.configure.index({ integration, @@ -149,7 +154,12 @@ export const IntegrationCreatorApp: React.FunctionComponent = () => { mode={'editing'} appStepRoutes={routes.create.configure.editStep} appResolvers={resolvers.create.configure.editStep} - cancelHref={resolvers.list} + cancelHref={(params, state) => + resolvers.create.configure.index({ + ...params, + ...state, + }) + } postConfigureHref={(integration, params) => resolvers.create.configure.index({ integration, diff --git a/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx index bad715f1e6a..2df31027650 100644 --- a/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/IntegrationEditorApp.tsx @@ -115,7 +115,12 @@ export const IntegrationEditorApp: React.FunctionComponent = () => { mode={'adding'} appStepRoutes={routes.integration.edit.addStep} appResolvers={resolvers.integration.edit.addStep} - cancelHref={resolvers.list} + cancelHref={(params, state) => + resolvers.integration.edit.index({ + ...params, + ...state, + }) + } postConfigureHref={(updatedIntegration, params) => resolvers.integration.edit.index({ integration: updatedIntegration, @@ -131,7 +136,12 @@ export const IntegrationEditorApp: React.FunctionComponent = () => { mode={'editing'} appStepRoutes={routes.integration.edit.editStep} appResolvers={resolvers.integration.edit.editStep} - cancelHref={resolvers.list} + cancelHref={(params, state) => + resolvers.integration.edit.index({ + ...params, + ...state, + }) + } postConfigureHref={(updatedIntegration, params) => resolvers.integration.edit.index({ integration: updatedIntegration, diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx index 315922b80e2..5ab7616d49f 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorApp.tsx @@ -2,7 +2,7 @@ import * as H from '@syndesis/history'; import { Integration } from '@syndesis/models'; import * as React from 'react'; -import resolvers, { RouteResolver } from '../../resolvers'; +import { RouteResolver } from '../../resolvers'; import { ReviewPage } from './api-provider/EditPage'; import { EditPage } from './api-provider/ReviewPage'; import { UploadPage } from './api-provider/UploadPage'; @@ -60,22 +60,32 @@ export const EditorApp: React.FunctionComponent = ({ } filterHref={appResolvers.basicFilter} mapperHref={appResolvers.dataMapper} - templateHref={appResolvers.template} + templateHref={(step, params, state) => + appResolvers.template({ + step, + ...params, + ...state, + }) + } stepHref={(step, params, state) => - resolvers.create.finish.step({ + appResolvers.step({ step, ...params, ...state, }) } - sidebar={props => } + sidebar={props => ( + + )} /> ); const selectActionPage = ( } + sidebar={props => ( + + )} selectHref={(actionId, p, s) => appResolvers.connection.configureAction({ actionId, @@ -89,7 +99,7 @@ export const EditorApp: React.FunctionComponent = ({ const configureActionPage = ( appResolvers.connection.selectAction({ ...p, ...s })} - cancelHref={resolvers.list} + cancelHref={cancelHref} mode={mode} nextStepHref={(p, s) => appResolvers.connection.configureAction({ @@ -97,7 +107,9 @@ export const EditorApp: React.FunctionComponent = ({ ...s, }) } - sidebar={props => } + sidebar={props => ( + + )} postConfigureHref={postConfigureHref} /> ); @@ -106,7 +118,9 @@ export const EditorApp: React.FunctionComponent = ({ } + sidebar={props => ( + + )} postConfigureHref={postConfigureHref} /> ); @@ -115,7 +129,9 @@ export const EditorApp: React.FunctionComponent = ({ } + sidebar={props => ( + + )} postConfigureHref={postConfigureHref} /> ); diff --git a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx index 275aed04654..7d242150cf9 100644 --- a/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx +++ b/app/ui-react/syndesis/src/modules/integrations/components/editor/EditorSidebar.tsx @@ -11,6 +11,8 @@ import { getDataShapeText, toUIStepCollection } from './utils'; function makeActiveStep( position: number, expanded: boolean, + title: string, + tooltip: string, activeStep?: IUIStep ) { return activeStep ? ( @@ -39,11 +41,11 @@ function makeActiveStep( ) : ( } - i18nTitle={`${position}. Finish`} - i18nTooltip={'Finish'} + i18nTitle={`${position}. ${title}`} + i18nTooltip={tooltip} active={true} showDetails={expanded} - description={'Choose a connection'} + description={tooltip} /> ); } @@ -53,11 +55,11 @@ export interface IEditorSidebarProps { activeStep?: IUIStep; activeIndex: number; } -export const EditorSidebar: React.FunctionComponent = ({ - activeIndex, - activeStep, - steps, -}) => { +export const EditorSidebar: React.FunctionComponent< + IEditorSidebarProps & { + isAdding: boolean; + } +> = ({ activeIndex, activeStep, steps, isAdding }) => { const UISteps = toUIStepCollection(steps); return ( @@ -65,7 +67,13 @@ export const EditorSidebar: React.FunctionComponent = ({ if (UISteps.length === 0) { return ( <> - {makeActiveStep(1, expanded, activeStep)} + {makeActiveStep( + 1, + expanded, + 'Start', + 'Choose a step', + activeStep + )} } i18nTitle={'2. Finish'} @@ -99,7 +107,13 @@ export const EditorSidebar: React.FunctionComponent = ({ startStep.outputDataShape )} /> - {makeActiveStep(2, expanded, activeStep)} + {makeActiveStep( + 2, + expanded, + 'Finish', + 'Choose a step', + activeStep + )} ); } else { @@ -107,9 +121,10 @@ export const EditorSidebar: React.FunctionComponent = ({ <> {UISteps.map((s, idx) => { const isActive = idx === activeIndex; - const hasAddStep = activeIndex === idx + 1; + const hasAddStep = isAdding && activeIndex === idx + 1; const isAfterActiveAddStep = activeIndex - 1 < idx; - const position = isAfterActiveAddStep ? idx + 2 : idx + 1; + const position = + isAdding && isAfterActiveAddStep ? idx + 2 : idx + 1; return ( @@ -119,7 +134,9 @@ export const EditorSidebar: React.FunctionComponent = ({ } i18nTitle={`${position}. ${s.name}`} i18nTooltip={`${position}. ${s.title}`} - active={isActive && !isAfterActiveAddStep} + active={ + isAdding ? isActive && !isAfterActiveAddStep : isActive + } showDetails={expanded} name={s.name} action={s.action && s.action.name!} @@ -130,7 +147,13 @@ export const EditorSidebar: React.FunctionComponent = ({ } /> {hasAddStep - ? makeActiveStep(position, expanded, activeStep) + ? makeActiveStep( + position + 1, + expanded, + 'Set up this step', + 'Choose a step', + activeStep + ) : null} );