View | Details | Raw Unified | Return to bug 26374 | Differences between
and this patch

Collapse All | Expand All

(-)univention-management-console/src/univention/management/console/protocol/modserver.py (+1 lines)
 Lines 100-105    Link Here 
100
100
101
	def _timed_out( self ):
101
	def _timed_out( self ):
102
		MODULE.info( "Commiting suicide" )
102
		MODULE.info( "Commiting suicide" )
103
		self.__handler.destroy()
103
		self.exit()
104
		self.exit()
104
		sys.exit( 0 )
105
		sys.exit( 0 )
105
106
(-)univention-management-console/src/univention/management/console/modules/__init__.py (+5 lines)
 Lines 87-92    Link Here 
87
		that passes the base configuration to the module process'''
87
		that passes the base configuration to the module process'''
88
		pass
88
		pass
89
89
90
	def destroy( self ):
91
		'''this function is invoked before before the module process is
92
		exiting.'''
93
		pass
94
90
	def execute( self, method, request ):
95
	def execute( self, method, request ):
91
		self.__requests[ request.id ] = ( request, method )
96
		self.__requests[ request.id ] = ( request, method )
92
97
(-)univention-management-console-frontend/umc/widgets/StandbyMixin.js (-10 / +28 lines)
 Lines 41-52    Link Here 
41
41
42
	standbyOpacity: 0.75,
42
	standbyOpacity: 0.75,
43
43
44
	uninitialize: function() {
44
	_lastContent: null,
45
		this.inherited(arguments);
46
45
47
		this._standbyWidget.destroy();
48
	},
49
50
	buildRendering: function() {
46
	buildRendering: function() {
51
		this.inherited(arguments);
47
		this.inherited(arguments);
52
48
 Lines 62-87    Link Here 
62
		this._standbyWidget.startup();
58
		this._standbyWidget.startup();
63
	},
59
	},
64
60
61
	_cleanUp: function() {
62
		if (this._lastContent && this._lastContent.declaredClass && this._lastContent.domNode) {
63
			// we got a widget as last element, remove it from the DOM
64
			try {
65
				this._standbyWidget._textNode.removeChild(this._lastContent.domNode);
66
			}
67
			catch(e) {
68
				console.log('Could remove standby widget from DOM:', e);
69
			}
70
			this._lastContent = null;
71
		}
72
	},
73
65
	_updateContent: function(content) {
74
	_updateContent: function(content) {
66
		// type check of the content
75
		// type check of the content
67
		if (dojo.isString(content)) {
76
		if (dojo.isString(content)) {
68
			// string
77
			// string
78
			this._cleanUp();
69
			this._standbyWidget.set('text', content);
79
			this._standbyWidget.set('text', content);
70
			this._standbyWidget.set('centerIndicator', 'text');
80
			this._standbyWidget.set('centerIndicator', 'text');
71
		}
81
		}
72
		else if (dojo.isObject(content) && content.declaredClass && content.domNode) {
82
		else if (dojo.isObject(content) && content.declaredClass && content.domNode) {
73
			// widget
83
			// widget
74
			this._standbyWidget.set('text', '');
84
			if (!this._lastContent || this._lastContent != content) {
75
			this._standbyWidget.set('centerIndicator', 'text');
85
				// we only need to add a new widget to the DOM
86
				this._cleanUp();
87
				this._standbyWidget.set('text', '');
88
				this._standbyWidget.set('centerIndicator', 'text');
76
89
77
			// hook the given widget to the text node
90
				// hook the given widget to the text node
78
			dojo.place(content.domNode, this._standbyWidget._textNode);
91
				dojo.place(content.domNode, this._standbyWidget._textNode);
79
			content.startup();
92
				content.startup();
93
			}
80
		}
94
		}
81
		else {
95
		else {
82
			// set default image
96
			// set default image
97
			this._cleanUp();
83
			this._standbyWidget.set('centerIndicator', 'image');
98
			this._standbyWidget.set('centerIndicator', 'image');
84
		}
99
		}
100
101
		// cache the widget
102
		this._lastContent = content;
85
	},
103
	},
86
104
87
	standby: function(/*Boolean*/ doStandby, /*mixed?*/ content) {
105
	standby: function(/*Boolean*/ doStandby, /*mixed?*/ content) {
(-)univention-management-console-frontend/umc/widgets/Uploader.js (-11 / +51 lines)
 Lines 106-112    Link Here 
106
106
107
	buildRendering: function() {
107
	buildRendering: function() {
108
		this.inherited(arguments);
108
		this.inherited(arguments);
109
		
109
110
		this._uploader = new dojox.form.Uploader({
110
		this._uploader = new dojox.form.Uploader({
111
			url: '/umcp/upload' + (this.command ? '/' + this.command : ''),
111
			url: '/umcp/upload' + (this.command ? '/' + this.command : ''),
112
			label: this.buttonLabel,
112
			label: this.buttonLabel,
 Lines 131-137    Link Here 
131
			this.addChild(this._clearButton);
131
			this.addChild(this._clearButton);
132
		}
132
		}
133
	},
133
	},
134
	
134
135
	postCreate: function() {
135
	postCreate: function() {
136
		this.inherited(arguments);
136
		this.inherited(arguments);
137
137
 Lines 144-167    Link Here 
144
			}, this);
144
			}, this);
145
			if (!allOk) {
145
			if (!allOk) {
146
				umc.dialog.alert(this._('File cannot be uploaded, its maximum size may be %.1f MB.', this.maxSize / 1048576.0));
146
				umc.dialog.alert(this._('File cannot be uploaded, its maximum size may be %.1f MB.', this.maxSize / 1048576.0));
147
				this._uploader.reset();
147
			}
148
			}
148
			else {
149
			else {
149
				this._updateLabel();
150
				dojo.when(this.canUpload(data[0]), dojo.hitch(this, function(doUpload) {
150
				this._uploader.upload({
151
					if (!doUpload) {
151
					iframe: (this._uploader.uploadType === 'iframe') ? true : false
152
						// upload canceled
152
				});
153
						this._uploader.reset();
154
						return;
155
					}
156
157
					// perform the upload
158
					this._updateLabel();
159
					this._uploader.upload({
160
						iframe: (this._uploader.uploadType === 'iframe') ? true : false
161
					});
162
					this.onUploadStarted(data[0]);
163
				}));
153
			}
164
			}
154
		});
165
		});
155
166
156
		// hook for showing the progress
167
		// hook for showing the progress
157
		/*this.connect(this._uploader, 'onProgress', function(data) {
168
		this.connect(this._uploader, 'onProgress', 'onProgress');
158
			console.log('onProgress:', dojo.toJson(data));
159
			this._updateLabel(data.percent);
160
		});*/
161
169
162
		// notification as soon as the file has been uploaded
170
		// notification as soon as the file has been uploaded
163
		this.connect(this._uploader, 'onComplete', function(data) {
171
		this.connect(this._uploader, 'onComplete', function(data) {
164
			this.set('data', data.result[0]);
172
			if (data && dojo.isArray(data.result)) {
173
				this.set('data', data.result[0]);
174
			}
175
			else {
176
				this.set('data', null);
177
			}
165
			this.onUploaded(this.data);
178
			this.onUploaded(this.data);
166
			this._resetLabel();
179
			this._resetLabel();
167
		});
180
		});
 Lines 199-204    Link Here 
199
	},
212
	},
200
213
201
	_resetLabel: function() {
214
	_resetLabel: function() {
215
		if (!this._uploader.button) {
216
			return;
217
		}
202
		this.set('disabled', false);
218
		this.set('disabled', false);
203
		this.set('buttonLabel', this._origButtonLabel);
219
		this.set('buttonLabel', this._origButtonLabel);
204
		this._uploader.reset();
220
		this._uploader.reset();
 Lines 213-223    Link Here 
213
	},
229
	},
214
230
215
	_setButtonLabelAttr: function(newVal) {
231
	_setButtonLabelAttr: function(newVal) {
232
		if (!this._uploader.button) {
233
			return;
234
		}
216
		this.buttonLabel = newVal;
235
		this.buttonLabel = newVal;
217
		this._uploader.button.set('label', newVal);
236
		this._uploader.button.set('label', newVal);
218
	},
237
	},
219
238
220
	_setDisabledAttr: function(newVal) {
239
	_setDisabledAttr: function(newVal) {
240
		if (!this._uploader.button) {
241
			return;
242
		}
221
		this._uploader.set('disabled', newVal);
243
		this._uploader.set('disabled', newVal);
222
		dojo.style(this._uploader.button.domNode, 'display', 'inline-block');
244
		dojo.style(this._uploader.button.domNode, 'display', 'inline-block');
223
	},
245
	},
 Lines 226-235    Link Here 
226
		return this._uploader.get('disabled');
248
		return this._uploader.get('disabled');
227
	},
249
	},
228
250
251
	canUpload: function(fileInfo) {
252
		// summary:
253
		//		Before uploading a file, this function is called to make sure
254
		//		that the given filename is valid. Return boolean or dojo.Deferred.
255
		// fileInfo: Object
256
		//		Info object for the requested file, contains properties 'name',
257
		//		'size', 'type'.
258
		return true;
259
	},
260
261
	onUploadStarted: function(fileInfo) {
262
		// event stub
263
	},
264
229
	onUploaded: function(data) {
265
	onUploaded: function(data) {
230
		// event stub
266
		// event stub
231
	},
267
	},
232
268
269
	onProgress: function(data) {
270
		// event stub
271
	},
272
233
	onChange: function(data) {
273
	onChange: function(data) {
234
		// event stub
274
		// event stub
235
	},
275
	},
(-)univention-management-console-frontend/umc/widgets/MultiUploader.js (+325 lines)
Line 0    Link Here 
1
/*
2
 * Copyright 2011 Univention GmbH
3
 *
4
 * http://www.univention.de/
5
 *
6
 * All rights reserved.
7
 *
8
 * The source code of this program is made available
9
 * under the terms of the GNU Affero General Public License version 3
10
 * (GNU AGPL V3) as published by the Free Software Foundation.
11
 *
12
 * Binary versions of this program provided by Univention to you as
13
 * well as other copyrighted, protected or trademarked materials like
14
 * Logos, graphics, fonts, specific documentations and configurations,
15
 * cryptographic keys etc. are subject to a license agreement between
16
 * you and Univention and not subject to the GNU AGPL V3.
17
 *
18
 * In the case you use this program under the terms of the GNU AGPL V3,
19
 * the program is provided in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public
25
 * License with the Debian GNU/Linux or Univention distribution in file
26
 * /usr/share/common-licenses/AGPL-3; if not, see
27
 * <http://www.gnu.org/licenses/>.
28
 */
