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-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}
|
||||||
|
|
||||||
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
|
.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);
|
resizeBoard(message.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'export':
|
||||||
|
download(message.data.filename, message.data.text);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//unknown message
|
//unknown message
|
||||||
alert('action inconnue : ' + JSON.stringify(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() {
|
$(function() {
|
||||||
|
|
||||||
|
|
||||||
|
@ -840,5 +864,43 @@ $(function() {
|
||||||
containment: 'parent'
|
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);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
248
server.js
248
server.js
|
@ -1,3 +1,4 @@
|
||||||
|
// vim:set noexpandtab:
|
||||||
/**************
|
/**************
|
||||||
SYSTEM INCLUDES
|
SYSTEM INCLUDES
|
||||||
**************/
|
**************/
|
||||||
|
@ -83,27 +84,26 @@ router.get('/:id', function(req, res){
|
||||||
/**************
|
/**************
|
||||||
SOCKET.I0
|
SOCKET.I0
|
||||||
**************/
|
**************/
|
||||||
io.sockets.on('connection', function (client) {
|
//sanitizes text
|
||||||
//santizes text
|
function scrub( text ) {
|
||||||
function scrub( text ) {
|
if (typeof text != "undefined" && text !== null)
|
||||||
if (typeof text != "undefined" && text !== null)
|
{
|
||||||
{
|
|
||||||
|
|
||||||
//clip the string if it is too long
|
//clip the string if it is too long
|
||||||
if (text.length > 65535)
|
if (text.length > 65535)
|
||||||
{
|
|
||||||
text = text.substr(0,65535);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sanitizer.sanitize(text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return null;
|
text = text.substr(0,65535);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sanitizer.sanitize(text);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
io.sockets.on('connection', function (client) {
|
||||||
|
|
||||||
client.on('message', function( message ){
|
client.on('message', function( message ){
|
||||||
//console.log(message.action + " -- " + sys.inspect(message.data) );
|
//console.log(message.action + " -- " + sys.inspect(message.data) );
|
||||||
|
@ -302,6 +302,22 @@ io.sockets.on('connection', function (client) {
|
||||||
broadcastToRoom( client, { action: 'setBoardSize', data: size } );
|
broadcastToRoom( client, { action: 'setBoardSize', data: size } );
|
||||||
break;
|
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:
|
default:
|
||||||
//console.log('unknown action');
|
//console.log('unknown action');
|
||||||
break;
|
break;
|
||||||
|
@ -490,6 +506,206 @@ function cleanAndInitializeDemoRoom()
|
||||||
createCard('/demo', 'card8', '.', roundRand(600), roundRand(300), Math.random() * 10 - 5, 'green');
|
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)
|
span.you-text (vous)
|
||||||
ul#names-ul
|
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
|
//div.trash
|
||||||
// i.fa.fa-trash-o.fa-lg.faded-icon
|
// i.fa.fa-trash-o.fa-lg.faded-icon
|
||||||
hr(role="presentation")
|
hr(role="presentation")
|
||||||
|
|
Loading…
Add table
Reference in a new issue