edgeconnect-cryptpad-deploy.../www/form/export.js
Richard Robert Reitz addc3725ea
Some checks failed
build / build (push) Has been cancelled
first commit
2025-08-28 15:13:14 +02:00

214 lines
7.4 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and contributors
//
// SPDX-License-Identifier: AGPL-3.0-or-later
define([
'/common/common-util.js',
'/customize/messages.js'
], function (Util, Messages) {
var Export = {
ext: '.json'
};
var escapeCSV = function (v) {
if (!/("|,|\n|;)/.test(v)) {
return v || '';
}
var value = '';
var vv = (v || '').replaceAll('"', '""');
value += '"' + vv + '"';
return value;
};
// Get all responses
var sortAnswers = function (answers) {
var allUnsorted = {};
Object.keys(answers).forEach(function (curve) {
var userAnswers = answers[curve];
Object.keys(userAnswers).forEach(function (uid) {
allUnsorted[curve + '|' + uid] = userAnswers[uid];
});
});
var sorted = Object.keys(allUnsorted).sort(function (uid1, uid2) {
return (allUnsorted[uid1].time || 0) - (allUnsorted[uid2].time || 0);
});
return {
answers: allUnsorted,
sortedKeys: sorted
};
};
var exportJSON = function (content, answers, TYPES, order) {
var form = content.form;
var res = {
questions: {},
responses: []
};
var q = res.questions;
var r = res.responses;
var sortObj = sortAnswers(answers);
answers = sortObj.answers;
var sortedKeys = sortObj.sortedKeys;
// Add questions
var i = 1;
order.forEach(function (key) {
var obj = form[key];
if (!obj) { return; }
var type = obj.type;
if (!TYPES[type]) { return; } // Ignore static types
var id = `q${i++}`;
if (TYPES[type] && TYPES[type].exportCSV) {
var _obj = Util.clone(obj);
_obj.q = "tmp";
q[id] = {
question: obj.q,
items: TYPES[type].exportCSV(false, _obj).map(function (str) {
return str.slice(6); // Remove "tmp | "
})
};
} else {
q[id] = obj.q || Messages.form_default;
}
});
sortedKeys.forEach(function (k) {
var obj = answers[k];
var time = new Date(obj.time).toISOString();
var msg = obj.msg || {};
var user = msg._userdata || {};
var data = {
'_time': time,
'_name': user.name || Messages.anonymous
};
var i = 1;
order.forEach(function (key) {
if (!form[key]) { return; }
var type = form[key].type;
if (!TYPES[type]) { return; } // Ignore static types
var id = `q${i++}`;
if (TYPES[type].exportCSV) {
data[id] = TYPES[type].exportCSV(msg[key], form[key]);
return;
}
if (type === 'date') {
data[id] = new Date(msg[key]).toISOString();
} else {
data[id] = msg[key];
}
});
r.push(data);
});
return JSON.stringify(res, 0, 2);
};
Export.results = function (content, answers, TYPES, order, format) {
if (!content || !content.form) { return; }
if (format === "json") { return exportJSON(content, answers, TYPES, order); }
var sortObj = sortAnswers(answers);
answers = sortObj.answers;
var sortedKeys = sortObj.sortedKeys;
var isArray = format === "array";
var csv = "";
var array = [];
var form = content.form;
var questions = [Messages.form_poll_time, Messages.share_formView];
order.forEach(function (key) {
var obj = form[key];
if (!obj) { return; }
var type = obj.type;
if (!TYPES[type]) { return; } // Ignore static types
var c;
if (TYPES[type] && TYPES[type].exportCSV) { c = TYPES[type].exportCSV(false, obj); }
if (!c) { c = [obj.q || Messages.form_default]; }
Array.prototype.push.apply(questions, c);
});
questions.forEach(function (v, i) {
if (i) { csv += ','; }
csv += escapeCSV(v);
});
array.push(questions);
sortedKeys.forEach(function (k) {
var obj = answers[k];
csv += '\n';
var time = new Date(obj.time).toISOString();
var msg = obj.msg || {};
var user = msg._userdata || {};
var line = [];
line.push(time);
line.push(user.name || Messages.anonymous);
order.forEach(function (key) {
var type = form[key].type;
if (!TYPES[type]) { return; } // Ignore static types
if (TYPES[type].exportCSV) {
var res = TYPES[type].exportCSV(msg[key], form[key]);
Array.prototype.push.apply(line, res);
return;
}
line.push(String(msg[key] || ''));
});
line.forEach(function (v, i) {
if (i) { csv += ','; }
csv += escapeCSV(v);
});
array.push(line);
});
if (isArray) { return array; }
return csv;
};
var getFullOrder = function (content) {
var order = content.order.slice();
var getSections = function (content) {
var uids = Object.keys(content.form).filter(function (uid) {
return content.form[uid].type === 'section';
});
return uids;
};
getSections(content).forEach(function (uid) {
var block = content.form[uid];
if (!block.opts || !Array.isArray(block.opts.questions)) { return; }
var idx = order.indexOf(uid);
if (idx === -1) { return; }
idx++;
block.opts.questions.forEach(function (el, i) {
order.splice(idx+i, 0, el);
});
});
return order;
};
Export.main = function (content, cb, ext, sframeChan, parsed) {
if (sframeChan && content.form) {
var _answers = content["answers"];
_answers['href'] = parsed.hash;
_answers['password'] = parsed.password;
_answers['drive'] = true;
var answers;
sframeChan.query("Q_FORM_FETCH_ANSWERS", _answers, function (err, obj) {
answers = obj && obj.results;
var types = {input: {}, textarea: {}, radio: {}, multiradio: {}, date: {}, checkbox: {}, multicheck: {}, sort: {}, poll: {}};
var arr = Export.results(content, answers, types, getFullOrder(content), "json");
cb(new Blob([arr], {
type: 'application/json;charset=utf-8'
}));
});
} else {
var json = Util.clone(content || {});
delete json.answers;
cb(new Blob([JSON.stringify(json, 0, 2)], {
type: 'application/json;charset=utf-8'
}));
}
};
return Export;
});