Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

Commit fda666b

Browse files
committed
Merge branch 'labeler' into dev
2 parents 662d1ca + 8241845 commit fda666b

File tree

14 files changed

+406
-60
lines changed

14 files changed

+406
-60
lines changed

containers/ArticleViwer/BodyFooter.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ const Content = ({ thread }) => {
1212
case THREAD.JOB: {
1313
return (
1414
<Wrapper>
15-
<Labeler label="城市" iconSrc={`${ICON_CMD}/city_map.svg`} />
15+
<Labeler label="city" />
1616
<Divider src={`${ICON_CMD}/more.svg`} />
17-
<Labeler label="薪资" iconSrc={`${ICON_CMD}/money_yuan.svg`} />
17+
<Labeler label="salary" />
1818
</Wrapper>
1919
)
2020
}

containers/Labeler/Options.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React from 'react'
2+
import R from 'ramda'
3+
import TagList from './TagList'
4+
5+
import { ICON_CMD } from '../../config'
6+
7+
import {
8+
OptionWrapper,
9+
OptionItem,
10+
OptionCheckIcon,
11+
OptionText,
12+
} from './styles/options'
13+
14+
import optionMap from './option_map'
15+
import { uid } from '../../utils'
16+
17+
const OptionItems = ({ items, selected, onOptionSelect }) => {
18+
return (
19+
<OptionWrapper>
20+
{items.map(item => (
21+
<OptionItem key={uid.gen()}>
22+
<OptionCheckIcon
23+
src={`${ICON_CMD}/check.svg`}
24+
active={R.contains(item, selected)}
25+
/>
26+
<OptionText onClick={onOptionSelect.bind(this, item)}>
27+
{item}
28+
</OptionText>
29+
</OptionItem>
30+
))}
31+
</OptionWrapper>
32+
)
33+
}
34+
35+
const renderOptions = (label, tagsData, selected, onOptionSelect) => {
36+
switch (label) {
37+
case 'default': {
38+
return <TagList data={tagsData} />
39+
}
40+
case 'city': {
41+
return <TagList data={tagsData} />
42+
}
43+
default: {
44+
return (
45+
<OptionItems
46+
items={optionMap[label].data}
47+
selected={selected}
48+
onOptionSelect={onOptionSelect}
49+
/>
50+
)
51+
}
52+
}
53+
}
54+
55+
const Options = ({ label, tagsData, selected, onOptionSelect }) => (
56+
<React.Fragment>
57+
{renderOptions(label, tagsData, selected, onOptionSelect)}
58+
</React.Fragment>
59+
)
60+
61+
export default Options

containers/Labeler/Selected.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react'
2+
import R from 'ramda'
3+
4+
import { Maybe } from '../../components'
5+
import { Wrapper, Item, Hightlight } from './styles/selected'
6+
7+
const renderItems = items => {
8+
if (items.length === 1) {
9+
return (
10+
<Item>
11+
(<Hightlight>{items[0]}</Hightlight>)
12+
</Item>
13+
)
14+
}
15+
// {items.map(item => <div key={uid.gen()}>{item}</div>)}
16+
return (
17+
<Item>
18+
(<Hightlight>{items[0]}, ..</Hightlight>)
19+
</Item>
20+
)
21+
}
22+
23+
const Selected = ({ items }) => (
24+
<Maybe test={!R.isEmpty(items)}>
25+
<Wrapper>{renderItems(items)}</Wrapper>
26+
</Maybe>
27+
)
28+
29+
export default Selected

containers/Labeler/index.js

Lines changed: 73 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,73 +6,111 @@
66

77
import React from 'react'
88
import PropTypes from 'prop-types'
9+
import R from 'ramda'
910
import { inject, observer } from 'mobx-react'
1011

11-
import { ICON_CMD } from '../../config'
12-
import { makeDebugger, storePlug } from '../../utils'
13-
1412
import { Popover } from '../../components'
15-
import TagList from './TagList'
13+
import Options from './Options'
14+
import Selected from './Selected'
1615
import { Wrapper, LabelItem, LabelIcon, Title } from './styles'
1716

17+
import optionMap from './option_map'
18+
import { makeDebugger, storePlug, uid } from '../../utils'
1819
import * as logic from './logic'
1920
/* eslint-disable no-unused-vars */
2021
const debug = makeDebugger('C:Labeler')
2122
/* eslint-enable no-unused-vars */
2223

24+
const trans = {
25+
default: '标签',
26+
city: '城市',
27+
salary: '月薪',
28+
exp: '经验',
29+
education: '学历',
30+
finance: '融资',
31+
scale: '规模',
32+
field: '领域',
33+
}
34+
2335
class LabelerContainer extends React.Component {
24-
componentWillMount() {
25-
const { labeler } = this.props
26-
logic.init(labeler)
36+
state = {
37+
uniqId: uid.gen(),
2738
}
2839

29-
state = { visible: false }
40+
componentWillMount() {
41+
const { labeler, label, multi } = this.props
42+
const { uniqId } = this.state
43+
44+
const options = { label, multi }
45+
logic.init(labeler, uniqId, options)
46+
}
3047

31-
onVisibleChange(visible) {
32-
if (visible) {
33-
logic.loadTagsIfNeed()
34-
}
35-
this.setState({ visible })
48+
componentWillUnmount() {
49+
const { uniqId } = this.state
50+
logic.uninit(uniqId)
3651
}
3752

3853
render() {
39-
const { labeler, label, iconSrc } = this.props
40-
const { tagsData } = labeler
54+
const { uniqId } = this.state
55+
const { labeler, label } = this.props
56+
/* const { tagsData, popVisible, bucketData, labelEntriesData } = labeler */
57+
const { labelEntriesData } = labeler
58+
const targetIndex = R.findIndex(R.propEq('uniqId', uniqId))(
59+
labelEntriesData
60+
)
4161

42-
const { visible } = this.state
62+
const { tags, popVisible, bucket } = labelEntriesData[targetIndex] || {}
4363

4464
return (
4565
<Wrapper>
46-
<Popover
47-
content={<TagList data={tagsData} />}
48-
placement="right"
49-
trigger="click"
50-
visible={visible}
51-
onVisibleChange={this.onVisibleChange.bind(this)}
52-
>
53-
<LabelItem>
54-
<LabelIcon src={iconSrc} />
55-
<Title>{label}</Title>
56-
</LabelItem>
57-
</Popover>
66+
{targetIndex >= 0 ? (
67+
<Popover
68+
content={
69+
<Options
70+
label={label}
71+
tagsData={tags}
72+
selected={bucket}
73+
onOptionSelect={logic.onOptionSelect.bind(this, uniqId)}
74+
/>
75+
}
76+
placement="right"
77+
trigger="click"
78+
visible={popVisible}
79+
onVisibleChange={logic.onVisibleChange.bind(this, uniqId)}
80+
>
81+
<LabelItem>
82+
<LabelIcon src={optionMap[label].iconSrc} />
83+
<Title>
84+
{trans[label]}
85+
<Selected items={bucket} />
86+
</Title>
87+
</LabelItem>
88+
</Popover>
89+
) : null}
5890
</Wrapper>
5991
)
6092
}
6193
}
6294

6395
LabelerContainer.propTypes = {
64-
// https://www.npmjs.com/package/prop-types
65-
label: PropTypes.oneOf(['标签', '薪资', '城市', '编辑']),
66-
// label: PropTypes.oneOf(['tag', 'salary', 'city']),
67-
iconSrc: PropTypes.string,
96+
label: PropTypes.oneOf([
97+
'default',
98+
'salary',
99+
'city',
100+
'exp',
101+
'education',
102+
'finance',
103+
'scale',
104+
'field',
105+
]),
68106
labeler: PropTypes.any,
107+
multi: PropTypes.bool,
69108
}
70109

71110
LabelerContainer.defaultProps = {
72-
label: '标签',
73-
// label: 'tag',
74-
iconSrc: `${ICON_CMD}/extra_tag.svg`,
111+
label: 'default',
75112
labeler: {},
113+
multi: false,
76114
}
77115

78116
export default inject(storePlug('labeler'))(observer(LabelerContainer))

containers/Labeler/logic.js

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import R from 'ramda'
22

3-
import { makeDebugger, $solver, asyncRes } from '../../utils'
3+
import { makeDebugger, $solver, makeGQClient } from '../../utils'
44
import SR71 from '../../utils/network/sr71'
55

66
import S from './schema'
@@ -14,35 +14,83 @@ const debug = makeDebugger('L:Labeler')
1414

1515
let store = null
1616

17-
export function loadTags() {
17+
export function loadTags(uniqId) {
1818
const communityId = store.curCommunity.id
1919
const thread = R.toUpper(store.curThread)
2020

2121
const args = { communityId, thread }
22-
sr71$.query(S.partialTags, args)
22+
const { request } = makeGQClient()
23+
24+
request(S.partialTags, args)
25+
.then(({ partialTags: tags }) => store.markUniqState(uniqId, { tags }))
26+
.catch(() => store.toast('error', { title: 'tag 加载失败', msg: '--' }))
2327
}
2428

25-
export function loadTagsIfNeed() {
26-
loadTags()
29+
export function onOptionSelect(uniqId, item) {
30+
const index = R.findIndex(R.propEq('uniqId', uniqId))(store.labelEntriesData)
31+
if (index < 0) return false
32+
// return false
33+
// toggle item if exsit
34+
if (R.contains(item, store.labelEntriesData[index].bucket)) {
35+
return store.markUniqState(uniqId, {
36+
bucket: R.reject(e => e === item, store.labelEntriesData[index].bucket),
37+
})
38+
}
39+
// replace bucket if single select mode
40+
if (!store.labelEntriesData[index].multi) {
41+
return store.markUniqState(uniqId, { popVisible: false, bucket: [item] })
42+
}
43+
// push to bucket if multi select mode
44+
store.markUniqState(uniqId, {
45+
bucket: R.uniq(R.concat(store.labelEntriesData[index].bucket, [item])),
46+
})
47+
}
48+
49+
export function onVisibleChange(uniqId, popVisible) {
50+
store.markUniqState(uniqId, { popVisible })
51+
52+
const index = R.findIndex(R.propEq('uniqId', uniqId))(store.labelEntriesData)
53+
if (index < 0) return false
54+
55+
const needLoad =
56+
store.labelEntriesData[index].label === 'default' ||
57+
store.labelEntriesData[index].label === 'city'
58+
59+
if (popVisible && needLoad) {
60+
// logic.loadTagsIfNeed()
61+
loadTags(uniqId)
62+
}
2763
}
2864

2965
// ###############################
3066
// Data & Error handlers
3167
// ###############################
3268

3369
const DataSolver = [
70+
/*
3471
{
3572
match: asyncRes('partialTags'),
36-
action: ({ partialTags: tags }) => store.markState({ tags }),
73+
action: ({ partialTags: tags }) => store.markUniqState({ tags }),
3774
},
75+
*/
3876
]
3977
const ErrSolver = []
4078

41-
export function init(_store) {
42-
if (store) return false
79+
export function init(_store, uniqId, options) {
80+
if (store) {
81+
return store.markUniqState(uniqId, options)
82+
// return store.markState({ ...options })
83+
}
4384
store = _store
4485

4586
debug(store)
4687
if (sub$) sub$.unsubscribe()
4788
sub$ = sr71$.data().subscribe($solver(DataSolver, ErrSolver))
89+
90+
return store.markUniqState(uniqId, options)
91+
// return store.markState({ ...options })
92+
}
93+
94+
export function uninit(uniqId) {
95+
store.uninit(uniqId)
4896
}

0 commit comments

Comments
 (0)