Skip to content

Commit

Permalink
feat: 简化新建字段的流程,不再弹窗啦!
Browse files Browse the repository at this point in the history
  • Loading branch information
bigfengyu committed Aug 21, 2019
1 parent 696c697 commit 35d0718
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 54 deletions.
2 changes: 2 additions & 0 deletions src/components/editor/InterfaceEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class InterfaceEditor extends Component<
/>
<RequestPropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
Expand All @@ -135,6 +136,7 @@ class InterfaceEditor extends Component<
/>
<ResponsePropertyList
properties={this.state.properties}
auth={auth}
editable={editable}
repository={repository}
mod={mod}
Expand Down
4 changes: 2 additions & 2 deletions src/components/editor/PropertyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import { Button } from '@material-ui/core'
export const TYPES = ['String', 'Number', 'Boolean', 'Object', 'Array', 'Function', 'RegExp']

// 模拟数据
const mockProperty = process.env.NODE_ENV === 'development'
export const mockProperty = process.env.NODE_ENV === 'development'
? () => Mock.mock({
'scope|1': ['request', 'response'],
name: '@WORD(6)',
'type|1': TYPES,
'type|1': ['String', 'Number', 'Boolean'],
'value|1': ['@INT', '@FLOAT', '@TITLE', '@NAME'],
description: '@CSENTENCE',
parentId: -1,
Expand Down
101 changes: 93 additions & 8 deletions src/components/editor/PropertyList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,38 @@ import { GoPlus, GoTrashcan, GoQuestion } from 'react-icons/go'
import { rptFromStr2Num } from './InterfaceSummary'
import './PropertyList.css'
import { ButtonGroup, Button, Checkbox } from '@material-ui/core'
import classNames from 'classnames'
import _ from 'lodash'
import Mock from 'mockjs'
import JSON5 from 'json5'
import { elementInViewport } from 'utils/ElementInViewport'

const mockProperty = process.env.NODE_ENV === 'development'
? () => Mock.mock({
'scope|1': ['request', 'response'],
name: '@WORD(6)',
'type|1': ['String', 'Number', 'Boolean'],
'value|1': ['@INT', '@FLOAT', '@TITLE', '@NAME'],
description: '@CSENTENCE',
parentId: -1,
interfaceId: '@NATURAL',
moduleId: '@NATURAL',
repositoryId: '@NATURAL',
})
: () => ({
scope: 'response',
name: '',
type: 'String',
value: '',
description: '',
parentId: -1,
interfaceId: undefined,
moduleId: undefined,
repositoryId: undefined,
})

export const RequestPropertyListPreviewer = (props: any) => (
<Previewer {...props} />
<Previewer {...props}/>
)

export const ResponsePropertyListPreviewer = (props: any) => (
Expand Down Expand Up @@ -94,15 +122,40 @@ const getFormattedValue = (itf: any) => {
}

class SortableTreeTableRow extends Component<any, any> {
focusNameInput: HTMLInputElement | undefined = undefined
state = {
property: { children: [] },
childrenAdded: false,
}
static getDerivedStateFromProps(nextProps: any, prevState: any) {
return {
property: nextProps.property,
childrenAdded: nextProps.property.children.length > prevState.property.children.length,
}
}
componentDidMount() {
this.focusInput()
}
componentDidUpdate() {
this.focusInput()
}
focusInput() {
if (this.focusNameInput && this.state.childrenAdded) {
this.focusNameInput.focus()
if (!elementInViewport(this.focusNameInput)) {
this.focusNameInput.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' })
}
}
}
render() {
const { property, editable } = this.props
const { handleClickCreateChildPropertyButton, handleDeleteMemoryProperty, handleChangePropertyField, handleSortProperties } = this.props
const { property, editable, handleClickCreateChildPropertyButton, highlightId,
handleDeleteMemoryProperty, handleChangePropertyField, handleSortProperties } = this.props
return (
<RSortable group={property.depth} handle=".SortableTreeTableRow" disabled={!editable} onChange={handleSortProperties}>
<div className={`RSortableWrapper depth${property.depth}`}>
{property.children.sort((a: any, b: any) => a.priority - b.priority).map((item: any) =>
<div key={item.id} className="SortableTreeTableRow" data-id={item.id}>
<div className="flex-row">
<div className={classNames('flex-row', { highlight: item.id === highlightId })}>
{editable &&
<div className="td operations nowrap">
{(item.type === 'Object' || item.type === 'Array')
Expand All @@ -125,6 +178,11 @@ class SortableTreeTableRow extends Component<any, any> {
<div style={{ float: 'right' }}><PropertyLabel pos={item.pos} /></div> : null}
</>
: <input
ref={(input: HTMLInputElement) => {
if (item.id === highlightId) {
this.focusNameInput = input
}
}}
value={item.name}
onChange={e => handleChangePropertyField(item.id, 'name', e.target.value)}
className="form-control editable"
Expand Down Expand Up @@ -231,18 +289,22 @@ class PropertyList extends Component<any, any> {
label: PropTypes.string.isRequired,
scope: PropTypes.string.isRequired,
properties: PropTypes.array,
auth: PropTypes.object.isRequired,
repository: PropTypes.object.isRequired,
mod: PropTypes.object.isRequired,
itf: PropTypes.object.isRequired,
editable: PropTypes.bool.isRequired,

/** optional */
bodyOption: PropTypes.string,
requestParamsType: PropTypes.string,
}
static contextTypes = {
handleAddMemoryProperty: PropTypes.func.isRequired,
}
constructor(props: any) {
super(props)
this.state = {
highlightId: undefined,
createProperty: false,
createChildProperty: false,
previewer: props.scope === 'response',
Expand Down Expand Up @@ -279,6 +341,8 @@ class PropertyList extends Component<any, any> {
<SortableTreeTable
root={Tree.arrayToTree(scopedProperties)}
editable={editable}
highlightId={this.state.highlightId}
// handlefocused={this.handlefocused}
handleClickCreateChildPropertyButton={this.handleClickCreateChildPropertyButton}
handleDeleteMemoryProperty={this.handleDeleteMemoryProperty}
handleChangePropertyField={this.handleChangePropertyField}
Expand Down Expand Up @@ -310,10 +374,31 @@ class PropertyList extends Component<any, any> {
)
}
handleClickCreatePropertyButton = () => {
this.setState({ createProperty: true })
this.handleClickCreateChildPropertyButton()
}
handleClickCreateChildPropertyButton = (item: any) => {
this.setState({ createChildProperty: item })
// handlefocused = () => {
// this.setState({ highlightId: undefined })
// }
handleClickCreateChildPropertyButton = (parent: any = { id: -1 }) => {
const { handleAddMemoryProperty } = this.context
const { auth, scope, repository = {}, mod = {}, itf = {} } = this.props
const childId = _.uniqueId('memory-')
const child = {
...mockProperty(),
id: childId,
creatorId: auth.id,
repositoryId: repository.id,
moduleId: mod.id,
interfaceId: itf.id,
scope,
parentId: parent.id,
}
this.setState({
highlightId: childId,
})
handleAddMemoryProperty(child, () => {
/** empty */
})
}
handleClickImporterButton = () => {
this.setState({ importer: true })
Expand Down
16 changes: 14 additions & 2 deletions src/components/editor/RepositoryEditor.sass
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,22 @@
text-align: center
color: #999

@keyframes hightlight
0%
background-color: unset;
50%
background-color: #fff3cd
100%
background-color: unset;

.SortableTreeTable
.SortableTreeTableHeader,
.SortableTreeTableRow
.flex-row
display: flex
&.highlight
.thtd
animation: hightlight 1.5s 1
.thtd
border: 1px solid #eceeef
flex-grow: 1
Expand All @@ -340,7 +351,6 @@
margin-bottom: -1px
.th, .td
&.operations
background: #fff
width: 4.5rem
min-width: 4.5rem
&.name
Expand Down Expand Up @@ -413,7 +423,9 @@
&.payload.name
@for $i from 0 through 10
&.depth-#{$i}
padding-left: $i * 1rem
padding-left: $i * 1.3rem
&:after
width: $i * 1.3rem
&.payload.value
max-height: unset
overflow-wrap: break-word
Expand Down
8 changes: 4 additions & 4 deletions src/components/editor/RepositoryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ class RepositoryEditor extends Component<any, any> {
}

componentDidMount() {
const id = +this.props.location.params.id
if (!this.props.repository.data || this.props.repository.data.id !== id) {
this.props.onFetchRepository({ id })
}
// const id = +this.props.location.params.id
// if (!this.props.repository.data || this.props.repository.data.id !== id) {
// this.props.onFetchRepository({ id })
// }
}
render() {
const { location: { params }, auth } = this.props
Expand Down
74 changes: 38 additions & 36 deletions src/relatives/RepositoryRelative.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,42 +172,44 @@ export default {
),
},
}
case 'INTERFACE_LIST_SORT_SUCCEEDED':
modules = state.data.modules
const iftIds = action.ids
const itfIdsMap: any = {}
iftIds.forEach((id: number, index: number) => {
itfIdsMap[id] = index
})
const moduleId = action.moduleId
return {
...state,
data: {
...state.data,
modules: modules.map((mod: any) =>
mod.id === moduleId
? {
...mod,
interfaces: [...mod.interfaces].sort((a: any, b: any) => itfIdsMap[a.id] - itfIdsMap[b.id]),
}
: mod
),
},
}
case 'MODULE_LIST_SORT_SUCCEEDED':
modules = state.data.modules
const moduleIds = action.ids
const moduleIdsMap: any = {}
moduleIds.forEach((id: number, index: number) => {
moduleIdsMap[id] = index
})
return {
...state,
data: {
...state.data,
modules: [...modules].sort((a: any, b: any) => moduleIdsMap[a.id] - moduleIdsMap[b.id]),
},
}
case 'INTERFACE_LIST_SORT_SUCCEEDED': {
const modules = state.data.modules
const iftIds = action.ids
const itfIdsMap: any = {}
iftIds.forEach((id: number, index: number) => {
itfIdsMap[id] = index
})
const moduleId = action.moduleId
return {
...state,
data: {
...state.data,
modules: modules.map((mod: any) =>
mod.id === moduleId
? {
...mod,
interfaces: [...mod.interfaces].sort((a: any, b: any) => itfIdsMap[a.id] - itfIdsMap[b.id]),
}
: mod
),
},
}
}
case 'MODULE_LIST_SORT_SUCCEEDED': {
const modules = state.data.modules
const moduleIds = action.ids
const moduleIdsMap: any = {}
moduleIds.forEach((id: number, index: number) => {
moduleIdsMap[id] = index
})
return {
...state,
data: {
...state.data,
modules: [...modules].sort((a: any, b: any) => moduleIdsMap[a.id] - moduleIdsMap[b.id]),
},
}
}
default:
return state
}
Expand Down
5 changes: 3 additions & 2 deletions src/relatives/effects/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ export function* updateRepository(action: any) {
acceptedKeys.forEach(x => {
params[x] = r[x]
})
const repository = yield call(RepositoryService.updateRepository, params)
yield put(RepositoryAction.updateRepositorySucceeded(repository))
yield call(RepositoryService.updateRepository, params)
yield put(RepositoryAction.updateRepositorySucceeded(params))
yield put(RepositoryAction.fetchRepository({id: params.id}))
if (action.onResolved) { action.onResolved() }
} catch (e) {
yield put(RepositoryAction.updateRepositoryFailed(e.message))
Expand Down
19 changes: 19 additions & 0 deletions src/utils/ElementInViewport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export function elementInViewport(el: HTMLElement) {
let top = el.offsetTop
let left = el.offsetLeft
const width = el.offsetWidth
const height = el.offsetHeight

while (el.offsetParent) {
el = el.offsetParent as HTMLElement
top += el.offsetTop
left += el.offsetLeft
}

return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
)
}

0 comments on commit 35d0718

Please sign in to comment.