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