Skip to content

Commit 1da5c19

Browse files
committed
Allow sub views to hide destroy button in EditConfigurationView
Sub views can now optionally hide the destroy button by setting the hideDestroyButton property to true or implementing it as a function that returns a boolean. This provides more flexibility for configuration views that shouldn't allow deletion in certain contexts. The implementation maintains backward compatibility - all existing views continue to show the destroy button by default. REDMINE-20979
1 parent 60d3467 commit 1da5c19

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

package/spec/editor/views/EditConfigurationView-spec.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,83 @@ describe('EditConfigurationView', () => {
272272
expect(view.$el.find('.back').text()).toBe('Back');
273273
});
274274
});
275+
276+
describe('hideDestroyButton', () => {
277+
it('shows destroy button by default', () => {
278+
const Model = Backbone.Model.extend({
279+
mixins: [configurationContainer(), failureTracking]
280+
});
281+
const View = EditConfigurationView.extend({
282+
configure(configurationEditor) {
283+
configurationEditor.tab('general', function() {
284+
});
285+
}
286+
});
287+
288+
const view = new View({model: new Model()}).render();
289+
290+
expect(view.$el.find('.destroy')).toHaveLength(1);
291+
});
292+
293+
it('hides destroy button when hideDestroyButton is true', () => {
294+
const Model = Backbone.Model.extend({
295+
mixins: [configurationContainer(), failureTracking]
296+
});
297+
const View = EditConfigurationView.extend({
298+
hideDestroyButton: true,
299+
300+
configure(configurationEditor) {
301+
configurationEditor.tab('general', function() {
302+
});
303+
}
304+
});
305+
306+
const view = new View({model: new Model()}).render();
307+
308+
expect(view.$el.find('.destroy')).toHaveLength(0);
309+
});
310+
311+
it('supports hideDestroyButton as function', () => {
312+
const Model = Backbone.Model.extend({
313+
mixins: [configurationContainer(), failureTracking]
314+
});
315+
const View = EditConfigurationView.extend({
316+
hideDestroyButton() {
317+
return this.model.get('preventDestroy');
318+
},
319+
320+
configure(configurationEditor) {
321+
configurationEditor.tab('general', function() {
322+
});
323+
}
324+
});
325+
326+
const viewWithDestroy = new View({model: new Model({preventDestroy: false})}).render();
327+
const viewWithoutDestroy = new View({model: new Model({preventDestroy: true})}).render();
328+
329+
expect(viewWithDestroy.$el.find('.destroy')).toHaveLength(1);
330+
expect(viewWithoutDestroy.$el.find('.destroy')).toHaveLength(0);
331+
});
332+
333+
it('does not prevent destroy event handler when button is shown', () => {
334+
const Model = Backbone.Model.extend({
335+
mixins: [configurationContainer(), failureTracking],
336+
destroyWithDelay: jest.fn()
337+
});
338+
const View = EditConfigurationView.extend({
339+
hideDestroyButton: false,
340+
341+
configure(configurationEditor) {
342+
configurationEditor.tab('general', function() {
343+
});
344+
}
345+
});
346+
347+
const view = new View({model: new Model()}).render();
348+
window.confirm = () => true;
349+
view.$el.find('.destroy').click();
350+
351+
expect(view.model.destroyWithDelay).toHaveBeenCalled();
352+
});
353+
});
275354
});

package/src/editor/views/EditConfigurationView.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ import {editor} from '../base';
4242
* Override the `goBackPath` property or method to customize the path
4343
* that the back button navigates to. Defaults to `/`.
4444
*
45+
* Set the `hideDestroyButton` property to `true` to hide the destroy
46+
* button.
47+
*
4548
* @param {Object} options
4649
* @param {Backbone.Model} options.model -
4750
* Model including the {@link configurationContainer},
@@ -52,9 +55,9 @@ import {editor} from '../base';
5255
export const EditConfigurationView = Marionette.Layout.extend({
5356
className: 'edit_configuration_view',
5457

55-
template: ({t, backLabel}) => `
58+
template: ({t, backLabel, hideDestroyButton}) => `
5659
<a class="back">${backLabel}</a>
57-
<a class="destroy">${t('destroy')}</a>
60+
${hideDestroyButton ? '' : `<a class="destroy">${t('destroy')}</a>`}
5861
5962
<div class="failure">
6063
<p>${t('save_error')}</p>
@@ -68,7 +71,8 @@ export const EditConfigurationView = Marionette.Layout.extend({
6871
serializeData() {
6972
return {
7073
t: key => this.t(key),
71-
backLabel: this.getBackLabel()
74+
backLabel: this.getBackLabel(),
75+
hideDestroyButton: _.result(this, 'hideDestroyButton')
7276
};
7377
},
7478

0 commit comments

Comments
 (0)