Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin cart page revamp #1710

Merged
merged 16 commits into from
Feb 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion backend/app/assets/javascripts/spree/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
//= require spree/backend/images/new
//= require spree/backend/images/upload
//= require spree/backend/line_items
//= require spree/backend/line_items_on_order_edit
//= require spree/backend/navigation
//= require spree/backend/number_field_updater
//= require spree/backend/option_type_autocomplete
Expand Down
153 changes: 98 additions & 55 deletions backend/app/assets/javascripts/spree/backend/line_items.js.coffee
Original file line number Diff line number Diff line change
@@ -1,55 +1,98 @@
editing = (e) ->
e.preventDefault()
$(e.delegateTarget).addClass('editing')

editingDone = (e) ->
e.preventDefault()
$(e.delegateTarget).removeClass('editing')

onSaveLineItem = (e) ->
e.preventDefault()
line_item = $(this).closest('.line-item')
line_item_id = line_item.data('line-item-id')
quantity = parseInt(line_item.find('input.line_item_quantity').val())
adjustLineItem(line_item_id, quantity)
editingDone(e)

onDeleteLineItem = (e) ->
e.preventDefault()
return unless confirm(Spree.translations.are_you_sure_delete)
line_item = $(this).closest('.line-item')
line_item_id = line_item.data('line-item-id')
deleteLineItem(line_item_id)
editingDone(e)

$(document).ready ->
$('.line-item')
.on('click', '.edit-line-item', editing)
.on('click', '.cancel-line-item', editingDone)
.on('click', '.save-line-item', onSaveLineItem)
.on('click', '.delete-line-item', onDeleteLineItem)

lineItemURL = (id) ->
"#{Spree.routes.line_items_api(order_number)}/#{id}.json"

adjustLineItem = (line_item_id, quantity) ->
url = lineItemURL(line_item_id)
Spree.ajax(
type: "PUT",
url: url,
data:
line_item:
quantity: quantity
).done (msg) ->
window.Spree.advanceOrder()

deleteLineItem = (line_item_id) ->
url = lineItemURL(line_item_id)
Spree.ajax(
type: "DELETE"
url: url
).done (msg) ->
$('#line-item-' + line_item_id).remove()
if $('.line-items tr.line-item').length == 0
$('.line-items').remove()
window.Spree.advanceOrder()

Spree.CartLineItemView = Backbone.View.extend
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can also introduce a Spree.Views namespace for views as we discussed for models in #1715?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather address this in the #1715, which is a follow up to this. This PR was intended only to be the UI change, with #1715 being a more complete switch to backbone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

tagName: 'tr'
className: 'line-item'

initialize: (options) ->
@editing = options.editing || @model.isNew()
@noCancel = options.noCancel

events:
'click .edit-line-item': 'onEdit'
'click .cancel-line-item': 'onCancel'
'click .save-line-item': 'onSave'
'click .delete-line-item': 'onDelete'
'change .js-select-variant': 'onChangeVariant'

onEdit: (e) ->
e.preventDefault()
@editing = true
@render()

onCancel: (e) ->
e.preventDefault()
@trigger('cancel')
if @model.isNew()
@remove()
else
@editing = false
@render()

validate: () ->
@$('[name=quantity]').toggleClass 'error', !@$('[name=quantity]').val()
@$('.select2-container').toggleClass 'error', !@$('[name=variant_id]').val()

!@$('.select2-container').hasClass('error') && !@$('[name=quantity]').hasClass('error')

onSave: (e) ->
e.preventDefault()
return unless @validate()
attrs = {
quantity: parseInt(@$('input.line_item_quantity').val())
}
if @model.isNew()
attrs['variant_id'] = @$("[name=variant_id]").val()
@model.save attrs,
patch: true,
success: =>
window.Spree.advanceOrder()
@editing = false
@render()

onDelete: (e) ->
e.preventDefault()
return unless confirm(Spree.translations.are_you_sure_delete)
@remove()
@model.destroy
success: =>
window.Spree.advanceOrder()

