-
Notifications
You must be signed in to change notification settings - Fork 2
/
form.js
358 lines (310 loc) · 12.8 KB
/
form.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
// ---------------------------------------------------------------------------------------------------------------- setupForm
/**
* establish a form for parties to fill in their personal details
*
*/
function setupForm(sheet) {
var sheetPassedIn = ! (sheet == undefined);
if (! sheetPassedIn && (SpreadsheetApp.getActiveSpreadsheet().getName().toLowerCase() == "legalese controller"
||
SpreadsheetApp.getActiveSheet().getSheetName().toLowerCase() == "controller")
) {
fmLog("in controller mode, switching to setupOtherForms_()");
setupOtherForms_();
return;
}
var sheet = sheet || SpreadsheetApp.getActiveSheet();
var ss = sheet.getParent();
var entitiesByName = {};
var readRows_ = new readRows(sheet, entitiesByName);
// fmLog("setupForm: readRows complete: %s", readRows_);
if (readRows_.principal
&& readRows_.principal._origin_sheet_id
&& readRows_.principal._origin_sheet_id != sheet.getSheetId()) {
fmLog("setupForm: switching target of the form to the %s sheet.", sheet.getSheetName());
sheet = getSheetById_(ss, readRows_.principal._origin_sheet_id);
entitiesByName = {};
readRows_ = new readRows(sheet, entitiesByName);
}
var data = readRows_.terms;
var config = readRows_.config;
var form = ss.getFormUrl();
if (form != undefined) {
var ui = SpreadsheetApp.getUi();
var response = ui.prompt('A form was previously created.', 'Reset it?', ui.ButtonSet.YES_NO);
if (response.getSelectedButton() == ui.Button.NO) { return }
// resetting the form internals isn't enough because the form title may have changed.
// TODO: delete the old form. delete the old onSubmit Trigger. then recreate the form entirely from scratch.
form = FormApp.openByUrl(form);
var items = form.getItems();
for (var i in items) {
form.deleteItem(0);
}
}
else {
var form_title = config.form_title != undefined ? config.form_title.value : ss.getName();
var form_description = config.form_description != undefined ? config.form_description.value : "Please fill in your details.";
var form_confirmation = config.form_confirmation || 'Thanks for responding!';
form = FormApp.create(form_title)
.setDescription(form_description)
.setConfirmationMessage(form_confirmation)
.setAllowResponseEdits(true)
.setAcceptingResponses(true)
.setProgressBar(false);
// don't create a new trigger if there is already one available
var triggers = ScriptApp.getUserTriggers(ss);
if (triggers.length > 0 && // is there already a trigger for onFormSubmit?
triggers.filter(function(t) { return t.getEventType() == ScriptApp.EventType.ON_FORM_SUBMIT }).length > 0) {
fmLog("we already have an onFormSubmit trigger, so no need to add a new one.");
}
else {
ScriptApp.newTrigger('onFormSubmit').forSpreadsheet(ss).onFormSubmit().create();
fmLog("setting onFormSubmit trigger");
}
}
// Create the form and add a multiple-choice question for each timeslot.
form.setDestination(FormApp.DestinationType.SPREADSHEET, ss.getId());
fmLog("setting form destination to %s", ss.getId());
PropertiesService.getUserProperties().setProperty("legalese."+ss.getId()+".formActiveSheetId", sheet.getSheetId().toString());
fmLog("setting formActiveSheetId to %s", sheet.getSheetId().toString());
var origentityfields = readRows_._origentityfields;
fmLog("origentityfields = " + origentityfields);
for (var i in origentityfields) {
if (i == undefined) { continue }
var entityfield = origentityfields[i];
if (entityfield == undefined) { continue }
fmLog("entityfield "+i+" = " + entityfield.fieldname);
if (i == "undefined") { fmLog("that's, like, literally the string undefined, btw."); continue; } // yes, this actually happens.
if (entityfield.itemtype.match(/^list/)) {
var enums = entityfield.itemtype.split(' ');
enums.shift();
// TODO: get this out of the Data Validation https://developers.google.com/apps-script/reference/spreadsheet/data-validation
// instead of the Config section.
form.addListItem()
.setTitle(entityfield.fieldname)
.setRequired(entityfield.required)
.setChoiceValues(enums)
.setHelpText(entityfield.helptext);
}
else if (entityfield.itemtype.match(/^(email|number)/)) {
form.addTextItem()
.setTitle(entityfield.fieldname)
.setRequired(entityfield.required)
.setHelpText(entityfield.helptext);
// in the future, when Google Apps Scripts adds validation to its FormApp, validate the input as a valid email address or number as appropriate.
}
else if (entityfield.itemtype.match(/^paragraph/)) { // for the address field
form.addParagraphTextItem()
.setTitle(entityfield.fieldname)
.setRequired(entityfield.required)
.setHelpText(entityfield.helptext);
}
else if (entityfield.itemtype.match(/^text/)) {
form.addTextItem()
.setTitle(entityfield.fieldname)
.setRequired(entityfield.required)
.setHelpText(entityfield.helptext);
}
else if (entityfield.itemtype.match(/^hidden/)) {
// we don't want to display the Legalese Status field.
}
}
if (config["form_extras"] != undefined) {
for (var i in config.form_extras.values) {
var field = asvar_(config.form_extras.values[i]);
form.addListItem()
.setTitle(config[field].dict["name"][0])
.setRequired(config[field].dict["required"][0])
.setChoiceValues(config[field].dict["choicevalues"])
.setHelpText(config[field].dict["helptext"][0]);
}
}
var legalese_root = legaleseRootFolder_();
legalese_root.addFile(DriveApp.getFileById(form.getId()));
legalese_root.addFile(DriveApp.getFileById(ss.getId()));
fmLog("added to legalese root folder");
DriveApp.getRootFolder().removeFile(DriveApp.getFileById(form.getId()));
DriveApp.getRootFolder().removeFile(DriveApp.getFileById(ss.getId()));
var form_url = form.getPublishedUrl();
var short_url = form.shortenFormUrl(form_url);
return short_url;
}
// {
// "form_extras": {
// "asRange": {},
// "values": [
// "Party Types",
// "Second Element"
// ],
// "dict": {
// "party_types": [
// "Second Element"
// ]
// }
// },
// "party_types": {
// "asRange": {},
// "values": [
// "helptext",
// "Your role, please."
// ],
// "dict": {
// "name": [
// "Party Role"
// ],
// "choicevalues": [
// "Founder",
// "Company",
// "Investor",
// "Existing Shareholder"
// ],
// "required": [],
// "helptext": [
// "Your role, please."
// ]
// }
// },
// "second_element": {
// "asRange": {},
// "values": [
// "",
// "",
// " "
// ],
// "dict": {
// "boo": [],
// "": [
// "",
// " "
// ]
// }
// }
// }
// ---------------------------------------------------------------------------------------------------------------- onFormSubmit
/**
* A trigger-driven function that sends out calendar invitations and a
* personalized Google Docs itinerary after a user responds to the form.
*
* @param {Object} e The event parameter for form submission to a spreadsheet;
* see https://developers.google.com/apps-script/understanding_events
*/
function onFormSubmit(e, legaleseSignature) {
fmLog("onFormSubmit: beginning");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetId = PropertiesService.getUserProperties().getProperty("legalese."+ss.getId()+".formActiveSheetId");
if (sheetId == undefined) { // uh-oh
fmLog("onFormSubmit: no formActiveSheetId property, so I don't know which sheet to record party data into. bailing.");
return;
}
else {
fmLog("onFormSubmit: formActiveSheetId property = %s", sheetId);
}
var sheet = getSheetById_(SpreadsheetApp.getActiveSpreadsheet(), sheetId);
var entitiesByName = {}
var readRows_ = new readRows(sheet, entitiesByName);
var data = readRows_.terms;
var config = readRows_.config;
if (config.demo_mode) {
// delete any existing user lines, then add this new one.
var parties = roles2parties(readRows_);
if (parties.user) {
for (var pui = parties.user.length - 1; pui >=0; pui--) {
var party = parties.user[pui];
fmLog("onFormSubmit: demo_mode = true, so deleting existing party %s on row %s", party.name, party._spreadsheet_row);
sheet.deleteRow(party._spreadsheet_row);
}
SpreadsheetApp.flush();
// reread.
readRows_ = new readRows(sheet, entitiesByName);
data = readRows_.terms;
config = readRows_.config;
}
}
// add a row and insert the received fields
fmLog("onFormSubmit: inserting a row after " + (parseInt(readRows_._last_entity_row)+1));
sheet.insertRowAfter(readRows_._last_entity_row+1); // might need to update the commitment sum range
var newrow = sheet.getRange(readRows_._last_entity_row+2,1,1,sheet.getMaxColumns());
// newrow.getCell(0,0).setValue("bar");
// loop through the origentityfields inserting the new data in the right place.
for (names in e.namedValues) {
fmLog("onFormSubmit: e.namedValues = " + names + ": "+e.namedValues[names][0]);
}
var origentityfields = readRows_._origentityfields;
fmLog("onFormSubmit: origentityfields = " + origentityfields);
for (var i = 0; i < origentityfields.length; i++) {
var entityfield = origentityfields[i];
// fill in the default party role
if (i == 0 && entityfield == undefined) {
entityfield = { fieldname: "_party_role", column: 1 };
e.namedValues["_party_role"] = [ config.default_party_role ? config.default_party_role.value : "" ];
fmLog("setting default party row in column 1 to %s", e.namedValues["_party_role"]);
}
else if (entityfield == undefined) { fmLog("entityfield %s is undefined!", i); continue; }
// fill in any fields which are hidden and have a default value configured. maybe in future we should extend the default-filling to all blank submissions
else if (e.namedValues[entityfield.fieldname] == undefined) {
fmLog("did not receive form submission for %s", entityfield.fieldname);
if (entityfield["default"] != undefined) {
fmLog("filling with default value %s", entityfield["default"]);
e.namedValues[entityfield.fieldname] = [ entityfield["default"] ];
}
else {
continue;
}
}
// TODO: set the time and date of submission if there is a timestamp
fmLog("onFormSubmit: entityfield "+i+" (" + entityfield.fieldname+") (column="+entityfield.column+") = " + e.namedValues[entityfield.fieldname][0]);
var newcell = newrow.getCell(1,parseInt(entityfield.column));
fmLog("onFormSubmit: setting value of cell to " + e.namedValues[entityfield.fieldname]);
newcell.setValue(e.namedValues[entityfield.fieldname][0]);
}
if (config.demo_mode) {
fmLog("onFormSubmit: demo_mode = TRUE ... will proceed to create templates and mail out");
fillTemplates(sheet);
fmLog("onFormSubmit: demo_mode = TRUE ... fillTemplates() completed. next we should inject into echosign.");
SpreadsheetApp.flush();
if (legaleseSignature) {
fmLog("onFormSubmit: demo_mode = TRUE ... injecting into echosign. but first we will sleep for 3 minutes.");
// we might have to move this to a separate run loop
// because sometimes the InDesign script is busy and will take more than 3 minutes to produce results.
Utilities.sleep(1000*60*3);
fmLog("onFormSubmit: demo_mode = TRUE ... injecting into echosign by calling uploadAgreement().");
legaleseSignature.uploadAgreement(sheet, false);
}
else {
fmLog("onFormSubmit: demo_mode = TRUE ... but the legaleseSignature library is not available, so no echosign.");
}
}
}
function formActiveSheetChanged_(sheet) {
var formActiveSheetId = PropertiesService.getUserProperties().getProperty("legalese."+sheet.getParent().getId()+".formActiveSheetId");
if (formActiveSheetId == undefined) { return false }
if ( sheet == undefined) { return false }
if (sheet.getParent().getFormUrl() == undefined) { return false }
return (formActiveSheetId != sheet.getSheetId());
}
function muteFormActiveSheetWarnings_(setter) {
if (setter == undefined) { // getter
var myprop = PropertiesService.getDocumentProperties().getProperty("legalese.muteFormActiveSheetWarnings");
if (myprop != undefined) {
return JSON.parse(myprop);
}
else {
return false;
}
}
else {
PropertiesService.getDocumentProperties().setProperty("legalese.muteFormActiveSheetWarnings", JSON.stringify(setter));
}
}
// for the controller
// ---------------------------------------------------------------------------------------------------------------- setupOtherForms_
function setupOtherForms_() {
var sheets = otherSheets();
for (var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
var shortUrl = setupForm(sheet);
var myRow = SpreadsheetApp.getActiveRange().getSheet().getRange(SpreadsheetApp.getActiveRange().getRow()+i, 1, 1, 10);
fmLog("smoochy says setupOtherForms_: sheet %s is on row %s", i.toString(), myRow.getRowIndex().toString());
myRow.getCell(1,7).setValue(shortUrl);
}
}