1
+ import React from 'react'
2
+ import LABELS_TO_ADD from '../Labels' ;
3
+ import ProjectListApplyer from '../Components/ProjectListApplyer' ;
4
+ import TrelloLogo from '../assets/images/trello.svg'
5
+ import { API_KEY } from './trelloConstants'
6
+ import Loading from '../Components/Loading'
7
+ import { proximity } from 'colour-proximity'
8
+ import './helper.css'
9
+
10
+ const COLORS = [
11
+ { name : 'yellow' , color : 'f2d600' } ,
12
+ { name : 'green' , color : '61bd4f' } ,
13
+ { name : 'purple' , color : 'c377e0' } ,
14
+ { name : 'blue' , color : '0079bf' } ,
15
+ { name : 'red' , color : 'eb5a46' } ,
16
+ { name : 'orange' , color : 'ffab4a' } ,
17
+ { name : 'black' , color : '4d4d4d' } ,
18
+ { name : 'sky' , color : '00c2e0' } ,
19
+ { name : 'pink' , color : 'ff80ce' } ,
20
+ { name : 'lime' , color : '51e898' } ,
21
+ ]
22
+
23
+ window . p = proximity ;
24
+ window . cs = COLORS
25
+
26
+ const mustNear = ( color ) => {
27
+ return COLORS
28
+ . map ( c => Object . assign ( { } , c , { proximity : proximity ( '#' + color , '#' + c . color ) } ) )
29
+ . sort ( ( a , b ) => a . proximity < b . proximity ? 1 : - 1 )
30
+ . pop ( )
31
+ }
32
+
33
+ const TRELLO_LABELS = LABELS_TO_ADD . map ( l => {
34
+ const color = mustNear ( l . color )
35
+ return Object . assign ( { } , l , { color : color . color , trelloColor : color . name } )
36
+ } )
37
+
38
+ class Trello extends React . Component {
39
+
40
+ constructor ( props ) {
41
+ super ( props ) ;
42
+
43
+ const { location } = props
44
+ const token = new URLSearchParams ( location . hash . substr ( 1 ) ) . get ( 'token' )
45
+
46
+ this . state = {
47
+ token,
48
+ loading : true ,
49
+ boards : [ ] ,
50
+ selectedOption : null ,
51
+ applying : false ,
52
+ applyedLabels : [ ] ,
53
+ applyingStatus : null ,
54
+ alert : null ,
55
+ }
56
+ }
57
+
58
+ fetch ( { path, method, query, body } ) {
59
+ const queryStr = ( query && Object . keys ( query ) . reduce ( ( c , key ) => `${ c } &${ key } =${ query [ key ] } ` , '' ) ) || ''
60
+ return fetch ( `https://api.trello.com/1/${ path } ?key=${ API_KEY } &token=${ this . state . token } ${ queryStr } ` , {
61
+ method : method || 'GET' ,
62
+ body : body ,
63
+ } )
64
+ }
65
+
66
+ async componentDidMount ( ) {
67
+ const resp = await this . fetch ( {
68
+ path : 'members/me/boards' ,
69
+ query : { filter : 'open' , organizations : true } ,
70
+ } ) ;
71
+ const boards = await resp . json ( ) ;
72
+
73
+ this . setState ( {
74
+ loading : false ,
75
+ boards : boards ,
76
+ } )
77
+
78
+ boards . map ( b => b . idOrganization )
79
+ . reduce ( ( c , id ) => c . indexOf ( id ) > - 1 ? c : [ ...c , id ] , [ ] )
80
+ . filter ( id => id !== null )
81
+ . map ( id => this . showOrganizationName ( id ) ) ;
82
+ }
83
+
84
+ async showOrganizationName ( id ) {
85
+ const resp = await this . fetch ( { path : `organizations/${ id } ` , query : { fields : 'id,displayName' } } )
86
+ const org = await resp . json ( )
87
+
88
+ this . setState ( prevState => ( {
89
+ boards : prevState . boards . map ( board => {
90
+ if ( board . idOrganization !== id ) {
91
+ return board ;
92
+ }
93
+
94
+ return Object . assign ( board , {
95
+ organization : org ,
96
+ name : `${ board . name } (${ org . displayName } )`
97
+ } )
98
+ } )
99
+ } ) )
100
+ }
101
+
102
+ handleApply ( selectedOption ) {
103
+ this . setState ( { selectedOption, applying : true } )
104
+ this . applyChangesToBoard ( selectedOption . value )
105
+ }
106
+
107
+ async applyChangesToBoard ( boardId ) {
108
+ this . setState ( {
109
+ applyedLabels : [ ] ,
110
+ alert : null
111
+ } )
112
+
113
+
114
+ try {
115
+ const currentLabels = ( await ( await this . fetch ( { path : `boards/${ boardId } /labels` , query : { fields : 'name' } } ) ) . json ( ) )
116
+ const createLabelsPromices = TRELLO_LABELS . map ( l => this . createLabel ( boardId , l , currentLabels ) )
117
+
118
+ await Promise . all ( createLabelsPromices )
119
+ this . setState ( {
120
+ applying : false ,
121
+ alert : { type : 'success' , message : 'Setup completed !' }
122
+ } ) ;
123
+ } catch ( error ) {
124
+ this . setState ( {
125
+ applying : false ,
126
+ alert : { type : 'danger' , message : error . message }
127
+ } ) ;
128
+ }
129
+ }
130
+
131
+ async createLabel ( boardId , { name, trelloColor } , currentLabels ) {
132
+ if ( currentLabels . find ( cl => cl . name === name ) ) {
133
+ this . addApplyedLabel ( name ) ;
134
+ return ;
135
+ }
136
+
137
+ let formData = new FormData ( )
138
+ formData . append ( 'idBoard' , boardId ) ;
139
+ formData . append ( 'name' , name ) ;
140
+ formData . append ( 'color' , trelloColor ) ;
141
+
142
+ const resp = await this . fetch ( { path : `labels` , method : 'POST' , body : formData } ) ;
143
+
144
+ if ( resp . status !== 200 ) {
145
+ const content = await resp . json ( ) ;
146
+ throw new Error ( content . message ) ;
147
+ }
148
+
149
+ this . addApplyedLabel ( name ) ;
150
+ }
151
+
152
+ addApplyedLabel ( name ) {
153
+ this . setState ( ( { applyedLabels } ) => ( {
154
+ applyedLabels : [ ...applyedLabels , name ] ,
155
+ applyingStatus : `${ name } created` ,
156
+ } ) )
157
+ }
158
+
159
+ async removeLabel ( boardId , { name } ) {
160
+ await this . fetch (
161
+ `https://Trello.com/api/v4/boards/${ boardId } /labels?name=${ name } ` ,
162
+ 'DELETE'
163
+ ) ;
164
+
165
+ this . setState ( ( { applyedLabels } ) => ( {
166
+ applyedLabels : [ ...applyedLabels , name ] ,
167
+ applyingStatus : `${ name } removed` ,
168
+ } ) )
169
+ }
170
+
171
+ render ( ) {
172
+ const { loading, boards, selectedOption, applyedLabels, applying, applyingStatus, alert } = this . state ;
173
+
174
+ if ( loading ) {
175
+ return < section >
176
+ < h2 > Loading Trello...</ h2 >
177
+ < Loading />
178
+ </ section >
179
+ }
180
+ return (
181
+ < div className = "Trello" >
182
+ < section className = "origin-header" >
183
+ < h1 >
184
+ < span className = "origin-logo" > < TrelloLogo /> </ span >
185
+ < span className = "origin-name" > Trello</ span >
186
+ </ h1 >
187
+ </ section >
188
+ < ProjectListApplyer
189
+ projects = { boards . map ( r => Object . assign ( r , {
190
+ value : r . id ,
191
+ label : r . name ,
192
+ } ) ) }
193
+ selectedPreject = { selectedOption }
194
+
195
+ labelsToAdd = { TRELLO_LABELS }
196
+
197
+ onApply = { ( selected ) => this . handleApply ( selected ) }
198
+
199
+ applyedLabels = { applyedLabels }
200
+ applying = { applying }
201
+ applyingStatus = { applyingStatus }
202
+ alert = { alert }
203
+ />
204
+ </ div >
205
+ )
206
+ }
207
+ }
208
+
209
+ export default Trello
0 commit comments