Sort and delete form questions

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

@ -428,6 +428,6 @@
@cp_calendar-now-fg: @cryptpad_color_grey_800; @cp_calendar-now-fg: @cryptpad_color_grey_800;
// Forms // Forms
@cp_forms-bg1: @cryptpad_color_grey_800; @cp_form-bg1: @cryptpad_color_grey_800;
@cp_forms-bg2: @cryptpad_color_grey_900; @cp_form-bg2: @cryptpad_color_grey_900;
@cp_forms-border: @cryptpad_color_grey_800; @cp_form-border: @cryptpad_color_grey_800;

@ -428,6 +428,6 @@
@cp_calendar-now-fg: @cryptpad_color_grey_200; @cp_calendar-now-fg: @cryptpad_color_grey_200;
// Forms // Forms
@cp_forms-bg1: @cryptpad_color_grey_200; @cp_form-bg1: @cryptpad_color_grey_200;
@cp_forms-bg2: @cryptpad_color_grey_100; @cp_form-bg2: @cryptpad_color_grey_100;
@cp_forms-border: @cryptpad_color_grey_200; @cp_form-border: @cryptpad_color_grey_200;

@ -71,6 +71,12 @@
div.cp-button-confirm { div.cp-button-confirm {
display: inline-block; display: inline-block;
&.new {
vertical-align: top;
button {
height: 35px;
}
}
button { button {
margin: 0 !important; margin: 0 !important;
} }
@ -85,7 +91,7 @@
} }
} }
} }
button.cp-button-confirm-placeholder { button.cp-button-confirm-placeholder:not(.new) {
margin-bottom: 3px !important; margin-bottom: 3px !important;
} }

@ -747,6 +747,7 @@ define([
cb = Util.once(cb); cb = Util.once(cb);
} }
var classes = 'btn ' + (config.classes || 'btn-primary'); var classes = 'btn ' + (config.classes || 'btn-primary');
var newCls = config.new ? '.new' : '';
var button = h('button', { var button = h('button', {
"class": classes, "class": classes,
@ -759,7 +760,7 @@ define([
}); });
var timer = h('div.cp-button-timer', div); var timer = h('div.cp-button-timer', div);
var content = h('div.cp-button-confirm', [ var content = h('div.cp-button-confirm'+newCls, [
button, button,
timer timer
]); ]);
@ -795,7 +796,8 @@ define([
to = setTimeout(todo, INTERVAL); to = setTimeout(todo, INTERVAL);
}; };
$(originalBtn).addClass('cp-button-confirm-placeholder').click(function (e) { var newCls2 = config.new ? 'new' : '';
$(originalBtn).addClass('cp-button-confirm-placeholder').addClass(newCls2).click(function (e) {
e.stopPropagation(); e.stopPropagation();
// If we have a validation function, continue only if it's true // If we have a validation function, continue only if it's true
if (config.validate && !config.validate()) { return; } if (config.validate && !config.validate()) { return; }

@ -11,6 +11,8 @@
display: flex; display: flex;
flex-flow: column; flex-flow: column;
font: @colortheme_app-font;
color: @cryptpad_text_col;
#cp-app-form-editor { #cp-app-form-editor {
flex: 1; flex: 1;
@ -56,17 +58,26 @@
display: flex; display: flex;
flex-flow: column; flex-flow: column;
flex: 1; flex: 1;
overflow: auto;
.cp-form-block { .cp-form-block {
.tools_unselectable();
background: @cp_form-bg1;
padding: 10px;
&:not(:last-child) { &:not(:last-child) {
margin-bottom: 20px; margin-bottom: 20px;
} }
.cp-form-block-question {
margin-bottom: 5px;
}
.cp-form-input-block { .cp-form-input-block {
display: flex; display: flex;
//width: @form_input-width; //width: @form_input-width;
&:not(:focus-within) { &:not(.editing) {
input { input {
background: transparent; background: transparent;
border: none; border: none;
padding: 0 !important;
& ~ button:not(:disabled) { & ~ button:not(:disabled) {
.cp-form-edit { display: inline; } .cp-form-edit { display: inline; }
.cp-form-save { display: none; } .cp-form-save { display: none; }
@ -76,16 +87,25 @@
input { input {
flex: 1; flex: 1;
min-width: 100px; min-width: 100px;
padding: 0 10px !important;
height: auto;
} }
button { button {
.cp-form-edit { .cp-form-edit {
display: none; display: none;
margin: 0 !important;
} }
.cp-form-save { display: inline; } .cp-form-save { display: inline; }
} }
.cp-form-block-drag {
font-size: 22px;
width: 20px;
margin-left: 5px;
text-align: center;
line-height: 31px;
} }
} }
&.editable { cursor: grab; }
}
.cp-form-edit-block { .cp-form-edit-block {
.cp-form-edit-block-input { .cp-form-edit-block-input {
display: flex; display: flex;
@ -107,7 +127,7 @@
flex-flow: column; flex-flow: column;
position: relative; position: relative;
& > div { & > div {
background: @cp_forms-bg1; background: @cp_form-bg1;
padding: 10px; padding: 10px;
&:not(:last-child) { &:not(:last-child) {
margin-bottom: 20px; margin-bottom: 20px;
@ -122,14 +142,14 @@
margin-top: -10px; margin-top: -10px;
margin-right: -10px; margin-right: -10px;
i { margin-right: 5px; } i { margin-right: 5px; }
background: @cp_forms-bg2; background: @cp_form-bg2;
} }
.cp-form-results-type-text { .cp-form-results-type-text {
max-height: 300px; max-height: 300px;
overflow: auto; overflow: auto;
.cp-form-results-type-text-data { .cp-form-results-type-text-data {
padding: 5px 10px; padding: 5px 10px;
background: @cp_forms-bg2; background: @cp_form-bg2;
&:not(:last-child) { margin-bottom: 1px; } &:not(:last-child) { margin-bottom: 1px; }
} }
} }
@ -137,12 +157,12 @@
display: table; display: table;
.cp-form-results-type-radio-data { .cp-form-results-type-radio-data {
display: table-row; display: table-row;
border: 1px solid @cp_forms-border; border: 1px solid @cp_form-border;
& > span { & > span {
border: 1px solid @cp_forms-border; border: 1px solid @cp_form-border;
display: table-cell; display: table-cell;
padding: 5px 10px; padding: 5px 10px;
background: @cp_forms-bg2; background: @cp_form-bg2;
&.cp-value { &.cp-value {
min-width: 200px; min-width: 200px;
} }
@ -152,5 +172,14 @@
} }
} }
.cp-form-type-radio {
display: flex;
flex-flow: column;
align-items: baseline;
.cp-radio {
display: inline-flex;
}
}
} }

@ -20,6 +20,8 @@ define([
'/common/inner/access.js', '/common/inner/access.js',
'/common/inner/properties.js', '/common/inner/properties.js',
'/bower_components/sortablejs/Sortable.min.js',
'/bower_components/file-saver/FileSaver.min.js', '/bower_components/file-saver/FileSaver.min.js',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/form/app-form.less', 'less!/form/app-form.less',
@ -40,7 +42,8 @@ define([
h, h,
Messages, Messages,
AppConfig, AppConfig,
Share, Access, Properties Share, Access, Properties,
Sortable
) )
{ {
var SaveAs = window.saveAs; var SaveAs = window.saveAs;
@ -50,6 +53,7 @@ define([
Messages.button_newform = "New Form"; // XXX Messages.button_newform = "New Form"; // XXX
Messages.form_invalid = "Invalid form"; Messages.form_invalid = "Invalid form";
Messages.form_editBlock = "Edit options"; Messages.form_editBlock = "Edit options";
Messages.form_editQuestion = "Edit question";
Messages.form_newOption = "New option"; Messages.form_newOption = "New option";
@ -63,6 +67,7 @@ define([
Messages.form_update = "Update"; Messages.form_update = "Update";
Messages.form_reset = "Reset"; Messages.form_reset = "Reset";
Messages.form_sent = "Sent"; Messages.form_sent = "Sent";
Messages.form_delete = "Delete block";
Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form."; Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form.";
@ -170,7 +175,7 @@ define([
$(radio).find('input').data('val', data); $(radio).find('input').data('val', data);
return radio; return radio;
}); });
var tag = h('div.radio-group', els); var tag = h('div.radio-group.cp-form-type-radio', els);
return { return {
tag: tag, tag: tag,
getValue: function () { getValue: function () {
@ -266,7 +271,7 @@ define([
APP.formBlocks = []; APP.formBlocks = [];
// XXX order array later // XXX order array later
var elements = Object.keys(form).map(function (uid) { var elements = content.order.map(function (uid) {
var block = form[uid]; var block = form[uid];
var type = block.type; var type = block.type;
var model = TYPES[type]; var model = TYPES[type];
@ -277,7 +282,7 @@ define([
if (answers && answers[uid]) { data.setValue(answers[uid]); } if (answers && answers[uid]) { data.setValue(answers[uid]); }
var q = h('div.cp-form-block-question', block.q || Messages.form_default); var q = h('div.cp-form-block-question', block.q || Messages.form_default);
var edit, editContainer; var editButtons, editContainer;
APP.formBlocks.push(data); APP.formBlocks.push(data);
@ -288,32 +293,64 @@ define([
value: block.q || Messages.form_default value: block.q || Messages.form_default
}); });
var $inputQ = $(inputQ); var $inputQ = $(inputQ);
var saveQ = h('button.btn.btn-primary', [ var saveQ = h('button.btn.btn-primary.small', [
h('i.fa.fa-pencil.cp-form-edit'), h('i.fa.fa-pencil.cp-form-edit'),
h('span.cp-form-edit', Messages.form_editQuestion),
h('i.fa.fa-floppy-o.cp-form-save'),
h('span.cp-form-save', Messages.settings_save) h('span.cp-form-save', Messages.settings_save)
]); ]);
var dragHandle = h('i.fa.fa-arrows-v.cp-form-block-drag');
var $saveQ = $(saveQ).click(function () { var $saveQ = $(saveQ).click(function () {
if (!$(q).hasClass('editing')) {
$(q).addClass('editing');
$inputQ.focus();
return;
}
var v = $inputQ.val(); var v = $inputQ.val();
if (!v || !v.trim() || v === block.q) { return; } if (!v || !v.trim()) { return void UI.warn(Messages.error); }
block.q = v.trim(); block.q = v.trim();
framework.localChange(); framework.localChange();
$saveQ.attr('disabled', 'disabled'); $saveQ.attr('disabled', 'disabled');
framework._.cpNfInner.chainpad.onSettle(function () { framework._.cpNfInner.chainpad.onSettle(function () {
$(q).removeClass('editing');
$saveQ.removeAttr('disabled'); $saveQ.removeAttr('disabled');
$saveQ.blur(); $inputQ.blur();
UI.log(Messages.saved); UI.log(Messages.saved);
}); });
}); });
var onBlur = function (e) { var onCancelQ = function (e) {
if (e && e.relatedTarget && e.relatedTarget === saveQ) { return; } if (e && e.relatedTarget && e.relatedTarget === saveQ) { return; }
$inputQ.val(block.q); $inputQ.val(block.q || Messages.form_default);
if (!e) { $inputQ.blur(); }
$(q).removeClass('editing');
}; };
$inputQ.keydown(function (e) { $inputQ.keydown(function (e) {
if (e.which === 13) { return void $saveQ.click(); } if (e.which === 13) { return void $saveQ.click(); }
if (e.which === 27) { return void $inputQ.blur(); } if (e.which === 27) { return void onCancelQ(); }
});
$inputQ.focus(function () {
$(q).addClass('editing');
});
$inputQ.blur(onCancelQ);
q = h('div.cp-form-input-block', [inputQ, saveQ, dragHandle]);
// Delete question
var edit;
var del = h('button.btn.btn-danger', [
h('i.fa.fa-trash-o'),
h('span', Messages.form_delete)
]);
UI.confirmButton(del, {
classes: 'btn-danger',
new: true
}, function () {
delete content.form[uid];
var idx = content.order.indexOf(uid);
content.order.splice(idx, 1);
$('.cp-form-block[data-id="'+uid+'"]').remove();
framework.localChange();
}); });
$inputQ.blur(onBlur);
q = h('div.cp-form-input-block', [inputQ, saveQ]);
// Values // Values
if (data.edit) { if (data.edit) {
@ -325,7 +362,7 @@ define([
var onSave = function (newOpts) { var onSave = function (newOpts) {
if (!newOpts) { // Cancel edit if (!newOpts) { // Cancel edit
$(editContainer).empty(); $(editContainer).empty();
$edit.show(); $(editButtons).show();
$(data.tag).show(); $(data.tag).show();
return; return;
} }
@ -334,37 +371,62 @@ define([
framework.localChange(); framework.localChange();
var $oldTag = $(data.tag); var $oldTag = $(data.tag);
framework._.cpNfInner.chainpad.onSettle(function () { framework._.cpNfInner.chainpad.onSettle(function () {
$edit.show(); $(editButtons).show();
UI.log(Messages.saved); UI.log(Messages.saved);
data = model.get(newOpts); data = model.get(newOpts);
$oldTag.before(data.tag).remove(); $oldTag.before(data.tag).remove();
}); });
}; };
var $edit = $(edit).click(function () { $(edit).click(function () {
$(data.tag).hide(); $(data.tag).hide();
$(editContainer).append(data.edit(onSave)); $(editContainer).append(data.edit(onSave));
$edit.hide(); $(editButtons).hide();
}); });
} }
editButtons = h('div.cp-form-edit-buttons-container', [
edit, del
]);
} }
return h('div.cp-form-block', [ var editableCls = editable ? ".editable" : "";
return h('div.cp-form-block'+editableCls, {
'data-id':uid
}, [
q, q,
h('div.cp-form-block-content', [ h('div.cp-form-block-content', [
data.tag, data.tag,
edit editButtons
]), ]),
editContainer editContainer
]); ]);
}); });
$container.empty().append(elements); $container.empty().append(elements);
if (editable) {
Sortable.create($container[0], {
direction: "vertical",
filter: "input, button",
preventOnFilter: false,
store: {
set: function (s) {
content.order = s.toArray();
framework.localChange();
}
}
});
return;
}
// In view mode, add "Submit" and "reset" buttons
$container.append(makeFormControls(framework, content, Boolean(answers))); $container.append(makeFormControls(framework, content, Boolean(answers)));
}; };
var renderResults = function (content, answers) { var renderResults = function (content, answers) {
var $container = $('div.cp-form-creator-results').empty(); var $container = $('div.cp-form-creator-results').empty();
var form = content.form; var form = content.form;
var elements = Object.keys(form).map(function (uid) { var elements = content.order.map(function (uid) {
var block = form[uid]; var block = form[uid];
var type = block.type; var type = block.type;
var model = TYPES[type]; var model = TYPES[type];
@ -427,6 +489,26 @@ define([
// Button to clear all answers? // Button to clear all answers?
}; };
var checkIntegrity = function (getter) {
var changed = false;
content.order.forEach(function (uid) {
if (!content.form[uid]) {
var idx = content.order.indexOf(uid);
content.order.splice(idx, 1);
changed = true;
}
});
Object.keys(content.form).forEach(function (uid) {
var idx = content.order.indexOf(uid);
if (idx === -1) {
changed = true;
content.order.push(uid);
}
});
if (!getter && changed) { framework.localChange(); }
};
var makeFormCreator = function () { var makeFormCreator = function () {
var controlContainer; var controlContainer;
@ -444,6 +526,7 @@ define([
//opts: opts //opts: opts
type: type, type: type,
}; };
content.order.push(uid);
framework.localChange(); framework.localChange();
updateForm(framework, content, true); updateForm(framework, content, true);
}); });
@ -479,6 +562,10 @@ define([
content.form = {}; content.form = {};
framework.localChange(); framework.localChange();
} }
if (!content.order) {
content.order = [];
framework.localChange();
}
if (!content.answers || !content.answers.channel || !content.answers.publicKey || !content.answers.validateKey) { if (!content.answers || !content.answers.channel || !content.answers.publicKey || !content.answers.validateKey) {
content.answers = { content.answers = {
channel: Hash.createChannelId(), channel: Hash.createChannelId(),
@ -502,6 +589,7 @@ define([
publicKey: content.answers.publicKey publicKey: content.answers.publicKey
}, function (err, obj) { }, function (err, obj) {
if (obj) { APP.answers = obj; } if (obj) { APP.answers = obj; }
checkIntegrity(false);
updateForm(framework, content, true); updateForm(framework, content, true);
}); });
@ -518,6 +606,7 @@ define([
} }
var answers; var answers;
if (obj && !obj.error) { answers = obj; } if (obj && !obj.error) { answers = obj; }
checkIntegrity(false);
updateForm(framework, content, false, answers); updateForm(framework, content, false, answers);
}); });
@ -530,6 +619,7 @@ define([
}); });
framework.setContentGetter(function () { framework.setContentGetter(function () {
checkIntegrity(true);
return content; return content;
}); });

Loading…
Cancel
Save