Passed
Push — master ( fa41e0...4bd63f )
by Daniel
07:07 queued 12s
created

js/admin.js   B

Complexity

Total Complexity 49
Complexity/F 1.36

Size

Lines of Code 394
Function Count 36

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 49
eloc 180
c 0
b 0
f 0
dl 0
loc 394
rs 8.48
mnd 13
bc 13
fnc 36
bpm 0.361
cpm 1.3611
noi 0

How to fix   Complexity   

Complexity

Complex classes like js/admin.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * CMS Pico - Create websites using Pico CMS for Nextcloud.
3
 *
4
 * @copyright Copyright (c) 2017, Maxence Lange (<[email protected]>)
5
 * @copyright Copyright (c) 2019, Daniel Rudolf (<[email protected]>)
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/** global: OC */
24
/** global: OCA */
25
/** global: jQuery */
26
27
(function (document, $, OC, OCA) {
28
	'use strict';
29
30
	/**
31
	 * @class
32
	 * @extends OCA.CMSPico.List
33
	 *
34
	 * @param {jQuery}        $element
35
	 * @param {Object}        [options]
36
	 * @param {string}        [options.route]
37
	 * @param {jQuery|string} [options.template]
38
	 * @param {jQuery|string} [options.systemTemplate]
39
	 * @param {jQuery|string} [options.customTemplate]
40
	 * @param {jQuery|string} [options.newTemplate]
41
	 * @param {jQuery|string} [options.copyTemplate]
42
	 * @param {jQuery|string} [options.loadingTemplate]
43
	 * @param {jQuery|string} [options.errorTemplate]
44
	 */
45
	OCA.CMSPico.AdminList = function ($element, options) {
46
		this.initialize($element, options);
47
	};
48
49
	/**
50
	 * @lends OCA.CMSPico.AdminList.prototype
51
	 */
52
	OCA.CMSPico.AdminList.prototype = $.extend({}, OCA.CMSPico.List.prototype, {
53
		/** @member {Object[]|string[]} */
54
		staticItems: [],
55
56
		/** @member {Object[]|string[]} */
57
		systemItems: [],
58
59
		/** @member {Object[]|string[]} */
60
		customItems: [],
61
62
		/** @member {Object[]|string[]} */
63
		newItems: [],
64
65
		/** @member {jQuery} */
66
		$staticTemplate: $(),
67
68
		/** @member {jQuery} */
69
		$systemTemplate: $(),
70
71
		/** @member {jQuery} */
72
		$customTemplate: $(),
73
74
		/** @member {jQuery} */
75
		$newTemplate: $(),
76
77
		/** @member {jQuery} */
78
		$copyTemplate: $(),
79
80
		/**
81
		 * @constructs
82
		 *
83
		 * @param {jQuery}        $element
84
		 * @param {Object}        [options]
85
		 * @param {string}        [options.route]
86
		 * @param {jQuery|string} [options.template]
87
		 * @param {jQuery|string} [options.staticTemplate]
88
		 * @param {jQuery|string} [options.systemTemplate]
89
		 * @param {jQuery|string} [options.customTemplate]
90
		 * @param {jQuery|string} [options.newTemplate]
91
		 * @param {jQuery|string} [options.copyTemplate]
92
		 * @param {jQuery|string} [options.loadingTemplate]
93
		 * @param {jQuery|string} [options.errorTemplate]
94
		 */
95
		initialize: function ($element, options) {
96
			OCA.CMSPico.List.prototype.initialize.apply(this, arguments);
97
98
			options = $.extend({
99
				staticTemplate: $element.data('staticTemplate'),
100
				systemTemplate: $element.data('systemTemplate'),
101
				customTemplate: $element.data('customTemplate'),
102
				newTemplate: $element.data('newTemplate'),
103
				copyTemplate: $element.data('copyTemplate')
104
			}, options);
105
106
			this.$staticTemplate = $(options.staticTemplate);
107
			this.$systemTemplate = $(options.systemTemplate);
108
			this.$customTemplate = $(options.customTemplate);
109
			this.$newTemplate = $(options.newTemplate);
110
			this.$copyTemplate = $(options.copyTemplate);
111
112
			var signature = 'OCA.CMSPico.AdminList.initialize()';
113
			if (!this.$systemTemplate.length) {
114
				throw signature + ': No valid system item template given';
115
			}
116
			if (!this.$customTemplate.length) {
117
				throw signature + ': No valid custom item template given';
118
			}
119
120
			this._initStaticItems();
121
		},
122
123
		/**
124
		 * @protected
125
		 */
126
		_initStaticItems: function () {
127
			var $content = this.$staticTemplate.octemplate() || $(),
128
				filter = this.$staticTemplate.data('filter') || '*',
129
				that = this;
130
131
			this.staticItems = [];
132
			$content.filter(filter).each(function () {
133
				var $itemTemplate = $(this),
134
					itemData = {};
135
136
				if (that.$staticTemplate.data('replaces')) {
137
					$itemTemplate.data('replaces', that.$staticTemplate.data('replaces'));
138
				}
139
				if (that.$staticTemplate.data('appendTo')) {
140
					$itemTemplate.data('appendTo', that.$staticTemplate.data('appendTo'));
141
				}
142
143
				$.each($itemTemplate.data(), function (key, value) {
144
					if (key.substr(0, 4) === 'item') {
145
						key = key[4].toLowerCase() + key.substr(5);
146
						itemData[key] = value;
147
					}
148
				});
149
150
				that.staticItems.push({
151
					'$itemTemplate': $itemTemplate,
152
					'itemData': itemData
153
				});
154
			});
155
		},
156
157
		/**
158
		 * @public
159
		 *
160
		 * @param {Object}            data
161
		 * @param {Object[]|string[]} data.systemItems
162
		 * @param {Object[]|string[]} data.customItems
163
		 * @param {Object[]|string[]} data.newItems
164
		 */
165
		update: function (data) {
166
			var that = this;
167
168
			this.systemItems = data.systemItems;
169
			this.customItems = data.customItems;
170
			this.newItems = data.newItems;
171
172
			this._content(this.$template);
173
174
			$.each(this.staticItems, function (_, data) {
175
				var $item = that._content(data.$itemTemplate, data.itemData);
176
				that._setupItem($item, data.itemData);
177
			});
178
179
			$.each(this.systemItems, function (_, value) {
180
				var itemData = (typeof value === 'object') ? value : { name: value },
181
					$item = that._content(that.$systemTemplate, itemData);
182
				that._setupItem($item, itemData);
183
			});
184
185
			$.each(this.customItems, function (_, value) {
186
				var itemData = (typeof value === 'object') ? value : { name: value },
187
					$item = that._content(that.$customTemplate, itemData);
188
				that._setupItem($item, itemData);
189
			});
190
191
			$.each(this.newItems, function (_, value) {
192
				var itemData = (typeof value === 'object') ? value : { name: value },
193
					$item = that._content(that.$newTemplate, itemData);
194
				that._setupItem($item, itemData);
195
			});
196
197
			this._setup();
198
		},
199
200
		/**
201
		 * @protected
202
		 */
203
		_setup: function () {
204
			var $newItem = this.$element.find('.action-new-item'),
205
				$newItemButton = this.$element.find('.action-new'),
206
				that = this;
207
208
			if ($newItem.val()) {
209
				$newItemButton.on('click.CMSPicoAdminList', function (event) {
210
					that._api('POST', '', { item: $newItem.val() });
211
				});
212
			} else {
213
				$newItemButton.add($newItem).prop('disabled', true);
214
			}
215
216
			this.$element.find('.action-reload').on('click.CMSPicoAdminList', function (event) {
217
				that.reload();
218
			});
219
		},
220
221
		/**
222
		 * @protected
223
		 *
224
		 * @param {jQuery}  $item
225
		 * @param {Object}  itemData
226
		 * @param {string}  itemData.name
227
		 * @param {boolean} [itemData.compat]
228
		 * @param {string}  [itemData.compatReason]
229
		 * @param {Object}  [itemData.compatReasonData]
230
		 */
231
		_setupItem: function ($item, itemData) {
232
			var that = this;
233
234
			$item.find('.info-compat').each(function () {
235
				var $this = $(this),
236
					$icon = $this.find('[class^="icon-"], [class*=" icon-"]'),
237
					compat = (itemData.compat === undefined) || !!itemData.compat;
238
239
				$this.data('value', compat);
240
241
				$icon
242
					.addClass(compat ? 'icon-checkmark' : 'icon-error-color')
243
					.removeClass(compat ? 'icon-error-color' : 'icon-checkmark');
244
245
				if ($icon.hasClass('has-tooltip')) {
246
					var compatReason = $icon.prop('title') || '';
247
					if (itemData.compatReason) {
248
						var rawCompatReason = OCA.CMSPico.Util.unescape(itemData.compatReason);
249
						compatReason = t('cms_pico', rawCompatReason, itemData.compatReasonData);
250
					}
251
252
					$icon
253
						.tooltip('dispose')
254
						.attr('title', compatReason)
255
						.tooltip();
256
				}
257
			});
258
259
			$item.find('.action-sync').on('click.CMSPicoAdminList', function (event) {
260
				that._api('POST', itemData.name);
261
			});
262
263
			$item.find('.action-copy').each(function () {
264
				var $this = $(this);
265
266
				var dialog = new OCA.CMSPico.Dialog(that.$copyTemplate, {
267
					title: $this.data('originalTitle') || $this.prop('title') || $this.text(),
268
					templateData: { source: itemData.name },
269
					buttons: [
270
						{ type: OCA.CMSPico.Dialog.BUTTON_ABORT },
271
						{
272
							type: OCA.CMSPico.Dialog.BUTTON_SUBMIT,
273
							text: t('cms_pico', 'Copy')
274
						}
275
					]
276
				});
277
278
				dialog.on('open.CMSPicoAdminList', function () {
279
					this.$element.find('.input-name').focus();
280
				});
281
282
				dialog.on('submit.CMSPicoAdminList', function () {
283
					var value = this.$element.find('.input-name').val();
284
					that._api('CLONE', itemData.name, { name: value });
285
				});
286
287
				$this.on('click.CMSPicoAdminList', function (event) {
288
					dialog.open();
289
				});
290
			});
291
292
			$item.find('.action-delete').on('click.CMSPicoAdminList', function (event) {
293
				that._api('DELETE', itemData.name);
294
			});
295
		}
296
	});
297
298
	$('.picocms-admin-list').each(function () {
299
		var $this = $(this),
300
			adminList = new OCA.CMSPico.AdminList($this);
301
302
		$this.data('CMSPicoAdminList', adminList);
303
		adminList.reload();
304
	});
305
306
	/**
307
	 * @class
308
	 * @extends OCA.CMSPico.Form
309
	 *
310
	 * @param {jQuery} $element
311
	 * @param {Object} [options]
312
	 * @param {string} [options.route]
313
	 */
314
	OCA.CMSPico.LimitGroupsForm = function ($element, options) {
315
		this.initialize($element, options);
316
	};
317
318
	/**
319
	 * @lends OCA.CMSPico.LimitGroupsForm.prototype
320
	 */
321
	OCA.CMSPico.LimitGroupsForm.prototype = $.extend({}, OCA.CMSPico.Form.prototype, {
322
		/**
323
		 * @public
324
		 */
325
		prepare: function () {
326
			var that = this,
327
				$input = this.$element.find('input');
328
329
			// loading order is crucial - and Nextcloud loads its own JS settings files last... m(
330
			$(function () {
331
				OC.Settings.setupGroupsSelect($input);
332
333
				$input.on('change.CMSPicoLimitGroupsForm', function (event) {
334
					that.submit();
335
				});
336
			});
337
		},
338
339
		/**
340
		 * @public
341
		 */
342
		submit: function () {
343
			var $input = this.$element.find(':input'),
344
				data = this.$element.serialize();
345
346
			$input.prop('disabled', true);
347
348
			$.ajax({
349
				method: 'POST',
350
				url: OC.generateUrl(this.route),
351
				data: data
352
			}).done(function (data, textStatus, jqXHR) {
353
				$input.prop('disabled', false);
354
			});
355
		}
356
	});
357
358
	$('.picocms-limit_groups-form').each(function () {
359
		var $this = $(this),
360
			limitGroupsForm = new OCA.CMSPico.LimitGroupsForm($this);
361
362
		$this.data('CMSPicoLimitGroupsForm', limitGroupsForm);
363
		limitGroupsForm.prepare();
364
	});
365
366
	/**
367
	 * @class
368
	 * @extends OCA.CMSPico.Form
369
	 *
370
	 * @param {jQuery} $element
371
	 * @param {Object} [options]
372
	 * @param {string} [options.route]
373
	 */
374
	OCA.CMSPico.LinkModeForm = function ($element, options) {
375
		this.initialize($element, options);
376
	};
377
378
	/**
379
	 * @lends OCA.CMSPico.LinkModeForm.prototype
380
	 */
381
	OCA.CMSPico.LinkModeForm.prototype = $.extend({}, OCA.CMSPico.Form.prototype, {
382
		/**
383
		 * @public
384
		 */
385
		prepare: function () {
386
			var that = this,
387
				$input = this.$element.find('input[type="radio"]');
388
389
			$input.on('change.CMSPicoLinkModeForm', function (event) {
390
				that.submit();
391
			});
392
		},
393
394
		/**
395
		 * @public
396
		 */
397
		submit: function () {
398
			var $input = this.$element.find(':input'),
399
				data = this.$element.serialize();
400
401
			$input.prop('disabled', true);
402
403
			$.ajax({
404
				method: 'POST',
405
				url: OC.generateUrl(this.route),
406
				data: data
407
			}).done(function (data, textStatus, jqXHR) {
408
				$input.prop('disabled', false);
409
			});
410
		}
411
	});
412
413
	$('.picocms-link_mode-form').each(function () {
414
		var $this = $(this),
415
			linkModeForm = new OCA.CMSPico.LinkModeForm($this);
416
417
		$this.data('CMSPicoLinkModeForm', linkModeForm);
418
		linkModeForm.prepare();
419
	});
420
})(document, jQuery, OC, OCA);
421