Last active
June 11, 2021 17:27
-
-
Save nsrCodes/8e37ba510d55dba2265909cd38040f37 to your computer and use it in GitHub Desktop.
If you have ever exported data from trello, you know that it is the worst structured json that you will ever see. I was trying to make sense from all that data while shifting from trello to github discussions but this is the overall structuring result complete
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Actual structure | |
*Important parts* | |
{ | |
id, | |
name, | |
desc, | |
cards { | |
id, | |
name, | |
desc, // description | |
idList, | |
idCheckLists, // if any | |
idMembers, | |
url, | |
attachments { // if exists... else empty | |
// array of attachments | |
date, // Date() | |
mimeType, | |
name, | |
url, // openToAll | |
fileName, | |
id, | |
isUploaded // idk, just felt important | |
}, | |
labels: { | |
// array of labels applied to card | |
id, | |
name, | |
color | |
} | |
}, | |
checklists { | |
// array of check lists | |
id, | |
idCard, | |
name, | |
checkItems { // array of items of checklist | |
state, // complete or incomplete | |
name, | |
} | |
}, | |
actions { // comments | |
// array of actions like add members, update cards, etc | |
id, | |
data { | |
text, | |
type, // we are looking for commentCard | |
date, // Date() | |
card { | |
id | |
}, | |
list { | |
id, | |
name, | |
}, | |
}, | |
memberCreator { | |
username, | |
fullName | |
} | |
}, | |
lists { | |
id, | |
name, | |
closed, // true or false, | |
}, | |
labels { // Labels i the board | |
id, | |
name, | |
color | |
}, | |
members { | |
// array of members on the board | |
id, | |
bio | |
fullName, | |
username, | |
url | |
} | |
} | |
# Rewamped structure | |
*First Draft* | |
[ ] figure out whether as issue or notes, currently for preparing as issue | |
[ ] Might have problems with attachments in comments | |
## Issue draft | |
**Title** | |
<description> | |
> auto generated issue while importing | |
*description text* | |
--- | |
**checklists** | |
**attachments** | |
--- | |
by *author* | |
url *trello url* | |
</description> | |
{ | |
Board : { | |
info : { | |
id, | |
name, | |
members: [], | |
labels: [], | |
}, | |
data : { | |
lists : { | |
info: { | |
id, | |
name, | |
closed, | |
} | |
cards : { | |
raw_data: { | |
id, | |
name, // title | |
desc, // description | |
labels, | |
attachments, | |
checkLists: [] // from idCheckLists | |
members, // participants | |
comments, | |
otherActions: // array of actions of other types | |
} | |
info : { | |
ids: { | |
id, | |
idList, | |
idCheckLists, | |
idMembers, | |
}, | |
url, | |
}, | |
data : { | |
title, | |
description, | |
// make sure to keep this as the top most comment | |
// include attachments and checklists in this as markup | |
// include data of creator and link to original ticket | |
comments: [] // array in order | |
issue_info: { | |
labels, | |
participants | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
```javascript | |
let card = { | |
raw_data: { | |
id: "", | |
name: "", // title | |
desc: "", // description | |
labels: [], | |
attachments: [], | |
checkLists: [], // from idCheckLists | |
members: [], // participants | |
comments: [], | |
otherActions: [],// array of actions of other types | |
}, | |
info : { | |
ids: { | |
id: "", | |
idList: "", | |
idCheckLists: "", | |
idMembers: "", | |
}, | |
url: "", | |
}, | |
data : { | |
title: "", | |
// make sure to keep this as the top most comment | |
// include attachments and checklists in this as markup | |
// include data of creator and link to original ticket | |
description : "", | |
comments: [], // array in order | |
issueInfo: { | |
labels: [], | |
participants: [] | |
} | |
} | |
} | |
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const store = true | |
// const dir = `./${Date.now()}`; | |
const dir = "doingAgain" | |
if (store && !fs.existsSync(dir)) | |
fs.mkdirSync(dir) | |
const rawData = fs.readFileSync('trello.json'); | |
const importedTrelloData = JSON.parse(rawData); | |
const storeData = (data, name) => { | |
try { | |
if (store) | |
fs.writeFileSync(path.join(dir, name), JSON.stringify(data)) | |
} catch (err) { | |
console.error(err) | |
} | |
} | |
// Create markdown description from collected data | |
const getDescription = (data, ticketURL) => { | |
// return data.desc | |
let final, start, main, checkList, attachments, end; | |
start = `> This is an auto generated issue made during migration from trello` | |
main = `\n ${data.desc} \n --- \n` | |
end = `\n *trello ticket url - ${ticketURL}* \n` | |
// Checklist string | |
if (data.checkLists.length > 0) { | |
for(let list of data.checkLists) { | |
let listString = `### CheckList - ${list.name} \n` | |
// Writing each list item as markdown | |
for (const item of list.checkItems) { | |
listString += `[${(item.state=="complete")?"X":" "}] ${item.name} \n` | |
} | |
checkList += listString + "\n"; | |
} | |
checkList += "\n --- \n" | |
} else checkList = "" | |
// Attachment string | |
if (data.attachments.length > 0) { | |
attachments += "### Attachments \n" | |
for( let item of data.attachments ){ | |
attachments += `![${item.name}](${item.url}) \n` | |
} | |
attachments += "\n\n --- \n" | |
} else attachments = "" | |
final = start + main + checkList + attachments + end; | |
return final | |
} | |
const getMembers = () => { | |
let rawData = importedTrelloData.members; | |
let data = [] | |
for (let i=0; i < rawData.length; i++) { | |
data[i] = { | |
id: rawData[i].id, | |
bio: rawData[i].bio, | |
fullName: rawData[i].fullName, | |
username: rawData[i].username, | |
url: rawData[i].url, | |
} | |
} | |
return data; | |
} | |
const getLabels = () => { | |
let rawData = importedTrelloData.labels; | |
let data = [] | |
for (let i=0; i < rawData.length; i++) { | |
data[i] = { | |
id: rawData[i].id, | |
color: rawData[i].color, | |
name: rawData[i].name, | |
} | |
} | |
return data; | |
} | |
const getOrganizedListData = () => { | |
let rawListsData = {}; | |
let rawCardsData = importedTrelloData.cards; | |
let rawCheckListsData = importedTrelloData.checklists; | |
let rawActionsData = importedTrelloData.actions; | |
let cards = {}; | |
// | |
for (const rawCard of rawCardsData) { | |
let card = { | |
raw_data: { | |
id: rawCard.id, | |
name: rawCard.name, // title | |
desc: rawCard.desc, // description | |
labels: rawCard.labels, // array | |
attachments: rawCard.attachments, // array | |
members: rawCard.members, // array | |
checkLists: [], // from idCheckLists | |
comments: [], // from actions | |
// otherActions: [],//actions of other types // took out because data was not consistent | |
}, | |
info : { | |
ids: { | |
id: rawCard.id, | |
idList: rawCard.idList, | |
idCheckLists: rawCard.idCheckLists, | |
idMembers: rawCard.idMembers, | |
}, | |
url: rawCard.url, | |
}, | |
} | |
// rawListsData[rawCard.idList][rawCard.id] = card | |
cards[card.raw_data.id] = card | |
} | |
// | |
for (const rawCheckList of rawCheckListsData) { | |
// Refining individual checkItems | |
let rawCheckItems = rawCheckList.checkItems, checkItems = []; | |
rawCheckItems.forEach(item => { | |
checkItems.push({ | |
state: item.state, | |
name: item.name, | |
}) | |
}); | |
let checkList = { | |
id: rawCheckList.id, | |
idCard: rawCheckList.idCard, | |
name: rawCheckList.name, | |
// checkItems: { // array of items of checklist | |
// state: rawCheckList.state, // complete or incomplete | |
// name: rawCheckList.name, | |
// } | |
checkItems: checkItems, | |
// checkItems: rawCheckList.checkItems, | |
} | |
// checkLists[checkList.id] = checkList | |
cards[checkList.idCard].raw_data.checkLists.push(checkList) | |
} | |
// | |
for (const rawAction of rawActionsData) { | |
if (rawAction.type == "comentCard") { | |
let action = { | |
id: rawAction.id, | |
data: { | |
text: rawAction.data.text, | |
type: rawAction.data.type, // we are looking for commentCard | |
date: rawAction.data.date, // Date() | |
card: { | |
id: rawAction.data.card.id, | |
}, | |
// list: { | |
// id: rawAction.data.list.id, | |
// name: rawAction.data.list.name, | |
// }, | |
}, | |
// memberCreator: { | |
// username: rawAction.data.memberCreator.username, | |
// fullName: rawAction.data.memberCreator.fullName, | |
// } | |
} | |
if (rawAction.data.list) { | |
action.data.list = { | |
id: rawAction.data.list.id, | |
name: rawAction.data.list.name, | |
} | |
} | |
if (rawAction.data.memberCreator) { | |
action.memberCreator = { | |
username: rawAction.data.memberCreator.username, | |
fullName: rawAction.data.memberCreator.fullName, | |
} | |
} | |
// actions[action.id] = action | |
// if (action.type == "commentCard") { | |
// cards[action.card.id].raw_data.comments.push(action) | |
// } else { | |
// // cards[action.card.id].raw_data.otherActions.push(action) | |
// console.log(action) | |
// } | |
cards[action.card.id].raw_data.comments.push(action) | |
} // catch (e) { | |
// console.log(rawAction) | |
// console.log(e) | |
// } | |
} | |
// final structuring of cards | |
for (const cardId in cards) { | |
const cardData = cards[cardId].raw_data | |
let data = { | |
title: cardData.name, | |
description : getDescription(cardData, cards[cardId].info.url), | |
comments: cardData.comments, // array in order | |
issueInfo: { | |
labels: cardData.labels, | |
participants: cardData.members, | |
} | |
} | |
let cardListId = cards[cardId].info.ids.idList | |
cards[cardId].data = data; | |
if (!rawListsData[cardListId]) | |
rawListsData[cardListId] = {} | |
rawListsData[cardListId][cardData.id] = cards[cardId] | |
} | |
// return [cards, rawListsData] | |
storeData(cards, `cards.json`) | |
return rawListsData | |
} | |
const getLists = () => { | |
let rawListData = importedTrelloData.lists; | |
let data = [] | |
for (let i=0; i < rawListData.length; i++) { | |
data[i] = { | |
info: { | |
id: rawListData[i].id, | |
closed: rawListData[i].closed, | |
name: rawListData[i].name, | |
}, | |
cards : [] | |
} | |
} | |
// TODO: refine data | |
listData = getOrganizedListData() | |
for (const listId of Object.keys(listData)) { | |
let listIndex = data.findIndex(list => { | |
return list.info.id == listId | |
}) | |
if (listIndex != -1) { | |
data[listIndex].cards = listData | |
} | |
} | |
storeData(data, `lists.json`) | |
return data; | |
} | |
function main() { | |
let structuredData = { | |
info : { | |
id : importedTrelloData.id, | |
name: importedTrelloData.name, | |
members: [], | |
labels: [], | |
}, | |
data : { | |
lists : [] | |
} | |
} | |
structuredData.info.members = getMembers() | |
structuredData.info.labels = getLabels() | |
structuredData.data.lists = getLists() | |
storeData(structuredData, `board.json`) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment