// Register eslint ignored glabals - to be revisited. // https://github.com/woocommerce/automatewoo/issues/1212 /* global AW, Backbone, _, ajaxurl, automatewooWorkflowLocalizeScript */ ( function ( $, data ) { // MODELS AW.Rules = Backbone.Model.extend( { initialize() { const ruleOptions = []; if ( this.get( 'rawRuleOptions' ) ) { // convert rule options from json to models _.each( this.get( 'rawRuleOptions' ), ( rawRuleGroup ) => { const group = new AW.RuleGroup( this ); const rules = []; _.each( rawRuleGroup, function ( rawRule ) { const rule = new AW.Rule( group ); rule.set( 'name', rawRule.name ); rule.resetOptions(); rule.set( 'compare', rawRule.compare ); rule.set( 'value', rawRule.value ); // for objects if ( rawRule.selected ) { rule.set( 'selected', rawRule.selected ); } rules.push( rule ); } ); group.set( 'rules', rules ); ruleOptions.push( group ); } ); } this.set( 'ruleOptions', ruleOptions ); this.resetAvailableRules(); }, defaults() { return { allRules: {}, availableRules: {}, // array of condition group models ruleOptions: [], }; }, resetAvailableRules() { // calculate available conditions based on the selected trigger const trigger = AW.workflow.get( 'trigger' ); this.set( 'availableRules', _.filter( this.get( 'allRules' ), function ( rule ) { return ( trigger && trigger.supplied_data_items.indexOf( rule.data_item ) !== -1 ); } ) ); // put rules into groups for select const groupedRules = {}; _.each( this.get( 'availableRules' ), function ( rule ) { if ( ! groupedRules[ rule.group ] ) { groupedRules[ rule.group ] = []; } groupedRules[ rule.group ].push( rule ); } ); this.set( 'groupedRules', groupedRules ); }, isRuleAvailable( ruleName ) { const availableRules = AW.rules.get( 'availableRules' ); const names = _.pluck( availableRules, 'name' ); return _.indexOf( names, ruleName ) !== -1; }, clearIncompatibleRules() { const rulesToRemove = []; _.each( AW.rules.get( 'ruleOptions' ), function ( ruleGroup ) { _.each( ruleGroup.get( 'rules' ), function ( rule ) { if ( rule && ! AW.rules.isRuleAvailable( rule.get( 'name' ) ) ) { rulesToRemove.push( rule ); } } ); } ); // clear out of initial loop to avoid index changing issues, when rules are cleared _.each( rulesToRemove, function ( rule ) { rule.clear(); } ); }, createGroup() { const groups = this.get( 'ruleOptions' ); const group = new AW.RuleGroup( this ); group.createRule(); groups.push( group ); this.set( 'ruleOptions', groups ); this.trigger( 'ruleGroupChange' ); return group; }, removeGroup( id ) { const groups = this.get( 'ruleOptions' ); // find index - note we cant use _.findIndex due to backwards compatibility const index = groups .map( function ( group ) { return group.id; } ) .indexOf( id ); groups[ index ].destroy(); groups.splice( index, 1 ); this.set( 'ruleOptions', groups ); this.trigger( 'ruleGroupChange' ); }, } ); AW.Rule = Backbone.Model.extend( { initialize( group ) { this.set( 'id', _.uniqueId( 'rule_' ) ); this.set( 'group', group ); this.resetOptions(); }, getRuleObject() { return data.allRules[ this.get( 'name' ) ]; }, resetOptions() { const name = this.get( 'name' ); const ruleObject = this.getRuleObject(); if ( name ) { this.set( 'object', ruleObject ); } else { this.set( 'object', {} ); } this.set( 'compare', false ); this.set( 'value', false ); this.loadSelectOptions(); return this; }, /** * async gather rule select choices, if not already loaded */ loadSelectOptions() { const ruleObject = this.getRuleObject(); if ( ! ruleObject || ruleObject.type !== 'select' || ruleObject.select_choices ) { return this; } this.set( 'isValueLoading', true ); $.getJSON( ajaxurl, { action: 'aw_get_rule_select_choices', rule_name: ruleObject.name, }, ( response ) => { if ( ! response.success ) { return; } ruleObject.select_choices = response.data.select_choices; this.set( 'isValueLoading', false ); this.set( 'object', ruleObject ); this.trigger( 'optionsLoaded' ); } ); return this; }, clear() { const group = this.get( 'group' ); group.removeRule( this.id ); }, destroy() { this.trigger( 'destroy' ); }, } ); AW.RuleGroup = Backbone.Model.extend( { initialize( app ) { this.set( 'id', _.uniqueId( 'rule_group_' ) ); this.set( 'app', app ); this.set( 'rules', [] ); }, createRule() { const rules = this.get( 'rules' ); const rule = new AW.Rule( this ); rules.push( rule ); this.set( 'rules', rules ); return rule; }, removeRule( id ) { const rules = this.get( 'rules' ); // find rule index - note we cant use _.findIndex due to backwards compatibility const index = rules .map( function ( rule ) { return rule.id; } ) .indexOf( id ); // if only 1 rule left delete the whole group object if ( rules.length > 1 ) { rules[ index ].destroy(); rules.splice( index, 1 ); this.set( 'rules', rules ); } else { rules[ index ].destroy(); // destroy the last rule this.clear(); } }, clear() { const app = this.get( 'app' ); app.removeGroup( this.id ); }, destroy() { this.trigger( 'destroy' ); }, } ); // VIEWS AW.RuleView = Backbone.View.extend( { className: 'automatewoo-rule-container', template: wp.template( 'aw-rule' ), events: { 'change .js-rule-select': 'updatedName', 'change .js-rule-compare-field': 'updatedCompare', 'change .js-rule-value-field': 'updatedValue', 'click .js-remove-rule': 'clear', 'change .js-rule-value-from': 'updateMinFromValueDate', }, initialize() { this.listenTo( this.model, 'change:id', this.render ); this.listenTo( this.model, 'change:group', this.render ); this.listenTo( this.model, 'optionsLoaded', this.render ); this.listenTo( this.model, 'destroy', this.remove ); }, render() { this.$el.html( this.template( { rule: this.model.toJSON(), groupedRules: AW.rules.get( 'groupedRules' ), fieldNameBase: this.getFieldNameBase(), } ) ); this.setName(); this.setCompare(); this.setValue(); this.maybeToggleValueDisplay(); this.initDatepicker(); $( document.body ).trigger( 'wc-enhanced-select-init' ); return this; }, setName() { this.$el.find( '.js-rule-select' ).val( this.model.get( 'name' ) ); }, setCompare() { const $compareField = this.$el.find( '.js-rule-compare-field' ); const compare = this.model.get( 'compare' ); // Default selected value to first option. if ( $compareField.filter( 'select' ).length && ! compare ) { const $option = $compareField.find( 'option:first-child' ); const optionValue = $compareField .find( 'option:first-child' ) .prop( 'value' ); $option.prop( 'selected', true ); $compareField.val( optionValue ); this.model.set( 'compare', optionValue ); } if ( compare ) { $compareField.val( compare ); $compareField .find( 'option[value~="' + compare + '"]' ) .prop( 'selected', true ); } }, setValue() { const selectedTitle = this.model.get( 'selected' ); const selectedId = this.model.get( 'value' ); let $valueField; if ( selectedTitle ) { $valueField = this.$el.find( '.js-rule-value-field' ); if ( $valueField.is( 'select' ) ) { if ( _.isArray( selectedId ) ) { _.each( selectedId, function ( id, i ) { $valueField.append( $( '