feat: 懒加载接口

pull/103/head
bigfengyu 5 years ago
parent 4394f206ef
commit f7f6d05994

@ -3,6 +3,7 @@ export const addInterface = (itf: any, onResolved: any) => ({
interface: itf,
onResolved,
})
export const addInterfaceSucceeded = (payload: any) => ({
type: 'INTERFACE_ADD_SUCCEEDED',
payload,
@ -12,6 +13,21 @@ export const addInterfaceFailed = (message: any) => ({
message,
})
export const fetchInterface = (id: number, onResolved: any) => ({
type: 'INTERFACE_FETCH',
id,
onResolved,
})
export const fetchInterfaceSucceeded = (payload: any) => ({
type: 'INTERFACE_FETCH_SUCCEEDED',
payload,
})
export const fetchInterfaceFailed = (message: any) => ({
type: 'INTERFACE_FETCH_FAILED',
message,
})
export const updateInterface = (itf: any, onResolved: any) => ({
type: 'INTERFACE_UPDATE',
interface: itf,

@ -4,7 +4,7 @@ import InterfaceEditorToolbar from './InterfaceEditorToolbar'
import InterfaceSummary, {
BODY_OPTION,
REQUEST_PARAMS_TYPE,
rptFromStr2Num
rptFromStr2Num,
} from './InterfaceSummary'
import PropertyList from './PropertyList'
import MoveInterfaceForm from './MoveInterfaceForm'
@ -13,40 +13,35 @@ import { RootState } from 'actions/types'
import { lockInterface, unlockInterface } from 'actions/interface'
import { updateProperties } from 'actions/property'
import { updateInterface } from 'actions/interface'
import Spin from '../../components/utils/Spin'
export const RequestPropertyList = (props: any) => {
return (
<PropertyList scope="request" title="请求参数" label="请求" {...props} />
)
return <PropertyList scope="request" title="请求参数" label="请求" {...props} />
}
export const ResponsePropertyList = (props: any) => (
<PropertyList scope="response" title="响应内容" label="响应" {...props} />
)
type InterfaceEditorProps = {
auth: any;
itf: any;
properties: any[];
mod: any;
repository: any;
lockInterface: typeof lockInterface;
unlockInterface: typeof unlockInterface;
updateInterface: typeof updateInterface;
updateProperties: typeof updateProperties;
auth: any
itf: any
mod: any
repository: any
lockInterface: typeof lockInterface
unlockInterface: typeof unlockInterface
updateInterface: typeof updateInterface
updateProperties: typeof updateProperties
}
type InterfaceEditorState = {
summaryState: any;
itf: any;
properties: any;
editable: boolean;
moveInterfaceDialogOpen: boolean;
summaryState: any
itf: any
properties: any
editable: boolean
moveInterfaceDialogOpen: boolean
}
// TODO 2.x 参考 MySQL Workbench 的字段编辑器
// TODO 2.x 支持复制整个接口到其他模块、其他项目
class InterfaceEditor extends Component<
InterfaceEditorProps,
InterfaceEditorState
> {
class InterfaceEditor extends Component<InterfaceEditorProps, InterfaceEditorState> {
static childContextTypes = {
handleLockInterface: PropTypes.func.isRequired,
handleUnlockInterface: PropTypes.func.isRequired,
@ -68,15 +63,19 @@ class InterfaceEditor extends Component<
moveInterfaceDialogOpen: false,
}
this.summaryStateChange = this.summaryStateChange.bind(this)
// { itf: {}, properties: [] }
}
static mapPropsToState(prevProps: any, prevStates: any = {}) {
const { auth, itf, properties } = prevProps
const { auth, itf } = prevProps
const editable = !!(itf.locker && itf.locker.id === auth.id)
return {
...prevStates,
itf,
properties: properties.map((property: any) => ({ ...property })),
editable: !!(itf.locker && itf.locker.id === auth.id),
// 编辑模式下不替换 properties
properties:
editable && prevStates.properties
? prevStates.properties
: itf.properties?.map((property: any) => ({ ...property })),
editable,
}
}
getChildContext() {
@ -90,7 +89,8 @@ class InterfaceEditor extends Component<
componentWillReceiveProps(nextProps: any) {
if (
nextProps.itf.id === this.state.itf.id &&
nextProps.itf.updatedAt === this.state.itf.updatedAt
nextProps.itf.updatedAt === this.state.itf.updatedAt &&
this.state.properties !== undefined
) {
return
}
@ -128,28 +128,35 @@ class InterfaceEditor extends Component<
stateChangeHandler={this.summaryStateChange}
handleChangeInterface={this.handleChangeInterface}
/>
<RequestPropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
interfaceId={itf.id}
bodyOption={this.state.summaryState.bodyOption}
requestParamsType={this.state.summaryState.requestParamsType}
handleChangeProperty={this.handleChangeProperty}
handleDeleteMemoryProperty={this.handleDeleteMemoryProperty}
/>
<ResponsePropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
interfaceId={itf.id}
handleChangeProperty={this.handleChangeProperty}
handleDeleteMemoryProperty={this.handleDeleteMemoryProperty}
/>
{this.state.properties ? (
<>
<RequestPropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
interfaceId={itf.id}
bodyOption={this.state.summaryState.bodyOption}
requestParamsType={this.state.summaryState.requestParamsType}
handleChangeProperty={this.handleChangeProperty}
handleDeleteMemoryProperty={this.handleDeleteMemoryProperty}
/>
<ResponsePropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
interfaceId={itf.id}
handleChangeProperty={this.handleChangeProperty}
handleDeleteMemoryProperty={this.handleDeleteMemoryProperty}
/>
</>
) : (
<Spin />
)}
{this.state.moveInterfaceDialogOpen && (
<MoveInterfaceForm
@ -166,7 +173,7 @@ class InterfaceEditor extends Component<
}
handleAddMemoryProperty = (property: any, cb: any) => {
this.handleAddMemoryProperties([property], cb)
};
}
handleAddMemoryProperties = (properties: any, cb: any) => {
const requestParamsType = this.state.summaryState.requestParamsType
const rpt = rptFromStr2Num(requestParamsType)
@ -186,7 +193,7 @@ class InterfaceEditor extends Component<
cb(properties)
}
})
};
}
handleDeleteMemoryProperty = (property: any, cb: any) => {
const properties = [...this.state.properties]
const index = properties.findIndex(item => item.id === property.id)
@ -209,7 +216,7 @@ class InterfaceEditor extends Component<
}
})
}
};
}
handleChangeProperty = (property: any) => {
const properties = [...this.state.properties]
const index = properties.findIndex(item => item.id === property.id)
@ -217,7 +224,7 @@ class InterfaceEditor extends Component<
properties.splice(index, 1, property)
this.setState({ properties })
}
};
}
handleChangeInterface = (newItf: any) => {
this.setState({
itf: {
@ -225,7 +232,7 @@ class InterfaceEditor extends Component<
...newItf,
},
})
};
}
handleSaveInterfaceAndProperties = (e: any) => {
e.preventDefault()
const { itf } = this.state
@ -241,33 +248,28 @@ class InterfaceEditor extends Component<
},
() => {
/** empty */
}
)
updateProperties(
this.state.itf.id,
this.state.properties,
this.state.summaryState,
() => {
this.handleUnlockInterface()
}
},
)
};
updateProperties(this.state.itf.id, this.state.properties, this.state.summaryState, () => {
this.handleUnlockInterface()
})
}
handleMoveInterface = () => {
this.setState({
moveInterfaceDialogOpen: true,
})
};
}
handleMoveInterfaceSubmit = () => {
/** empty */
};
}
handleLockInterface = () => {
const { itf, lockInterface } = this.props
lockInterface(itf.id)
};
}
handleUnlockInterface = () => {
const { itf, unlockInterface } = this.props
unlockInterface(itf.id)
};
}
}
const mapStateToProps = (state: RootState) => ({
@ -281,7 +283,4 @@ const mapDispatchToProps = {
updateProperties,
updateInterface,
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(InterfaceEditor)
export default connect(mapStateToProps, mapDispatchToProps)(InterfaceEditor)

@ -1,105 +0,0 @@
import React, { Component } from 'react'
import { PropTypes, connect, Link } from '../../family'
import { moveInterface } from '../../actions/interface'
const OP_MOVE = 1
const OP_COPY = 2
class MoveInterfaceForm extends Component {
static contextTypes = {
rmodal: PropTypes.instanceOf(Component),
onAddInterface: PropTypes.func.isRequired,
onUpdateInterface: PropTypes.func.isRequired
}
static propTypes = {
title: PropTypes.string.isRequired,
repository: PropTypes.object.isRequired,
itfId: PropTypes.number.isRequired,
moveInterface: PropTypes.func.isRequired
}
constructor (props) {
super(props)
const { repository } = props
let modId = 0
if (repository.modules.length > 0) {
modId = repository.modules[0].id
}
this.state = {
op: OP_MOVE, // 1 move, 2 copy
modId
}
}
render () {
const { rmodal } = this.context
const { repository } = this.props
const { modId, op } = this.state
return (
<section>
<div className='rmodal-header'>
<span className='rmodal-title'>{this.props.title}</span>
</div>
<form className='form-horizontal w600' onSubmit={this.handleSubmit} >
<div className='rmodal-body'>
<div className='form-group row'>
<label className='col-sm-2 control-label'>模块</label>
<div className='col-sm-10'>
<select className='form-control' onChange={e => { this.setState({ modId: +e.target.value }) }}>
{repository.modules.map(x => <option key={x.id} value={x.id} checked={x.id === modId}>{x.name}</option>)}
</select>
</div>
</div>
<div className='form-group row'>
<label className='col-sm-2 control-label'>选项</label>
<div className='col-sm-10'>
<div className='col-sm-10'>
<div className='form-check'>
<input className='form-check-input' type='radio' name='op' id='gridRadios1' value='1' checked={op === OP_MOVE} onChange={() => { this.setState({ op: OP_MOVE }) }} />
<label className='form-check-label' htmlFor='gridRadios1'> 移动 </label>
</div>
<div className='form-check'>
<input className='form-check-input' type='radio' name='op' id='gridRadios2' value='2' checked={op === OP_COPY} onChange={() => { this.setState({ op: OP_COPY }) }} />
<label className='form-check-label' htmlFor='gridRadios2'> 复制 </label>
</div>
</div>
</div>
</div>
<div className='rmodal-footer'>
<div className='form-group row mb0'>
<label className='col-sm-2 control-label' />
<div className='col-sm-10'>
<button type='submit' className='btn btn-success w140 mr20'>提交</button>
<Link to='' onClick={e => { e.preventDefault(); rmodal.close() }} className='mr10'>取消</Link>
</div>
</div>
</div>
</div>
</form>
</section>
)
}
componentDidUpdate () {
this.context.rmodal.reposition()
}
handleSubmit = (e) => {
e.preventDefault()
const params = {
modId: this.state.modId,
op: this.state.op,
itfId: this.props.itfId
}
this.props.moveInterface(params, () => {
let { rmodal } = this.context
if (rmodal) rmodal.resolve()
})
}
}
const mapStateToProps = (state) => ({
})
const mapDispatchToProps = ({
moveInterface
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(MoveInterfaceForm)

@ -155,15 +155,12 @@ class RepositoryEditor extends Component<Props, States> {
const mod: Module =
repository && repository.modules && repository.modules.length
? repository.modules.find(item => item.id === +params.mod) ||
repository.modules[0]
: {} as Module
? repository.modules.find(item => item.id === +params.mod) || repository.modules[0]
: ({} as Module)
const itf: Interface =
mod.interfaces && mod.interfaces.length
? mod.interfaces.find((item: any) => item.id === +params.itf) ||
mod.interfaces[0]
: {} as Interface
const properties = itf.properties || []
? mod.interfaces.find((item: any) => item.id === +params.itf) || mod.interfaces[0]
: ({} as Interface)
const ownerlink = repository.organization
? `/organization/repository?organization=${repository.organization.id}`
@ -273,7 +270,7 @@ class RepositoryEditor extends Component<Props, States> {
<ModuleList mods={repository.modules} repository={repository} mod={mod} />
<div className="InterfaceWrapper">
<InterfaceList itfs={mod.interfaces} repository={repository} mod={mod} itf={itf} />
<InterfaceEditor itf={itf} properties={properties} mod={mod} repository={repository} />
<InterfaceEditor itf={itf} mod={mod} repository={repository} />
</div>
</div>
</article >

@ -23,12 +23,13 @@ class DropdownMenuBase extends Component<any, any> {
static contextTypes = {
store: PropTypes.object,
}
static filter = (respository: any, seed: any) => {
static filter = (respository: any, seed: string) => {
const nextRespository = { ...respository, modules: [] }
let counter = 0
seed = seed.toLowerCase()
respository.modules.forEach((mod: any) => {
const nextModule = { ...mod, interfaces: [] }
let matchModule = nextModule.name.indexOf(seed) !== -1
let matchModule = nextModule.name.toLowerCase().indexOf(seed) !== -1
if (matchModule) {
counter++
nextRespository.modules.push(nextModule)
@ -36,7 +37,10 @@ class DropdownMenuBase extends Component<any, any> {
mod.interfaces.forEach((itf: any) => {
const nextInterface = { ...itf, properties: [] }
let matchInterface = nextInterface.name.indexOf(seed) !== -1 || nextInterface.url.indexOf(seed) !== -1 || nextInterface.method === seed
const matchInterface =
nextInterface.name.toLowerCase().indexOf(seed) !== -1 ||
nextInterface.url.toLowerCase().indexOf(seed) !== -1 ||
nextInterface.method === seed
if (matchInterface) {
counter++
if (!matchModule) {
@ -46,22 +50,22 @@ class DropdownMenuBase extends Component<any, any> {
nextModule.interfaces.push(nextInterface)
}
itf.properties.forEach((property: any) => {
const nextProperty = { ...property }
const matchProperty = nextProperty.name.indexOf(seed) !== -1
if (matchProperty) {
counter++
if (!matchModule) {
matchModule = true
nextRespository.modules.push(nextModule)
}
if (!matchInterface) {
matchInterface = true
nextModule.interfaces.push(nextInterface)
}
nextInterface.properties.push(nextProperty)
}
})
// itf.properties.forEach((property: any) => {
// const nextProperty = { ...property }
// const matchProperty = nextProperty.name.indexOf(seed) !== -1
// if (matchProperty) {
// counter++
// if (!matchModule) {
// matchModule = true
// nextRespository.modules.push(nextModule)
// }
// if (!matchInterface) {
// matchInterface = true
// nextModule.interfaces.push(nextInterface)
// }
// nextInterface.properties.push(nextProperty)
// }
// })
})
})
return { nextRespository, counter }
@ -123,16 +127,16 @@ interface IState {
// TODO 2.2 自动隐藏,高阶组件
class RepositorySearcher extends Component<any, IState> {
debouncedInput = AwesomeDebouncePromise((val: string) => this.setState({ result: val }), 300)
constructor(props: any) {
super(props)
this.state = { seed: '', result: '' }
this.debouncedInput = this.debouncedInput.bind(this)
}
render() {
const { repository } = this.props
const { seed, result } = this.state
const debouncedInput = AwesomeDebouncePromise((val: string) => this.setState({ result: val }), 500)
return (
<div className="RepositorySearcher dropdown">
<input
@ -140,12 +144,12 @@ class RepositorySearcher extends Component<any, IState> {
onChange={e => {
const val = e.target.value
this.setState({ seed: val })
debouncedInput(val)
this.debouncedInput(val)
}}
className="dropdown-input form-control"
placeholder="工作区搜索"
/>
{this.state.result && <DropdownMenu repository={repository} seed={result} onSelect={this.clearSeed} />}
{result && <DropdownMenu repository={repository} seed={result} onSelect={this.clearSeed} />}
</div>
)
}

@ -2,16 +2,11 @@ import { takeLatest } from 'redux-saga/effects'
import start from './start'
import handleLocation from './handleLocation'
import { createBrowserHistory as createHistory, History } from 'history'
import {
createStore,
applyMiddleware,
combineReducers,
compose,
Store
} from 'redux'
import { createStore, applyMiddleware, combineReducers, compose, Store } from 'redux'
import {
routerMiddleware as createRouterMiddleware,
connectRouter
connectRouter,
LOCATION_CHANGE,
} from 'connected-react-router'
import loggerMiddleware from './loggerMiddleware'
import createSagaMiddleware from 'redux-saga'
@ -22,12 +17,11 @@ const _reducers: any = {} // { id/key: reducer }
const _prefilters: any[] = []
const _sagas: any = {} // { pattern: [sagas] }
const _listeners: any = {} // { pathname: [listeners] }
// let _routes: any
const Family: {
store?: Store;
history?: History;
[k: string]: any;
store?: Store
history?: History
[k: string]: any
} = {
store: undefined,
history: undefined,
@ -93,13 +87,6 @@ const Family: {
}
return this
},
// setRoutes(routes: any) {
// if (!routes) {
// return this
// }
// _routes = routes
// return this
// },
start(container: any) {
_relatives.forEach(({ reducers = {}, sagas = {}, listeners = {} }: any) => {
this.addReducers(reducers)
@ -126,22 +113,17 @@ const Family: {
: [routerMiddleware, sagaMiddleware]
const store = createStore<any, any, any, any>(
combineReducers({ ..._reducers, router: connectRouter(history) }),
composeEnhancers(applyMiddleware(...middlewares))
composeEnhancers(applyMiddleware(...middlewares)),
)
// 初始化当前页所需的数据
// @ts-ignore
history.location.params = URI(history.location.search || '').search(true)
history.listen((location, action: any) =>
handleLocation({ store, listeners: _listeners, location, action })
)
Family.store = store
Family.history = history
/** init store end */
function* rootSaga() {
try {
for (const prefilter of _prefilters) {
yield* prefilter({ store })
@ -153,11 +135,11 @@ const Family: {
// 在执行 prefilter 之后再开始渲染主UI
start(container, { store, history })
// handleLocation({
// store,
// listeners: _listeners,
// location: { pathname: '*' },
// })
// 监听 connected-react-router 地质变化的 action 而不是用 hisory.listen 以防冲突
yield takeLatest(LOCATION_CHANGE, (action: any) => {
handleLocation({ store, listeners: _listeners, location: action.payload.location })
})
handleLocation({
store,
listeners: _listeners,
@ -169,10 +151,8 @@ const Family: {
yield takeLatest(pattern, saga)
}
}
}
sagaMiddleware.run(rootSaga)
},
}

@ -14,7 +14,7 @@ export const PropTypes = _PropTypes
export { render, findDOMNode } from 'react-dom' // ReactDOM
export { connect, Provider } from 'react-redux'
export { createStore, applyMiddleware, combineReducers, compose } from 'redux'
export { BrowserRouter, HashRouter, NavLink, Link, Redirect, Router, Route, Switch } from 'react-router-dom'
export { NavLink, Link, Redirect, Router, Route, Switch } from 'react-router-dom'
export { push, replace, go, goBack, goForward } from 'connected-react-router'
export { call, put, take, takeLatest } from 'redux-saga/effects'
export { delay } from 'redux-saga/effects'

@ -12,6 +12,7 @@ export default {
MODULE_MOVE: ModuleEffects.moveModule,
MODULE_DELETE: ModuleEffects.deleteModule,
INTERFACE_FETCH: InterfaceEffects.fetchInterface,
INTERFACE_ADD: InterfaceEffects.addInterface,
INTERFACE_UPDATE: InterfaceEffects.updateInterface,
INTERFACE_MOVE: InterfaceEffects.moveInterface,

@ -6,6 +6,7 @@ import * as ModuleAction from '../actions/module'
import * as ModuleEffects from './effects/module'
import * as RepositoryAction from '../actions/repository'
import * as RepositoryEffects from './effects/repository'
import _ from 'lodash'
export default {
reducers: {
repository(
@ -51,7 +52,9 @@ export default {
modules: modules.map((mod: any) => ({
...mod,
interfaces: mod.interfaces.map((itf: any) => {
if (itf.id !== itfId) { return itf }
if (itf.id !== itfId) {
return itf
}
return {
...itf,
lockerId: locker.id,
@ -62,6 +65,28 @@ export default {
})),
},
}
case 'INTERFACE_FETCH_SUCCEEDED': {
modules = state.data.modules
const fetchedItf = _.omit(action.payload, ['requestProperties', 'responseProperties'])
return {
...state,
data: {
...state.data,
modules: modules.map((mod: any) => ({
...mod,
interfaces: mod.interfaces.map((itf: any) => {
if (itf.id !== fetchedItf.id) {
return itf
}
return {
...itf,
...fetchedItf,
}
}),
})),
},
}
}
case InterfaceAction.unlockInterfaceSucceeded(undefined).type:
modules = state.data.modules
itfId = action.payload.itfId
@ -72,7 +97,9 @@ export default {
modules: modules.map((mod: any) => ({
...mod,
interfaces: mod.interfaces.map((itf: any) => {
if (itf.id !== itfId) { return itf }
if (itf.id !== itfId) {
return itf
}
return {
...itf,
lockerId: null,
@ -94,7 +121,9 @@ export default {
modules: modules.map((mod: any) => ({
...mod,
interfaces: mod.interfaces.map((itf: any) => {
if (itf.id !== itfId) { return itf }
if (itf.id !== itfId) {
return itf
}
return {
...itf,
properties,
@ -114,7 +143,9 @@ export default {
modules: modules.map((mod: any) => ({
...mod,
interfaces: mod.interfaces.map((x: any) => {
if (x.id !== itf.id) { return x }
if (x.id !== itf.id) {
return x
}
return {
...itf,
locker: x.locker,
@ -147,10 +178,10 @@ export default {
modules: modules.map((mod: any) =>
mod.id === itf.moduleId
? {
...mod,
interfaces: [...mod.interfaces, itf],
}
: mod
...mod,
interfaces: [...mod.interfaces, itf],
}
: mod,
),
},
}
@ -164,11 +195,11 @@ export default {
modules: modules.map((x: any) =>
x.id === mod.id
? {
...x,
name: mod.name,
description: mod.description,
}
: x
...x,
name: mod.name,
description: mod.description,
}
: x,
),
},
}
@ -187,10 +218,12 @@ export default {
modules: modules.map((mod: any) =>
mod.id === moduleId
? {
...mod,
interfaces: [...mod.interfaces].sort((a: any, b: any) => itfIdsMap[a.id] - itfIdsMap[b.id]),
}
: mod
...mod,
interfaces: [...mod.interfaces].sort(
(a: any, b: any) => itfIdsMap[a.id] - itfIdsMap[b.id],
),
}
: mod,
),
},
}
@ -206,7 +239,9 @@ export default {
...state,
data: {
...state.data,
modules: [...modules].sort((a: any, b: any) => moduleIdsMap[a.id] - moduleIdsMap[b.id]),
modules: [...modules].sort(
(a: any, b: any) => moduleIdsMap[a.id] - moduleIdsMap[b.id],
),
},
}
}

@ -8,6 +8,22 @@ import * as InterfaceAction from '../../actions/interface'
import EditorService from '../services/Editor'
import * as RepositoryAction from '../../actions/repository'
export function* fetchInterface(action: any) {
try {
const payload = yield call(EditorService.fetchInterface, action.id)
yield put(InterfaceAction.fetchInterfaceSucceeded(payload))
if (action.onResolved) {
action.onResolved()
}
} catch (e) {
console.error(e.message)
yield put(InterfaceAction.fetchInterfaceFailed(e.message))
if (action.onRejected) {
action.onRejected()
}
}
}
export function* addInterface(action: any) {
try {
const payload = yield call(EditorService.addInterface, action.interface)

@ -1,7 +1,9 @@
import { call, put, select } from 'redux-saga/effects'
import { call, put, select, take } from 'redux-saga/effects'
import * as RepositoryAction from '../../actions/repository'
import * as InterfaceAction from '../../actions/interface'
import RepositoryService from '../services/Repository'
import { RootState } from 'actions/types'
import { getCurrentInterfaceId } from '../../selectors/interface'
import { StoreStateRouterLocationURI } from 'family/index'
import { IFetchDefaultValsAction, fetchDefaultValsFailed, IUpdateDefaultValsAction } from '../../actions/repository'
@ -89,17 +91,31 @@ export function* fetchRepository(action: any) {
const router = yield select((state: RootState) => state.router)
const uri = StoreStateRouterLocationURI(router)
const params = uri.search(true)
const count = yield call(RepositoryService.fetchRepository, action.repository || action.id, params.token)
yield put(RepositoryAction.fetchRepositorySucceeded(count))
const repository = yield call(
RepositoryService.fetchRepository,
action.repository || action.id,
params.token,
)
yield put(RepositoryAction.fetchRepositorySucceeded(repository))
} catch (e) {
yield put(RepositoryAction.fetchRepositoryFailed(e.message))
}
}
export function* handleRepositoryLocationChange(action: any) {
const repositoryId = yield select((state: RootState) => state.repository && state.repository.data && state.repository.data.id)
const repositoryId = yield select(
(state: RootState) => state.repository && state.repository.data && state.repository.data.id,
)
if (Number(action.id) !== repositoryId) {
// 切换仓库
yield put(RepositoryAction.fetchRepository(action))
yield take('REPOSITORY_FETCH_SUCCEEDED')
const itfId = yield select(getCurrentInterfaceId)
yield put(InterfaceAction.fetchInterface(itfId, () => {}))
} else if (repositoryId) {
// 切换接口
const itfId = yield select(getCurrentInterfaceId)
yield put(InterfaceAction.fetchInterface(itfId, () => {}))
}
}

@ -25,10 +25,10 @@ export default {
},
fetchRepository(id: any, token?: string) {
return fetch(
`${serve}/repository/get?id=${id}${
`${serve}/repository/get?id=${id}&excludeProperty=true${
token !== undefined ? `&token=${token}` : ''
}`,
{ ...CREDENTIALS }
{ ...CREDENTIALS },
)
.then(res => res.json())
.then(json => json.data)

@ -1,9 +1,5 @@
import {
createSelector
} from 'reselect'
import {
getRouter
} from './router'
import { createSelector } from 'reselect'
import { getRouter } from './router'
import { RootState } from 'actions/types'
const interfaceSelector = (state: RootState) => {
@ -21,7 +17,18 @@ const interfaceSelector = (state: RootState) => {
return null
}
export const getCurrentInterface = createSelector(
interfaceSelector,
result => result
export const getCurrentInterface = createSelector(interfaceSelector, result => result)
export const getCurrentInterfaceId = createSelector(
state => state.repository.data,
getRouter,
(repository: any, router: RootState['router']) => {
const itfId = +((router.location as any).params || (router.location as any).query).itf
if (itfId) {
return itfId
}
const modId = +((router.location as any).params || (router.location as any).query).mod
const mod = modId ? repository?.modules?.find((m: any) => m.id === modId) : repository?.modules[0]
return mod?.interfaces?.[0]?.id
},
)

@ -113,6 +113,7 @@
"no-unused-expression": false,
"jsx-no-lambda": false,
"no-shadowed-variable": false,
"react-hooks-nesting": "error"
"react-hooks-nesting": "error",
"no-empty": false
}
}
Loading…
Cancel
Save