Merge branch 'staging' into admin-network-pane

pull/1/head
ansuz 4 years ago
commit 93edc4e63a

@ -64,7 +64,8 @@
@cryptpad_color_light_green: #c5ffa8;
@cryptpad_color_light_green_fade: fade(@cryptpad_color_light_green, 20%);
@cryptpad_color_light_yellow: #FFE69C;
@cryptpad_color_yellow_fade: fade(#FFE69C, 15%);
@cryptpad_color_yellow_fade: fade(@cryptpad_color_light_yellow, 50%);
@cryptpad_color_yellow_fader: fade(#FFE69C, 15%); // not in light theme
@cryptpad_color_lighter_blue: #d2e1f2;
@cryptpad_color_link:@cryptpad_color_brand_300;
@ -115,7 +116,7 @@
@cp_forms-disabled: @cryptpad_color_grey_500;
// Bootstrap alerts
@cp_alerts-warning-bg: @cryptpad_color_yellow_fade;
@cp_alerts-warning-bg: @cryptpad_color_yellow_fader;
@cp_alerts-warning-fg: @cryptpad_color_light_yellow;
@cp_alerts-warning-text: @cryptpad_color_light_yellow;
@cp_alerts-danger-bg: @cryptpad_color_red_fader;
@ -432,8 +433,8 @@
@cp_form-bg2: @cryptpad_color_grey_900;
@cp_form-border: @cryptpad_color_grey_800;
@cp_form-poll-color: @cryptpad_color_grey_800;
@cp_form-poll-no: @cryptpad_color_light_red;
@cp_form-poll-yes: @cryptpad_color_light_green;
@cp_form-poll-maybe: @cryptpad_color_light_yellow;
@cp_form-poll-no: fade(@cryptpad_color_red, 25%);
@cp_form-poll-yes: fade(@cryptpad_color_green, 25%);
@cp_form-poll-maybe: @cryptpad_color_grey_700;
@cp_form-poll-yes-color: @cryptpad_color_green;
@cp_form-invalid: @cryptpad_color_red;

@ -432,8 +432,8 @@
@cp_form-bg2: @cryptpad_color_grey_100;
@cp_form-border: @cryptpad_color_grey_200;
@cp_form-poll-color: @cryptpad_color_grey_800;
@cp_form-poll-no: @cryptpad_color_light_red;
@cp_form-poll-yes: @cryptpad_color_light_green;
@cp_form-poll-maybe: @cryptpad_color_light_yellow;
@cp_form-poll-no: fade(@cryptpad_color_light_red, 75%);
@cp_form-poll-yes: fade(@cryptpad_color_light_green, 75%);
@cp_form-poll-maybe: @cryptpad_color_grey_300;
@cp_form-poll-yes-color: @cryptpad_color_green;
@cp_form-invalid: @cryptpad_color_red;

@ -1921,6 +1921,7 @@ define([
if (active.indexOf('-') !== -1) {
active = active.split('-')[0];
}
if (!categories[active]) { active = 'general'; }
common.setHash(active);
Object.keys(categories).forEach(function (key) {
var $category = $('<div>', {'class': 'cp-sidebarlayout-category'}).appendTo($categories);

@ -1069,6 +1069,7 @@ define([
editor.replaceSelections(newTexts, 'around');
editor.focus();
};
Messages.mdToolbar_embed = "Embed file"; // XXX
for (var k in actions) {
$('<button>', {
'data-type': k,
@ -2084,7 +2085,6 @@ define([
AppConfig.registeredOnlyTypes.indexOf(p) !== -1) { return; }
return true;
});
Messages.type.form = "Form"; // XXX
types.forEach(function (p) {
var $element = $('<li>', {
'class': 'cp-icons-element',
@ -2661,6 +2661,18 @@ define([
$creation.focus();
};
Messages.restrictedLoginPrompt = "You are not authorized to access this document. <a>Log in</a> if you think your account should be able to access it."; // XXX
UIElements.loginErrorScreenContent = function (common) {
var msg = Pages.setHTML(h('span'), Messages.restrictedLoginPrompt);
$(msg).find('a').attr({
href: '/login/',
}).click(function (ev) {
ev.preventDefault();
common.setLoginRedirect('login');
});
return msg;
};
var autoStoreModal = {};
UIElements.onServerError = function (common, err, toolbar, cb) {
//if (["EDELETED", "EEXPIRED", "ERESTRICTED"].indexOf(err.type) === -1) { return; }
@ -2708,6 +2720,10 @@ define([
if (toolbar && typeof toolbar.deleted === "function") { toolbar.deleted(); }
} else if (err.type === 'ERESTRICTED') {
msg = Messages.restrictedError;
if (!common.isLoggedIn()) {
msg = UIElements.loginErrorScreenContent(common);
}
if (toolbar && typeof toolbar.failed === "function") { toolbar.failed(true); }
} else if (err.type === 'HASH_NOT_FOUND' && priv.isHistoryVersion) {
msg = Messages.oo_deletedVersion;
@ -2868,7 +2884,13 @@ define([
UIElements.displayStorePadPopup = function (common, data) {
if (storePopupState) { return; }
storePopupState = true;
if (data && data.stored) { return; } // We won't display the popup for dropped files
// We won't display the popup for dropped files or already stored pads
if (data && data.stored) {
if (!data.inMyDrive) {
$('.cp-toolbar-storeindrive').show();
}
return;
}
var priv = common.getMetadataMgr().getPrivateData();
// This pad will be deleted automatically, it shouldn't be stored

@ -502,9 +502,6 @@ define([
var auditor;
if (isForm) {
Messages.share_formEdit = "Author"; // XXX
Messages.share_formView = "Participant"; // XXX
Messages.share_formAuditor = "Auditor"; // XXX
labelEdit = Messages.share_formEdit;
labelView = Messages.share_formView;
auditor = UI.createRadio('accessRights', 'cp-share-form', Messages.share_formAuditor, false, {

@ -1228,7 +1228,7 @@ define([
});
// Add the pad if it does not exist in our drive
if (!contains) { // || (ownedByMe && !inMyDrive)) {
if (!contains || (data.forceSave && !inMyDrive)) {
var autoStore = Util.find(store.proxy, ['settings', 'general', 'autostore']);
if (autoStore !== 1 && !data.forceSave && !data.path) {
// send event to inner to display the corner popup
@ -1269,7 +1269,8 @@ define([
});
// Let inner know that dropped files shouldn't trigger the popup
postMessage(clientId, "AUTOSTORE_DISPLAY_POPUP", {
stored: true
stored: true,
inMyDrive: inMyDrive
});
nThen(function (waitFor) {
sendTo.forEach(function (teamId) {

@ -572,7 +572,9 @@ define([
if (!readOnly) { onLocal(); }
evOnReady.fire(newPad);
common.openPadChat(onLocal);
// In forms, only editors can see the chat
if (!readOnly || type !== 'form') { common.openPadChat(onLocal); }
if (!readOnly && cursorGetter) {
common.openCursorChannel(onLocal);
cursor = common.createCursor(onLocal);

@ -73,6 +73,8 @@ define([
else {
editor.setSelection(posToCursor(selects[0], remoteDoc), posToCursor(selects[1], remoteDoc));
}
editor.scrollTo(scroll.left, scroll.top);
};
module.handleImagePaste = function (editor) {

@ -166,6 +166,7 @@ MessengerUI, Messages, Pages) {
var showColors = false;
var updateUserList = function (toolbar, config, forceOffline) {
if (!config.displayed || config.displayed.indexOf('userlist') === -1) { return; }
if (toolbar.isAlone) { return; }
// Make sure the elements are displayed
var $userButtons = toolbar.userlist;
var $userlistContent = toolbar.userlistContent;
@ -1216,6 +1217,7 @@ MessengerUI, Messages, Pages) {
if (!config.metadataMgr) { return; }
var metadataMgr = config.metadataMgr;
var notify = function(type, name, oldname) {
if (toolbar.isAlone) { return; }
// type : 1 (+1 user), 0 (rename existing user), -1 (-1 user)
if (typeof name === "undefined") { return; }
name = name || Messages.anonymous;
@ -1515,6 +1517,15 @@ MessengerUI, Messages, Pages) {
}
};
// disable notification, userlist and chat
toolbar.alone = function () {
toolbar.userlist.hide();
toolbar.chat.hide();
$('.cp-toolbar-userlist-drawer').remove();
$('.cp-toolbar-chat-drawer').remove();
toolbar.isAlone = true;
};
// On log out, remove permanently the realtime elements of the toolbar
Common.onLogout(function () {
failed();

@ -910,7 +910,7 @@
"access_main": "Access",
"access_allow": "List",
"accessButton": "Access",
"restrictedError": "You are not authorised to access this document",
"restrictedError": "You are not authorized to access this document",
"contacts": "Contacts",
"access_noContact": "No other contact to add",
"allow_checkbox": "Enable access list",
@ -918,7 +918,7 @@
"allow_disabled": "disabled",
"allow_label": "Access list: {0}",
"access_muteRequests": "Mute access requests for this pad",
"owner_text": "The owner(s) of a pad are the only users authorised to: add/remove owners, restrict access to the pad with an access list, or delete the pad.",
"owner_text": "The owner(s) of a pad are the only users authorized to: add/remove owners, restrict access to the pad with an access list, or delete the pad.",
"logoutEverywhere": "Log out everywhere",
"allow_text": "Using an access list means that only selected users and owners will be able to access this document.",
"teams": "Teams",
@ -1117,7 +1117,7 @@
"whatis_model": "Business model",
"whatis_model_info": "<p>CryptPad has been supported since 2016 by French and European research grants such as BPI France, NLNet Foundation, NGI Trust, Mozilla Open Source Support, as well as donations and subscriptions to cryptpad.fr. We believe that public money should fund public code, so the service is fully open source. This means anyone can use, host, and modify the software.</p><p>CryptPad does not profit from user data. This is part of a vision for online services that respect privacy. Unlike the big platforms that pretend to be \"free\" while making profits from personal information, CryptPad aims to build a sustainable model funded willingly by users.</p><p>We offer CryptPad's functionality for free because we believe everyone deserves personal privacy, not just people with disposable income. If you are in a position to support the project, you will contribute new features, improvements and maintenance that benefit all users.</p><p>Now that the feasibility of the project has been established, the next goal is to make it financially sustainable through user funding. If you would like to support CryptPad and help make it a sustainable alternative to the big platforms, please consider making a one-time or recurring donation.</p>",
"whatis_xwiki": "Made at XWiki",
"whatis_xwiki_info": "<p>CryptPad is made at <a>XWiki</a>, a company based in Paris, France that has been making open-source software for over 15 years. We have extensive experience making collaborative software to organise information. Our track record shows we are committed to the long-term development and maintenance of CryptPad.</p>",
"whatis_xwiki_info": "<p>CryptPad is made at <a>XWiki</a>, a company based in Paris, France that has been making open-source software for over 15 years. We have extensive experience making collaborative software to organize information. Our track record shows we are committed to the long-term development and maintenance of CryptPad.</p>",
"creation_expiresIn": "Expires in",
"creation_helperText": "Open in documentation",
"docs_link": "Documentation",
@ -1238,5 +1238,92 @@
"admin_supportInitGenerate": "Generate support keys",
"admin_supportPrivHint": "Display the private key that other admins will need to view support tickets. A form to enter this key will be displayed on their admin panel.",
"admin_supportPrivButton": "Show key",
"admin_emailButton": "Update"
"admin_emailButton": "Update",
"share_formEdit": "Author",
"share_formAuditor": "Auditor",
"share_formView": "Participant",
"button_newform": "New Form",
"form_invalid": "Invalid form",
"form_editBlock": "Edit",
"form_editMax": "Maximum selectable options",
"form_editMaxLength": "Maximum characters",
"form_editType": "Option type",
"form_poll_text": "Text",
"form_poll_day": "Day",
"form_poll_time": "Time",
"form_poll_switch": "Swap axes",
"form_pollTotal": "Total",
"form_pollYourAnswers": "Your answers",
"form_textType": "Text type",
"form_text_text": "Text",
"form_text_url": "Link",
"form_text_email": "Email",
"form_text_number": "Number",
"form_default": "Your question here?",
"form_type_input": "Text",
"form_type_textarea": "Paragraph",
"form_type_radio": "Choice",
"form_type_multiradio": "Choice Grid",
"form_type_checkbox": "Checkbox",
"form_type_multicheck": "Checkbox Grid",
"form_type_poll": "Poll",
"form_type_sort": "Ordered list",
"form_sort_hint": "Please drag these items from most (1) to least ({0}) preferred.",
"form_type_md": "Description",
"form_type_page": "Page break",
"form_description_default": "Your text here",
"form_duplicates": "Duplicate entries have been removed",
"form_maxOptions": "maximum {0} answer(s)",
"form_maxLength": "Character limit: {0}/{1}",
"form_submit": "Submit",
"form_update": "Update",
"form_reset": "Reset",
"form_sent": "Sent",
"form_delete": "Delete",
"form_submitWarning": "Submit anyway",
"form_updateWarning": "Update anyway",
"form_cantFindAnswers": "Unable to retrieve your existing answers for this form.",
"form_answered": "You have already answered this form",
"form_results": "Responses",
"form_results_empty": "There are no responses",
"form_editor": "Editor",
"form_form": "Form",
"form_viewResults": "Go to responses",
"form_showIndividual": "Show individual answers",
"form_showSummary": "Show summary",
"form_answerAnonymous": "Anonymous answer on {0}",
"form_viewButton": "View",
"form_backButton": "Back",
"form_answerName": "Answer from {0} on {1}",
"form_answerWarning": "Unconfirmed identity",
"form_notAnswered": "<b>{0}</b> empty answers",
"form_input_ph_email": "email@example.com",
"form_input_ph_url": "https://example.com",
"form_invalidWarning": "There are errors in some answers:",
"form_invalidQuestion": "Question {0}",
"form_makePublic": "Publish responses",
"form_makePublicWarning": "Are you sure you want to make responses to this form public? This cannot be undone.",
"form_isPublic": "Responses are public",
"form_isPrivate": "Responses are private",
"form_open": "Open",
"form_setEnd": "Set closing date",
"form_removeEnd": "Remove closing date",
"form_isOpen": "This form is open",
"form_isClosed": "This form was closed on {0}",
"form_willClose": "This form will close on {0}",
"form_anonymous": "Anonymous answers",
"form_anonymous_on": "Allowed",
"form_anonymous_off": "Blocked",
"form_defaultOption": "Option {0}",
"form_defaultItem": "Item {0}",
"form_newOption": "New option",
"form_newItem": "New item",
"form_add_option": "Add option",
"form_add_item": "Add item",
"form_anonymous_blocked": "Anonymous responses are blocked for this form. You must <a href=\"/login/\">log in</a> or <a href=\"/register/\">register</a> to submit answers.",
"form_addMultiple": "Add all",
"form_addMultipleHint": "Add multiple dates and times",
"form_clear": "Clear",
"form_page": "Page {0}/{1}",
"form_anonymousBox": "Answer anonymously"
}

@ -32,6 +32,9 @@
div.cp-form-creator-results, .cp-app-form-button-creator {
display: none !important;
}
.cp-form-block {
.tools_unselectable();
}
}
#cp-app-form-container {
@ -67,6 +70,9 @@
.cp-form-creator-settings {
padding: 30px;
.cp-form-actions {
margin-top: 5px;
}
& > div:not(:last-child) {
margin-bottom: 20px;
}
@ -90,6 +96,7 @@
div.cp-form-creator-content, div.cp-form-creator-results {
max-width: 1000px;
min-width: 300px;
margin-top: 10px;
padding: 10px;
display: flex;
flex-flow: column;
@ -193,6 +200,24 @@
.cp-form-page + .cp-form-send-container {
margin-top: 10px;
}
.cp-form-send-container {
text-align: center;
margin: 50px auto 100px auto;
button {
&:not(:last-child) {
margin-right: 10px;
}
}
.cp-form-invalid-warning {
color: @cp_form-invalid;
ul {
list-style-type: disclosure-closed;
}
li {
text-align: left;
}
}
}
.cp-form-page-container {
display: flex;
@ -206,16 +231,16 @@
justify-content: center;
}
button {
&.cp-next {
.fa {
display: flex;
height: 38px;
align-items: center;
i {
margin-right: 0;
margin-left: 5px;
}
font-size: 25px;
}
}
}
.cp-form-block {
.tools_unselectable();
background: @cp_form-bg1;
padding: 10px;
&:not(:last-child) {
@ -240,12 +265,22 @@
&.sortable-ghost { visibility: hidden; }
&.sortable-drag { opacity: 0.9 !important; }
.flatpickr-calendar.inline {
box-shadow: unset;
border: 1px solid @cryptpad_text_col;
}
.cp-form-block-question {
margin-bottom: 5px;
.cp-form-block-question-number {
font-weight: bold;
margin-right: 10px;
}
}
.cp-form-block-content {
overflow-x: auto;
.cp-form-page-break-edit {
font-size: 20px;
text-align: center;
padding: 10px;
i {
@ -258,7 +293,13 @@
justify-content: space-between;
}
input:invalid {
border: 1px solid @cp_form-invalid;
border: 2px solid @cp_form-invalid;
color: @cp_form-invalid;
}
media-tag {
& > * {
max-width: 100%;
}
}
}
.cp-form-input-block {
@ -312,6 +353,12 @@
margin-left: 10px;
}
}
.cp-form-multiple-picker {
margin: 10px 0px 0px 0px;
button {
margin: 10px 10px 0px 0px;
}
}
}
}
.cp-form-edit-max-options {
@ -357,7 +404,7 @@
}
}
.cp-form-edit-block-input {
margin-bottom: 5px; // XXX DB margin bug
margin-bottom: 5px;
&.sortable-ghost { visibility: hidden; }
&.sortable-drag { opacity: 0.9 !important; }
display: flex;
@ -409,9 +456,9 @@
}
.cp-form-results-type-textarea-data {
white-space: pre-wrap;
font-size: 14px;
border: 1px solid @cp_profile-hint;
padding: 0 5px;
padding: 5px 10px;
background: @cp_form-bg2;
&:not(:last-child) { margin-bottom: 1px; }
}
.cp-form-results-type-radio {
display: table;
@ -475,49 +522,126 @@
}
}
}
.cp-form-sort-hint {
margin-bottom: 10px;
}
.cp-form-type-sort {
cursor: grab;
padding: 2px;
padding: 5px;
.cp-form-handle {
margin-right: 5px;
}
.cp-form-sort-order {
border: 1px solid @cp_profile-hint;
border: 1px solid @cryptpad_text_col;
padding: 0 5px;
margin-right: 5px;
}
&:hover {
background-color: @cp_app-bg;
color: @cryptpad_color_link;
.cp-form-sort-order {
border-color: @cryptpad_color_link;
}
}
}
.cp-form-type-poll-container {
overflow: auto;
}
.cp-form-type-poll {
display: inline-flex;
flex-flow: column;
& > div {
display: flex;
}
.cp-form-poll-body {
flex-flow: column;
max-height: 225px;
overflow: auto;
& > div {
display: flex;
}
}
.cp-poll-cell {
width: 100px;
height: 40px;
height: 35px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-top:5px;
margin-left:5px;
&:first-child {
width: 200px;
}
button {
width: 100%;
border-top: 0px;
border-left: 0px;
background-color: @cp_form-bg1;
.fa{
margin-left:10px;
transform: rotate(-45deg);
}
}
.cp-form-total-yes {
margin-right: 5px;
}
&.cp-poll-best {
font-weight: bold;
}
}
.cp-poll-answer-name {
padding: 0 5px;
display: flex;
:last-child {
flex: 1;
min-width: 0;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.cp-avatar {
.avatar_main(30px);
margin-right: 10px;
}
}
.cp-poll-time-day {
flex-basis: 100px;
border-right: 1px solid @cryptpad_text_col;
border-left: 1px solid @cryptpad_text_col;
border-top: 1px solid @cryptpad_text_col;
border-bottom: 1px solid @cryptpad_text_col;
}
&:not(.cp-form-poll-switch) {
& > div {
&:last-child {
margin-bottom: 5px;
}
}
.cp-form-poll-body {
&::-webkit-scrollbar {
display: none;
}
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}
&.cp-form-poll-switch {
display: flex;
flex-flow: row;
.cp-avatar {
.avatar_main(20px);
}
& > div {
flex-flow: column;
&.cp-form-poll-body {
flex-flow: row;
max-width: 550px;
max-height: unset;
scroll-snap-type: x mandatory;
& > div {
flex-flow: column;
}
}
}
.cp-poll-cell:not(.cp-poll-switch) {
&:first-child {
width: 100px;
@ -529,9 +653,8 @@
.cp-poll-time-day {
flex-basis: 40px;
border-right: none;
border-bottom: 1px solid @cryptpad_text_col;
border-left: 1px solid @cryptpad_text_col;
border-top: 1px solid @cryptpad_text_col;
border-right: 1px solid @cryptpad_text_col;
border-bottom: 0px;
}
}
.cp-form-poll-choice, .cp-form-poll-answer {
@ -539,6 +662,7 @@
display: none;
}
color: @cp_form-poll-color;
font-size: 25px;
&[data-value="0"] {
background: @cp_form-poll-no;
.cp-no { display: inline; }
@ -555,7 +679,9 @@
div.cp-form-poll-choice {
cursor: pointer;
padding: 5px;
border: 5px double @cp_form-bg1;
//margin: 10px 0px 0px 10px;
//border: 1px solid @cryptpad_text_col;
color: @cryptpad_text_col;
}
div.cp-form-poll-answer {
color: @cp_form-poll-yes-color;

@ -27,7 +27,7 @@ define([
'/bower_components/sortablejs/Sortable.min.js',
'cm/addon/display/placeholder',
'cm/mode/markdown/markdown',
'cm/mode/gfm/gfm',
'css!cm/lib/codemirror.css',
'css!/bower_components/codemirror/lib/codemirror.css',
@ -76,98 +76,6 @@ define([
timeFormat = "h:i K";
}
Messages.button_newform = "New Form"; // XXX
Messages.form_invalid = "Invalid form";
Messages.form_editBlock = "Edit";
Messages.form_editMax = "Max selectable options";
Messages.form_editMaxLength = "Maximum characters";
Messages.form_editType = "Options type";
Messages.form_poll_text = "Text";
Messages.form_poll_day = "Day";
Messages.form_poll_time = "Time";
Messages.form_textType = "Text type";
Messages.form_text_text = "Text";
Messages.form_text_url = "URL";
Messages.form_text_email = "Email";
Messages.form_text_number = "Number";
Messages.form_default = "Your question here?";
Messages.form_type_input = "Text"; // XXX
Messages.form_type_textarea = "Textarea"; // XXX
Messages.form_type_radio = "Radio"; // XXX
Messages.form_type_multiradio = "Multiline Radio"; // XXX
Messages.form_type_checkbox = "Checkbox"; // XXX
Messages.form_type_multicheck = "Multiline Checkbox"; // XXX
Messages.form_type_poll = "Poll"; // XXX
Messages.form_type_sort = "Ordered list"; // XXX
Messages.form_type_md = "Description"; // XXX
Messages.form_type_page = "Page break"; // XXX
Messages.form_description_default = "Your text here";
Messages.form_duplicates = "Duplicate entries have been removed";
Messages.form_maxOptions = "{0} answer(s) max";
Messages.form_submit = "Submit";
Messages.form_update = "Update";
Messages.form_reset = "Reset";
Messages.form_sent = "Sent";
Messages.form_delete = "Delete";
Messages.form_cantFindAnswers = "Unable to retrieve your existing answers for this form.";
Messages.form_answered = "You already answered this form";
Messages.form_results = "Responses";
Messages.form_editor = "Editor";
Messages.form_form = "Form";
Messages.form_viewResults = "Go to responses";
Messages.form_viewCreator = "Go to form creator";
Messages.form_showIndividual = "Show individual answers";
Messages.form_showSummary = "Show summary";
Messages.form_answerAnonymous = "Anonymous answer on <em>{0}</em>";
Messages.form_viewButton = "View";
Messages.form_backButton = "Back";
Messages.form_answerName = "Answer from {0} on <em>{1}</em>";
Messages.form_answerWarning = "Unconfirmed identity";
Messages.form_notAnswered = "And <b>{0}</b> empty answers";
Messages.form_makePublic = "Publish results";
Messages.form_makePublicWarning = "Are you sure you want to make the results of this form public? This can't be undone.";
Messages.form_isPublic = "Results are public";
Messages.form_isPrivate = "Results are private";
Messages.form_open = "Open";
Messages.form_setEnd = "Set closing date";
Messages.form_removeEnd = "Remove closing date";
Messages.form_isOpen = "This form is open";
Messages.form_isClosed = "This form was closed on {0}";
Messages.form_willClose = "This form will close on {0}";
Messages.form_anonymous = "Anonymous answers";
Messages.form_anonymous_on = "Allowed";
Messages.form_anonymous_off = "Blocked";
Messages.form_anonymous_blocked = "Anonymous responses are blocked for this form. You must log in or register to submit answers.";
Messages.form_defaultOption = "Option {0}";
Messages.form_defaultItem = "Item {0}";
Messages.form_newOption = "New option";
Messages.form_newItem = "New item";
Messages.form_add_option = "Add option";
Messages.form_add_item = "Add item";
Messages.form_addMultiple = "Add all";
Messages.form_clear = "Clear";
Messages.form_page_prev = "Previous";
Messages.form_page = "Page {0}/{1}";
Messages.form_page_next = "Next";
Messages.form_anonymousBox = "Answer anonymously";
var MAX_OPTIONS = 15; // XXX
var MAX_ITEMS = 10; // XXX
@ -440,13 +348,13 @@ define([
// Calendar time
if (v.type) {
var multipleInput = h('input');
var multipleInput = h('input', {placeholder: Messages.form_addMultipleHint});
var multipleClearButton = h('button.btn', Messages.form_clear);
var addMultipleButton = h('button.btn', [
h('i.fa.fa-plus'),
h('span', Messages.form_addMultiple)
]);
addMultiple = h('div', { style: "display: none;" }, [
addMultiple = h('div.cp-form-multiple-picker', { style: "display: none;" }, [
multipleInput,
addMultipleButton,
multipleClearButton
@ -487,6 +395,7 @@ define([
$(addMultiple).hide();
}
} else {
$(addMultiple).hide();
$calendar.show();
$container.hide();
}
@ -500,6 +409,7 @@ define([
refreshView();
if (val !== "text") {
$container.find('.cp-form-edit-block-input').remove();
$(add).click();
return;
}
$container.find('input').each(function (i, input) {
@ -598,12 +508,13 @@ define([
val = +f.selectedDates[0];
}
}
if (values.indexOf(val) === -1) { values.push(val); }
if (val && values.indexOf(val) === -1) { values.push(val); }
else { duplicates = true; }
});
}
values = values.filter(Boolean); // Block empty or undeinfed options
if (!values.length) {
return void UI.warn(Messages.error); // XXX error message: no values
return void UI.warn(Messages.error);
}
var res = { values: values };
@ -672,10 +583,13 @@ define([
var _dateT = new Date(data);
data = Flatpickr.formatDate(_dateT, timeFormat);
}
return h('div.cp-poll-cell.cp-form-poll-option', data);
return h('div.cp-poll-cell.cp-form-poll-option', {
title: Util.fixHTML(data)
}, data);
});
// Insert axis switch button
var switchAxis = h('button.btn.btn-default', [
Messages.form_poll_switch,
h('i.fa.fa-exchange'),
]);
els.unshift(h('div.cp-poll-cell.cp-poll-switch', switchAxis));
@ -700,10 +614,14 @@ define([
}
// Add answers
var bodyEls = [];
if (Array.isArray(answers)) {
answers.forEach(function (answer) {
if (!answer.name || !answer.values) { return; }
var _name = answer.name;
answers.forEach(function (answerObj) {
var answer = answerObj.results;
if (!answer || !answer.values) { return; }
var name = Util.find(answerObj, ['user', 'name']) || answer.name || Messages.anonymous;
var avatar = h('span.cp-avatar');
APP.common.displayAvatar($(avatar), Util.find(answerObj, ['user', 'avatar']), name);
var values = answer.values || {};
var els = opts.values.map(function (data) {
var res = values[data] || 0;
@ -713,10 +631,17 @@ define([
}, v);
return cell;
});
els.unshift(h('div.cp-poll-cell.cp-poll-answer-name', _name));
lines.push(h('div', els));
els.unshift(h('div.cp-poll-cell.cp-poll-answer-name', {
title: Util.fixHTML(name)
}, [
avatar,
h('span', name)
]));
bodyEls.push(h('div', els));
});
}
var body = h('div.cp-form-poll-body', bodyEls);
lines.push(body);
var $s = $(switchAxis).click(function () {
$s.closest('.cp-form-type-poll').toggleClass('cp-form-poll-switch');
@ -724,6 +649,111 @@ define([
return lines;
};
var makePollTotal = function (answers, opts, myLine, evOnChange) {
if (!Array.isArray(answers)) { return; }
var totals = {};
var myTotals = {};
var updateMyTotals = function () {
if (!myLine) { return; }
opts.values.forEach(function (data) {
myLine.some(function (el) {
if ($(el).data('option') !== data) { return; }
var res = Number($(el).attr('data-value')) || 0;
if (res === 1) {
myTotals[data] = {
y: 1,
m: 0
};
}
else if (res === 2) {
myTotals[data] = {
y: 0,
m: 1
};
} else {
delete myTotals[data];
}
return true;
});
});
};
var totalEls = opts.values.map(function (data) {
var y = 0; // Yes
var m = 0; // Maybe
answers.forEach(function (answerObj) {
var answer = answerObj.results;
if (!answer || !answer.values) { return; }
var values = answer.values || {};
var res = Number(values[data]) || 0;
if (res === 1) { y++; }
else if (res === 2) { m++; }
});
totals[data] = {
y: y,
m: m
};
return h('div.cp-poll-cell', {
'data-id': data
}, [
h('span.cp-form-total-yes', y),
h('span.cp-form-total-maybe', '('+m+')'),
]);
});
totalEls.unshift(h('div.cp-poll-cell', Messages.form_pollTotal));
var total = h('div.cp-poll-total', totalEls);
var $total = $(total);
var refreshBest = function () {
var totalMax = {
value: 0,
data: []
};
Object.keys(totals).forEach(function (k) {
var obj = Util.clone(totals[k]);
if (myTotals[k]) {
obj.y += myTotals[k].y || 0;
obj.m += myTotals[k].m || 0;
}
if (obj.y === totalMax.value) {
totalMax.data.push(k);
} else if (obj.y > totalMax.value) {
totalMax.value = obj.y;
totalMax.data = [k];
}
});
if (totalMax.value) {
$total.find('[data-id]').removeClass('cp-poll-best');
totalMax.data.forEach(function (k) {
$total.find('[data-id="'+k+'"]').addClass('cp-poll-best');
});
}
};
refreshBest();
if (myLine && evOnChange) {
var updateValues = function () {
totalEls.forEach(function (cell) {
var $c = $(cell);
var data = $c.attr('data-id');
if (!data) { return; }
var y = totals[data].y + ((myTotals[data] || {}).y || 0);
var m = totals[data].m + ((myTotals[data] || {}).m || 0);
$c.find('.cp-form-total-yes').text(y);
$c.find('.cp-form-total-maybe').text('('+m+')');
});
};
evOnChange.reg(function () {
updateMyTotals();
updateValues();
refreshBest();
});
}
return total;
};
var getEmpty = function (empty) {
if (empty) {
@ -744,10 +774,14 @@ define([
};
var getBlockAnswers = function (answers, uid, filterCurve) {
if (!answers) { return; }
return Object.keys(answers || {}).map(function (user) {
if (filterCurve && user === filterCurve) { return; }
try {
return answers[user].msg[uid];
return {
user: answers[user].msg._userdata,
results: answers[user].msg[uid]
};
} catch (e) { console.error(e); }
}).filter(Boolean);
};
@ -877,7 +911,8 @@ define([
get: function (opts, a, n, evOnChange) {
if (!opts) { opts = TYPES.input.defaultOpts; }
var tag = h('input', {
type: opts.type
type: opts.type,
placeholder: Messages['form_input_ph_'+opts.type] || ''
});
var $tag = $(tag);
$tag.on('change keypress', Util.throttle(function () {
@ -922,23 +957,49 @@ define([
},
get: function (opts, a, n, evOnChange) {
if (!opts) { opts = TYPES.textarea.defaultOpts; }
var tag = h('textarea', {maxlength: opts.maxLength});
var $tag = $(tag);
$tag.on('change keypress', Util.throttle(function () {
var text = h('textarea', {maxlength: opts.maxLength});
var $text = $(text);
var charCount = h('div.cp-form-type-textarea-charcount');
var updateChar = function () {
var l = $text.val().length;
if (l > opts.maxLength) {
$text.val($text.val().slice(0, opts.maxLength));
l = $text.val().length;
}
$(charCount).text(Messages._getKey('form_maxLength', [
$text.val().length,
opts.maxLength
]));
};
updateChar();
var tag = h('div.cp-form-type-textarea', [
text,
charCount
]);
var evChange = Util.throttle(function () {
evOnChange.fire();
}, 500));
}, 500);
$text.on('change keypress keyup keydown', function () {
setTimeout(updateChar);
evChange();
});
var cursorGetter;
var setCursorGetter = function (f) { cursorGetter = f; };
return {
tag: tag,
getValue: function () { return $tag.val(); },
setValue: function (val) { $tag.val(val); },
getValue: function () { return $text.val().slice(0, opts.maxLength); },
setValue: function (val) {
$text.val(val);
updateChar();
},
edit: function (cb, tmp) {
var v = Util.clone(opts);
return editTextOptions(v, setCursorGetter, cb, tmp);
},
getCursor: function () { return cursorGetter(); },
reset: function () { $tag.val(''); }
reset: function () { $text.val(''); }
};
},
printResults: function (answers, uid) {
@ -1108,6 +1169,7 @@ define([
printResults: function (answers, uid, form) {
var structure = form[uid];
if (!structure) { return; }
var opts = structure.opts || TYPES.multiradio.defaultOpts;
var results = [];
var empty = 0;
var count = {};
@ -1125,7 +1187,6 @@ define([
});
});
Object.keys(count).forEach(function (q_uid) {
var opts = structure.opts || TYPES.multiradio.defaultOpts;
var q = findItem(opts.items, q_uid);
var c = count[q_uid];
var values = Object.keys(c).map(function (res) {
@ -1321,6 +1382,7 @@ define([
printResults: function (answers, uid, form) {
var structure = form[uid];
if (!structure) { return; }
var opts = structure.opts || TYPES.multicheck.defaultOpts;
var results = [];
var empty = 0;
var count = {};
@ -1339,7 +1401,7 @@ define([
});
});
Object.keys(count).forEach(function (q_uid) {
var q = findItem(structure.opts.items, q_uid);
var q = findItem(opts.items, q_uid);
var c = count[q_uid];
var values = Object.keys(c).map(function (res) {
return h('div.cp-form-results-type-radio-data', [
@ -1358,94 +1420,6 @@ define([
},
icon: h('i.cptools.cptools-form-grid-check')
},
poll: {
defaultOpts: {
type: 'text', // Text or Days or Time
values: [1, 2, 3].map(function (i) {
return Messages._getKey('form_defaultOption', [i]);
})
},
get: function (opts, answers, username, evOnChange) {
if (!opts) { opts = TYPES.poll.defaultOpts; }
if (!Array.isArray(opts.values)) { return; }
var lines = makePollTable(answers, opts);
// Add form
var addLine = opts.values.map(function (data) {
var cell = h('div.cp-poll-cell.cp-form-poll-choice', [
h('i.fa.fa-times.cp-no'),
h('i.fa.fa-check.cp-yes'),
h('i.fa.fa-question.cp-maybe'),
]);
var $c = $(cell);
$c.data('option', data);
var val = 0;
$c.attr('data-value', val);
$c.click(function () {
val = (val+1)%3;
$c.attr('data-value', val);
evOnChange.fire();
});
cell._setValue = function (v) {
val = v;
$c.attr('data-value', val);
};
return cell;
});
// Name input
var nameInput = h('input', { value: username || Messages.anonymous });
addLine.unshift(h('div.cp-poll-cell', nameInput));
lines.push(h('div', addLine));
var tag = h('div.cp-form-type-poll', lines);
var $tag = $(tag);
var cursorGetter;
var setCursorGetter = function (f) { cursorGetter = f; };
return {
tag: tag,
getValue: function () {
var res = {};
var name = $(nameInput).val().trim() || Messages.anonymous;
$tag.find('.cp-form-poll-choice').each(function (i, el) {
var $el = $(el);
res[$el.data('option')] = $el.attr('data-value');
});
return {
name: name,
values: res
};
},
reset: function () {
$tag.find('.cp-form-poll-choice').attr('data-value', 0);
},
edit: function (cb, tmp) {
var v = Util.clone(opts);
return editOptions(v, setCursorGetter, cb, tmp);
},
getCursor: function () { return cursorGetter(); },
setValue: function (res) {
this.reset();
if (!res || !res.values || !res.name) { return; }
var val = res.values;
$(nameInput).val(res.name);
$tag.find('.cp-form-poll-choice').each(function (i, el) {
if (!el._setValue) { return; }
var $el = $(el);
el._setValue(val[$el.data('option')] || 0);
});
}
};
},
printResults: function (answers, uid, form) {
var _answers = getBlockAnswers(answers, uid);
var lines = makePollTable(_answers, form[uid].opts);
return h('div.cp-form-type-poll', lines);
},
icon: h('i.cptools.cptools-form-poll')
},
sort: {
defaultOpts: {
values: [1,2].map(function (i) {
@ -1453,7 +1427,7 @@ define([
})
},
get: function (opts, a, n, evOnChange) {
if (!opts) { opts = TYPES.radio.defaultOpts; }
if (!opts) { opts = TYPES.sort.defaultOpts; }
if (!Array.isArray(opts.values)) { return; }
var map = {};
var invMap = {};
@ -1472,7 +1446,10 @@ define([
$(div).data('val', data);
return div;
});
var tag = h('div.cp-form-type-sort-container', els);
var tag = h('div.cp-form-type-sort-container', [
h('div.cp-form-sort-hint', Messages._getKey('form_sort_hint', [els.length])),
els
]);
var $tag = $(tag);
var reorder = function () {
$tag.find('.cp-form-type-sort').each(function (i, el) {
@ -1527,7 +1504,7 @@ define([
},
printResults: function (answers, uid, form) {
var opts = form[uid].opts || TYPES.radio.defaultOpts;
var opts = form[uid].opts || TYPES.sort.defaultOpts;
var l = (opts.values || []).length;
var results = [];
var empty = 0;
@ -1556,15 +1533,116 @@ define([
},
icon: h('i.cptools.cptools-form-list-ordered')
},
poll: {
defaultOpts: {
type: 'text', // Text or Days or Time
values: [1, 2, 3].map(function (i) {
return Messages._getKey('form_defaultOption', [i]);
})
},
get: function (opts, answers, username, evOnChange) {
if (!opts) { opts = TYPES.poll.defaultOpts; }
if (!Array.isArray(opts.values)) { return; }
var lines = makePollTable(answers, opts);
// Add form
var addLine = opts.values.map(function (data) {
var cell = h('div.cp-poll-cell.cp-form-poll-choice', [
h('i.fa.fa-times.cp-no'),
h('i.fa.fa-check.cp-yes'),
h('i.fa.fa-question.cp-maybe'),
]);
var $c = $(cell);
$c.data('option', data);
var val = 0;
$c.attr('data-value', val);
$c.click(function () {
val = (val+1)%3;
$c.attr('data-value', val);
evOnChange.fire();
});
cell._setValue = function (v) {
val = v;
$c.attr('data-value', val);
};
return cell;
});
// Name input
//var nameInput = h('input', { value: username || Messages.anonymous });
var nameInput = h('span.cp-poll-your-answers', Messages.form_pollYourAnswers)
addLine.unshift(h('div.cp-poll-cell', nameInput));
lines.push(h('div', addLine));
var total = makePollTotal(answers, opts, addLine, evOnChange);
if (total) { lines.push(h('div', total)); }
var tag = h('div.cp-form-type-poll-container', h('div.cp-form-type-poll', lines));
var $tag = $(tag);
var cursorGetter;
var setCursorGetter = function (f) { cursorGetter = f; };
return {
tag: tag,
getValue: function () {
var res = {};
$tag.find('.cp-form-poll-choice').each(function (i, el) {
var $el = $(el);
res[$el.data('option')] = $el.attr('data-value');
});
return {
values: res
};
},
reset: function () {
$tag.find('.cp-form-poll-choice').attr('data-value', 0);
},
edit: function (cb, tmp) {
var v = Util.clone(opts);
return editOptions(v, setCursorGetter, cb, tmp);
},
getCursor: function () { return cursorGetter(); },
setValue: function (res) {
this.reset();
if (!res || !res.values) { return; }
var val = res.values;
$tag.find('.cp-form-poll-choice').each(function (i, el) {
if (!el._setValue) { return; }
var $el = $(el);
el._setValue(val[$el.data('option')] || 0);
});
}
};
},
printResults: function (answers, uid, form) {
var opts = form[uid].opts || TYPES.poll.defaultOpts;
var _answers = getBlockAnswers(answers, uid);
var lines = makePollTable(_answers, opts);
var total = makePollTotal(_answers, opts);
if (total) { lines.push(h('div', total)); }
return h('div.cp-form-type-poll', lines);
},
icon: h('i.cptools.cptools-form-poll')
},
};
var renderResults = function (content, answers) {
var $container = $('div.cp-form-creator-results').empty();
if (!Object.keys(answers || {}).length) {
$container.append(h('div.alert.alert-info', Messages.form_results_empty));
return;
}
var controls = h('div.cp-form-creator-results-controls');
var $controls = $(controls).appendTo($container);
var results = h('div.cp-form-creator-results-content');
var $results = $(results).appendTo($container);
var summary = true;
var form = content.form;
@ -1715,7 +1793,7 @@ define([
});
return results;
};
var makeFormControls = function (framework, content, update) {
var makeFormControls = function (framework, content, update, evOnChange) {
var loggedIn = framework._.sfCommon.isLoggedIn();
var metadataMgr = framework._.cpNfInner.metadataMgr;
@ -1768,6 +1846,7 @@ define([
console.error(err || data.error);
return void UI.warn(Messages.error);
}
window.onbeforeunload = undefined;
if (!update) {
// Add results button
addResultsButton(framework, content);
@ -1783,7 +1862,53 @@ define([
reset = undefined;
}
var invalid = h('div.cp-form-invalid-warning');
var $invalid = $(invalid);
if (evOnChange) {
var origin, priv;
if (APP.common) {
var metadataMgr = APP.common.getMetadataMgr();
priv = metadataMgr.getPrivateData();
origin = priv.origin;
}
evOnChange.reg(function () {
var $container = $('div.cp-form-creator-content');
var $inputs = $container.find('input:invalid');
if (!$inputs.length) {
$send.text(update ? Messages.form_update : Messages.form_submit);
return void $invalid.empty();
}
$send.text(update ? Messages.form_updateWarning : Messages.form_submitWarning);
var lis = [];
$inputs.each(function (i, el) {
var $el = $(el).closest('.cp-form-block');
var number = $el.find('.cp-form-block-question-number').text();
var a = h('a', {
href: origin + '#' + Messages._getKey('form_invalidQuestion', [number])
}, Messages._getKey('form_invalidQuestion', [number]));
$(a).click(function (e) {
e.preventDefault();
if (!$el.is(':visible')) {
var pages = $el.closest('.cp-form-page').index();
if (APP.refreshPage) { APP.refreshPage(pages + 1); }
}
$el[0].scrollIntoView();
});
var li = h('li', a);
lis.push(li);
});
var list = h('ul', lis);
var content = [
h('span', Messages.form_invalidWarning),
list
];
$invalid.empty().append(content);
});
evOnChange.fire(true);
}
return h('div.cp-form-send-container', [
invalid,
cbox ? h('div', cbox) : undefined,
send, reset
]);
@ -1801,7 +1926,8 @@ define([
var _answers = Util.clone(answers || {});
delete _answers._proof;
delete _answers._userdata;
evOnChange.reg(function () {
evOnChange.reg(function (noBeforeUnload) {
if (noBeforeUnload) { return; }
var results = getFormResults();
if (!answers || Sortify(_answers) !== Sortify(results)) {
window.onbeforeunload = function () {
@ -1884,6 +2010,7 @@ define([
var elements = [];
var n = 1; // Question number
content.order.forEach(function (uid) {
var block = form[uid];
var type = block.type;
@ -1913,7 +2040,10 @@ define([
var dragHandle;
var q = h('div.cp-form-block-question', block.q || Messages.form_default);
var q = h('div.cp-form-block-question', [
h('span.cp-form-block-question-number', (n++)+'.'),
h('span', block.q || Messages.form_default)
]);
var editButtons, editContainer;
APP.formBlocks.push(data);
@ -2013,7 +2143,7 @@ define([
framework._.cpNfInner.chainpad.onSettle(function () {
$(editButtons).show();
UI.log(Messages.saved);
var _answers = getBlockAnswers(APP.answers, uid);
_answers = getBlockAnswers(APP.answers, uid);
data = model.get(newOpts, _answers, null, evOnChange);
if (!data) { data = {}; }
$oldTag.before(data.tag).remove();
@ -2085,19 +2215,19 @@ define([
var pageContainer = h('div.cp-form-page-container');
var $page = $(pageContainer);
_content.push(pageContainer);
var refreshPage = function (current) {
var refreshPage = APP.refreshPage = function (current) {
$page.empty();
if (!current || current < 1) { current = 1; }
if (current > pages) { current = pages; }
var left = h('button.btn.btn-secondary.small.cp-prev', [
h('i.fa.fa-chevron-left'),
h('span', Messages.form_page_prev)
var left = h('button.btn.btn-secondary.cp-prev', [
h('i.fa.fa-arrow-left'),
]);
var state = h('span', Messages._getKey('form_page', [current, pages]));
var right = h('button.btn.btn-secondary.small.cp-next', [
h('span', Messages.form_page_next),
h('i.fa.fa-chevron-right'),
var right = h('button.btn.btn-secondary.cp-next', [
h('i.fa.fa-arrow-right'),
]);
if (current === pages) { $(right).css('visibility', 'hidden'); }
if (current === 1) { $(left).css('visibility', 'hidden'); }
$(left).click(function () { refreshPage(current - 1); });
$(right).click(function () { refreshPage(current + 1); });
$page.append([left, state, right]);
@ -2139,7 +2269,7 @@ define([
}
// In view mode, add "Submit" and "reset" buttons
$container.append(makeFormControls(framework, content, Boolean(answers)));
$container.append(makeFormControls(framework, content, Boolean(answers), evOnChange));
};
var getTempFields = function () {
@ -2172,6 +2302,9 @@ define([
var helpMenu = framework._.sfCommon.createHelpMenu(['text', 'pad']);
$toolbarContainer.after(helpMenu.menu);
if (!APP.isEditor) {
framework._.toolbar.alone();
}
var makeFormSettings = function () {
// Private / public status
@ -2180,7 +2313,7 @@ define([
var refreshPublic = function () {
$results.empty();
var makePublic = h('button.btn.btn-secondary', Messages.form_makePublic);
var makePublicDiv = h('div', makePublic);
var makePublicDiv = h('div.cp-form-actions', makePublic);
if (content.answers.privateKey) { makePublicDiv = undefined; }
var publicText = content.answers.privateKey ? Messages.form_isPublic : Messages.form_isPrivate;
$results.append(h('span.cp-form-results-type', publicText));

@ -230,7 +230,7 @@ define([
results[senderCurve] = {
msg: parsed,
hash: hash,
time: cfg.time
time: cfg && cfg.time
};
};
CPNetflux.start(config);

Loading…
Cancel
Save