render: ->
line_item = @model.attributes
image = line_item.variant && line_item.variant.images[0]
html = HandlebarsTemplates['orders/line_item'](
line_item: line_item,
image: image,
editing: @editing,
isNew: @model.isNew(),
noCancel: @noCancel
)
el = @$el.html(html)
@$("[name=variant_id]").variantAutocomplete({ in_stock_only: true })

$ ->
if $("table.line-items").length
url = Spree.routes.orders_api + "/" + order_number
lineItemModel = Backbone.Model.extend
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this model into its own file and use the Spree.Model namespace discussed in #1715?

Copy link
Contributor Author

@jhawthorn jhawthorn Feb 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't be done here. At this point the model needs to be defined where we have access to url. #1715 is a follow up to this where this will be fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okidoki

urlRoot: Spree.routes.line_items_api(order_number)

add_button = $('.js-add-line-item')
add_button.click ->
add_button.prop("disabled", true)
view = new Spree.CartLineItemView(model: new lineItemModel())
view.render()
view.on('cancel', (event) -> add_button.prop("disabled", false))
$("table.line-items > tbody").append(view.el)

Spree.ajax(url: url).done (result) ->
for line_item in result.line_items
model = new lineItemModel(line_item)
view = new Spree.CartLineItemView(model: model)
view.render()
$("table.line-items > tbody").append(view.el)

add_button.prop("disabled", !result.line_items.length)
if !result.line_items.length
view = new Spree.CartLineItemView(model: new lineItemModel(), noCancel: true)
view.render()
$("table.line-items > tbody").append(view.el)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//= require spree/backend/templates/orders/customer_details/autocomplete
//= require spree/backend/templates/orders/line_item
//= require spree/backend/templates/products/sortable
//= require spree/backend/templates/products/upload_progress
//= require spree/backend/templates/promotions/calculators/fields/tiered_flat_rate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{{#if isNew}}
<td class="line-item-select-variant" colspan="2">
<input type="hidden" name="variant_id" class="js-select-variant select-variant fullwidth">
</td>
{{else}}
<td class="line-item-image">
<img src="{{ image.mini_url }}">
</td>
<td class="line-item-name">
{{ line_item.variant.name }}<br>
{{#if line_item.variant.options_text }}
{{ line_item.variant.options_text }}<br/>
{{/if}}
<strong>{{ t "sku" }}:</strong> {{ line_item.variant.sku }}
</td>
{{/if}}
<td class="line-item-price align-center">
{{ line_item.single_display_amount }}
</td>
{{#if editing}}
<td class="line-item-qty-edit">
<input type="number" name="quantity" value="{{ line_item.quantity }}" min="0" class="line_item_quantity" size="5">
</td>
{{else}}
<td class="line-item-qty-show align-center">
{{ line_item.quantity }}
</td>
{{/if}}
<td class="line-item-total align-center">
{{ line_item.display_amount }}
</td>
<td class="cart-line-item-delete actions" data-hook="cart_line_item_delete">
{{#if editing}}
<a class="save-line-item fa fa-ok no-text with-tip" href="#" title="{{ t "actions.save" }}"></a>
{{#unless noCancel}}
<a class="cancel-line-item fa fa-cancel no-text with-tip" href="#" title="{{ t "actions.cancel" }}"></a>
{{/unless}}
{{else}}
<a class="edit-line-item fa fa-edit no-text with-tip" href="#" title="{{ t "actions.edit" }}"></a>
<a class="delete-line-item fa fa-trash no-text with-tip" href="#" title="{{ t "actions.delete" }}"></a>
{{/if}}
</td>
26 changes: 11 additions & 15 deletions backend/app/assets/stylesheets/spree/backend/sections/_orders.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
.line-item.editing {
.edit-line-item,
.delete-line-item,
.line-item-qty-show {
display: none !important;
}
}

.line-item:not(.editing) {
.save-line-item,
.cancel-line-item,
.line-item-qty-edit {
display: none !important;
}
}

// Customize orders filter
[data-hook="admin_orders_index_search"] {
Expand Down Expand Up @@ -95,3 +80,14 @@ form.admin-ship-shipment {
text-align: center;
input[type='submit'] { margin-left: 5px; }
}

table.line-items {
input.error {
border-color: $color-error;
}

.select2-container.error {
border-radius: 4px;
border: 1px solid $color-error;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ button, .button {
width: 100%;
text-align: center;
}

&[disabled], &.disabled {
background-color: #c2c4c7;
cursor: default;
}
}

span.info {
Expand Down
70 changes: 22 additions & 48 deletions backend/app/views/spree/admin/orders/_line_items.html.erb
Original file line number Diff line number Diff line change
@@ -1,50 +1,24 @@
<% if order.line_items.exists? %>
<table class="line-items index" data-hook="line-items">
<colgroup>
<col style="width: 10%;" />
<col style="width: 20%;" />
<col style="width: 20%;" />
<col style="width: 15%;" />
</colgroup>
<table class="line-items index" data-hook="line-items">
<colgroup>
<col style="width: 10%;" />
<col style="width: 45%;" />
<col style="width: 10%;" />
<col style="width: 10%;" />
<col style="width: 10%;" />
<col style="width: 15%;" />
</colgroup>

<thead>
<tr>
<th colspan="2"><%= Spree::Product.human_attribute_name(:name) %></th>
<th><%= Spree::LineItem.human_attribute_name(:price) %></th>
<th><%= Spree::LineItem.human_attribute_name(:quantity) %></th>
<th><%= Spree::LineItem.human_attribute_name(:total) %></th>
<th class="orders-actions actions" data-hook="admin_order_form_line_items_header_actions">&nbsp;</th>
</tr>
</thead>
<thead>
<tr>
<th colspan="2"><%= Spree::Product.human_attribute_name(:name) %></th>
<th><%= Spree::LineItem.human_attribute_name(:price) %></th>
<th><%= Spree::LineItem.human_attribute_name(:quantity) %></th>
<th><%= Spree::LineItem.human_attribute_name(:total) %></th>
<th class="orders-actions actions" data-hook="admin_order_form_line_items_header_actions">&nbsp;</th>
</tr>
</thead>

<tbody>
<% order.line_items.each do |item| %>
<%= content_tag :tr, class: 'line-item', id: "line-item-#{item.id}", data: { line_item_id: item.id } do %>
<td class="line-item-image"><%= image_tag item.variant.display_image.attachment(:mini) %></td>
<td class="line-item-name">
<%= item.variant.product.name %><br><%= "(" + variant_options(item.variant) + ")" unless item.variant.option_values.empty? %>
<% if item.variant.sku.present? %>
<strong><%= Spree::Variant.human_attribute_name(:sku) %>:</strong> <%= item.variant.sku %>
<% end %>
</td>
<td class="line-item-price align-center"><%= item.single_money.to_html %></td>
<td class="line-item-qty-show align-center">
<%= item.quantity %>
</td>
<td class="line-item-qty-edit">
<%= number_field_tag :quantity, item.quantity, min: 0, class: "line_item_quantity", size: 5 %>
</td>
<td class="line-item-total align-center"><%= line_item_shipment_price(item, item.quantity) %></td>
<td class="cart-line-item-delete actions" data-hook="cart_line_item_delete">
<% if can? :update, item %>
<%= link_to '', '#', class: 'save-line-item fa fa-ok no-text with-tip', title: Spree.t('actions.save') %>
<%= link_to '', '#', class: 'cancel-line-item fa fa-cancel no-text with-tip', title: Spree.t('actions.cancel') %>
<%= link_to '', '#', class: 'edit-line-item fa fa-edit no-text with-tip', title: Spree.t('actions.edit') %>
<%= link_to '', '#', class: 'delete-line-item fa fa-trash no-text with-tip', title: Spree.t('actions.delete') %>
<% end %>
</td>
<% end %>
<% end %>
</tbody>
</table>
<% end %>
<tbody>
<%# Rendered by JS %>
</tbody>
</table>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
<% end %>

<%= render partial: "spree/admin/orders/line_items", locals: { order: order } %>

<% if can?(:update, @order) && can?(:create, Spree::LineItem) %>
<button class="js-add-line-item" disabled><%= t('spree.add_line_item') %></button>
<% end %>

<%= render partial: "spree/admin/orders/adjustments", locals: {
adjustments: @order.line_item_adjustments,
order: order,
Expand Down
Loading