Compare commits
5 Commits
57bb634fff
...
bf6fcf94d1
Author | SHA1 | Date |
---|---|---|
renovate | bf6fcf94d1 | |
kolaente | bc19a2fb78 | |
kolaente | 994aaeb920 | |
kolaente | ee3d20e1d2 | |
Elscrux | 8458e77341 |
|
@ -5,7 +5,7 @@
|
|||
"eslint.packageManager": "pnpm",
|
||||
"editor.formatOnSave": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": true
|
||||
"source.fixAll": "explicit"
|
||||
},
|
||||
"eslint.format.enable": true,
|
||||
"[javascript]": {
|
||||
|
|
|
@ -132,8 +132,8 @@
|
|||
"@cypress/vite-dev-server": "5.0.7",
|
||||
"@cypress/vue": "6.0.0",
|
||||
"@faker-js/faker": "8.4.1",
|
||||
"@histoire/plugin-screenshot": "0.17.16",
|
||||
"@histoire/plugin-vue": "0.17.16",
|
||||
"@histoire/plugin-screenshot": "0.17.17",
|
||||
"@histoire/plugin-vue": "0.17.17",
|
||||
"@rushstack/eslint-patch": "1.10.1",
|
||||
"@tsconfig/node18": "18.2.4",
|
||||
"@types/codemirror": "5.60.15",
|
||||
|
@ -162,7 +162,7 @@
|
|||
"eslint": "8.57.0",
|
||||
"eslint-plugin-vue": "9.24.1",
|
||||
"happy-dom": "14.7.1",
|
||||
"histoire": "0.17.16",
|
||||
"histoire": "0.17.17",
|
||||
"postcss": "8.4.38",
|
||||
"postcss-easing-gradients": "3.0.1",
|
||||
"postcss-easings": "4.0.0",
|
||||
|
|
|
@ -256,11 +256,11 @@ devDependencies:
|
|||
specifier: 8.4.1
|
||||
version: 8.4.1
|
||||
'@histoire/plugin-screenshot':
|
||||
specifier: 0.17.16
|
||||
version: 0.17.16(histoire@0.17.16)
|
||||
specifier: 0.17.17
|
||||
version: 0.17.17(histoire@0.17.17)
|
||||
'@histoire/plugin-vue':
|
||||
specifier: 0.17.16
|
||||
version: 0.17.16(histoire@0.17.16)(vite@5.2.8)(vue@3.4.21)
|
||||
specifier: 0.17.17
|
||||
version: 0.17.17(histoire@0.17.17)(vite@5.2.8)(vue@3.4.21)
|
||||
'@rushstack/eslint-patch':
|
||||
specifier: 1.10.1
|
||||
version: 1.10.1
|
||||
|
@ -343,8 +343,8 @@ devDependencies:
|
|||
specifier: 14.7.1
|
||||
version: 14.7.1
|
||||
histoire:
|
||||
specifier: 0.17.16
|
||||
version: 0.17.16(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
specifier: 0.17.17
|
||||
version: 0.17.17(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
postcss:
|
||||
specifier: 8.4.38
|
||||
version: 8.4.38
|
||||
|
@ -2497,12 +2497,12 @@ packages:
|
|||
'@hapi/hoek': 9.2.1
|
||||
dev: true
|
||||
|
||||
/@histoire/app@0.17.16(vite@5.2.8):
|
||||
resolution: {integrity: sha512-ds7aF9xzMSaLl+aQZYPGw8EllPJwn9Jb+DdVRdfkqAx2ZN4Lc2Ut3j5E+2IVz2DKLvP8Zio7CPqoatP2UfaoDg==}
|
||||
/@histoire/app@0.17.17(vite@5.2.8):
|
||||
resolution: {integrity: sha512-2i1V38o08V+eaR0d3L0/EA6AYG14xyQBJbyYv0Hz3r4sH3Elj1FoJiwolbCfTDmkOnSgwWTc7+JoCqkLIbxfhA==}
|
||||
dependencies:
|
||||
'@histoire/controls': 0.17.16(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.16(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.16
|
||||
'@histoire/controls': 0.17.17(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.17(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.17
|
||||
'@types/flexsearch': 0.7.6
|
||||
flexsearch: 0.7.21
|
||||
shiki-es: 0.2.0
|
||||
|
@ -2510,8 +2510,8 @@ packages:
|
|||
- vite
|
||||
dev: true
|
||||
|
||||
/@histoire/controls@0.17.16(vite@5.2.8):
|
||||
resolution: {integrity: sha512-yU5xGpAckcExYVdfnN1w7HFg1SwnOHW96RM+6THgu3ejPjRDVAoyMumM4xRWuY/y3PzlmW7kSoLJu9ykwufIGg==}
|
||||
/@histoire/controls@0.17.17(vite@5.2.8):
|
||||
resolution: {integrity: sha512-W22HZ/X078IZmE09XEKj4Fq7LxQPP/w/aMYAzm94V2NIGhI0fkiSaBDvyTUl7NYrGT66Wq5+9Po1IWPMllk3cQ==}
|
||||
dependencies:
|
||||
'@codemirror/commands': 6.3.2
|
||||
'@codemirror/lang-json': 6.0.1
|
||||
|
@ -2520,21 +2520,21 @@ packages:
|
|||
'@codemirror/state': 6.3.2
|
||||
'@codemirror/theme-one-dark': 6.1.2
|
||||
'@codemirror/view': 6.22.1
|
||||
'@histoire/shared': 0.17.16(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.16
|
||||
'@histoire/shared': 0.17.17(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.17
|
||||
transitivePeerDependencies:
|
||||
- vite
|
||||
dev: true
|
||||
|
||||
/@histoire/plugin-screenshot@0.17.16(histoire@0.17.16):
|
||||
resolution: {integrity: sha512-+KdQM5bkWfXJTUKpL1mQvDF/riQncijzRcFHTpXR++XXPAKMW2sRMf2psn51YJxQybJQuMPj5dEZlHowUfvSiw==}
|
||||
/@histoire/plugin-screenshot@0.17.17(histoire@0.17.17):
|
||||
resolution: {integrity: sha512-R5JL22bz274VZwLNu83Q3+xVDkdXOUuqjUc3ARVHWAObq8bZfHm5vNtQzE9uEN7DQi5NXZtnDEts8OfOxSu6rA==}
|
||||
peerDependencies:
|
||||
histoire: ^0.17.16
|
||||
histoire: ^0.17.17
|
||||
dependencies:
|
||||
capture-website: 2.4.1
|
||||
defu: 6.1.3
|
||||
fs-extra: 10.1.0
|
||||
histoire: 0.17.16(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
histoire: 0.17.17(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
pathe: 1.1.1
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
|
@ -2543,18 +2543,18 @@ packages:
|
|||
- utf-8-validate
|
||||
dev: true
|
||||
|
||||
/@histoire/plugin-vue@0.17.16(histoire@0.17.16)(vite@5.2.8)(vue@3.4.21):
|
||||
resolution: {integrity: sha512-sne2u5pIWy8hyivhYGA5P1lA3z/jstOCkNN9DnneLjan347exD3ASjbpVyMQjISUKCfNlY0dXKnlCgac7d6Qlg==}
|
||||
/@histoire/plugin-vue@0.17.17(histoire@0.17.17)(vite@5.2.8)(vue@3.4.21):
|
||||
resolution: {integrity: sha512-O5h/Ww6IT2CygVVT4onN27IZt11Z2qE8XeHeXJCEese3dxnnVWRhjMpsaWAU5XqgfjKNAiALJk86b49/6NQaRg==}
|
||||
peerDependencies:
|
||||
histoire: ^0.17.16
|
||||
histoire: ^0.17.17
|
||||
vue: ^3.2.47
|
||||
dependencies:
|
||||
'@histoire/controls': 0.17.16(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.16(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.16
|
||||
'@histoire/controls': 0.17.17(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.17(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.17
|
||||
change-case: 4.1.2
|
||||
globby: 13.2.2
|
||||
histoire: 0.17.16(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
histoire: 0.17.17(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8)
|
||||
launch-editor: 2.6.1
|
||||
pathe: 1.1.1
|
||||
vue: 3.4.21(typescript@5.4.4)
|
||||
|
@ -2562,12 +2562,12 @@ packages:
|
|||
- vite
|
||||
dev: true
|
||||
|
||||
/@histoire/shared@0.17.16(vite@5.2.8):
|
||||
resolution: {integrity: sha512-VsrBSh6EVQDttb/K512vurgUb1PwkAavt4VQWZ7LrQNCGhuoz/EJ6wLMpI0xkMRGvblBjoy204HOh+0W9vDBog==}
|
||||
/@histoire/shared@0.17.17(vite@5.2.8):
|
||||
resolution: {integrity: sha512-ueGtURysonT0MujCObPCR57+mgZluMEXCrbc2FBgKAD/DoAt38tNwSGsmLldk2O6nTr7lr6ClbVSgWrLwgY6Xw==}
|
||||
peerDependencies:
|
||||
vite: ^2.9.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
dependencies:
|
||||
'@histoire/vendors': 0.17.16
|
||||
'@histoire/vendors': 0.17.17
|
||||
'@types/fs-extra': 9.0.13
|
||||
'@types/markdown-it': 12.2.3
|
||||
chokidar: 3.5.3
|
||||
|
@ -2576,8 +2576,8 @@ packages:
|
|||
vite: 5.2.8(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)
|
||||
dev: true
|
||||
|
||||
/@histoire/vendors@0.17.16:
|
||||
resolution: {integrity: sha512-J/e1sjT/TaFT44aDkszRbqHnNvL7Bwrbl0GgqqH+T1MlkFv9e6prDIGzs8wvtdIDQbCq2T8NZOYhO/PGrcuJUA==}
|
||||
/@histoire/vendors@0.17.17:
|
||||
resolution: {integrity: sha512-QZvmffdoJlLuYftPIkOU5Q2FPAdG2JjMuQ5jF7NmEl0n1XnmbMqtRkdYTZ4eF6CO1KLZ0Zyf6gBQvoT1uWNcjA==}
|
||||
dev: true
|
||||
|
||||
/@humanwhocodes/config-array@0.11.14:
|
||||
|
@ -6296,17 +6296,17 @@ packages:
|
|||
engines: {node: '>=12.0.0'}
|
||||
dev: false
|
||||
|
||||
/histoire@0.17.16(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8):
|
||||
resolution: {integrity: sha512-zN67L0mbhJzreCz6VM9N9E203FBs0Adanf597bA8e4GAiLABHmcimsihOLaHQRG9g0qvjr3mU0H7Wi2wsYDRkg==}
|
||||
/histoire@0.17.17(@types/node@20.12.6)(sass@1.74.1)(terser@5.24.0)(vite@5.2.8):
|
||||
resolution: {integrity: sha512-DAwY4sgIoP7NGE5ldaws2d3RWz4OOQcwhS8elRMiA2euqzLvDU2IXm+ZjeDDFVtGkvmQNQyfZBDKLCLHfRkSUg==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
vite: ^2.9.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
|
||||
dependencies:
|
||||
'@akryum/tinypool': 0.3.1
|
||||
'@histoire/app': 0.17.16(vite@5.2.8)
|
||||
'@histoire/controls': 0.17.16(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.16(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.16
|
||||
'@histoire/app': 0.17.17(vite@5.2.8)
|
||||
'@histoire/controls': 0.17.17(vite@5.2.8)
|
||||
'@histoire/shared': 0.17.17(vite@5.2.8)
|
||||
'@histoire/vendors': 0.17.17
|
||||
'@types/flexsearch': 0.7.6
|
||||
'@types/markdown-it': 12.2.3
|
||||
birpc: 0.1.1
|
||||
|
|
|
@ -155,7 +155,6 @@ const savedFilterProjects = computed(() => projectStore.savedFilterProjects)
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
transform: translateX(-100%);
|
||||
overflow-x: auto;
|
||||
width: $navbar-width;
|
||||
|
||||
@media screen and (max-width: $tablet) {
|
||||
|
|
|
@ -107,80 +107,109 @@ func (m *Migration) AuthURL() string {
|
|||
"&return_url=" + config.MigrationTrelloRedirectURL.GetString()
|
||||
}
|
||||
|
||||
func getTrelloData(token string) (trelloData []*trello.Board, err error) {
|
||||
allArg := trello.Arguments{"fields": "all"}
|
||||
|
||||
client := trello.NewClient(config.MigrationTrelloKey.GetString(), token)
|
||||
client.Logger = log.GetLogger()
|
||||
|
||||
func getTrelloBoards(client *trello.Client) (trelloData []*trello.Board, err error) {
|
||||
log.Debugf("[Trello Migration] Getting boards...")
|
||||
|
||||
trelloData, err = client.GetMyBoards(trello.Defaults())
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d trello boards", len(trelloData))
|
||||
|
||||
for _, board := range trelloData {
|
||||
log.Debugf("[Trello Migration] Getting projects for board %s", board.ID)
|
||||
return
|
||||
}
|
||||
|
||||
board.Lists, err = board.GetLists(trello.Defaults())
|
||||
if err != nil {
|
||||
return
|
||||
func getTrelloOrganizationsWithBoards(boards []*trello.Board) (boardsByOrg map[string][]*trello.Board) {
|
||||
|
||||
boardsByOrg = make(map[string][]*trello.Board)
|
||||
|
||||
for _, board := range boards {
|
||||
// Trello boards without an organization are considered personal boards
|
||||
if board.IDOrganization == "" {
|
||||
board.IDOrganization = "Personal"
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d projects for board %s", len(board.Lists), board.ID)
|
||||
|
||||
listMap := make(map[string]*trello.List, len(board.Lists))
|
||||
for _, list := range board.Lists {
|
||||
listMap[list.ID] = list
|
||||
_, has := boardsByOrg[board.IDOrganization]
|
||||
if !has {
|
||||
boardsByOrg[board.IDOrganization] = []*trello.Board{}
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Getting cards for board %s", board.ID)
|
||||
boardsByOrg[board.IDOrganization] = append(boardsByOrg[board.IDOrganization], board)
|
||||
}
|
||||
|
||||
cards, err := board.GetCards(allArg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
func fillCardData(client *trello.Client, board *trello.Board) (err error) {
|
||||
allArg := trello.Arguments{"fields": "all"}
|
||||
|
||||
log.Debugf("[Trello Migration] Getting projects for board %s", board.ID)
|
||||
|
||||
board.Lists, err = board.GetLists(trello.Defaults())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d projects for board %s", len(board.Lists), board.ID)
|
||||
|
||||
listMap := make(map[string]*trello.List, len(board.Lists))
|
||||
for _, list := range board.Lists {
|
||||
listMap[list.ID] = list
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Getting cards for board %s", board.ID)
|
||||
|
||||
cards, err := board.GetCards(allArg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d cards for board %s", len(cards), board.ID)
|
||||
|
||||
for _, card := range cards {
|
||||
list, exists := listMap[card.IDList]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got %d cards for board %s", len(cards), board.ID)
|
||||
|
||||
for _, card := range cards {
|
||||
list, exists := listMap[card.IDList]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
if card.Badges.Attachments > 0 {
|
||||
card.Attachments, err = card.GetAttachments(allArg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
if len(card.IDCheckLists) > 0 {
|
||||
for _, checkListID := range card.IDCheckLists {
|
||||
checklist, err := client.GetChecklist(checkListID, allArg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
checklist.CheckItems = []trello.CheckItem{}
|
||||
err = client.Get("checklists/"+checkListID+"/checkItems", allArg, &checklist.CheckItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
card.Checklists = append(card.Checklists, checklist)
|
||||
log.Debugf("Retrieved checklist %s for card %s", checkListID, card.ID)
|
||||
}
|
||||
}
|
||||
|
||||
list.Cards = append(list.Cards, card)
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Looked for attachements on all cards of board %s", board.ID)
|
||||
if card.Badges.Comments > 0 {
|
||||
card.Actions, err = card.GetCommentActions()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(card.IDCheckLists) > 0 {
|
||||
for _, checkListID := range card.IDCheckLists {
|
||||
checklist, err := client.GetChecklist(checkListID, allArg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checklist.CheckItems = []trello.CheckItem{}
|
||||
err = client.Get("checklists/"+checkListID+"/checkItems", allArg, &checklist.CheckItems)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
card.Checklists = append(card.Checklists, checklist)
|
||||
log.Debugf("Retrieved checklist %s for card %s", checkListID, card.ID)
|
||||
}
|
||||
}
|
||||
|
||||
list.Cards = append(list.Cards, card)
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Looked for attachements on all cards of board %s", board.ID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -196,7 +225,7 @@ func convertMarkdownToHTML(input string) (output string, err error) {
|
|||
|
||||
// Converts all previously obtained data from trello into the vikunja format.
|
||||
// `trelloData` should contain all boards with their projects and cards respectively.
|
||||
func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullVikunjaHierachie []*models.ProjectWithTasksAndBuckets, err error) {
|
||||
func convertTrelloDataToVikunja(organizationName string, trelloData []*trello.Board, token string, currentMember *trello.Member) (fullVikunjaHierachie []*models.ProjectWithTasksAndBuckets, err error) {
|
||||
|
||||
log.Debugf("[Trello Migration] ")
|
||||
|
||||
|
@ -205,7 +234,7 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
|||
{
|
||||
Project: models.Project{
|
||||
ID: pseudoParentID,
|
||||
Title: "Imported from Trello",
|
||||
Title: organizationName,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -252,9 +281,11 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
|||
log.Debugf("[Trello Migration] Converting card %s", card.ID)
|
||||
|
||||
// The usual stuff: Title, description, position, bucket id
|
||||
task := &models.Task{
|
||||
Title: card.Name,
|
||||
BucketID: bucketID,
|
||||
task := &models.TaskWithComments{
|
||||
Task: models.Task{
|
||||
Title: card.Name,
|
||||
BucketID: bucketID,
|
||||
},
|
||||
}
|
||||
|
||||
task.Description, err = convertMarkdownToHTML(card.Desc)
|
||||
|
@ -362,7 +393,32 @@ func convertTrelloDataToVikunja(trelloData []*trello.Board, token string) (fullV
|
|||
task.CoverImageAttachmentID = coverAttachment.ID
|
||||
}
|
||||
|
||||
project.Tasks = append(project.Tasks, &models.TaskWithComments{Task: *task})
|
||||
for _, action := range card.Actions {
|
||||
if action.DidCommentCard() {
|
||||
if task.Comments == nil {
|
||||
task.Comments = []*models.TaskComment{}
|
||||
}
|
||||
|
||||
comment := &models.TaskComment{
|
||||
Comment: action.Data.Text,
|
||||
Created: action.Date,
|
||||
Updated: action.Date,
|
||||
}
|
||||
|
||||
if currentMember == nil || action.IDMemberCreator != currentMember.ID {
|
||||
comment.Comment = "*" + action.MemberCreator.FullName + "*:\n\n" + comment.Comment
|
||||
}
|
||||
|
||||
comment.Comment, err = convertMarkdownToHTML(comment.Comment)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
task.Comments = append(task.Comments, comment)
|
||||
}
|
||||
}
|
||||
|
||||
project.Tasks = append(project.Tasks, task)
|
||||
}
|
||||
|
||||
project.Buckets = append(project.Buckets, bucket)
|
||||
|
@ -392,29 +448,62 @@ func (m *Migration) Migrate(u *user.User) (err error) {
|
|||
log.Debugf("[Trello Migration] Starting migration for user %d", u.ID)
|
||||
log.Debugf("[Trello Migration] Getting all trello data for user %d", u.ID)
|
||||
|
||||
trelloData, err := getTrelloData(m.Token)
|
||||
client := trello.NewClient(config.MigrationTrelloKey.GetString(), m.Token)
|
||||
client.Logger = log.GetLogger()
|
||||
|
||||
boards, err := getTrelloBoards(client)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got all trello data for user %d", u.ID)
|
||||
log.Debugf("[Trello Migration] Start converting trello data for user %d", u.ID)
|
||||
|
||||
fullVikunjaHierachie, err := convertTrelloDataToVikunja(trelloData, m.Token)
|
||||
if err != nil {
|
||||
return
|
||||
organizationMap := getTrelloOrganizationsWithBoards(boards)
|
||||
for organizationID, boards := range organizationMap {
|
||||
log.Debugf("[Trello Migration] Getting organization with id %s for user %d", organizationID, u.ID)
|
||||
orgName := organizationID
|
||||
if organizationID != "Personal" {
|
||||
organization, err := client.GetOrganization(organizationID, trello.Defaults())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
orgName = organization.DisplayName
|
||||
}
|
||||
|
||||
for _, board := range boards {
|
||||
log.Debugf("[Trello Migration] Getting card data for board %s for user %d for organization %s", board.ID, u.ID, organizationID)
|
||||
|
||||
err = fillCardData(client, board)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Got card data for board %s for user %d for organization %s", board.ID, u.ID, organizationID)
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Start converting trello data for user %d for organization %s", u.ID, organizationID)
|
||||
|
||||
currentMember, err := client.GetMyMember(trello.Defaults())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hierarchy, err := convertTrelloDataToVikunja(orgName, boards, client.Token, currentMember)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Done migrating trello data for user %d for organization %s", u.ID, organizationID)
|
||||
log.Debugf("[Trello Migration] Start inserting trello data for user %d for organization %s", u.ID, organizationID)
|
||||
|
||||
err = migration.InsertFromStructure(hierarchy, u)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Done inserting trello data for user %d for organization %s", u.ID, organizationID)
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Done migrating trello data for user %d", u.ID)
|
||||
log.Debugf("[Trello Migration] Start inserting trello data for user %d", u.ID)
|
||||
log.Debugf("[Trello Migration] Done migrating all trello data for user %d", u.ID)
|
||||
|
||||
err = migration.InsertFromStructure(fullVikunjaHierachie, u)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("[Trello Migration] Done inserting trello data for user %d", u.ID)
|
||||
log.Debugf("[Trello Migration] Migration done for user %d", u.ID)
|
||||
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
|
|
@ -32,20 +32,23 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
func getTestBoard(t *testing.T) ([]*trello.Board, time.Time) {
|
||||
|
||||
config.InitConfig()
|
||||
|
||||
time1, err := time.Parse(time.RFC3339Nano, "2014-09-26T08:25:05Z")
|
||||
require.NoError(t, err)
|
||||
exampleFile, err := os.ReadFile(config.ServiceRootpath.GetString() + "/pkg/modules/migration/testimage.jpg")
|
||||
require.NoError(t, err)
|
||||
|
||||
trelloData := []*trello.Board{
|
||||
{
|
||||
Name: "TestBoard",
|
||||
Desc: "This is a description",
|
||||
Closed: false,
|
||||
Name: "TestBoard",
|
||||
Organization: trello.Organization{
|
||||
ID: "orgid",
|
||||
DisplayName: "TestOrg",
|
||||
},
|
||||
IDOrganization: "orgid",
|
||||
Desc: "This is a description",
|
||||
Closed: false,
|
||||
Lists: []*trello.List{
|
||||
{
|
||||
Name: "Test Project 1",
|
||||
|
@ -168,8 +171,13 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Name: "TestBoard 2",
|
||||
Closed: false,
|
||||
Organization: trello.Organization{
|
||||
ID: "orgid2",
|
||||
DisplayName: "TestOrg2",
|
||||
},
|
||||
IDOrganization: "orgid2",
|
||||
Name: "TestBoard 2",
|
||||
Closed: false,
|
||||
Lists: []*trello.List{
|
||||
{
|
||||
Name: "Test Project 4",
|
||||
|
@ -183,8 +191,13 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
},
|
||||
{
|
||||
Name: "TestBoard Archived",
|
||||
Closed: true,
|
||||
Organization: trello.Organization{
|
||||
ID: "orgid",
|
||||
DisplayName: "TestOrg",
|
||||
},
|
||||
IDOrganization: "orgid",
|
||||
Name: "TestBoard Archived",
|
||||
Closed: true,
|
||||
Lists: []*trello.List{
|
||||
{
|
||||
Name: "Test Project 5",
|
||||
|
@ -197,67 +210,91 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Personal Board",
|
||||
Lists: []*trello.List{
|
||||
{
|
||||
Name: "Test Project 6",
|
||||
Cards: []*trello.Card{
|
||||
{
|
||||
Name: "Test Card 5659",
|
||||
Pos: 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
trelloData[0].Prefs.BackgroundImage = "https://vikunja.io/testimage.jpg" // Using an image which we are hosting, so it'll still be up
|
||||
|
||||
expectedHierachie := []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 1,
|
||||
Title: "Imported from Trello",
|
||||
},
|
||||
},
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 2,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard",
|
||||
Description: "This is a description",
|
||||
BackgroundInformation: bytes.NewBuffer(exampleFile),
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
return trelloData, time1
|
||||
}
|
||||
|
||||
func TestConvertTrelloToVikunja(t *testing.T) {
|
||||
trelloData, time1 := getTestBoard(t)
|
||||
|
||||
exampleFile, err := os.ReadFile(config.ServiceRootpath.GetString() + "/pkg/modules/migration/testimage.jpg")
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedHierarchyOrg := map[string][]*models.ProjectWithTasksAndBuckets{
|
||||
"orgid": {
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 1,
|
||||
Title: "Test Project 1",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "Test Project 2",
|
||||
Title: "orgid",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 1",
|
||||
Description: "<p>Card Description <strong>bold</strong></p>\n",
|
||||
BucketID: 1,
|
||||
DueDate: time1,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 1",
|
||||
HexColor: trelloColorMap["green"],
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 2,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard",
|
||||
Description: "This is a description",
|
||||
BackgroundInformation: bytes.NewBuffer(exampleFile),
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "Test Project 1",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "Test Project 2",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 1",
|
||||
Description: "<p>Card Description <strong>bold</strong></p>\n",
|
||||
BucketID: 1,
|
||||
DueDate: time1,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 1",
|
||||
HexColor: trelloColorMap["green"],
|
||||
},
|
||||
{
|
||||
Title: "Label 2",
|
||||
HexColor: trelloColorMap["orange"],
|
||||
},
|
||||
},
|
||||
{
|
||||
Title: "Label 2",
|
||||
HexColor: trelloColorMap["orange"],
|
||||
},
|
||||
},
|
||||
Attachments: []*models.TaskAttachment{
|
||||
{
|
||||
File: &files.File{
|
||||
Name: "Testimage.jpg",
|
||||
Mime: "image/jpg",
|
||||
Size: uint64(len(exampleFile)),
|
||||
FileContent: exampleFile,
|
||||
Attachments: []*models.TaskAttachment{
|
||||
{
|
||||
File: &files.File{
|
||||
Name: "Testimage.jpg",
|
||||
Mime: "image/jpg",
|
||||
Size: uint64(len(exampleFile)),
|
||||
FileContent: exampleFile,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 2",
|
||||
Description: `
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 2",
|
||||
Description: `
|
||||
|
||||
<h2> Checkproject 1</h2>
|
||||
|
||||
|
@ -270,117 +307,180 @@ func TestConvertTrelloToVikunja(t *testing.T) {
|
|||
<ul data-type="taskList">
|
||||
<li data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p>Pending Task</p></div></li>
|
||||
<li data-checked="false" data-type="taskItem"><label><input type="checkbox"><span></span></label><div><p>Another Pending Task</p></div></li></ul>`,
|
||||
BucketID: 1,
|
||||
BucketID: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 3",
|
||||
BucketID: 1,
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 3",
|
||||
BucketID: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 4",
|
||||
BucketID: 1,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 2",
|
||||
HexColor: trelloColorMap["orange"],
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 4",
|
||||
BucketID: 1,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 2",
|
||||
HexColor: trelloColorMap["orange"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 5",
|
||||
BucketID: 2,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 3",
|
||||
HexColor: trelloColorMap["blue"],
|
||||
},
|
||||
{
|
||||
Title: "Label 4",
|
||||
HexColor: trelloColorMap["green_dark"],
|
||||
},
|
||||
{
|
||||
Title: "Label 5",
|
||||
HexColor: trelloColorMap["transparent"],
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 5",
|
||||
BucketID: 2,
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label 3",
|
||||
HexColor: trelloColorMap["blue"],
|
||||
},
|
||||
{
|
||||
Title: "Label 4",
|
||||
HexColor: trelloColorMap["green_dark"],
|
||||
},
|
||||
{
|
||||
Title: "Label 5",
|
||||
HexColor: trelloColorMap["transparent"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 6",
|
||||
BucketID: 2,
|
||||
DueDate: time1,
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 6",
|
||||
BucketID: 2,
|
||||
DueDate: time1,
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 7",
|
||||
BucketID: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 8",
|
||||
BucketID: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 7",
|
||||
BucketID: 2,
|
||||
},
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 3,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard Archived",
|
||||
IsArchived: true,
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 3,
|
||||
Title: "Test Project 5",
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 8",
|
||||
BucketID: 2,
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 63423",
|
||||
BucketID: 3,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 3,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard 2",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 3,
|
||||
Title: "Test Project 4",
|
||||
"orgid2": {
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 1,
|
||||
Title: "orgid2",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 634",
|
||||
BucketID: 3,
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 2,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard 2",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "Test Project 4",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 634",
|
||||
BucketID: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 4,
|
||||
ParentProjectID: 1,
|
||||
Title: "TestBoard Archived",
|
||||
IsArchived: true,
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 4,
|
||||
Title: "Test Project 5",
|
||||
"Personal": {
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 1,
|
||||
Title: "Personal",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 63423",
|
||||
BucketID: 4,
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 2,
|
||||
ParentProjectID: 1,
|
||||
Title: "Personal Board",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "Test Project 6",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Test Card 5659",
|
||||
BucketID: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
hierachie, err := convertTrelloDataToVikunja(trelloData, "")
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, hierachie)
|
||||
if diff, equal := messagediff.PrettyDiff(hierachie, expectedHierachie); !equal {
|
||||
t.Errorf("converted trello data = %v, want %v, diff: %v", hierachie, expectedHierachie, diff)
|
||||
organizationMap := getTrelloOrganizationsWithBoards(trelloData)
|
||||
for organizationID, boards := range organizationMap {
|
||||
hierarchy, err := convertTrelloDataToVikunja(organizationID, boards, "", nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, hierarchy)
|
||||
if diff, equal := messagediff.PrettyDiff(hierarchy, expectedHierarchyOrg[organizationID]); !equal {
|
||||
t.Errorf("converted trello data = %v,\nwant %v,\ndiff: %v", hierarchy, expectedHierarchyOrg[organizationID], diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateOrganizationMap(t *testing.T) {
|
||||
trelloData, _ := getTestBoard(t)
|
||||
|
||||
organizationMap := getTrelloOrganizationsWithBoards(trelloData)
|
||||
expectedMap := map[string][]*trello.Board{
|
||||
"orgid": {
|
||||
trelloData[0],
|
||||
trelloData[2],
|
||||
},
|
||||
"orgid2": {
|
||||
trelloData[1],
|
||||
},
|
||||
"Personal": {
|
||||
trelloData[3],
|
||||
},
|
||||
}
|
||||
if diff, equal := messagediff.PrettyDiff(organizationMap, expectedMap); !equal {
|
||||
t.Errorf("converted trello data = %v,\nwant %v,\ndiff: %v", organizationMap, expectedMap, diff)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue