1
|
|
|
import React from 'react' |
2
|
|
|
import PropTypes from 'prop-types' |
3
|
|
|
import { withTranslation } from 'react-i18next' |
4
|
|
|
import { connect } from 'react-redux' |
5
|
|
|
import Markdown from 'react-markdown' |
6
|
|
|
import { autoDetectDmy } from '../../utils/timeFormat' |
7
|
|
|
import Icon from './Icon' |
8
|
|
|
import projectListStyle from './index.scss' |
9
|
|
|
import stackIconList from './stackIcons' |
10
|
|
|
|
11
|
|
|
const Item = ({ |
12
|
|
|
name, |
13
|
|
|
url, |
14
|
|
|
urlTitle, |
15
|
|
|
gitUrl, |
16
|
|
|
githubUrl, |
17
|
|
|
npmUrl, |
18
|
|
|
date, |
19
|
|
|
stack, |
20
|
|
|
desc, |
21
|
|
|
currentLang, |
22
|
|
|
t, |
23
|
|
|
}) => { |
24
|
|
|
const links = |
25
|
|
|
url || gitUrl || githubUrl || npmUrl ? ( |
26
|
|
|
<span className={projectListStyle.links}> |
27
|
|
|
{url && ( |
28
|
|
|
<Icon |
29
|
|
|
type="home" |
30
|
|
|
url={url} |
31
|
|
|
title={urlTitle || t('Home page')} |
32
|
|
|
size="large" |
33
|
|
|
/> |
34
|
|
|
)} |
35
|
|
|
{gitUrl && <Icon type="git" url={gitUrl} title={t('git repository')} />} |
36
|
|
|
{githubUrl && ( |
37
|
|
|
<Icon type="github" url={githubUrl} title={t('GitHub page')} /> |
38
|
|
|
)} |
39
|
|
|
{npmUrl && ( |
40
|
|
|
<Icon type="npm" url={npmUrl} title={t('npm package page')} /> |
41
|
|
|
)} |
42
|
|
|
</span> |
43
|
|
|
) : null |
44
|
|
|
|
45
|
|
|
let dateLine |
46
|
|
|
if (!date) { |
47
|
|
|
dateLine = '' |
48
|
|
|
} else if (typeof date === 'string') { |
49
|
|
|
dateLine = autoDetectDmy(date, currentLang) |
50
|
|
|
} else if (Array.isArray(date) && (date.length === 1 || date[1] === '')) { |
51
|
|
|
dateLine = t('{{from}} – now', { |
52
|
|
|
from: autoDetectDmy(date[0], currentLang), |
53
|
|
|
}) |
54
|
|
|
} else { |
55
|
|
|
dateLine = t('{{from}} – {{to}}', { |
56
|
|
|
from: autoDetectDmy(date[0], currentLang), |
57
|
|
|
to: autoDetectDmy(date[1], currentLang), |
58
|
|
|
}) |
59
|
|
|
} |
60
|
|
|
dateLine = <span className={projectListStyle.date}>{dateLine}</span> |
61
|
|
|
|
62
|
|
|
return ( |
63
|
|
|
<div className={projectListStyle.item}> |
64
|
|
|
<h4 className={projectListStyle.itemtitle}>{name}</h4> |
65
|
|
|
{links} |
66
|
|
|
{dateLine} |
67
|
|
|
{stack && ( |
68
|
|
|
<div className={projectListStyle.stack}> |
69
|
|
|
{stack.map((tech) => ( |
70
|
|
|
<Icon |
71
|
|
|
key={tech} |
72
|
|
|
type={tech} |
73
|
|
|
title={ |
74
|
|
|
( |
75
|
|
|
stackIconList[tech.toLowerCase()] || { |
76
|
|
|
name: t('Warning: Can\'t find icon for "{{tech}}"', { |
77
|
|
|
tech, |
78
|
|
|
}), |
79
|
|
|
} |
80
|
|
|
).name |
81
|
|
|
} |
82
|
|
|
size="middle" |
83
|
|
|
/> |
84
|
|
|
))} |
85
|
|
|
</div> |
86
|
|
|
)} |
87
|
|
|
{desc && ( |
88
|
|
|
<div className={projectListStyle.desc}> |
89
|
|
|
<Markdown source={desc} /> |
90
|
|
|
</div> |
91
|
|
|
)} |
92
|
|
|
</div> |
93
|
|
|
) |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
Item.propTypes = { |
97
|
|
|
name: PropTypes.string.isRequired, |
98
|
|
|
url: PropTypes.string, |
99
|
|
|
urlTitle: PropTypes.string, |
100
|
|
|
gitUrl: PropTypes.string, |
101
|
|
|
githubUrl: PropTypes.string, |
102
|
|
|
npmUrl: PropTypes.string, |
103
|
|
|
date: PropTypes.oneOfType([ |
104
|
|
|
PropTypes.string, |
105
|
|
|
PropTypes.arrayOf(PropTypes.string), |
106
|
|
|
]), |
107
|
|
|
stack: PropTypes.arrayOf(PropTypes.string), |
108
|
|
|
desc: PropTypes.string, |
109
|
|
|
currentLang: PropTypes.string.isRequired, |
110
|
|
|
t: PropTypes.func.isRequired, |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
const mapStateToProps = (state) => ({ |
114
|
|
|
currentLang: state.lang, |
115
|
|
|
}) |
116
|
|
|
|
117
|
|
|
export default connect(mapStateToProps)(withTranslation()(Item)) |
118
|
|
|
|