-
-
Notifications
You must be signed in to change notification settings - Fork 301
Expand file tree
/
Copy pathprojectCard.js
More file actions
159 lines (152 loc) · 5.64 KB
/
projectCard.js
File metadata and controls
159 lines (152 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import messages from './messages';
import { RelativeTimeWithUnit } from '../../utils/formattedRelativeTime';
import ProjectProgressBar from './projectProgressBar';
import { DifficultyMessage } from '../mappingLevel';
import { ProjectStatusBox } from '../projectDetail/statusBox';
import { PROJECTCARD_CONTRIBUTION_SHOWN_THRESHOLD } from '../../config/index';
import { PriorityBox } from './priorityBox';
import { DueDateBox } from './dueDateBox';
import { htmlFromMarkdown } from '../../utils/htmlFromMarkdown';
import './styles.scss';
export function ProjectTeaser({
lastUpdated,
totalContributors,
className,
littleFont = 'f7',
bigFont = 'f6',
}: Object) {
/* outerDivStyles must have f6 even if sub-divs have f7 to fix grid issues*/
const outerDivStyles = 'f6 tl blue-grey truncate mb2';
if (totalContributors < PROJECTCARD_CONTRIBUTION_SHOWN_THRESHOLD) {
return (
<div title={lastUpdated} className={`${outerDivStyles} ${className || ''}`}>
<span className={littleFont}>
<FormattedMessage {...messages['projectLastContribution']} />{' '}
<RelativeTimeWithUnit date={lastUpdated} />
</span>
</div>
);
} else {
return (
<div title={lastUpdated} className={`${outerDivStyles} ${className || ''}`}>
<span className={`${littleFont}`}>
<FormattedMessage
{...messages['projectTotalContributors']}
values={{
number: <span className={`blue-grey b ${bigFont}`}>{totalContributors || 0}</span>,
}}
/>
</span>
</div>
);
}
}
export function ProjectCard({
projectId,
name,
shortDescription,
organisationName,
organisationLogo,
lastUpdated,
dueDate,
priority,
status,
difficulty,
sandbox = false,
campaignTag,
percentMapped,
percentValidated,
totalContributors,
showBottomButtons = false,
}: Object) {
const [isHovered, setHovered] = useState(false);
const linkCombo = 'link pa2 f6 ba b--grey-light di w-50 truncate tc';
const showBottomButtonsHovered = showBottomButtons === true ? isHovered : false;
const bottomButtonSpacer = showBottomButtons ? 'pt3 pb4' : 'pv3';
const bottomButtonMargin = showBottomButtons ? 'project-card-with-btn' : 'project-card';
const showPriorityIndicator = !sandbox && !['DRAFT', 'ARCHIVED'].includes(status);
const bottomButtons = (
<div className="absolute bottom-0 w-100">
<Link
to={`/manage/projects/${projectId}`}
className={`fl bg-grey-light blue-grey bn ${linkCombo}`}
>
<FormattedMessage {...messages.editProject} />
</Link>
<Link to={`/projects/${projectId}/tasks`} className={`fr bg-red white bn ${linkCombo}`}>
<FormattedMessage {...messages.projectTasks} />
</Link>
</div>
);
return (
<article
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
className={`relative blue-dark ${sandbox ? 'bt bw2 b--blue-dark br1' : ''}`}
>
<Link className="no-underline color-inherit" to={`/projects/${projectId}`}>
<div
className={`${bottomButtonSpacer} ba br1 bg-white shadow-hover h-100 flex flex-column justify-between b--card ${bottomButtonMargin}`}
>
<div>
<div className="flex justify-between items-center">
<div className="red">
<img
className="h2"
src={organisationLogo}
alt={organisationLogo ? organisationName : ''}
/>
</div>
<div className="">
{!showPriorityIndicator ? (
<ProjectStatusBox status={status} className={'pv1 ph1 dib'} />
) : (
<PriorityBox
priority={priority}
extraClasses={'pv1 ph2 dib f8'}
showIcon={!['URGENT', 'MEDIUM'].includes(priority)} // inside the cards, don't show the icon for urgent or medium, due to the space required
/>
)}
</div>
</div>
<div className="mt4 w-100">
<div className="flex items-center justify-between">
<div className="f7 blue-grey flex-grow">#{projectId}</div>
<div className="f7 blue-grey flex-grow">{sandbox ? 'Sandbox' : 'OSM'}</div>
</div>
<h3
title={name}
className="mt3 f125 fw7 lh-title overflow-y-hidden pr4 project-title"
>
{name}
</h3>
<div className="tc f6">
<div className="w-100 tl pr2 f7 blue-grey dib mb2 project-desc">
{shortDescription?.trim() && (
<div dangerouslySetInnerHTML={htmlFromMarkdown(shortDescription)} />
)}
{campaignTag ? ' · ' + campaignTag : ''}
</div>
</div>
</div>
</div>
<div>
<ProjectTeaser totalContributors={totalContributors} lastUpdated={lastUpdated} />
<ProjectProgressBar percentMapped={percentMapped} percentValidated={percentValidated} />
<div className="pt2 truncate flex justify-between items-center">
<DifficultyMessage
level={difficulty}
className="fl f7 pv2 ttc fw5 blue-grey truncate"
/>
<DueDateBox dueDate={dueDate} />
</div>
</div>
</div>
</Link>
{showBottomButtonsHovered && bottomButtons}
</article>
);
}