Test Setup Failed
Push — master ( d60e73...a71a5d )
by
unknown
04:37 queued 10s
created

ghlight   C

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 1
Ratio 11.11 %

Importance

Changes 0
Metric Value
cc 2
nc 2
dl 1
loc 9
rs 6.2142
c 0
b 0
f 0
nop 1
1
define(function(require) {
2
    'use strict';
3
4
    var TransitionEditView;
5
    var _ = require('underscore');
6
    var $ = require('jquery');
7
    var __ = require('orotranslation/js/translator');
8
    var BaseView = require('oroui/js/app/views/base/view');
9
    var DialogWidget = require('oro/dialog-widget');
10
    var helper = require('oroworkflow/js/tools/workflow-helper');
11
    var AttributeFormOptionEditView = require('../attribute/attribute-form-option-edit-view');
12
    var AttributeFormOptionListView = require('../attribute/attribute-form-option-list-view');
13
    require('jquery.validate');
14
15
    TransitionEditView = BaseView.extend({
16
        attributes: {
17
            'class': 'widget-content'
18
        },
19
20
        events: {
21
            'change [name=label]': 'updateExampleView',
22
            'change [name=button_label]': 'updateExampleView',
23
            'change [name=button_title]': 'updateExampleView',
24
            'change [name$="[transition_prototype_icon]"]': 'updateExampleView',
25
            'change [name=button_color]': 'updateExampleView',
26
            'change [name=display_type]': 'updateDestinationPageView'
27
        },
28
29
        options: {
30
            template: null,
31
            workflow: null,
32
            step_from: null,
33
            button_example_template: '<button type="button" class="btn <%- button_color %>" ' +
34
                'title="<%- button_title %>">' +
35
                '<% if (transition_prototype_icon) { %><i class="<%- transition_prototype_icon %>"/> <% } %>' +
36
                '<%- button_label %></button>',
37
            allowed_button_styles: [
38
                {
39
                    label: __('Gray button'),
40
                    name: ''
41
                },
42
                {
43
                    label: __('Navy blue button'),
44
                    name: 'btn-primary'
45
                },
46
                {
47
                    label: __('Blue button'),
48
                    name: 'btn-info'
49
                },
50
                {
51
                    label: __('Green button'),
52
                    name: 'btn-success'
53
                },
54
                {
55
                    label: __('Yellow button'),
56
                    name: 'btn-warning'
57
                },
58
                {
59
                    label: __('Red button'),
60
                    name: 'btn-danger'
61
                },
62
                {
63
                    label: __('Black button'),
64
                    name: 'btn-inverse'
65
                },
66
                {
67
                    label: __('Link'),
68
                    name: 'btn-link'
69
                }
70
            ]
71
        },
72
73
        requiredOptions: ['workflow', 'entityFieldsProvider'],
74
75
        listen: {
76
            'destroy model': 'remove'
77
        },
78
79
        /**
80
         * @inheritDoc
81
         */
82
        constructor: function TransitionEditView() {
83
            TransitionEditView.__super__.constructor.apply(this, arguments);
84
        },
85
86
        /**
87
         * @inheritDoc
88
         */
89
        initialize: function(options) {
90
            options = options || {};
91
            var requiredMissed = this.requiredOptions.filter(function(option) {
92
                return _.isUndefined(options[option]);
93
            });
94
            if (requiredMissed.length) {
95
                throw new TypeError('Missing required option(s): ' + requiredMissed.join(', '));
96
            }
97
            this.options = _.defaults(options, this.options);
98
99
            var template = this.options.template || $('#transition-form-template').html();
100
            this.template = _.template(template);
101
            this.button_example_template = _.template(this.options.button_example_template);
102
            this.widget = null;
103
        },
104
105
        initDestinationPageView: function(form) {
106
            var availableDestinations = this.options.workflow.getAvailableDestinations();
107
            var entityRoutes = _.keys(this.options.entityFieldsProvider.getEntityRoutes());
108
            entityRoutes.push('');
109
110
            var enabledRedirects = _.intersection(availableDestinations, entityRoutes);
111
112
            var currentRedirects = $(form).find('[name=destination_page] option');
113
            _.each(currentRedirects, function(item) {
114
                $(item).toggle(_.indexOf(enabledRedirects, $(item).val()) >= 0);
115
            });
116
        },
117
118
        updateDestinationPageView: function() {
119
            var $displayType = $(this.widget.form).find('[name=display_type]');
120
            var $pageRedirectRow = $(this.widget.form).find('.destination-page-controls');
121
122
            $pageRedirectRow.toggle($displayType.val() === 'page');
123
        },
124
125
        updateExampleView: function() {
126
            var formData = helper.getFormData(this.widget.form);
127
            formData.transition_prototype_icon = formData.transition_prototype_icon || this._getFrontendOption('icon');
128
            formData.button_label = formData.button_label || formData.label;
129
            formData.button_title = formData.button_title || formData.button_label;
130
131
            if (formData.transition_prototype_icon || formData.button_label || formData.button_title) {
132
                this.$exampleBtnContainer.html(
133
                    this.button_example_template(formData)
134
                );
135
            }
136
        },
137
138
        onTransitionAdd: function() {
139
            var formData = helper.getFormData(this.widget.form);
140
            var modelUpdateData = _.pick(formData,
141
                'label', 'button_label', 'button_title', 'step_to', 'display_type', 'destination_page', 'message');
142
            if (!this.model.get('name')) {
143
                modelUpdateData.name = helper.getNameByString(formData.label, 'transition_');
144
            }
145
            var frontendOptions = this.model.get('frontend_options');
146
            modelUpdateData.frontend_options = _.extend({}, frontendOptions, {
147
                'icon': formData.transition_prototype_icon,
148
                'class': formData.button_color
149
            });
150
            modelUpdateData._is_clone = false;
151
            var attributeFields = {};
152
            _.each(this.subview('attributes-list-view').getCollection(), function(item) {
153
                this.options.workflow.ensureAttributeByPropertyPath(item.property_path);
154
                var attribute = this.options.workflow.getAttributeByPropertyPath(item.property_path);
155
                var attributeName = attribute.get('name');
156
                var formOptionsData = _.pick(item, 'options');
157
                if (item.required) {
158
                    formOptionsData.options = _.extend({}, formOptionsData.options, {required: true});
159
                } else if (formOptionsData.options) {
160
                    delete formOptionsData.options.required;
161
                    delete formOptionsData.options.constraints;
162
                }
163
164
                if (item.label && item.isLabelUpdated) {
165
                    formOptionsData.label = item.label;
166
                    if (formOptionsData.options) {
167
                        delete formOptionsData.options.label;
168
                    }
169
                }
170
171
                attributeFields[attributeName] = formOptionsData;
172
            }, this);
173
174
            modelUpdateData.form_options = {
175
                attribute_fields: attributeFields
176
            };
177
178
            this.model.set(modelUpdateData);
179
180
            var stepFrom = formData.step_from ? formData.step_from : this.options.step_from;
181
            this.trigger('transitionAdd', this.model, stepFrom);
182
            this.widget.remove();
183
        },
184
185
        _getFrontendOption: function(key) {
186
            var result = '';
187
            var formOptions = this.model.get('frontend_options');
188
            if (formOptions && formOptions.hasOwnProperty(key)) {
189
                result = formOptions[key];
190
            }
191
            return result;
192
        },
193
194
        renderAddAttributeForm: function(el) {
195
            var attributesFormView = new AttributeFormOptionEditView({
196
                autoRender: true,
197
                el: el.find('.transition-attributes-form-container'),
198
                workflow: this.options.workflow,
199
                entityFieldsProvider: this.options.entityFieldsProvider,
200
                entity: this.options.entity,
201
                filterPreset: 'workflow'
202
            });
203
204
            this.listenTo(attributesFormView, 'formOptionAdd', this.addFormOption);
205
            this.subview('attributes-form-view', attributesFormView);
206
            return attributesFormView;
207
        },
208
209
        addFormOption: function(data) {
210
            var attributeName;
211
            var attribute = this.options.workflow.getAttributeByPropertyPath(data.property_path);
212
            if (attribute) {
213
                attributeName = attribute.get('name');
214
            } else {
215
                attributeName = this.options.workflow.generateAttributeName(data.property_path);
216
            }
217
            if (data.label) {
218
                data.isLabelUpdated = true;
219
            }
220
            data.attribute_name = attributeName;
221
            data.is_entity_attribute = true;
222
223
            this.subview('attributes-list-view').addItem(data);
224
        },
225
226
        renderAttributesList: function(el) {
227
            var attributesList = new AttributeFormOptionListView({
228
                autoRender: true,
229
                el: el.find('.transition-attributes-list-container'),
230
                items: this.getFormOptions(),
231
                fieldsChoiceView: this.subview('attributes-form-view').getFieldChoiceView(),
232
                workflow: this.options.workflow,
233
                entityFieldsProvider: this.options.entityFieldsProvider
234
            });
235
236
            this.listenTo(attributesList, 'editFormOption', this.editFormOption);
237
            this.subview('attributes-list-view', attributesList);
238
        },
239
240
        editFormOption: function(data) {
241
            this.subview('attributes-form-view').editRow(data);
242
        },
243
244
        getFormOptions: function() {
245
            var results = [];
246
            var entityPropertyPathPrefix = this.options.workflow.get('entity_attribute') + '.';
247
            _.each(this.model.get('form_options').attribute_fields, function(formOption, attributeName) {
248
                formOption = formOption || {};
249
                var attribute = this.options.workflow.getAttributeByName(attributeName);
250
                var propertyPath = attribute.get('property_path');
251
                var isEntityAttribute = Boolean(propertyPath);
252
                if (isEntityAttribute && propertyPath.indexOf(entityPropertyPathPrefix) === 0) {
253
                    propertyPath = propertyPath.substr(entityPropertyPathPrefix.length);
254
                }
255
                var options = formOption.hasOwnProperty('options') ? formOption.options : {};
256
                var isRequired = options.hasOwnProperty('required') ? options.required : false;
257
258
                var label = formOption.hasOwnProperty('label') ? formOption.label : null;
259
                if (!label && options.hasOwnProperty('label')) {
260
                    label = options.label;
261
                }
262
                var result = {
263
                    itemId: _.uniqueId(),
264
                    is_entity_attribute: isEntityAttribute,
265
                    attribute_name: attributeName,
266
                    property_path: propertyPath || attributeName,
267
                    required: isRequired,
268
                    label: label,
269
                    isLabelUpdated: false,
270
                    translateLinks: attribute.attributes.translateLinks[this.model.get('name')]
271
                };
272
                if ('options' in formOption) {
273
                    result.options = _.clone(formOption.options);
274
                }
275
                results.push(result);
276
            }, this);
277
278
            return results;
279
        },
280
281
        onCancel: function() {
282
            if (this.model.get('_is_clone')) {
283
                this.model.destroy();
284
            } else {
285 View Code Duplication
                this.remove();
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
286
            }
287
        },
288
289
        remove: function() {
290
            this.removeSubview('attributes-form-view');
291
            this.removeSubview('attributes-list-view');
292
            TransitionEditView.__super__.remove.call(this);
293
        },
294
295
        renderWidget: function() {
296
            if (!this.widget) {
297
                var title = this.model.get('name') ? __('Edit transition') : __('Add new transition');
298
                if (this.model.get('_is_clone')) {
299
                    title = __('Clone transition');
300
                }
301
                this.widget = new DialogWidget({
302
                    title: title,
303
                    el: this.$el,
304
                    stateEnabled: false,
305
                    incrementalPosition: false,
306
                    dialogOptions: {
307
                        close: _.bind(this.onCancel, this),
308
                        width: 800,
309
                        modal: true
310
                    }
311
                });
312
                this.widget.render();
313
            } else {
314
                this.widget._adoptWidgetActions();
315
            }
316
317
            // Disable widget submit handler and set our own instead
318
            this.widget.form.off('submit');
319
            this.widget.form.validate({
320
                submitHandler: _.bind(this.onTransitionAdd, this),
321
                ignore: '[type="hidden"]',
322
                highlight: function(element) {
323
                    var tabContent = $(element).closest('.tab-pane');
324
                    if (tabContent.is(':hidden')) {
325
                        tabContent
326
                            .closest('.oro-tabs')
327
                            .find('[href="#' + tabContent.prop('id') + '"]')
328
                            .click();
329
                    }
330
                }
331
            });
332
        },
333
334
        render: function() {
335
            this._deferredRender();
336
            var data = this.model.toJSON();
337
            var steps = this.options.workflow.get('steps').models;
338
            data.stepFrom = this.options.step_from;
339
            if (!data.step_to) {
340
                data.step_to = this.options.step_to ? this.options.step_to.get('name') : undefined;
341
            }
342
            data.allowedButtonStyles = _.sortBy(this.options.allowed_button_styles, 'label');
343
            data.buttonIcon = this._getFrontendOption('icon');
344
            data.buttonStyle = this._getFrontendOption('class');
345
            data.allowedStepsFrom = steps;
346
            data.allowedStepsTo = steps.slice(1);
347
348
            var form = $(this.template(data));
349
350
            this.initDestinationPageView(form);
351
            var attributesFormView = this.renderAddAttributeForm(form);
352
            $.when(attributesFormView.getDeferredRenderPromise()).then(function() {
353
                this.renderAttributesList(form);
354
                this.$el.append(form);
355
356
                this.renderWidget();
357
358
                this.$exampleContainer = this.$('.transition-example-container');
359
                this.$exampleBtnContainer = this.$exampleContainer.find('.transition-btn-example');
360
                this.updateExampleView();
361
                this.updateDestinationPageView();
362
                this._resolveDeferredRender();
363
            }.bind(this));
364
365
            return this;
366
        }
367
    });
368
369
    return TransitionEditView;
370
});
371