Add export (txt, csv, json) and import
This commit is contained in:
parent
38b830f6eb
commit
b9c99d284c
4 changed files with 311 additions and 16 deletions
|
@ -608,3 +608,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, .import * {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
|
|
@ -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('action inconnue : ' + 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,43 @@ $(function() {
|
|||
containment: 'parent'
|
||||
});
|
||||
|
||||
$('#export-txt').click(function() {
|
||||
socket.json.send({
|
||||
action: 'exportTxt',
|
||||
data: ($('.col').length !== 0) ? $('.col').css('width').replace('px', '') : null
|
||||
});
|
||||
})
|
||||
|
||||
$('#export-csv').click(function() {
|
||||
socket.json.send({
|
||||
action: 'exportCsv',
|
||||
data: ($('.col').length !== 0) ? $('.col').css('width').replace('px', '') : null
|
||||
});
|
||||
})
|
||||
|
||||
$('#export-json').click(function() {
|
||||
socket.json.send({
|
||||
action: 'exportJson',
|
||||
data: {
|
||||
width: $('.board-outline').css('width').replace('px', ''),
|
||||
height: $('.board-outline').css('height').replace('px', '')
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
$('#import-file').click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
|
||||
var f = $('#import-input').get(0).files[0];
|
||||
var fr = new FileReader();
|
||||
fr.onloadend = function() {
|
||||
var text = fr.result;
|
||||
socket.json.send({
|
||||
action: 'importJson',
|
||||
data: JSON.parse(text)
|
||||
});
|
||||
};
|
||||
fr.readAsBinaryString(f);
|
||||
})
|
||||
});
|
||||
|
|
226
server.js
226
server.js
|
@ -1,3 +1,4 @@
|
|||
// vim:set noexpandtab:
|
||||
/**************
|
||||
SYSTEM INCLUDES
|
||||
**************/
|
||||
|
@ -83,9 +84,8 @@ router.get('/:id', function(req, res){
|
|||
/**************
|
||||
SOCKET.I0
|
||||
**************/
|
||||
io.sockets.on('connection', function (client) {
|
||||
//santizes text
|
||||
function scrub( text ) {
|
||||
//sanitizes text
|
||||
function scrub( text ) {
|
||||
if (typeof text != "undefined" && text !== null)
|
||||
{
|
||||
|
||||
|
@ -101,9 +101,9 @@ io.sockets.on('connection', function (client) {
|
|||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
io.sockets.on('connection', function (client) {
|
||||
|
||||
client.on('message', function( message ){
|
||||
//console.log(message.action + " -- " + sys.inspect(message.data) );
|
||||
|
@ -302,6 +302,22 @@ 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':
|
||||
exportJson( client, message.data );
|
||||
break;
|
||||
|
||||
case 'importJson':
|
||||
importJson( client, message.data );
|
||||
break;
|
||||
|
||||
default:
|
||||
//console.log('unknown action');
|
||||
break;
|
||||
|
@ -490,6 +506,206 @@ function cleanAndInitializeDemoRoom()
|
|||
createCard('/demo', 'card8', '.', roundRand(600), roundRand(300), Math.random() * 10 - 5, 'green');
|
||||
});
|
||||
}
|
||||
|
||||
// Export board in txt or csv
|
||||
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'] < (i + 1) * data) {
|
||||
cols[columns[i]].push(cards[j]);
|
||||
}
|
||||
} else if (i + 1 === columns.length) {
|
||||
if (cards[j]['x'] >= i * data) {
|
||||
cols[columns[i]].push(cards[j]);
|
||||
}
|
||||
} else if (cards[j]['x'] >= i * data && cards[j]['x'] < (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
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Export board in json, suitable for import
|
||||
function exportJson( client, data )
|
||||
{
|
||||
var result = new Array();
|
||||
getRoom(client, function(room) {
|
||||
db.getAllCards( room , function (cards) {
|
||||
db.getAllColumns ( room, function (columns) {
|
||||
db.getTheme( room, function(theme) {
|
||||
db.getBoardSize( room, function(size) {
|
||||
if (theme === null) theme = 'bigcards';
|
||||
if (size === null) size = { width: data.width, height: data.height };
|
||||
result = JSON.stringify({
|
||||
cards: cards,
|
||||
columns: columns,
|
||||
theme: theme,
|
||||
size: size
|
||||
});
|
||||
client.json.send(
|
||||
{
|
||||
action: 'export',
|
||||
data: {
|
||||
filename: room.replace('/', '')+'.json',
|
||||
text: result
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Import board from json
|
||||
function importJson( client, data )
|
||||
{
|
||||
getRoom(client, function(room) {
|
||||
db.clearRoom(room, function() {
|
||||
db.getAllCards( room , function (cards) {
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
db.deleteCard ( room, cards[i].id );
|
||||
}
|
||||
|
||||
cards = data.cards;
|
||||
var cards2 = new Array();
|
||||
for (var i = 0; i < cards.length; i++) {
|
||||
var card = cards[i];
|
||||
if (card.id !== undefined && card.colour !== undefined
|
||||
&& card.rot !== undefined && card.x !== undefined
|
||||
&& card.y !== undefined && card.text !== undefined
|
||||
&& card.sticker !== undefined) {
|
||||
var c = {
|
||||
id: card.id,
|
||||
colour: card.colour,
|
||||
rot: card.rot,
|
||||
x: card.x,
|
||||
y: card.y,
|
||||
text: scrub(card.text),
|
||||
sticker: card.sticker
|
||||
};
|
||||
db.createCard(room, c.id, c);
|
||||
cards2.push(c);
|
||||
}
|
||||
}
|
||||
var msg = { action: 'initCards', data: cards2 };
|
||||
broadcastToRoom(client, msg);
|
||||
client.json.send(msg);
|
||||
});
|
||||
|
||||
db.getAllColumns ( room, function (columns) {
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
db.deleteColumn(room);
|
||||
}
|
||||
|
||||
columns = data.columns;
|
||||
var columns2 = new Array();
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
var column = scrub(columns[i]);
|
||||
if (typeof(column) === 'string') {
|
||||
db.createColumn(room, column);
|
||||
columns2.push(column);
|
||||
}
|
||||
}
|
||||
msg = { action: 'initColumns', data: columns2 };
|
||||
broadcastToRoom(client, msg);
|
||||
client.json.send(msg);
|
||||
});
|
||||
|
||||
var size = data.size;
|
||||
if (size.width !== undefined && size.height !== undefined) {
|
||||
size = { width: scrub(size.width), height: scrub(size.height) };
|
||||
db.setBoardSize( room, size );
|
||||
msg = { action: 'setBoardSize', data: size };
|
||||
broadcastToRoom(client, msg);
|
||||
client.json.send(msg);
|
||||
}
|
||||
|
||||
data.theme = scrub(data.theme);
|
||||
if (data.theme === 'smallcards' || data.theme === 'bigcards') {
|
||||
db.setTheme( room, data.theme );
|
||||
msg = { action: 'changeTheme', data: data.theme };
|
||||
broadcastToRoom(client, msg);
|
||||
client.json.send(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
//
|
||||
|
||||
/**************
|
||||
|
|
|
@ -58,6 +58,19 @@ block body
|
|||
span.you-text (vous)
|
||||
ul#names-ul
|
||||
|
||||
div.export
|
||||
h3 Export board
|
||||
button#export-txt Text format
|
||||
button#export-csv CSV format
|
||||
button#export-json JSON format (for import in Scrumblr)
|
||||
|
||||
div.import
|
||||
h3 Import board
|
||||
div
|
||||
label(for="import-input") JSON file to import
|
||||
input(type="file")#import-input
|
||||
button#import-file Import
|
||||
|
||||
//div.trash
|
||||
// i.fa.fa-trash-o.fa-lg.faded-icon
|
||||
hr(role="presentation")
|
||||
|
|
Loading…
Add table
Reference in a new issue