Allow shipping classes interface to be extended.

This commit is contained in:
Mike Jolley 2016-05-19 12:38:28 +01:00
parent ed08e51ddb
commit 54231c2946
6 changed files with 72 additions and 39 deletions

View File

@ -112,12 +112,17 @@
var view = this; var view = this;
var $tr = view.$el.find( 'tr[data-id="' + rowData.term_id + '"]'); var $tr = view.$el.find( 'tr[data-id="' + rowData.term_id + '"]');
// Support select boxes
$tr.find( 'select' ).each( function() {
var attribute = $( this ).data( 'attribute' );
$( this ).find( 'option[value="' + rowData[ attribute ] + '"]' ).prop( 'selected', true );
} );
// Make the rows function // Make the rows function
$tr.find('.view').show(); $tr.find( '.view' ).show();
$tr.find('.edit').hide(); $tr.find( '.edit' ).hide();
$tr.find( '.wc-shipping-class-edit' ).on( 'click', { view: this }, this.onEditRow ); $tr.find( '.wc-shipping-class-edit' ).on( 'click', { view: this }, this.onEditRow );
$tr.find( '.wc-shipping-class-delete' ).on( 'click', { view: this }, this.onDeleteRow ); $tr.find( '.wc-shipping-class-delete' ).on( 'click', { view: this }, this.onDeleteRow );
$tr.find( '.wc-shipping-class-postcodes-toggle' ).on( 'click', { view: this }, this.onTogglePostcodes );
$tr.find( '.editing .wc-shipping-class-edit' ).trigger('click'); $tr.find( '.editing .wc-shipping-class-edit' ).trigger('click');
$tr.find( '.wc-shipping-class-cancel-edit' ).on( 'click', { view: this }, this.onCancelEditRow ); $tr.find( '.wc-shipping-class-cancel-edit' ).on( 'click', { view: this }, this.onCancelEditRow );

View File

