Last active
April 1, 2022 11:07
-
-
Save pavelpower/a7dfc40eff8c9375aaa30883b6671b8b to your computer and use it in GitHub Desktop.
Run this script from console in your browser. Run this script on the page "https://miro.com/app/dashboard/"
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
function getBoardId(src) { | |
return src.match(/boards\/([^\/]*)/)[1]; | |
} | |
function waitForElementToDisplay(selector, itemelem, callback, checkFrequencyInMs, timeoutInMs) { | |
var startTimeInMs = Date.now(); | |
(function loopSearch() { | |
let btn = document.querySelectorAll(selector)[itemelem || 0]; | |
if (btn != null) { | |
callback(btn); | |
return; | |
} | |
else { | |
setTimeout(function () { | |
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs) | |
return; | |
loopSearch(); | |
}, checkFrequencyInMs); | |
} | |
})(); | |
} | |
function clickButton({ selector, itemelem, timewaitafter, callback }) { | |
waitForElementToDisplay(selector, itemelem, (btn)=> { | |
btn.click(); | |
setTimeout(callback, timewaitafter || 500); | |
}, 1000, 9000); | |
} | |
function clickButtonMenu({ selector, itemelem, timewaitafter, callback, doCancel }) { | |
let btn = document.querySelectorAll(selector)[itemelem || 0]; | |
if (btn==null) { | |
console.log('undefined by selector:', selector, itemelem || 0); | |
if (doCancel) doCancel(); | |
} | |
if (btn.className.indexOf('exportItem_disabled') != -1) { | |
console.log('do cancel click on:', selector); | |
if (doCancel) doCancel(); | |
} | |
btn.click(); | |
setTimeout(callback, timewaitafter || 500); | |
} | |
function whileRtbLoader(callback) { | |
if (rtbLoader.rtbLoaderElement.style.display == 'block') { | |
setTimeout(()=>whileRtbLoader(callback), 500); | |
return; | |
} | |
if (document.querySelectorAll('.board-ui-skeleton__panel').length != 0) { | |
setTimeout(()=>whileRtbLoader(callback), 200); | |
return; | |
} | |
setTimeout(callback, 500); | |
} | |
function download(content, fileName, contentType, callback) { | |
var a = document.createElement("a"); | |
var file = new Blob([content], {type: contentType}); | |
a.href = URL.createObjectURL(file); | |
a.download = fileName; | |
a.click(); | |
if (!!callback) callback(); | |
} | |
// open all boards | |
let btn = document.querySelectorAll('[aria-label="Show all boards"]')[0]; | |
btn.click(); | |
setTimeout(()=> { | |
var lsBoards = JSON.parse(window.localStorage.getItem('export_boards')); | |
if (lsBoards == null || lsBoards.length == 0) { | |
let boardsid = []; | |
let buttonImg = document.querySelectorAll('[data-testid="board_image_original_autotest_id"]'); | |
buttonImg.forEach(b => boardsid.push(getBoardId(b.src))); | |
window.localStorage.setItem('export_boards', JSON.stringify(boardsid)); | |
} | |
load(); | |
function load() { | |
var boardsid = JSON.parse(window.localStorage.getItem('export_boards')); | |
// run | |
clickOpenAllBoards(); | |
function clickOpenAllBoards() { | |
clickButton({ | |
selector: '[aria-label="Show all boards"]', | |
itemelem: 0, | |
timewaitafter: 400, | |
callback: clickBoardIcon | |
}) | |
} | |
function clickBoardIcon() { | |
let boardId = boardsid.pop(); | |
window.localStorage.setItem('export_boards', JSON.stringify(boardsid)); | |
//дашборды закончились | |
if (boardId == null) | |
return; | |
console.log(boardsid); | |
clickButton({ | |
selector: `[src^="https://miro.com/api/v1/boards/${boardId}"]`, | |
itemelem: 0, | |
timewaitafter: 200, | |
callback: () => { | |
rtbLoader.rtbLoaderElement.style.display == 'block'; | |
openExportMenu(clickExportBackup); | |
} | |
}) | |
} | |
function openExportMenu(clickBtnExport) { | |
whileRtbLoader(()=> { | |
clickButton({ | |
selector: '[data-testid="board-header__export-icon"]', | |
itemelem: 0, | |
timewaitafter: 500, | |
callback: clickBtnExport | |
}); | |
}); | |
} | |
function clickExportBackup() { | |
clickButtonMenu({ | |
selector: '[data-testid="board-header__export-icon--BOARD_EXPORT_BACKUP"]', | |
itemelem: 0, | |
timewaitafter: 20000, | |
callback: backupBoardObjects, | |
doCancel: backupBoardObjects | |
}); | |
} | |
function backupBoardObjects() { | |
window.miro.board.info.get().then(boardinfo=>{ | |
const filename = boardinfo.title + '_' + boardinfo.updatedAt.replace(/\..*$/,''); | |
window.miro.board.getAllObjects().then(elems => { | |
const jsonData = JSON.stringify(elems, null, ' '); | |
download(jsonData, filename + '.canvas.json', 'text/plain', ()=>openExportMenu(clickExportPDF)); | |
}).catch((err) => { | |
openExportMenu(clickExportPDF); | |
}); | |
}); | |
} | |
function clickExportPDF () { | |
window.miro.board.getAllObjects().then(elems => { | |
// chack have frame | |
if (elems.findIndex((k) => k.type == 'FRAME') == -1) { | |
backToPageAllDashboard(); | |
return; | |
} | |
clickButtonMenu({ | |
selector: '[data-testid="board-header__export-icon--BOARD_EXPORT_PDF"]', | |
itemelem: 0, | |
timewaitafter: 500, | |
callback: clickQualityBest, | |
doCancel: backToPageAllDashboard | |
}); | |
}); | |
function clickQualityBest () { | |
clickButton({ | |
selector: '[hm-tap="modal.setQuality(+quality)"] label', | |
itemelem: 1, | |
timewaitafter: 300, | |
callback: clickDownloadPDF | |
}); | |
} | |
function clickDownloadPDF () { | |
clickButton({ | |
selector: 'button[hm-tap="modal.download()"]', | |
itemelem: 0, | |
timewaitafter: 20000, //wait 20 sec | |
callback: backToPageAllDashboard | |
}); | |
} | |
} | |
function backToPageAllDashboard() { | |
window.history.back(); | |
setTimeout(()=> { | |
load(); | |
}, 10000); | |
} | |
} | |
}, 200); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment