Skip to content

Commit

Permalink
Merge pull request #6 from lucassabreu/trello
Browse files Browse the repository at this point in the history
Trello
  • Loading branch information
lucassabreu authored Feb 25, 2018
2 parents 1929390 + 906edb5 commit dbf3b48
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 9 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## [0.1.4] - 2018-02-25

### Added
- Support for custom labels at the component
- Trello boards setup

## [0.1.3] - 2018-02-25

### Fixed
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"babel-runtime": "6.26.0",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
"colour-proximity": "^0.0.2",
"css-loader": "0.28.7",
"dotenv": "4.0.0",
"dotenv-expand": "4.0.1",
Expand Down
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Home from './Home'
import Footer from './Footer';
import GitHub from './Origins/GitHub';
import GitLab from './Origins/GitLab';
import Trello from './Origins/Trello';

const App = () => (
<div className="CWSPApp">
Expand All @@ -21,6 +22,7 @@ const App = () => (
<Route exact path="/" component={Home} />
<Route exact path="/github" component={GitHub} />
<Route exact path="/gitlab" component={GitLab} />
<Route exact path="/trello" component={Trello} />
</Switch>
</div>
<Footer />
Expand Down
15 changes: 10 additions & 5 deletions src/Components/ProjectListApplyer.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const ProjectListApplyer = ({
applyedLabels,
applyingStatus,
onApply,
labelsToAdd,
labelsToRemove,
alert
}) => (
Expand All @@ -61,7 +62,7 @@ const ProjectListApplyer = ({
<LabelList
header="Labels to Add:"
className="labels-to-add"
labels={LABELS_TO_ADD}
labels={labelsToAdd}
applyedLabels={applyedLabels}
/>
{labelsToRemove.length === 0 ? null :
Expand All @@ -76,6 +77,11 @@ const ProjectListApplyer = ({
</div>
);

const labelShape = PropTypes.shape({
name: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
});

ProjectListApplyer.propTypes = {
className: PropTypes.string,

Expand All @@ -91,17 +97,16 @@ ProjectListApplyer.propTypes = {
projects: PropTypes.arrayOf(projectShape).isRequired,
selectedPreject: projectShape,

labelsToRemove: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
color: PropTypes.string.isRequired,
})).isRequired,
labelsToAdd: PropTypes.arrayOf(labelShape),
labelsToRemove: PropTypes.arrayOf(labelShape).isRequired,
}

ProjectListApplyer.defaultProps = {
className: "",
applying: false,
applyedLabels: [],
labelsToRemove: [],
labelsToAdd: LABELS_TO_ADD,
}

export default ProjectListApplyer
9 changes: 6 additions & 3 deletions src/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import gitlabLogo from './assets/images/gitlab.svg'
import trelloLogo from './assets/images/trello.svg'
import Authenticator from 'netlify-auth-providers';
import { UncontrolledTooltip } from 'reactstrap';
import { API_KEY as TRELLO_API_KEY } from './Origins/trelloConstants'
import './Home.css'

const nullCallback = (event) => event.preventDefault();
const auth = new Authenticator({ site_id: "cwps.lucassabreu.net.br" });

const Home = ({ history }) => {
Expand Down Expand Up @@ -48,8 +48,11 @@ const Home = ({ history }) => {
{
name: "Trello",
logo: trelloLogo,
enabled: false,
callback: nullCallback,
enabled: true,
callback: (event) => {
const callbackUrl = `${window.location.href}trello`
window.location = `https://trello.com/1/authorize?callback_method=fragment&return_url=${callbackUrl}&scope=read,write&expiration=1day&name=Coderockr Way Project Setup&key=${TRELLO_API_KEY}`
},
},
];

Expand Down
209 changes: 209 additions & 0 deletions src/Origins/Trello.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import React from 'react'
import LABELS_TO_ADD from '../Labels';
import ProjectListApplyer from '../Components/ProjectListApplyer';
import TrelloLogo from '../assets/images/trello.svg'
import { API_KEY } from './trelloConstants'
import Loading from '../Components/Loading'
import { proximity } from 'colour-proximity'
import './helper.css'

const COLORS = [
{ name: 'yellow', color: 'f2d600' },
{ name: 'green', color: '61bd4f' },
{ name: 'purple', color: 'c377e0' },
{ name: 'blue', color: '0079bf' },
{ name: 'red', color: 'eb5a46' },
{ name: 'orange', color: 'ffab4a' },
{ name: 'black', color: '4d4d4d' },
{ name: 'sky', color: '00c2e0' },
{ name: 'pink', color: 'ff80ce' },
{ name: 'lime', color: '51e898' },
]

window.p = proximity;
window.cs = COLORS

const mustNear = (color) => {
return COLORS
.map(c => Object.assign({}, c, { proximity: proximity('#' + color, '#' + c.color) }))
.sort((a, b) => a.proximity < b.proximity ? 1 : -1)
.pop()
}

const TRELLO_LABELS = LABELS_TO_ADD.map(l => {
const color = mustNear(l.color)
return Object.assign({}, l, { color: color.color, trelloColor: color.name })
})

class Trello extends React.Component {

constructor(props) {
super(props);

const { location } = props
const token = new URLSearchParams(location.hash.substr(1)).get('token')

this.state = {
token,
loading: true,
boards: [],
selectedOption: null,
applying: false,
applyedLabels: [],
applyingStatus: null,
alert: null,
}
}

fetch({ path, method, query, body }) {
const queryStr = (query && Object.keys(query).reduce((c, key) => `${c}&${key}=${query[key]}`, '')) || ''
return fetch(`https://api.trello.com/1/${path}?key=${API_KEY}&token=${this.state.token}${queryStr}`, {
method: method || 'GET',
body: body,
})
}

async componentDidMount() {
const resp = await this.fetch({
path: 'members/me/boards',
query: { filter: 'open', organizations: true },
});
const boards = await resp.json();

this.setState({
loading: false,
boards: boards,
})

boards.map(b => b.idOrganization)
.reduce((c, id) => c.indexOf(id) > -1 ? c : [...c, id], [])
.filter(id => id !== null)
.map(id => this.showOrganizationName(id));
}

async showOrganizationName(id) {
const resp = await this.fetch({ path: `organizations/${id}`, query: { fields: 'id,displayName' } })
const org = await resp.json()

this.setState(prevState => ({
boards: prevState.boards.map(board => {
if (board.idOrganization !== id) {
return board;
}

return Object.assign(board, {
organization: org,
name: `${board.name} (${org.displayName})`
})
})
}))
}

handleApply(selectedOption) {
this.setState({ selectedOption, applying: true })
this.applyChangesToBoard(selectedOption.value)
}

async applyChangesToBoard(boardId) {
this.setState({
applyedLabels: [],
alert: null
})


try {
const currentLabels = (await (await this.fetch({ path: `boards/${boardId}/labels`, query: { fields: 'name' } })).json())
const createLabelsPromices = TRELLO_LABELS.map(l => this.createLabel(boardId, l, currentLabels))

await Promise.all(createLabelsPromices)
this.setState({
applying: false,
alert: { type: 'success', message: 'Setup completed !' }
});
} catch (error) {
this.setState({
applying: false,
alert: { type: 'danger', message: error.message }
});
}
}

async createLabel(boardId, { name, trelloColor }, currentLabels) {
if (currentLabels.find(cl => cl.name === name)) {
this.addApplyedLabel(name);
return;
}

let formData = new FormData()
formData.append('idBoard', boardId);
formData.append('name', name);
formData.append('color', trelloColor);

const resp = await this.fetch({ path: `labels`, method: 'POST', body: formData });

if (resp.status !== 200) {
const content = await resp.json();
throw new Error(content.message);
}

this.addApplyedLabel(name);
}

addApplyedLabel(name) {
this.setState(({ applyedLabels }) => ({
applyedLabels: [...applyedLabels, name],
applyingStatus: `${name} created`,
}))
}

async removeLabel(boardId, { name }) {
await this.fetch(
`https://Trello.com/api/v4/boards/${boardId}/labels?name=${name}`,
'DELETE'
);

this.setState(({ applyedLabels }) => ({
applyedLabels: [...applyedLabels, name],
applyingStatus: `${name} removed`,
}))
}

render() {
const { loading, boards, selectedOption, applyedLabels, applying, applyingStatus, alert } = this.state;

if (loading) {
return <section>
<h2>Loading Trello...</h2>
<Loading />
</section>
}
return (
<div className="Trello">
<section className="origin-header">
<h1>
<span className="origin-logo"><TrelloLogo /></span>
<span className="origin-name">Trello</span>
</h1>
</section>
<ProjectListApplyer
projects={boards.map(r => Object.assign(r, {
value: r.id,
label: r.name,
}))}
selectedPreject={selectedOption}

labelsToAdd={TRELLO_LABELS}

onApply={(selected) => this.handleApply(selected)}

applyedLabels={applyedLabels}
applying={applying}
applyingStatus={applyingStatus}
alert={alert}
/>
</div>
)
}
}

export default Trello
1 change: 1 addition & 0 deletions src/Origins/trelloConstants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const API_KEY = '8986ad2816e480952b9715eed4c5ed2a'
2 changes: 1 addition & 1 deletion src/assets/images/trello.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,10 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"

[email protected]:
version "0.2.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.2.1.tgz#363cab23c94b31a0d64db71048b8c6a940f8c68c"

color-convert@^1.3.0, color-convert@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
Expand All @@ -1405,6 +1409,12 @@ color-string@^0.3.0:
dependencies:
color-name "^1.0.0"

color-string@~0.1.2:
version "0.1.3"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.1.3.tgz#e865d2e3e59f665c3af0de14383f6bf0705685f3"
dependencies:
color-convert "0.2.x"

color@^0.11.0:
version "0.11.4"
resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764"
Expand All @@ -1425,6 +1435,12 @@ colors@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"

colour-proximity@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/colour-proximity/-/colour-proximity-0.0.2.tgz#139ad3afecf301bc803b8da698f32c972974769c"
dependencies:
color-string "~0.1.2"

combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
Expand Down

0 comments on commit dbf3b48

Please sign in to comment.