@ -1 +1 @@
!function(a,b,c,d){a(function(){var e=a(".wc-shipping-class-rows"),f=a(".wc-shipping-class-save"),g=c.template("wc-shipping-class-row"),h=c.template("wc-shipping-class-row-blank"),i=Backbone.Model.extend({changes:{},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{term_id:c},a)}),this.changes=b,this.trigger("change:classes")},save:function(){_.size(this.changes)?a.post(d+(d.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_classes_save_changes",{wc_shipping_classes_nonce:b.wc_shipping_classes_nonce,changes:this.changes},this.onSaveResponse,"json"):k.trigger("saved:classes")},discardChanges:function(a){var b=this.changes||{};delete b[a],0===_.size(this.changes)&&l.clearUnloadConfirmation()},onSaveResponse:function(a,c){"success"===c&&(a.success?(k.set("classes",a.data.shipping_classes),k.trigger("change:classes"),k.changes={},k.trigger("saved:classes")):a.data?window.alert(a.data):window.alert(b.strings.save_failed)),l.unblock()}}),j=Backbone.View.extend({rowTemplate:g,initialize:function(){this.listenTo(this.model,"change:classes",this.setUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.render),e.on("change",{view:this},this.updateModelOnChange),a(window).on("beforeunload",{view:this},this.unloadConfirmation),f.on("click",{view:this},this.onSubmit),a(document.body).on("click",".wc-shipping-class-add",{view:this},this.onAddNewRow),a(document.body).on("click",".wc-shipping-class-save-changes",{view:this},this.onSubmit)},block:function(){a(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){a(this.el).unblock()},render:function(){var b=_.indexBy(this.model.get("classes"),"term_id"),c=this;this.$el.empty(),this.unblock(),_.size(b)?(b=_.sortBy(b,function(a){return a.name}),a.each(b,function(a,b){c.renderRow(b)})):c.$el.append(h)},renderRow:function(a){var b=this;b.$el.append(b.rowTemplate(a)),b.initRow(a)},initRow:function(a){var b=this,c=b.$el.find('tr[data-id="'+a.term_id+'"]');c.find(".view").show(),c.find(".edit").hide(),c.find(".wc-shipping-class-edit").on("click",{view:this},this.onEditRow),c.find(".wc-shipping-class-delete").on("click",{view:this},this.onDeleteRow),c.find(".wc-shipping-class-postcodes-toggle").on("click",{view:this},this.onTogglePostcodes),c.find(".editing .wc-shipping-class-edit").trigger("click"),c.find(".wc-shipping-class-cancel-edit").on("click",{view:this},this.onCancelEditRow),!0===a.editing&&(c.addClass("editing"),c.find(".wc-shipping-class-edit").trigger("click"))},onSubmit:function(a){a.data.view.block(),a.data.view.model.save(),a.preventDefault()},onAddNewRow:function(a){a.preventDefault();var c=a.data.view,d=c.model,e=_.indexBy(d.get("classes"),"term_id"),f={},g=_.size(e),h=_.extend({},b.default_class,{term_id:"new-"+g+"-"+Date.now(),editing:!0,newRow:!0});f[h.term_id]=h,d.logChanges(f),c.renderRow(h)},onEditRow:function(b){b.preventDefault(),a(this).closest("tr").addClass("editing"),a(this).closest("tr").find(".view").hide(),a(this).closest("tr").find(".edit").show(),b.data.view.model.trigger("change:classes")},onDeleteRow:function(b){var c=b.data.view,d=c.model,e=a(this).closest("tr"),f=_.indexBy(d.get("classes"),"term_id"),g={},h=a(this).closest("tr").data("id");b.preventDefault(),f[h]&&(delete f[h],g[h]=_.extend(g[h]||{},{deleted:"deleted"}),d.set("classes",f),d.logChanges(g)),e.remove()},onCancelEditRow:function(b){var c=b.data.view,d=c.model,e=a(this).closest("tr"),f=a(this).closest("tr").data("id"),g=_.indexBy(d.get("classes"),"term_id");b.preventDefault(),d.discardChanges(f),g[f]&&(g[f].editing=!1,e.after(c.rowTemplate(g[f])),c.initRow(g[f])),e.remove()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,f.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,f.attr("disabled","disabled")},unloadConfirmation:function(a){return a.data.view.needsUnloadConfirm?(a.returnValue=b.strings.unload_confirmation_msg,window.event.returnValue=b.strings.unload_confirmation_msg,b.strings.unload_confirmation_msg):void 0},updateModelOnChange:function(b){var c=b.data.view.model,d=a(b.target),e=d.closest("tr").data("id"),f=d.data("attribute"),g=d.val(),h=_.indexBy(c.get("classes"),"term_id"),i={};h[e]&&h[e][f]===g||(i[e]={},i[e][f]=g),c.logChanges(i)}}),k=new i({classes:b.classes}),l=new j({model:k,el:e});l.render()})}(jQuery,shippingClassesLocalizeScript,wp,ajaxurl); !function(a,b,c,d){a(function(){var e=a(".wc-shipping-class-rows"),f=a(".wc-shipping-class-save"),g=c.template("wc-shipping-class-row"),h=c.template("wc-shipping-class-row-blank"),i=Backbone.Model.extend({changes:{},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{term_id:c},a)}),this.changes=b,this.trigger("change:classes")},save:function(){_.size(this.changes)?a.post(d+(d.indexOf("?")>0?"&":"?")+"action=woocommerce_shipping_classes_save_changes",{wc_shipping_classes_nonce:b.wc_shipping_classes_nonce,changes:this.changes},this.onSaveResponse,"json"):k.trigger("saved:classes")},discardChanges:function(a){var b=this.changes||{};delete b[a],0===_.size(this.changes)&&l.clearUnloadConfirmation()},onSaveResponse:function(a,c){"success"===c&&(a.success?(k.set("classes",a.data.shipping_classes),k.trigger("change:classes"),k.changes={},k.trigger("saved:classes")):a.data?window.alert(a.data):window.alert(b.strings.save_failed)),l.unblock()}}),j=Backbone.View.extend({rowTemplate:g,initialize:function(){this.listenTo(this.model,"change:classes",this.setUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.render),e.on("change",{view:this},this.updateModelOnChange),a(window).on("beforeunload",{view:this},this.unloadConfirmation),f.on("click",{view:this},this.onSubmit),a(document.body).on("click",".wc-shipping-class-add",{view:this},this.onAddNewRow),a(document.body).on("click",".wc-shipping-class-save-changes",{view:this},this.onSubmit)},block:function(){a(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){a(this.el).unblock()},render:function(){var b=_.indexBy(this.model.get("classes"),"term_id"),c=this;this.$el.empty(),this.unblock(),_.size(b)?(b=_.sortBy(b,function(a){return a.name}),a.each(b,function(a,b){c.renderRow(b)})):c.$el.append(h)},renderRow:function(a){var b=this;b.$el.append(b.rowTemplate(a)),b.initRow(a)},initRow:function(b){var c=this,d=c.$el.find('tr[data-id="'+b.term_id+'"]');d.find("select").each(function(){var c=a(this).data("attribute");a(this).find('option[value="'+b[c]+'"]').prop("selected",!0)}),d.find(".view").show(),d.find(".edit").hide(),d.find(".wc-shipping-class-edit").on("click",{view:this},this.onEditRow),d.find(".wc-shipping-class-delete").on("click",{view:this},this.onDeleteRow),d.find(".editing .wc-shipping-class-edit").trigger("click"),d.find(".wc-shipping-class-cancel-edit").on("click",{view:this},this.onCancelEditRow),!0===b.editing&&(d.addClass("editing"),d.find(".wc-shipping-class-edit").trigger("click"))},onSubmit:function(a){a.data.view.block(),a.data.view.model.save(),a.preventDefault()},onAddNewRow:function(a){a.preventDefault();var c=a.data.view,d=c.model,e=_.indexBy(d.get("classes"),"term_id"),f={},g=_.size(e),h=_.extend({},b.default_class,{term_id:"new-"+g+"-"+Date.now(),editing:!0,newRow:!0});f[h.term_id]=h,d.logChanges(f),c.renderRow(h)},onEditRow:function(b){b.preventDefault(),a(this).closest("tr").addClass("editing"),a(this).closest("tr").find(".view").hide(),a(this).closest("tr").find(".edit").show(),b.data.view.model.trigger("change:classes")},onDeleteRow:function(b){var c=b.data.view,d=c.model,e=a(this).closest("tr"),f=_.indexBy(d.get("classes"),"term_id"),g={},h=a(this).closest("tr").data("id");b.preventDefault(),f[h]&&(delete f[h],g[h]=_.extend(g[h]||{},{deleted:"deleted"}),d.set("classes",f),d.logChanges(g)),e.remove()},onCancelEditRow:function(b){var c=b.data.view,d=c.model,e=a(this).closest("tr"),f=a(this).closest("tr").data("id"),g=_.indexBy(d.get("classes"),"term_id");b.preventDefault(),d.discardChanges(f),g[f]&&(g[f].editing=!1,e.after(c.rowTemplate(g[f])),c.initRow(g[f])),e.remove()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,f.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,f.attr("disabled","disabled")},unloadConfirmation:function(a){return a.data.view.needsUnloadConfirm?(a.returnValue=b.strings.unload_confirmation_msg,window.event.returnValue=b.strings.unload_confirmation_msg,b.strings.unload_confirmation_msg):void 0},updateModelOnChange:function(b){var c=b.data.view.model,d=a(b.target),e=d.closest("tr").data("id"),f=d.data("attribute"),g=d.val(),h=_.indexBy(c.get("classes"),"term_id"),i={};h[e]&&h[e][f]===g||(i[e]={},i[e][f]=g),c.logChanges(i)}}),k=new i({classes:b.classes}),l=new j({model:k,el:e});l.render()})}(jQuery,shippingClassesLocalizeScript,wp,ajaxurl);

View File

@ -292,7 +292,7 @@ class WC_Settings_Shipping extends WC_Settings_Page {
'name' => '', 'name' => '',
'description' => '', 'description' => '',
), ),
'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ), 'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ),
'strings' => array( 'strings' => array(
'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ) 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' )
@ -300,6 +300,14 @@ class WC_Settings_Shipping extends WC_Settings_Page {
) ); ) );
wp_enqueue_script( 'wc-shipping-classes' ); wp_enqueue_script( 'wc-shipping-classes' );
// Extendable columns to show on the shipping classes screen.
$shipping_class_columns = apply_filters( 'woocommerce_shipping_classes_columns', array(
'wc-shipping-class-name' => __( 'Shipping Class', 'woocommerce' ),
'wc-shipping-class-slug' => __( 'Slug', 'woocommerce' ),
'wc-shipping-class-description' => __( 'Description', 'woocommerce' ),
'wc-shipping-class-count' => __( 'Product Count', 'woocommerce' ),
) );
include_once( 'views/html-admin-page-shipping-classes.php' ); include_once( 'views/html-admin-page-shipping-classes.php' );
} }
} }

