Skip to content

Commit f55c874

Browse files
committed
initial commit
1 parent 807563b commit f55c874

File tree

5 files changed

+608
-0
lines changed

5 files changed

+608
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
config.json
3+
_*.*

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# How to Use
2+
3+
1. Export Your Trello Board Backup file as JSON
4+
5+
2. Create Personal Token in Asana Connect
6+
- https://asana.com/guide/help/api/api#gl-connect
7+
8+
3. Edit Configuration for matching members, select asana team, workspace and so on.

index.js

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
var fs = require('fs-extra');
2+
var util = require('util');
3+
var Promise = require("bluebird");
4+
var _ = require('underscore');
5+
var package = fs.readJsonSync('package.json');
6+
var Asana = require('asana');
7+
8+
var LABEL_COLOR = {
9+
green: 'light-green',
10+
yellow: 'light-yellow',
11+
orange: 'dark-orange',
12+
red: 'light-red',
13+
purple: 'dark-purple',
14+
blue: 'dark-blue',
15+
sky: 'light-blue',
16+
lime: 'light-orange',
17+
pink: 'light-pink',
18+
black: 'dark-warm-gray'
19+
};
20+
21+
var opts = require('nomnom')
22+
.help('Import Asana Project from Trello Board with exported JSON file')
23+
.options({
24+
files: {
25+
help: 'Path JSON file exported from Trello',
26+
position: 0,
27+
list: true,
28+
required: true
29+
},
30+
config: {
31+
help: 'Specify Config File',
32+
string: '-c PATH, --config PATH',
33+
'default': 'config.json'
34+
},
35+
onlyMembers: {
36+
help: 'See Members of Trello without execute scripts.',
37+
abbr: 'm',
38+
full: 'only-members',
39+
flag: true
40+
}
41+
})
42+
.parse();
43+
44+
var parseJson = function (path) {
45+
return fs.readJson(path).then(function (data) {
46+
var output = _.pick(data, [
47+
'name', 'desc', 'labels', 'cards', 'lists', 'members', 'checklists'
48+
]);
49+
50+
output.cards = _.filter(output.cards, function (card) {
51+
return !card.closed;
52+
});
53+
54+
output.lists = _.filter(output.lists, function (list) {
55+
return !list.closed;
56+
});
57+
58+
return output;
59+
});
60+
};
61+
62+
var fetch = function (result) {
63+
return result.fetch();
64+
};
65+
66+
var getUniqueName = function getUniqueName(name, haystack) {
67+
const rxPostfix = / \(([0-9]+)\)$/;
68+
69+
if (_.contains(haystack, name)) {
70+
const mat = rxPostfix.exec(name);
71+
let pureName = name.replace(rxPostfix, '');
72+
const number = mat ? parseInt(mat[1], 10) + 1 : 1;
73+
74+
return getUniqueName(pureName + ` (${number})`, haystack);
75+
} else {
76+
return name;
77+
}
78+
};
79+
80+
fs.readJson(opts.config).then(function (config) {
81+
var client = Asana.Client.create().useAccessToken(config.asana.personal_access_token);
82+
var projects = [];
83+
84+
if (!config.asana.workspace) {
85+
console.log('You should select your workspace in asana.');
86+
console.log('<id>: <name>');
87+
88+
return client.workspaces.findAll().then(fetch).then(workspaces => {
89+
_.each(workspaces, workspace => {
90+
console.log(`${workspace.id}: ${workspace.name}`);
91+
});
92+
93+
throw Promise.CancellationError;
94+
});
95+
}
96+
97+
if (!config.asana.team) {
98+
return client.teams.findByOrganization(config.asana.workspace).then(fetch).then(teams => {
99+
console.log('You should select a team in asana.');
100+
console.log('<id>: <name>');
101+
102+
_.each(teams, team => {
103+
console.log(`${team.id}: ${team.name}`);
104+
});
105+
106+
throw Promise.CancellationError;
107+
});
108+
}
109+
110+
return client.projects.findByTeam(config.asana.team).then(fetch).then(results => {
111+
projects = results;
112+
113+
return Promise.map(opts.files, parseJson);
114+
}).then(function (files) {
115+
// Check only member list
116+
if (opts.onlyMembers) {
117+
var members = _.flatten(_.pluck(files, 'members'));
118+
119+
console.log('Trello Users');
120+
console.log('<username>: <FullName>');
121+
console.log(_.map(members, function (member) {
122+
return `${member.username}: ${member.fullName}`;
123+
}).join('\n'));
124+
125+
console.log('\nAsana Users');
126+
console.log('<id>: <Name>');
127+
128+
return client.users.findByWorkspace(config.asana.workspace).then(fetch).then(users => {
129+
_.each(users, user => {
130+
console.log(`${user.id}: ${user.name}`);
131+
});
132+
133+
throw Promise.CancellationError;
134+
});
135+
}
136+
137+
// Executes in order
138+
return Promise.mapSeries(files, function (file) {
139+
let projectData;
140+
let listToSectionMap = {};
141+
let cardToTaskMap = {};
142+
let labelToTagMap = {};
143+
144+
// Creates a Project
145+
return client.projects.createInTeam(config.asana.team, {
146+
name: getUniqueName(file.name, _.pluck(projects, 'name')),
147+
notes: file.desc,
148+
layout: 'board'
149+
}).then(result => {
150+
console.log(`Created ${result.name} project in your team.`);
151+
projectData = result;
152+
153+
// Creates sections in order
154+
return Promise.mapSeries(file.lists, list => {
155+
return client.sections.createInProject(projectData.id, {
156+
name: list.name
157+
}).then(result => {
158+
listToSectionMap[list.id] = result.id;
159+
console.log(`Created ${list.name} section.`);
160+
});
161+
});
162+
}).then(() => {
163+
// Creates tags
164+
return Promise.map(file.labels, label => {
165+
return client.tags.create({
166+
167+
}).then(result => {
168+
169+
});
170+
});
171+
172+
console.log(`Creating ${file.cards.length} parent tasks...`);
173+
174+
// Creates tasks
175+
return Promise.map(file.cards, card => {
176+
177+
}, { concurrency: 3 });
178+
});
179+
});
180+
});
181+
}).catch(Promise.CancellationError, function (reason) {
182+
// nothing to do
183+
}).catch(function (reason) {
184+
console.error(reason);
185+
});

package.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "trello2asana",
3+
"version": "0.0.1",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/davidshimjs/trello2asana.git"
12+
},
13+
"author": "",
14+
"license": "ISC",
15+
"bugs": {
16+
"url": "https://github.com/davidshimjs/trello2asana/issues"
17+
},
18+
"homepage": "https://github.com/davidshimjs/trello2asana#readme",
19+
"dependencies": {
20+
"asana": "git+https://github.com/davidshimjs/node-asana.git",
21+
"bluebird": "^3.5.1",
22+
"fs-extra": "^4.0.2",
23+
"nomnom": "^1.8.1",
24+
"underscore": "^1.8.3"
25+
}
26+
}

0 commit comments

Comments
 (0)