Skip to content

Instantly share code, notes, and snippets.

@peter-nikitin
Created September 14, 2020 14:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peter-nikitin/62587238dae97528c5c3d7d187e6bcd6 to your computer and use it in GitHub Desktop.
Save peter-nikitin/62587238dae97528c5c3d7d187e6bcd6 to your computer and use it in GitHub Desktop.
Код для интеграции Google Forms с Mindbox
/**
*
*
* The above comment directs Apps Script to limit the scope of file
* access for this add-on. It specifies that this add-on will only
* attempt to read or modify the files in which the add-on is used,
* and not all of the user's files. The authorization request message
* presented to users will reflect this limited scope.
*/
/**
* A global constant String holding the title of the add-on. This is
* used to identify the add-on in the notification emails.
*/
var ADDON_TITLE = "Google From -> Mindbox integration";
/**
* A global constant 'notice' text to include with each email
* notification.
*/
var NOTICE = `Этот аддон предназначен для интеграции гугль формы с Mindbox. В момент
отправки данных в форме происходит вызов API Mindbox в котром передаются все данные`;
/**
* Adds a custom menu to the active form to show the add-on sidebar.
*
* @param {object} e The event parameter for a simple onOpen trigger. To
* determine which authorization mode (ScriptApp.AuthMode) the trigger is
* running in, inspect e.authMode.
*/
function onOpen(e) {
FormApp.getUi()
.createAddonMenu()
.addItem("Настройка интеграции", "showSidebar")
.addToUi();
}
/**
* Runs when the add-on is installed.
*
* @param {object} e The event parameter for a simple onInstall trigger. To
* determine which authorization mode (ScriptApp.AuthMode) the trigger is
* running in, inspect e.authMode. (In practice, onInstall triggers always
* run in AuthMode.FULL, but onOpen triggers may be AuthMode.LIMITED or
* AuthMode.NONE).
*/
function onInstall(e) {
onOpen(e);
}
/**
* Opens a sidebar in the form containing the add-on's user interface for
* configuring the notifications this add-on will produce.
*/
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile("sidebar").setTitle(
"Интеграция с Mindbox"
);
FormApp.getUi().showSidebar(ui);
}
/**
* Opens a purely-informational dialog in the form explaining details about
* this add-on.
*/
function showAbout() {
var ui = HtmlService.createHtmlOutputFromFile("about")
.setWidth(420)
.setHeight(270);
FormApp.getUi().showModalDialog(ui, "About Form Notifications");
}
function logAuth() {
var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL);
Logger.log(authInfo.getAuthorizationStatus());
}
/**
* Save sidebar settings to this form's Properties, and update the onFormSubmit
* trigger as needed.
*
* @param {Object} settings An Object containing key-value
* pairs to store.
*/
function saveSettings(settings) {
PropertiesService.getDocumentProperties().setProperties(settings);
adjustFormSubmitTrigger();
}
/**
* Queries the User Properties and adds additional data required to populate
* the sidebar UI elements.
*
* @return {Object} A collection of Property values and
* related data used to fill the configuration sidebar.
*/
function getSettings() {
var settings = PropertiesService.getDocumentProperties().getProperties();
var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL);
// Get field items in the form and compile a list
// of their titles and IDs.
var form = FormApp.getActiveForm();
var formItems = form.getItems();
settings.formItems = [];
for (var i = 0; i < formItems.length; i++) {
settings.formItems.push({
title: formItems[i].getTitle(),
id: formItems[i].getId(),
type: formItems[i].getType(),
});
}
return settings;
}
/**
* Adjust the onFormSubmit trigger based on user's requests.
*/
function adjustFormSubmitTrigger() {
var form = FormApp.getActiveForm();
var triggers = ScriptApp.getUserTriggers(form);
var settings = PropertiesService.getDocumentProperties();
// Create a new trigger if required; delete existing trigger
// if it is not needed.
var existingTrigger = null;
for (var i = 0; i < triggers.length; i++) {
if (triggers[i].getEventType() == ScriptApp.EventType.ON_FORM_SUBMIT) {
existingTrigger = triggers[i];
break;
}
}
if (!existingTrigger) {
var trigger = ScriptApp.newTrigger("respondToFormSubmit")
.forForm(form)
.onFormSubmit()
.create();
} else if (existingTrigger) {
ScriptApp.deleteTrigger(existingTrigger);
var trigger = ScriptApp.newTrigger("respondToFormSubmit")
.forForm(form)
.onFormSubmit()
.create();
}
}
/**
* Responds to a form submission event if an onFormSubmit trigger has been
* enabled.
*
* @param {Object} e The event parameter created by a form
* submission; see
* https://developers.google.com/apps-script/understanding_events
*/
function respondToFormSubmit(e) {
var settings = PropertiesService.getDocumentProperties();
var authInfo = ScriptApp.getAuthorizationInfo(ScriptApp.AuthMode.FULL);
var formItems = e.response.getItemResponses();
var bodyToMb = {
customer: {
customFields: {},
},
};
var endpointId = settings.getProperty("endpoint");
var operation = settings.getProperty("operation");
for (var j = 0; j < formItems.length; j++) {
var filedSettings = settings
.getProperty(formItems[j].getItem().getId())
.split("-");
var isCustomField = filedSettings[1] === "true";
var isMultiple = filedSettings[2] === "true";
var filedName = filedSettings[0];
var filedValueText = String(formItems[j].getResponse());
var fieldValue = isMultiple ? filedValueText.split(",") : filedValueText;
if (isCustomField) {
bodyToMb.customer.customFields[filedName] = fieldValue;
} else {
bodyToMb.customer[filedName] = fieldValue;
}
}
Logger.log(formItems);
var url = `https://api.mindbox.ru/v3/operations/async?endpointId=${endpointId}&operation=${operation}`;
var headers = {
"Content-Type": "application/json; charset=utf-8",
Accept: "application/json",
};
var body = JSON.stringify(bodyToMb);
var options = {
method: "post",
headers: headers,
payload: body,
};
UrlFetchApp.fetch(url, options);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<!-- The CSS package above applies Google styling to buttons and other elements. -->
<style>
.branding-below {
bottom: 54px;
top: 0;
}
.branding-text {
left: 7px;
position: relative;
top: 3px;
}
.logo {
vertical-align: middle;
}
.width-100 {
width: 100%;
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
}
label {
font-weight: bold;
}
#creator-options,
#respondent-options {
background-color: #eee;
border-color: #eee;
border-width: 5px;
border-style: solid;
display: none;
}
#creator-email,
#respondent-email,
#button-bar,
#submit-subject {
margin-bottom: 10px;
}
.block__item {
margin-bottom: 10px;
}
#response-step {
display: inline;
}
</style>
</head>
<body>
<div class="sidebar branding-below">
<form>
<div class="block">
<h2>Настройки запроса в Mindbox</h2>
<div class="block__item">
<label>Операция <br>
<input type="text" id="operation">
</label>
</div>
<div class="block__item">
<label>Эндпоинт <br>
<input type="text" id="endpoint">
</label>
</div>
</div>
<h2>Настройки полей формы</h2>
<div class="block form-group">
<table id="field-options">
</table>
</div>
<div class="block" id="button-bar">
<button class="action" id="save-settings">Сохранить</button>
<button class="action" id="load-settings">Обновить</button>
</div>
</form>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
var globalSetting;
/**
* On document load, assign required handlers to each element,
* and attempt to load any saved settings.
*/
$(function() {
$('#save-settings').click(saveSettingsToServer);
$('#load-settings').click(updateSettings);
//$('#creator-notify').click(toggleCreatorNotify);
// $('#respondent-notify').click(toggleRespondentNotify);
// $('#response-step').change(validateNumber);
google.script.run
.withSuccessHandler(loadSettings)
.withFailureHandler(showStatus)
.withUserObject($('#button-bar').get())
.getSettings();
});
/**
* Callback function that populates the notification options using
* previously saved values.
*
* @param {Object} settings The saved settings from the client.
*/
function loadSettings(settings) {
$('#operation').val(settings.operation);
$('#endpoint').val(settings.endpoint);
$('#key').val(settings.key);
globalSetting = {
'formItems': settings.formItems
};
for (var i = 0; i < settings.formItems.length; i++) {
var line = document.createElement("tr");
var lineLabelFromSettings = "";
var lineLabelFromSettingsString = settings[settings.formItems[i]['id']]
if (typeof lineLabelFromSettingsString !== "undefined") {
lineLabelFromSettings = lineLabelFromSettingsString.split("-");
}
line.innerHTML = `
<td>${settings.formItems[i]['title']}</td>
<td>
<label>
Название поля в Mindbox
<input type="TEXT" id=${settings.formItems[i]['id']} value=${lineLabelFromSettings[0] || ""} >
</label>
<br>
<label>
<input type="checkbox" id=${settings.formItems[i]['id']}-cf ${lineLabelFromSettings[1] === "true" ? "checked" : ""} >
Доп поле?
</label>
<br>
<label>
<input type="checkbox" id=${settings.formItems[i]['id']}-multiple ${lineLabelFromSettings[1] === "true" ? "checked" : ""} >
Множественное?
</label>
</td>
`;
$('#field-options').append(line);
}
}
function updateSettings() {
google.script.run
.withSuccessHandler(function(settings) {
$('#field-options')[0].innerHTML = "";
loadSettings(settings)
})
.withFailureHandler(
function(msg, element) {
showStatus(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.getSettings();
}
/**
* Collects the options specified in the add-on sidebar and sends them to
* be saved as Properties on the server.
*/
function saveSettingsToServer() {
this.disabled = true;
$('#status').remove();
var operation = $('#operation')[0].value;
var endpoint = $('#endpoint')[0].value;
var initialRormLabel = {}
var settings = {
'operation': operation,
'endpoint': endpoint,
};
var settingsWithFormItemsFields = globalSetting.formItems.reduce((settingsObj, formItem) => {
var formItemFieldValue = $('#' + formItem.id)[0].value;
var isFormItemFieldChecked = $('#' + formItem.id + '-cf').is(':checked');
var isFormItemFieldMultiple = $('#' + formItem.id + '-multiple').is(':checked');
return {
...settingsObj,
[formItem.id]: `${formItemFieldValue}-${isFormItemFieldChecked}-${isFormItemFieldMultiple}`
}
}, settings)
// Save the settings on the server
google.script.run
.withSuccessHandler(
function(msg, element) {
showStatus('Saved settings', $('#button-bar'));
element.disabled = false;
})
.withFailureHandler(
function(msg, element) {
showStatus(msg, $('#button-bar'));
element.disabled = false;
})
.withUserObject(this)
.saveSettings(settingsWithFormItemsFields);
}
/**
* Inserts a div that contains an status message after a given element.
*
* @param {String} msg The status message to display.
* @param {Object} element The element after which to display the Status.
*/
function showStatus(msg, element) {
var div = $('<div>')
.attr('id', 'status')
.attr('class', 'error')
.text(msg);
$(element).after(div);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment