From 82213dc6a6cc5e3ecd612285efbac509b13224a0 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 13 Sep 2016 09:06:15 +0200 Subject: [PATCH] Add export function and buttons (txt, csv, json) --- client/css/style.css | 4 ++ client/script.js | 43 ++++++++++++++++++ server.js | 104 +++++++++++++++++++++++++++++++++++++++++++ views/index.jade | 6 +++ 4 files changed, 157 insertions(+) diff --git a/client/css/style.css b/client/css/style.css index 34bb56b6..411e2df6 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -617,3 +617,7 @@ img { .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } + +.export button { + margin-right: 15px; +} diff --git a/client/script.js b/client/script.js index fc288b0f..8a7e4c74 100644 --- a/client/script.js +++ b/client/script.js @@ -147,6 +147,10 @@ function getMessage(m) { resizeBoard(message.data); break; + case 'export': + download(message.data.filename, message.data.text); + break; + default: //unknown message alert('unknown action: ' + JSON.stringify(message)); @@ -679,6 +683,26 @@ function adjustCard(offsets, doSync) { ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// +function download(filename, text) { + var element = document.createElement('a'); + var mime = 'text/plain'; + if (filename.match(/.csv$/)) { + mime = 'text/csv'; + } + element.setAttribute('href', 'data:'+mime+';charset=utf-8,' + encodeURIComponent(text)); + element.setAttribute('download', filename); + + element.style.display = 'none'; + document.body.appendChild(element); + + element.click(); + + document.body.removeChild(element); +} + +////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////// + $(function() { @@ -840,5 +864,24 @@ $(function() { containment: 'parent' }); + $('#export-txt').click(function() { + socket.json.send({ + action: 'exportTxt', + data: $('.col').css('width').replace('px', '') + }); + }) + $('#export-csv').click(function() { + socket.json.send({ + action: 'exportCsv', + data: $('.col').css('width').replace('px', '') + }); + }) + + $('#export-json').click(function() { + socket.json.send({ + action: 'exportJson', + data: $('.col').css('width').replace('px', '') + }); + }) }); diff --git a/server.js b/server.js index 39d7a6fa..cef4028d 100644 --- a/server.js +++ b/server.js @@ -302,6 +302,18 @@ io.sockets.on('connection', function (client) { broadcastToRoom( client, { action: 'setBoardSize', data: size } ); break; + case 'exportTxt': + exportBoard( 'txt', client, message.data ); + break; + + case 'exportCsv': + exportBoard( 'csv', client, message.data ); + break; + + case 'exportJson': + exportBoard( 'json', client, message.data ); + break; + default: //console.log('unknown action'); break; @@ -490,6 +502,98 @@ function cleanAndInitializeDemoRoom() createCard('/demo', 'card8', '.', roundRand(600), roundRand(300), Math.random() * 10 - 5, 'green'); }); } + +// Export board in txt, csv or json +function exportBoard(format, client, data ) +{ + var result = new Array(); + getRoom(client, function(room) { + db.getAllCards( room , function (cards) { + db.getAllColumns ( room, function (columns) { + var text = new Array(); + var cols = {}; + if (columns.length > 0) { + for (var i = 0; i < columns.length; i++) { + cols[columns[i]] = new Array(); + for (var j = 0; j < cards.length; j++) { + if (i === 0) { + if (cards[j]['x'] + 34 < (i + 1) * data) { + cols[columns[i]].push(cards[j]); + } + } else if (i + 1 === columns.length) { + if (cards[j]['x'] + 34 >= i * data) { + cols[columns[i]].push(cards[j]); + } + } else if (cards[j]['x'] + 34 >= i * data && cards[j]['x'] + 34 < (i + 1) * data) { + cols[columns[i]].push(cards[j]); + } + } + cols[columns[i]].sort(function(a, b) { + if (a['y'] === b['y']) { + return (a['x'] - b['x']); + } else { + return a['y'] - b['y']; + } + }); + } + if (format === 'txt') { + for (var i = 0; i < columns.length; i++) { + if (i === 0) { + text.push("# "+columns[i]); + } else { + text.push("\n# "+columns[i]); + } + for (var j = 0; j < cols[columns[i]].length; j++) { + text.push('- '+cols[columns[i]][j]['text']); + } + } + } else if (format === 'csv') { + var max = 0; + var line = new Array(); + for (var i = 0; i < columns.length; i++) { + if (cols[columns[i]].length > max) { + max = cols[columns[i]].length; + } + line.push('"'+columns[i].replace(/"/g,'""')+'"'); + } + text.push(line.join(',')); + for (var j = 0; j < max; j++) { + line = new Array(); + for (var i = 0; i < columns.length; i++) { + var val = (cols[columns[i]][j] !== undefined) ? cols[columns[i]][j]['text'].replace(/"/g,'""') : ''; + line.push('"'+val+'"'); + } + text.push(line.join(',')); + } + } + } else { + for (var j = 0; j < cards.length; j++) { + if (format === 'txt') { + text.push('- '+cards[j]['text']); + } else if (format === 'csv') { + text.push('"'+cards[j]['text'].replace(/"/g,'""')+'"\n'); + } + } + } + var result; + if (format === 'txt' || format === 'csv') { + result = text.join("\n"); + } else if (format === 'json') { + result = JSON.stringify(cols); + } + client.json.send( + { + action: 'export', + data: { + filename: room.replace('/', '')+'.'+format, + text: result + } + } + ); + }); + }); + }); +} // /************** diff --git a/views/index.jade b/views/index.jade index 8aa66939..88f76c9d 100644 --- a/views/index.jade +++ b/views/index.jade @@ -60,6 +60,12 @@ block body span.you-text (you) ul#names-ul + div.export + h3 Export board + button#export-txt Text format + button#export-csv CSV format + button#export-json JSON format + //div.trash // i.fa.fa-trash-o.fa-lg.faded-icon