View responses

pull/1/head
yflory 4 years ago
parent 3b30cfcc55
commit 07c90b6a94

@ -427,3 +427,7 @@
@cp_calendar-now: @cryptpad_color_brand_300; @cp_calendar-now: @cryptpad_color_brand_300;
@cp_calendar-now-fg: @cryptpad_color_grey_800; @cp_calendar-now-fg: @cryptpad_color_grey_800;
// Forms
@cp_forms-bg1: @cryptpad_color_grey_800;
@cp_forms-bg2: @cryptpad_color_grey_900;
@cp_forms-border: @cryptpad_color_grey_800;

@ -426,3 +426,8 @@
@cp_calendar-border: @cryptpad_color_grey_300; @cp_calendar-border: @cryptpad_color_grey_300;
@cp_calendar-now: @cryptpad_color_brand; @cp_calendar-now: @cryptpad_color_brand;
@cp_calendar-now-fg: @cryptpad_color_grey_200; @cp_calendar-now-fg: @cryptpad_color_grey_200;
// Forms
@cp_forms-bg1: @cryptpad_color_grey_200;
@cp_forms-bg2: @cryptpad_color_grey_100;
@cp_forms-border: @cryptpad_color_grey_200;

@ -69,7 +69,7 @@ define([
}, cb); }, cb);
}; };
common.getAccessKeys = function (cb) { common.getAccessKeys = function (cb, opts) {
var keys = []; var keys = [];
Nthen(function (waitFor) { Nthen(function (waitFor) {
// Push account keys // Push account keys
@ -84,6 +84,7 @@ define([
}); });
} catch (e) { console.error(e); } } catch (e) { console.error(e); }
})); }));
// Push teams keys // Push teams keys
postMessage("GET", { postMessage("GET", {
key: ['teams'], key: ['teams'],
@ -92,6 +93,7 @@ define([
Object.keys(obj || {}).forEach(function (id) { Object.keys(obj || {}).forEach(function (id) {
var t = obj[id]; var t = obj[id];
var _keys = t.keys.drive || {}; var _keys = t.keys.drive || {};
_keys.id = id;
if (!_keys.edPrivate) { return; } if (!_keys.edPrivate) { return; }
keys.push(t.keys.drive); keys.push(t.keys.drive);
}); });

@ -20,6 +20,17 @@
overflow: hidden; overflow: hidden;
} }
&.cp-app-form-results {
div.cp-form-creator-content, .cp-app-form-button-results {
display: none !important;
}
}
&:not(.cp-app-form-results) {
div.cp-form-creator-results, .cp-app-form-button-creator {
display: none !important;
}
}
#cp-app-form-container { #cp-app-form-container {
display: flex; display: flex;
flex: 1; flex: 1;
@ -34,8 +45,13 @@
display: flex; display: flex;
flex-flow: column; flex-flow: column;
width: 300px; width: 300px;
.cp-form-creator-types {
margin-top: 20px;
display: flex;
flex-flow: column;
}
} }
div.cp-form-creator-content { div.cp-form-creator-content, div.cp-form-creator-results {
padding: 10px; padding: 10px;
display: flex; display: flex;
flex-flow: column; flex-flow: column;
@ -86,6 +102,54 @@
} }
} }
} }
div.cp-form-creator-results {
display: flex;
flex-flow: column;
position: relative;
& > div {
background: @cp_forms-bg1;
padding: 10px;
&:not(:last-child) {
margin-bottom: 20px;
}
}
.cp-form-block-question {
margin-bottom: 5px;
}
.cp-form-block-type {
float: right;
padding: 5px;
margin-top: -10px;
margin-right: -10px;
i { margin-right: 5px; }
background: @cp_forms-bg2;
}
.cp-form-results-type-text {
max-height: 300px;
overflow: auto;
.cp-form-results-type-text-data {
padding: 5px 10px;
background: @cp_forms-bg2;
&:not(:last-child) { margin-bottom: 1px; }
}
}
.cp-form-results-type-radio {
display: table;
.cp-form-results-type-radio-data {
display: table-row;
border: 1px solid @cp_forms-border;
& > span {
border: 1px solid @cp_forms-border;
display: table-cell;
padding: 5px 10px;
background: @cp_forms-bg2;
&.cp-value {
min-width: 200px;
}
}
}
}
}
} }
} }

