New page when form responses have been submitted
parent
7bbe9059a1
commit
925872679a
|
@ -127,6 +127,10 @@
|
|||
& > div:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.cp-forms-results-participant {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
}
|
||||
div.cp-form-filler-container {
|
||||
width: 300px;
|
||||
|
@ -313,6 +317,12 @@
|
|||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.cp-form-disabled {
|
||||
.cp-form-poll-choice, .cp-form-type-sort {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cp-form-preview {
|
||||
color: @cp_sidebar-hint;
|
||||
margin-bottom: 10px;
|
||||
|
@ -502,6 +512,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
div.cp-form-creator-answered {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
}
|
||||
div.cp-form-creator-results {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
|
|
|
@ -68,6 +68,7 @@ define([
|
|||
)
|
||||
{
|
||||
var APP = window.APP = {
|
||||
blocks: {}
|
||||
};
|
||||
|
||||
var is24h = UIElements.is24h();
|
||||
|
@ -1009,6 +1010,10 @@ define([
|
|||
return $tag.val();
|
||||
},
|
||||
setValue: function (val) { $tag.val(val); },
|
||||
setEditable: function (state) {
|
||||
if (state) { $tag.removeAttr('disabled'); }
|
||||
else { $tag.attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editTextOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1091,6 +1096,10 @@ define([
|
|||
$text.val(val);
|
||||
updateChar();
|
||||
},
|
||||
setEditable: function (state) {
|
||||
if (state) { $(tag).removeAttr('disabled'); }
|
||||
else { $(tag).attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editTextOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1151,6 +1160,10 @@ define([
|
|||
return res;
|
||||
},
|
||||
reset: function () { $(tag).find('input').removeAttr('checked'); },
|
||||
setEditable: function (state) {
|
||||
if (state) { $(tag).find('input').removeAttr('disabled'); }
|
||||
else { $(tag).find('input').attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1222,7 +1235,8 @@ define([
|
|||
var tag = h('div.radio-group.cp-form-type-multiradio', lines);
|
||||
var cursorGetter;
|
||||
var setCursorGetter = function (f) { cursorGetter = f; };
|
||||
$(tag).find('input[type="radio"]').on('change', function () {
|
||||
var $tag = $(tag);
|
||||
$tag.find('input[type="radio"]').on('change', function () {
|
||||
evOnChange.fire();
|
||||
});
|
||||
return {
|
||||
|
@ -1242,6 +1256,10 @@ define([
|
|||
return res;
|
||||
},
|
||||
reset: function () { $(tag).find('input').removeAttr('checked'); },
|
||||
setEditable: function (state) {
|
||||
if (state) { $tag.find('input').removeAttr('disabled'); }
|
||||
else { $tag.find('input').attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1350,13 +1368,16 @@ define([
|
|||
h('div.radio-group.cp-form-type-checkbox', els)
|
||||
]);
|
||||
var $tag = $(tag);
|
||||
$tag.find('input').on('change', function () {
|
||||
var checkDisabled = function () {
|
||||
var selected = $tag.find('input:checked').length;
|
||||
if (selected >= opts.max) {
|
||||
$tag.find('input:not(:checked)').attr('disabled', 'disabled');
|
||||
} else {
|
||||
$tag.find('input').removeAttr('disabled');
|
||||
}
|
||||
};
|
||||
$tag.find('input').on('change', function () {
|
||||
checkDisabled();
|
||||
evOnChange.fire();
|
||||
});
|
||||
var cursorGetter;
|
||||
|
@ -1374,6 +1395,10 @@ define([
|
|||
return res;
|
||||
},
|
||||
reset: function () { $(tag).find('input').removeAttr('checked'); },
|
||||
setEditable: function (state) {
|
||||
if (state) { checkDisabled(); }
|
||||
else { $tag.find('input').attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1388,10 +1413,7 @@ define([
|
|||
$el.prop('checked', true);
|
||||
}
|
||||
});
|
||||
var selected = $tag.find('input:checked').length;
|
||||
if (selected >= opts.max) {
|
||||
$tag.find('input:not(:checked)').attr('disabled', 'disabled');
|
||||
}
|
||||
checkDisabled();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1448,14 +1470,18 @@ define([
|
|||
|
||||
if (!opts.max) { opts.max = TYPES.multicheck.defaultOpts.max; }
|
||||
|
||||
var checkDisabled = function (l) {
|
||||
var selected = $(l).find('input:checked').length;
|
||||
if (selected >= opts.max) {
|
||||
$(l).find('input:not(:checked)').attr('disabled', 'disabled');
|
||||
} else {
|
||||
$(l).find('input').removeAttr('disabled');
|
||||
}
|
||||
};
|
||||
|
||||
lines.forEach(function (l) {
|
||||
$(l).find('input').on('change', function () {
|
||||
var selected = $(l).find('input:checked').length;
|
||||
if (selected >= opts.max) {
|
||||
$(l).find('input:not(:checked)').attr('disabled', 'disabled');
|
||||
} else {
|
||||
$(l).find('input').removeAttr('disabled');
|
||||
}
|
||||
checkDisabled(l);
|
||||
evOnChange.fire();
|
||||
});
|
||||
});
|
||||
|
@ -1484,6 +1510,10 @@ define([
|
|||
return res;
|
||||
},
|
||||
reset: function () { $(tag).find('input').removeAttr('checked'); },
|
||||
setEditable: function (state) {
|
||||
if (state) { lines.forEach(checkDisabled); }
|
||||
else { $(tag).find('input').attr('disabled', 'disabled'); }
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1498,6 +1528,7 @@ define([
|
|||
$(el).prop('checked', true);
|
||||
});
|
||||
});
|
||||
lines.forEach(checkDisabled);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1633,10 +1664,6 @@ define([
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(tag).find('input[type="radio"]').on('change', function () {
|
||||
evOnChange.fire();
|
||||
});
|
||||
return {
|
||||
tag: tag,
|
||||
getValue: function () {
|
||||
|
@ -1653,6 +1680,10 @@ define([
|
|||
sortable.sort(toSort);
|
||||
reorder(true);
|
||||
},
|
||||
setEditable: function (state) {
|
||||
sortable.options.disabled = !state;
|
||||
$(tag).toggleClass('cp-form-disabled', !state);
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -1704,6 +1735,7 @@ define([
|
|||
|
||||
var lines = makePollTable(answers, opts, false);
|
||||
|
||||
var disabled = false;
|
||||
// Add form
|
||||
var addLine = opts.values.map(function (data) {
|
||||
var cell = h('div.cp-poll-cell.cp-form-poll-choice', [
|
||||
|
@ -1716,6 +1748,7 @@ define([
|
|||
var val = 0;
|
||||
$c.attr('data-value', val);
|
||||
$c.click(function () {
|
||||
if (disabled) { return; }
|
||||
val = (val+1)%3;
|
||||
$c.attr('data-value', val);
|
||||
evOnChange.fire();
|
||||
|
@ -1768,6 +1801,10 @@ define([
|
|||
reset: function () {
|
||||
$tag.find('.cp-form-poll-choice').attr('data-value', 0);
|
||||
},
|
||||
setEditable: function (state) {
|
||||
disabled = !state;
|
||||
$tag.toggleClass('cp-form-disabled', disabled);
|
||||
},
|
||||
edit: function (cb, tmp) {
|
||||
var v = Util.clone(opts);
|
||||
return editOptions(v, setCursorGetter, cb, tmp);
|
||||
|
@ -2092,6 +2129,43 @@ define([
|
|||
framework._.toolbar.$bottomL.append($res);
|
||||
};
|
||||
|
||||
Messages.form_alreadyAnswered = "You've responded to this form on {0}"; // XXX
|
||||
Messages.form_editAnswer = "Edit my responses"; // XXX
|
||||
Messages.form_viewAnswer = "View my responses"; // XXX
|
||||
var showAnsweredPage = function (framework, content, answers) {
|
||||
var $formContainer = $('div.cp-form-creator-content').hide();
|
||||
var $container = $('div.cp-form-creator-answered').empty().css('display', '');
|
||||
|
||||
var viewOnly = content.answers.cantEdit;
|
||||
var action = h('button.btn.btn-primary', [
|
||||
viewOnly ? h('i.fa.fa-bar-chart') : h('i.fa.fa-pencil'),
|
||||
h('span', viewOnly ? Messages.form_viewAnswer : Messages.form_editAnswer)
|
||||
]);
|
||||
|
||||
$(action).click(function () {
|
||||
$formContainer.css('display', '');
|
||||
$container.hide();
|
||||
if (viewOnly) {
|
||||
$formContainer.find('.cp-form-send-container .cp-open').hide();
|
||||
Object.keys(APP.blocks).forEach(function (uid) {
|
||||
var b = APP.blocks[uid];
|
||||
if (!b.setEditable) { return; }
|
||||
b.setEditable(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (answers._time) { APP.lastAnswerTime = answers._time; }
|
||||
|
||||
var title = framework._.title.title || framework._.title.defaultTitle;
|
||||
$container.append(h('div.cp-form-submit-success', [
|
||||
h('h3.cp-form-view-title', title),
|
||||
h('div.alert.alert-info', Messages._getKey('form_alreadyAnswered', [
|
||||
new Date(APP.lastAnswerTime).toLocaleString()])),
|
||||
action
|
||||
]));
|
||||
};
|
||||
|
||||
var getFormResults = function () {
|
||||
if (!Array.isArray(APP.formBlocks)) { return; }
|
||||
var results = {};
|
||||
|
@ -2180,8 +2254,9 @@ define([
|
|||
addResultsButton(framework, content);
|
||||
}
|
||||
$send.removeAttr('disabled');
|
||||
UI.alert(Messages.form_sent);
|
||||
//UI.alert(Messages.form_sent); // XXX not needed anymore?
|
||||
$send.text(Messages.form_update);
|
||||
showAnsweredPage(framework, content, { '_time': +new Date() });
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2378,7 +2453,7 @@ define([
|
|||
name = user.name;
|
||||
}
|
||||
|
||||
var data = model.get(block.opts, _answers, name, evOnChange);
|
||||
var data = APP.blocks[uid] = model.get(block.opts, _answers, name, evOnChange);
|
||||
if (!data) { return; }
|
||||
data.uid = uid;
|
||||
if (answers && answers[uid] && data.setValue) { data.setValue(answers[uid]); }
|
||||
|
@ -2502,7 +2577,7 @@ define([
|
|||
$(editButtons).show();
|
||||
UI.log(Messages.saved);
|
||||
_answers = getBlockAnswers(APP.answers, uid);
|
||||
data = model.get(newOpts, _answers, null, evOnChange);
|
||||
data = APP.blocks[uid] = model.get(newOpts, _answers, null, evOnChange);
|
||||
if (!data) { data = {}; }
|
||||
$oldTag.before(data.tag).remove();
|
||||
});
|
||||
|
@ -2565,7 +2640,7 @@ define([
|
|||
framework.localChange();
|
||||
var $oldTag = $(data.tag);
|
||||
framework._.cpNfInner.chainpad.onSettle(function () {
|
||||
data = model.get(block.opts, _answers, null, evOnChange);
|
||||
data = APP.blocks[uid] = model.get(block.opts, _answers, null, evOnChange);
|
||||
$oldTag.before(data.tag).remove();
|
||||
});
|
||||
});
|
||||
|
@ -2676,12 +2751,11 @@ define([
|
|||
}
|
||||
|
||||
// If the form is already submitted, show an info message
|
||||
Messages.form_alreadyAnswered = "You've submitted answers to this form on {0}"; // XXX
|
||||
if (answers) {
|
||||
showAnsweredPage(framework, content, answers);
|
||||
$container.prepend(h('div.alert.alert-info',
|
||||
Messages._getKey('form_alreadyAnswered', [
|
||||
new Date(answers._time).toLocaleString()])));
|
||||
// XXX make the page read-only?
|
||||
new Date(answers._time || APP.lastAnswerTime).toLocaleString()])));
|
||||
}
|
||||
|
||||
// In view mode, add "Submit" and "reset" buttons
|
||||
|
@ -2705,8 +2779,8 @@ define([
|
|||
|
||||
if (!answers) {
|
||||
$container.find('.cp-reset-button').attr('disabled', 'disabled');
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var getTempFields = function () {
|
||||
if (!Array.isArray(APP.formBlocks)) { return; }
|
||||
|
@ -2916,6 +2990,38 @@ define([
|
|||
};
|
||||
refreshPrivacy();
|
||||
|
||||
// Allow responses edition
|
||||
Messages.form_editable = "Allow users to edit their responses"; // XXX
|
||||
var editableContainer = h('div.cp-form-editable-container');
|
||||
var $editable = $(editableContainer);
|
||||
var refreshEditable = function () {
|
||||
$editable.empty();
|
||||
var editable = !content.answers.cantEdit;
|
||||
var radioOn = UI.createRadio('cp-form-editable', 'cp-form-editable-on',
|
||||
Messages.form_anonymous_on, Boolean(editable), {
|
||||
input: { value: 1 },
|
||||
mark: { tabindex:1 }
|
||||
});
|
||||
var radioOff = UI.createRadio('cp-form-editable', 'cp-form-editable-off',
|
||||
Messages.form_anonymous_off, !editable, {
|
||||
input: { value: 0 },
|
||||
mark: { tabindex:1 }
|
||||
});
|
||||
var radioContainer = h('div.cp-form-editable-radio', [radioOn, radioOff]);
|
||||
$(radioContainer).find('input[type="radio"]').on('change', function() {
|
||||
var val = $('input:radio[name="cp-form-editable"]:checked').val();
|
||||
val = Number(val) || 0;
|
||||
content.answers.cantEdit = !val;
|
||||
framework.localChange();
|
||||
framework._.cpNfInner.chainpad.onSettle(function () {
|
||||
UI.log(Messages.saved);
|
||||
});
|
||||
});
|
||||
$editable.append(h('div.cp-form-status', Messages.form_editable));
|
||||
$editable.append(h('div.cp-form-actions', radioContainer));
|
||||
};
|
||||
refreshEditable();
|
||||
|
||||
// End date / Closed state
|
||||
var endDateContainer = h('div.cp-form-status-container');
|
||||
var $endDate = $(endDateContainer);
|
||||
|
@ -2979,6 +3085,7 @@ define([
|
|||
|
||||
evOnChange.reg(refreshPublic);
|
||||
evOnChange.reg(refreshPrivacy);
|
||||
evOnChange.reg(refreshEditable);
|
||||
evOnChange.reg(refreshEndDate);
|
||||
//evOnChange.reg(refreshResponse);
|
||||
|
||||
|
@ -2986,6 +3093,7 @@ define([
|
|||
preview,
|
||||
endDateContainer,
|
||||
privacyContainer,
|
||||
editableContainer,
|
||||
resultsType,
|
||||
responseMsg
|
||||
];
|
||||
|
@ -3027,10 +3135,14 @@ define([
|
|||
|
||||
var contentContainer = h('div.cp-form-creator-content');
|
||||
var resultsContainer = h('div.cp-form-creator-results');
|
||||
var answeredContainer = h('div.cp-form-creator-answered', {
|
||||
style: 'display: none;'
|
||||
});
|
||||
var div = h('div.cp-form-creator-container', [
|
||||
controlContainer,
|
||||
contentContainer,
|
||||
resultsContainer,
|
||||
answeredContainer,
|
||||
fillerContainer
|
||||
]);
|
||||
return div;
|
||||
|
|
|
@ -266,6 +266,7 @@ define([
|
|||
if (obj && obj.error) { return void cb(obj); }
|
||||
var messages = obj.messages;
|
||||
if (!messages.length) { return void cb(); }
|
||||
if (obj.lastKnownHash !== answer.hash) { return void cb(); }
|
||||
var res = Utils.Crypto.Mailbox.openOwnSecretLetter(messages[0].msg, {
|
||||
validateKey: data.validateKey,
|
||||
ephemeral_private: Nacl.util.decodeBase64(answer.curvePrivate),
|
||||
|
|
Loading…
Reference in New Issue