-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstudentmatrix-globalactions.js
195 lines (167 loc) · 7.85 KB
/
studentmatrix-globalactions.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
/**
* @file
* Module that allows global actions to be run, on the master sheet or so.
* Introduces the 'globalActions' component. @TODO: This module is mainly copied from the
* StudentActions module -- in a perfect world there would be code reuse instead.
*/
// Menu alias: Dialog for running actions on students.
function StudentMatrixMenu_globalActions() {
StudentMatrix.modules.globalActions.actionsDialog();
};
// Declares the GlobalActions module.
StudentMatrix.modules.globalActions = {
name : 'Global actions',
description : 'Provides a UI for running global actions in StudentMatrix.',
version : '1.2',
required : true,
updateUrl : 'https://raw.github.com/Itangalo/studentmatrix/3.x/studentmatrix-globalactions.js',
cell : 'D6',
dependencies : {
core : '3.2',
},
// Declares all menu entries for this module.
menuEntries : {
globalActions : {
name : 'Run global actions',
weight : 15,
},
},
// Declare required properties for components of type 'globalActions'.
properties : {
name : 'string',
group : 'string',
description : 'string',
processor : 'function',
},
// Displays dialog for running globalActions. Starting point for this module.
actionsDialog : function() {
StudentMatrix.loadComponents('globalActions');
var app = UiApp.createApplication().setTitle('Run global actions');
var descriptionHandler = StudentMatrix.addModuleHandler('globalActions', 'showDescriptions');
// Build a select list of the actions, by group.
var actionsList = app.createListBox().setId('SelectedAction').setName('SelectedAction');
var componentList = StudentMatrix.getComponentsByGroup('globalActions');
for (group in componentList) {
actionsList.addItem('-- ' + group + ' --', null);
for (component in componentList[group]) {
actionsList.addItem(componentList[group][component], component);
}
}
actionsList.addChangeHandler(descriptionHandler);
app.add(actionsList);
// Add two elements for description and help link, to be populated later.
app.add(app.createLabel('', true).setId('ActionDescription'));
app.add(app.createAnchor('', false, '').setId('ActionHelpLink'));
// Add the button for running actions.
var optionsHandler = StudentMatrix.addModuleHandler('globalActions', 'optionsHandler');
optionsHandler.addCallbackElement(actionsList);
app.add(app.createButton('Run the action', optionsHandler).setId('Process').setEnabled(false));
// We also have spot for an error message, should there be one.
app.add(app.createLabel('', true).setId('ErrorMessage'));
SpreadsheetApp.getActiveSpreadsheet().show(app);
return app;
},
// Handler for updating descriptions and help link for selected actions.
showDescriptions : function(eventInfo) {
StudentMatrix.loadComponents('globalActions');
var component = eventInfo.parameter.SelectedAction;
var app = UiApp.getActiveApplication();
// Fetch and reset some texts in the form.
var description = app.getElementById('ActionDescription');
var helpLink = app.getElementById('ActionHelpLink');
var errorMessage = app.getElementById('ErrorMessage');
description.setText('');
helpLink.setHTML('');
errorMessage.setText('');
// If the selected action is actually a group, disable button and quit.
if (component == 'null') {
app.getElementById('Process').setEnabled(false);
return app;
}
// Set description and help links, if available.
if (typeof StudentMatrix.components.globalActions[component].description == 'string') {
description.setText(StudentMatrix.components.globalActions[component].description);
}
if (typeof StudentMatrix.components.globalActions[component].helpLink == 'string') {
helpLink.setHref(StudentMatrix.components.globalActions[component].helpLink).setHTML('Help page<br />');
}
// Run basic validator on the component, if available.
if (typeof StudentMatrix.components.globalActions[component].validator == 'function') {
if (StudentMatrix.components.globalActions[component].validator() != null) {
errorMessage.setText('Cannot run action: ' + StudentMatrix.components.globalActions[component].validator());
app.getElementById('Process').setEnabled(false);
return app;
}
}
// All systems go. Enable the ok button.
app.getElementById('Process').setEnabled(true);
return app;
},
// Displays any options for an action, before running it.
optionsHandler : function(eventInfo) {
var app = UiApp.getActiveApplication();
// Get the component to run.
var component = eventInfo.parameter.SelectedAction;
// Check for an options builder for the component. If found, display a form with options.
StudentMatrix.loadComponents('globalActions');
if (typeof StudentMatrix.components.globalActions[component].optionsBuilder == 'function') {
// Options may overfill the normal popup, so we need a panel container.
var wrapper = app.createScrollPanel().setWidth('100%').setHeight('100%').setAlwaysShowScrollBars(true);
var panel = app.createVerticalPanel();
wrapper.add(panel);
// Create a handler and call the options builder to add any form elements.
var handler = StudentMatrix.addModuleHandler('globalActions', 'optionsProcessor');
StudentMatrix.components.globalActions[component].optionsBuilder(handler, panel);
// Add the component as a hidden widgets, to pass on the information.
var componentWidget = app.createHidden('component', component).setId('component');
handler.addCallbackElement(componentWidget);
panel.add(componentWidget);
panel.add(app.createHTML('<hr />'));
panel.add(app.createButton('Cancel', handler).setId('Cancel'));
panel.add(app.createButton('OK', handler).setId('OK'));
app.add(wrapper);
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
// If no options builder is found, just call the action execution method without any options.
else {
this.componentExecute(component);
}
},
// Handler for the componentOptionsDialog, allowing OK and Cancel.
optionsProcessor : function(eventInfo) {
// If it wasn't the OK button being clicked, close the dialog -- we're done.
if (eventInfo.parameter.source != 'OK') {
UiApp.getActiveApplication().close();
return UiApp.getActiveApplication();
}
// If it was the OK button that was clicked: build options and call the action.
else {
StudentMatrix.loadComponents('globalActions');
var app = UiApp.getActiveApplication();
var component = eventInfo.parameter.component;
// If there is an optionsProcessor declared in the component, use it.
if (typeof StudentMatrix.components.globalActions[component].optionsProcessor == 'function') {
var options = StudentMatrix.components.globalActions[component].optionsProcessor(eventInfo);
}
// If no optionsProcessor was found, just look for values for the declared options.
else {
// Load default options from the action component, overwrite with any set in the eventInfo.
var options = StudentMatrix.components.globalActions[component].options;
for (var option in StudentMatrix.components.globalActions[component].options) {
options[option] = eventInfo.parameter[option];
}
}
// Execute the action with the given options, in the given mode.
this.componentExecute(component, options);
return app;
}
},
// Calls the actual action and runs it.
componentExecute : function(component, options) {
// This process may be slow, so it makes sense to display a message while processing.
StudentMatrix.toast('Running action...');
UiApp.getActiveApplication().close();
StudentMatrix.components.globalActions[component].processor(options);
StudentMatrix.toast('Action completed.');
},
};