@ -59,21 +59,17 @@ define([
Messages.form_duplicates = "Duplicate entries have been removed"; Messages.form_duplicates = "Duplicate entries have been removed";
Messages.form_submit = "Submit";
Messages.form_update = "Update";
Messages.form_reset = "Reset"; Messages.form_reset = "Reset";
Messages.form_sent = "Sent"; Messages.form_sent = "Sent";
Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form."; Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form.";
// XXX to update our own answers, we need to store the server hash of the message Messages.form_viewResults = "Go to responses";
// and we'll be able to use getHistoryRange to fetch this message when we come back Messages.form_viewCreator = "Go to form creator";
Messages.form_notAnswered = "And <b>{0}</b> empty answers";
var makeFormSettings = function (framework) {
// XXX
// Button to set results as public
// Checkbox to allow anonymous answers
// Button to clear all answers?
};
var editOptions = function (v, cb) { var editOptions = function (v, cb) {
var add = h('button.btn.btn-secondary', [ var add = h('button.btn.btn-secondary', [
@ -128,6 +124,12 @@ define([
]; ];
}; };
var getEmpty = function (empty) {
if (empty) {
return UI.setHTML(h('div.cp-form-results-type-text-empty'), Messages._getKey('form_notAnswered', [empty]));
}
};
var TYPES = { var TYPES = {
input: { input: {
get: function () { get: function () {
@ -140,6 +142,19 @@ define([
reset: function () { $tag.val(''); } reset: function () { $tag.val(''); }
}; };
}, },
printResults: function (answers, uid) {
var results = [];
var empty = 0;
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
if (!answer || !answer.trim()) { return empty++; }
results.push(h('div.cp-form-results-type-text-data', answer));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-text', results);
},
icon: h('i.fa.fa-font') icon: h('i.fa.fa-font')
}, },
radio: { radio: {
@ -185,12 +200,33 @@ define([
}; };
}, },
printResults: function (answers, uid) {
var results = [];
var empty = 0;
var count = {};
Object.keys(answers).forEach(function (author) {
var obj = answers[author];
var answer = obj.msg[uid];
if (!answer || !answer.trim()) { return empty++; }
count[answer] = count[answer] || 0;
count[answer]++;
});
Object.keys(count).forEach(function (value) {
results.push(h('div.cp-form-results-type-radio-data', [
h('span.cp-value', value),
h('span.cp-count', count[value])
]));
});
results.push(getEmpty(empty));
return h('div.cp-form-results-type-radio', results);
},
icon: h('i.fa.fa-list-ul') icon: h('i.fa.fa-list-ul')
} }
}; };
var makeFormControls = function (framework, content) { var makeFormControls = function (framework, content, update) {
var send = h('button.btn.btn-primary', Messages.poll_commit); var send = h('button.btn.btn-primary', update ? Messages.form_update : Messages.form_submit);
var reset = h('button.btn.btn-danger-alt', Messages.form_reset); var reset = h('button.btn.btn-danger-alt', Messages.form_reset);
$(reset).click(function () { $(reset).click(function () {
if (!Array.isArray(APP.formBlocks)) { return; } if (!Array.isArray(APP.formBlocks)) { return; }
@ -211,12 +247,13 @@ define([
mailbox: content.answers, mailbox: content.answers,
results: results results: results
}, function (err, data) { }, function (err, data) {
console.error(data); $send.attr('disabled', 'disabled');
if (err || (data && data.error)) { if (err || (data && data.error)) {
console.error(err || data.error); console.error(err || data.error);
return void UI.warn(Messages.error); return void UI.warn(Messages.error);
} }
UI.alert(Messages.form_sent); UI.alert(Messages.form_sent);
$send.text(Messages.form_update);
}); });
}); });
return h('div.cp-form-send-container', [send, reset]); return h('div.cp-form-send-container', [send, reset]);
@ -321,7 +358,30 @@ define([
}); });
$container.empty().append(elements); $container.empty().append(elements);
$container.append(makeFormControls(framework, content)); $container.append(makeFormControls(framework, content, Boolean(answers)));
};
var renderResults = function (content, answers) {
var $container = $('div.cp-form-creator-results').empty();
var form = content.form;
var elements = Object.keys(form).map(function (uid) {
var block = form[uid];
var type = block.type;
var model = TYPES[type];
if (!model || !model.printResults) { return; }
var print = model.printResults(answers, uid);
var q = h('div.cp-form-block-question', block.q || Messages.form_default);
return h('div.cp-form-block', [
h('div.cp-form-block-type', [
TYPES[type].icon.cloneNode(),
h('span', Messages['form_type_'+type])
]),
q,
h('div.cp-form-block-content', print),
]);
});
$container.append(elements);
}; };
var andThen = function (framework) { var andThen = function (framework) {
@ -333,6 +393,39 @@ define([
var priv = metadataMgr.getPrivateData(); var priv = metadataMgr.getPrivateData();
APP.isEditor = Boolean(priv.form_public); APP.isEditor = Boolean(priv.form_public);
var $body = $('body');
var makeFormSettings = function () {
var viewResults = h('button.btn.btn-primary', [
h('span.cp-app-form-button-results', Messages.form_viewResults),
h('span.cp-app-form-button-creator', Messages.form_viewCreator),
]);
var $v = $(viewResults).click(function () {
if ($body.hasClass('cp-app-form-results')) {
$body.removeClass('cp-app-form-results');
return;
}
$v.attr('disabled', 'disabled');
sframeChan.query("Q_FORM_FETCH_ANSWERS", {
channel: content.answers.channel,
validateKey: content.answers.validateKey,
publicKey: content.answers.publicKey
}, function (err, answers) {
$v.removeAttr('disabled');
$body.addClass('cp-app-form-results');
renderResults(content, answers);
});
});
return [
viewResults
];
// XXX
// Button to set results as public
// Checkbox to allow anonymous answers
// Button to clear all answers?
};
var makeFormCreator = function () { var makeFormCreator = function () {
@ -356,13 +449,21 @@ define([
}); });
return btn; return btn;
}); });
controlContainer = h('div.cp-form-creator-control', controls);
var settings = makeFormSettings();
controlContainer = h('div.cp-form-creator-control', [
h('div.cp-form-creator-settings', settings),
h('div.cp-form-creator-types', controls)
]);
} }
var contentContainer = h('div.cp-form-creator-content'); var contentContainer = h('div.cp-form-creator-content');
var resultsContainer = h('div.cp-form-creator-results');
var div = h('div.cp-form-creator-container', [ var div = h('div.cp-form-creator-container', [
controlContainer, controlContainer,
contentContainer, contentContainer,
resultsContainer
]); ]);
return div; return div;
}; };
@ -397,8 +498,10 @@ define([
if (APP.isEditor) { if (APP.isEditor) {
sframeChan.query("Q_FORM_FETCH_ANSWERS", { sframeChan.query("Q_FORM_FETCH_ANSWERS", {
channel: content.answers.channel, channel: content.answers.channel,
validateKey: content.answers.validateKey,
publicKey: content.answers.publicKey publicKey: content.answers.publicKey
}, function () { }, function (err, obj) {
if (obj) { APP.answers = obj; }
updateForm(framework, content, true); updateForm(framework, content, true);
}); });

@ -30,7 +30,7 @@ define([
}; };
var addRpc = function (sframeChan, Cryptpad, Utils) { var addRpc = function (sframeChan, Cryptpad, Utils) {
sframeChan.on('Q_FORM_FETCH_ANSWERS', function (data, cb) { sframeChan.on('Q_FORM_FETCH_ANSWERS', function (data, cb) {
var keys; var myKeys;
var CPNetflux; var CPNetflux;
var network; var network;
nThen(function (w) { nThen(function (w) {
@ -40,7 +40,15 @@ define([
CPNetflux = _CPNetflux; CPNetflux = _CPNetflux;
})); }));
Cryptpad.getAccessKeys(w(function (_keys) { Cryptpad.getAccessKeys(w(function (_keys) {
keys = _keys; if (!Array.isArray(_keys)) { return; }
_keys.some(function (_k) {
if ((!Cryptpad.initialTeam && !_k.id) || Cryptpad.initialTeam === _k.id) {
myKeys = _k;
return true;
}
});
console.error(myKeys);
})); }));
Cryptpad.makeNetwork(w(function (err, nw) { Cryptpad.makeNetwork(w(function (err, nw) {
network = nw; network = nw;
@ -52,24 +60,31 @@ define([
var crypto = Utils.Crypto.Mailbox.createEncryptor({ var crypto = Utils.Crypto.Mailbox.createEncryptor({
curvePrivate: privateKey, curvePrivate: privateKey,
curvePublic: publicKey || data.publicKey curvePublic: publicKey || data.publicKey,
validateKey: data.validateKey
}); });
var config = { var config = {
network: network, network: network,
channel: data.channel, channel: data.channel,
noChainPad: true, noChainPad: true,
validateKey: keys.secondaryValidateKey, validateKey: keys.secondaryValidateKey,
owners: [], // XXX add pad owner owners: [myKeys.edPublic], // XXX add pad owner
crypto: crypto, crypto: crypto,
// XXX Cache // XXX Cache
}; };
var results = {};
config.onReady = function () { config.onReady = function () {
cb(); cb(results);
// XXX
network.disconnect(); network.disconnect();
}; };
config.onMessage = function () { config.onMessage = function (msg, peer, vKey, isCp, hash, senderCurve, cfg) {
// XXX var parsed = Utils.Util.tryParse(msg);
if (!parsed) { return; }
results[senderCurve] = {
msg: parsed,
hash: hash,
time: cfg.time
};
}; };
CPNetflux.start(config); CPNetflux.start(config);
}); });

Loading…
Cancel
Save