View File

@ -12,15 +12,14 @@ if ( ! defined( 'ABSPATH' ) ) {
<table class="wc-shipping-classes widefat"> <table class="wc-shipping-classes widefat">
<thead> <thead>
<tr> <tr>
<th class="wc-shipping-class-name"><?php esc_html_e( 'Shipping Class', 'woocommerce' ); ?></th> <?php foreach ( $shipping_class_columns as $class => $heading ) : ?>
<th class="wc-shipping-class-slug"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></th> <th class="<?php echo esc_attr( $class ); ?>"><?php echo esc_html( $heading ); ?></th>
<th class="wc-shipping-class-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th> <?php endforeach; ?>
<th class="wc-shipping-class-count"><?php esc_html_e( 'Product Count', 'woocommerce' ); ?></th>
</tr> </tr>
</thead> </thead>
<tfoot> <tfoot>
<tr> <tr>
<td colspan="4"> <td colspan="<?php echo absint( sizeof( $shipping_class_columns ) ); ?>">
<input type="submit" name="save" class="button button-primary wc-shipping-class-save" value="<?php esc_attr_e( 'Save Shipping Classes', 'woocommerce' ); ?>" disabled /> <input type="submit" name="save" class="button button-primary wc-shipping-class-save" value="<?php esc_attr_e( 'Save Shipping Classes', 'woocommerce' ); ?>" disabled />
<a class="button button-secondary wc-shipping-class-add" href="#"><?php esc_html_e( 'Add Shipping Class', 'woocommerce' ); ?></a> <a class="button button-secondary wc-shipping-class-add" href="#"><?php esc_html_e( 'Add Shipping Class', 'woocommerce' ); ?></a>
</td> </td>
@ -31,36 +30,55 @@ if ( ! defined( 'ABSPATH' ) ) {
<script type="text/html" id="tmpl-wc-shipping-class-row-blank"> <script type="text/html" id="tmpl-wc-shipping-class-row-blank">
<tr> <tr>
<td class="wc-shipping-classes-blank-state" colspan="4"><p><?php _e( 'No Shipping classes have been created.', 'woocommerce' ); ?></p></td> <td class="wc-shipping-classes-blank-state" colspan="<?php echo absint( sizeof( $shipping_class_columns ) ); ?>"><p><?php _e( 'No Shipping classes have been created.', 'woocommerce' ); ?></p></td>
</tr> </tr>
</script> </script>
<script type="text/html" id="tmpl-wc-shipping-class-row"> <script type="text/html" id="tmpl-wc-shipping-class-row">
<tr data-id="{{ data.term_id }}"> <tr data-id="{{ data.term_id }}">
<td class="wc-shipping-class-name"> <?php
<div class="view"> foreach ( $shipping_class_columns as $class => $heading ) {
{{ data.name }} echo '<td class="' . esc_attr( $class ) . '">';
<div class="row-actions"> switch ( $class ) {
<a class="wc-shipping-class-edit" href="#"><?php _e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-class-delete"><?php _e( 'Remove', 'woocommerce' ); ?></a> case 'wc-shipping-class-name' :
</div> ?>
</div> <div class="view">
<div class="edit"> {{ data.name }}
<input type="text" name="name[{{ data.term_id }}]" data-attribute="name" value="{{ data.name }}" placeholder="<?php esc_attr_e( 'Shipping Class Name', 'woocommerce' ); ?>" /> <div class="row-actions">
<div class="row-actions"> <a class="wc-shipping-class-edit" href="#"><?php _e( 'Edit', 'woocommerce' ); ?></a> | <a href="#" class="wc-shipping-class-delete"><?php _e( 'Remove', 'woocommerce' ); ?></a>
<a class="wc-shipping-class-cancel-edit" href="#"><?php _e( 'Cancel changes', 'woocommerce' ); ?></a> </div>
</div> </div>
</div> <div class="edit">
</td> <input type="text" name="name[{{ data.term_id }}]" data-attribute="name" value="{{ data.name }}" placeholder="<?php esc_attr_e( 'Shipping Class Name', 'woocommerce' ); ?>" />
<td class="wc-shipping-class-slug"> <div class="row-actions">
<div class="view">{{ data.slug }}</div> <a class="wc-shipping-class-cancel-edit" href="#"><?php _e( 'Cancel changes', 'woocommerce' ); ?></a>
<div class="edit"><input type="text" name="slug[{{ data.term_id }}]" data-attribute="slug" value="{{ data.slug }}" placeholder="<?php esc_attr_e( 'Slug', 'woocommerce' ); ?>" /></div> </div>
</td> </div>
<td class="wc-shipping-class-description"> <?php
<div class="view">{{ data.description }}</div> break;
<div class="edit"><input type="text" name="description[{{ data.term_id }}]" data-attribute="description" value="{{ data.description }}" placeholder="<?php esc_attr_e( 'Description for your reference', 'woocommerce' ); ?>" /></div> case 'wc-shipping-class-slug' :
</td> ?>
<td class="wc-shipping-class-count"> <div class="view">{{ data.slug }}</div>
<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&product_shipping_class=' ) ); ?>{{data.slug}}">{{ data.count }}</a> <div class="edit"><input type="text" name="slug[{{ data.term_id }}]" data-attribute="slug" value="{{ data.slug }}" placeholder="<?php esc_attr_e( 'Slug', 'woocommerce' ); ?>" /></div>
</td> <?php
break;
case 'wc-shipping-class-description' :
?>
<div class="view">{{ data.description }}</div>
<div class="edit"><input type="text" name="description[{{ data.term_id }}]" data-attribute="description" value="{{ data.description }}" placeholder="<?php esc_attr_e( 'Description for your reference', 'woocommerce' ); ?>" /></div>
<?php
break;
case 'wc-shipping-class-count' :
?>
<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&product_shipping_class=' ) ); ?>{{data.slug}}">{{ data.count }}</a>
<?php
break;
default :
do_action( 'woocommerce_shipping_classes_column_' . $class );
break;
}
echo '</td>';
}
?>
</tr> </tr>
</script> </script>

View File

@ -3323,10 +3323,12 @@ class WC_AJAX {
if ( empty( $update_args['name'] ) ) { if ( empty( $update_args['name'] ) ) {
continue; continue;
} }
$result = wp_insert_term( $update_args['name'], 'product_shipping_class', $update_args ); $term_id = wp_insert_term( $update_args['name'], 'product_shipping_class', $update_args );
} else { } else {
$result = wp_update_term( $term_id, 'product_shipping_class', $update_args ); wp_update_term( $term_id, 'product_shipping_class', $update_args );
} }
do_action( 'woocommerce_shipping_classes_save_class', $term_id, $data );
} }
$wc_shipping = WC_Shipping::instance(); $wc_shipping = WC_Shipping::instance();

View File

@ -196,7 +196,7 @@ class WC_Shipping {
$classes = get_terms( 'product_shipping_class', array( 'hide_empty' => '0', 'orderby' => 'name' ) ); $classes = get_terms( 'product_shipping_class', array( 'hide_empty' => '0', 'orderby' => 'name' ) );
$this->shipping_classes = ! is_wp_error( $classes ) ? $classes : array(); $this->shipping_classes = ! is_wp_error( $classes ) ? $classes : array();
} }
return $this->shipping_classes; return apply_filters( 'woocommerce_get_shipping_classes', $this->shipping_classes );
} }
/** /**