29
/*global dojo dijit dojox umc console */
30
31
dojo.provide("umc.widgets.MultiUploader");
32
33
dojo.require("umc.widgets.ContainerWidget");
34
dojo.require("umc.i18n");
35
dojo.require("umc.widgets.Button");
36
dojo.require("umc.widgets.Uploader");
37
dojo.require("umc.widgets.MultiSelect");
38
dojo.require("umc.widgets.ProgressInfo");
39
dojo.require("umc.tools");
40
dojo.require("umc.dialog");
41
42
dojo.declare("umc.widgets.MultiUploader", [ umc.widgets.ContainerWidget, umc.widgets._FormWidgetMixin, umc.i18n.Mixin ], {
43
	'class': 'umcMultiUploader',
44
45
	i18nClass: 'umc.app',
46
47
	// command: String
48
	//		The UMCP command to which the data shall be uploaded.
49
	//		If not given, the data is sent to umcp/upload which will return the
50
	//		file content encoded as base64.
51
	command: '',
52
53
	// buttonLabel: String
54
	//		The label that is displayed on the upload button.
55
	buttonLabel: 'Upload',
56
57
	// value: String[]
58
	//		'value' contains an array of the uploaded file names.
59
	value: [],
60
61
	// maxSize: Number
62
	//		A size limit for the uploaded file.
63
	maxSize: 524288,
64
65
	// make sure that no sizeClass is being set
66
	sizeClass: null,
67
68
	// this form element should always be valid
69
	valid: true,
70
71
	/*=====
72
	// state: String
73
	//		Specifies in which state the widget is:
74
	//		'Complete' -> default,
75
	//		'Incomplete' -> uploads are not completed yet
76
	state: 'Complete',
77
	=====*/
78
79
	// internal reference to the MultiSelect widget containing all filenames
80
	_files: null,
81
82
	// internal reference to the current Uploader widget
83
	_uploader: null,
84
85
	// internal reference to the progress bar
86
	_progressBar: null,
87
88
	// button for removing entries
89
	_removeButton: null,
90
91
	// container for the upload and remove buttons
92
	_container: null,
93
94
	// internal reference to the currently uploading files
95
	_uploadingFiles: [],
96
97
	constructor: function() {
98
		this.buttonLabel = this._('Upload');
99
		this._uploadingFiles = [];
100
	},
101
102
	buildRendering: function() {
103
		this.inherited(arguments);
104
105
		// MultiSelect widget for displaying the file list
106
		this._files = new umc.widgets.MultiSelect({
107
			style: 'width: 50em'
108
		});
109
		this.addChild(this._files);
110
111
		this._createProgressBar();
112
113
		// prepare remove button and container for upload/remove buttons
114
		this._container = new umc.widgets.ContainerWidget({});
115
		this._container.addChild(new umc.widgets.Button({
116
			label: this._('Remove'),
117
			iconClass: 'umcIconDelete',
118
			onClick: dojo.hitch(this, '_removeFiles'),
119
			style: 'float: right;'
120
		}));
121
		this.addChild(this._container);
122
123
		// add the uploader button
124
		this._addUploader();
125
	},
126
127
	destroy: function() {
128
		this.inherited(arguments);
129
130
		if (this._progressBar) {
131
			// destroy the old progress bar
132
			this._progressBar.destroyRecursive();
133
		}
134
	},
135
136
	_getStateAttr: function() {
137
		return this._uploadingFiles.length ? 'Incomplete' : 'Complete';
138
	},
139
140
	_setValueAttr: function(newVal) {
141
		this._files.set('staticValues', newVal);
142
	},
143
144
	_getValueAttr: function() {
145
		return this._files.get('staticValues');
146
	},
147
148
	_setButtonLabelAttr: function(newVal) {
149
		this.buttonLabel = newVal;
150
		this._uploader.set('buttonLabel', newVal);
151
	},
152
153
	_setDisabledAttr: function(newVal) {
154
		this._files.set('disabled', newVal);
155
		this._uploader.set('disabled', newVal);
156
	},
157
158
	_getDisabledAttr: function() {
159
		return this._files.get('disabled');
160
	},
161
162
	_removeFiles: function() {
163
		var selectedFiles = this._files.get('value');
164
		if (!selectedFiles.length) {
165
			return;
166
		}
167
168
		// make sure we may remove the selected items
169
		dojo.when(this.canRemove(selectedFiles), dojo.hitch(this, function(doUpload) {
170
			if (!doUpload) {
171
				// removal canceled
172
				return;
173
			}
174
175
			// remove items
176
			var files = this.get('value');
177
			files = dojo.filter(files, function(ifile) {
178
				return dojo.indexOf(selectedFiles, ifile) < 0;
179
			});
180
			this.set('value', files);
181
		}));
182
	},
183
184
	_createProgressBar: function() {
185
		if (this._progressBar) {
186
			// destroy the old progress bar
187
			this._progressBar.destroyRecursive();
188
		}
189
190
		// create progress bar for displaying the upload information
191
		this._progressBar = new umc.widgets.ProgressInfo({
192
			maximum: 1
193
		});
194
		this._progressBar._progressBar.set('style', 'min-width: 30em;');
195
		this._progressBar.updateTitle(this._('No upload in progress'));
196
	},
197
198
	_updateProgress: function() {
199
		if (!this._progressBar) {
200
			return;
201
		}
202
203
		var currentVal = 0;
204
		var nDone = 0;
205
		dojo.forEach(this._uploadingFiles, function(ifile) {
206
			nDone += ifile.done || 0;
207
			currentVal += ifile.done ? 1.0 : ifile.decimal || 0;
208
		});
209
		currentVal = Math.min(currentVal / this._uploadingFiles.length, 0.99);
210
		if (!this._uploadingFiles.length || nDone == this._uploadingFiles.length) {
211
			// all uploads are finished
212
			this._progressBar.update(1, '', this._('Uploads finished'));
213
		}
214
		else {
215
			this._progressBar.update(currentVal, '', this._('Uploading... %d of %d files remaining.', this._uploadingFiles.length - nDone, this._uploadingFiles.length));
216
		}
217
	},
218
219
	_addUploader: function() {
220
		// create a new Uploader widget
221
		this._uploader = new umc.widgets.Uploader({
222
			showClearButton: false,
223
			buttonLabel: this.buttonLabel,
224
			command: this.command,
225
			maxSize: this.maxSize,
226
			canUpload: this.canUpload,
227
			style: 'float: left;'
228
		});
229
		this._container.addChild(this._uploader);
230
231
		// register events
232
		var uploader = this._uploader;
233
		var startedSignal = this.connect(uploader, 'onUploadStarted', function(file) {
234
			//console.log('### onUploadStarted:', dojo.toJson(file));
235
			this.disconnect(startedSignal);
236
237
			// add current file to the list of uploading items
238
			if (!this._uploadingFiles.length) {
239
				// first file being uploaded -> show the standby animation
240
				//this._createProgressBar();
241
				this._files.standby(true, this._progressBar);
242
			}
243
			this._uploadingFiles.push(file);
244
			this._updateProgress();
245
246
			var progressSignal = this.connect(uploader, 'onProgress', function(info) {
247
				// update progress information
248
				//console.log('### onProgress:', dojo.toJson(info));
249
				dojo.mixin(file, info);
250
				this._updateProgress();
251
			});
252
			var uploadSignal = this.connect(uploader, 'onUploaded', function() {
253
				// disconnect events
254
				//console.log('### onUploaded');
255
				this.disconnect(progressSignal);
256
				this.disconnect(uploadSignal);
257
258
				// update progress information
259
				file.done = true;
260
				this._updateProgress();
261
262
				// remove Uploader widget from container
263
				this.removeChild(uploader);
264
				uploader.destroyRecursive();
265
266
				// when all files are uploaded, update the internal list of files
267
				var allDone = true;
268
				dojo.forEach(this._uploadingFiles, function(ifile) {
269
					allDone = allDone && ifile.done;
270
				});
271
				if (allDone) {
272
					// add files to internal list of files
273
					this._files.standby(false);
274
					var vals = this.get('value');
275
					dojo.forEach(this._uploadingFiles, function(ifile) {
276
						//console.log('### adding:', ifile.name);
277
						vals.unshift(ifile.name);
278
					});
279
					this.set('value', vals);
280
281
					// clear the list of uploading files
282
					this._uploadingFiles = [];
283
				}
284
			});
285
286
			// hide uploader widget and add a new one
287
			dojo.style(uploader.domNode, {
288
				width: '0',
289
				overflow: 'hidden'
290
			});
291
			this._addUploader();
292
		});
293
	},
294
295
	canUpload: function(fileInfo) {
296
		// summary:
297
		//		Before uploading a file, this function is called to make sure
298
		//		that the given filename is valid. Return boolean or dojo.Deferred.
299
		// fileInfo: Object
300
		//		Info object for the requested file, contains properties 'name',
301
		//		'size', 'type'.
302
		return true;
303
	},
304
305
	canRemove: function(filenames) {
306
		// summary:
307
		//		Before removing a files from the current list, this function
308
		//		is called to make sure that the given file may be removed.
309
		//		Return boolean or dojo.Deferred.
310
		// filenames: String[]
311
		//		List of filenames.
312
		return true;
313
	},
314
315
	onUploaded: function(data) {
316
		// event stub
317
	},
318
319
	onChange: function(data) {
320
		// event stub
321
	}
322
});
323
324
325

Return to bug 26374