Remove angular from admin orders index page

This commit is contained in:
Matt-Yorkley
2023-05-10 14:16:56 +01:00
parent 5ad68f25e3
commit 048df6230b
23 changed files with 538 additions and 317 deletions

View File

@@ -1,6 +1,6 @@
%tr
- @columns.each do |column|
%td.products_column{class: column[:id]}
- if column[:id] == "name" && @image
- if column[:id] == "name" && @image&.attachment.present?
= image_tag @image.url(:mini)
= column[:value]

View File

@@ -5,6 +5,7 @@ require 'open_food_network/spree_api_key_loader'
module Spree
module Admin
class OrdersController < Spree::Admin::BaseController
include CablecarResponses
include OpenFoodNetwork::SpreeApiKeyLoader
helper CheckoutHelper
@@ -16,6 +17,13 @@ module Spree
respond_to :html, :json
def index
orders = SearchOrders.new(search_params, spree_current_user).orders
@pagy, @orders = pagy(orders, items: params[:per_page] || 15)
update_search_results if searching?
end
def new
@order = Order.create
@order.created_by = spree_current_user
@@ -110,6 +118,25 @@ module Spree
private
def update_search_results
render cable_ready: cable_car.inner_html(
"#orders-index",
partial("spree/admin/orders/table", locals: { pagy: @pagy, orders: @orders })
)
end
def searching?
params[:q].present? && request.format.symbol == :cable_ready
end
def search_params
search_defaults.deep_merge(params.permit!).to_h.with_indifferent_access
end
def search_defaults
{ q: { completed_at_not_null: 1, s: "completed_at desc" } }
end
def on_update
@order.recreate_all_fees!

View File

@@ -26,7 +26,7 @@ class SearchOrders
base_query = ::Permissions::Order.new(current_user).editable_orders.not_empty
.or(::Permissions::Order.new(current_user).editable_orders.finalized)
return base_query unless params[:shipping_method_id]
return base_query if params[:shipping_method_id].blank?
base_query
.joins(shipments: :shipping_rates)

View File

@@ -0,0 +1,8 @@
= select_tag :per_page,
options_for_select([15, 50, 100].collect{|num| [t('js.admin.orders.index.per_page', results: num), num] }, params[:per_page]),
{ class: "no-search primary per-page-dropdown", data: { controller: "tom-select search", action: "change->search#changePerPage" } }
- if pagy
%span.per-page-feedback
= t("spree.admin.orders.index.results_found", number: pagy.count)
= t("spree.admin.orders.index.viewing", start: pagy.from, end: pagy.to )

View File

@@ -0,0 +1,22 @@
- link = pagy_link_proc(pagy)
.pagination{ "data-controller": "search" }
- if pagy.prev
%button{ data: { action: 'click->search#changePage', page: pagy.prev } }!= pagy_t('pagy.nav.prev')
- else
%button.disabled{disabled: "disabled"}!= pagy_t('pagy.nav.prev')
- pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
- if item.is_a?(Integer) # page link
%button{ data: { action: 'click->search#changePage', page: item } }= item
- elsif item.is_a?(String) # current page
%button.active= item
- elsif item == :gap # page gap
%span.pagination-ellipsis!= pagy_t('pagy.nav.gap')
- if pagy.next
%button{ data: { action: 'click->search#changePage', page: pagy.next } }!= pagy_t('pagy.nav.next')
- else
%button.disabled.pagination-next{disabled: "disabled"}!= pagy_t('pagy.nav.next')

View File

@@ -0,0 +1,20 @@
%button.plain.ofn-drop-down.disabled{ "data-checked-target": "disable" }
%span{ class: 'icon-reorder' }
="#{t('admin.actions')}".html_safe
%span.toggle-off.icon-caret-up
%span.toggle-on.icon-caret-down
%div.menu.dropdown-content
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" }
= t('spree.admin.orders.index.resend_confirmation')
- if Spree::Config[:enable_invoices?]
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" }
= t('spree.admin.orders.index.send_invoice')
%div.menu_item
%span.name.invoices-modal{'ng-controller' => 'bulkInvoiceCtrl', 'ng-click' => 'createBulkInvoice()' }
= t('spree.admin.orders.index.print_invoices')
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "cancel_orders" }
= t('spree.admin.orders.index.cancel_orders')

View File

@@ -1,59 +1,60 @@
%div.admin-orders-index-search
= form_tag spree.admin_orders_url, {name: "orders_form", "ng-submit" => "fetchResults()"} do
%div.admin-orders-index-search{ "data-controller": "search" }
= form_with url: spree.admin_orders_url, id: "orders_form", method: :get, data: { remote: true, "search-target": "form" } do
= hidden_field_tag :page, 1, class: "page"
= hidden_field_tag :per_page, 15, class: "per-page"
= hidden_field_tag "[q][s]", params.dig(:q, :s) || "completed_at desc", class: "sort", "data-default": "completed_at desc"
.field-block.alpha.four.columns
.date-range-filter.field
= label_tag nil, t(:date_range)
.date-range-fields{ data: { controller: "flatpickr", "flatpickr-mode-value": "range", "flatpickr-default-date": "{{ [q.completed_at_gteq, q.completed_at_lteq] }}" } }
.date-range-fields{ data: { controller: "flatpickr", "flatpickr-mode-value": "range" } }
= text_field_tag nil, nil, class: "datepicker", data: { "flatpickr-target": "instance", action: "flatpickr_clear@window->flatpickr#clear" }
= text_field_tag "q[completed_at_gteq]", nil, "ng-model": "q.completed_at_gteq", data: { "flatpickr-target": "start" }, style: "display: none"
= text_field_tag "q[completed_at_lteq]", nil, "ng-model": "q.completed_at_lteq", data: { "flatpickr-target": "end" }, style: "display: none"
.field
= label_tag nil, t(:status)
%select2-watch-ng-model{'ng-model': 'q.state_eq'}
= select_tag("q[state_eq]",
options_for_select(Spree::Order.state_machines[:state].states.collect {|s| [t("spree.order_state.#{s.name}"), s.value]}),
{include_blank: true, class: 'select2', 'ng-model' => 'q.state_eq'})
= select_tag("q[state_eq]",
options_for_select(Spree::Order.state_machines[:state].states.collect {|s| [t("spree.order_state.#{s.name}"), s.value]}),
{ include_blank: true, class: "primary", "data-controller": "tom-select" })
.four.columns
.field
= label_tag "q_number_cont", t(:order_number)
= text_field_tag "q[number_cont]", nil, "ng-model" => "q.number_cont", "ng-keypress" => "$event.keyCode === 13 && fetchResults()"
= text_field_tag "q[number_cont]", nil
.field
= label_tag "q_email_cont", t(:email)
= email_field_tag "q[email_cont]", nil, "ng-model" => "q.email_cont", "ng-keypress" => "$event.keyCode === 13 && fetchResults()"
= email_field_tag "q[email_cont]", nil
.four.columns
.field
= label_tag "q_bill_address_firstname_start", t(:first_name_begins_with)
= text_field_tag "q[bill_address_firstname_start]", nil, size: 25, "ng-model" => "q.bill_address_firstname_start", "ng-keypress" => "$event.keyCode === 13 && fetchResults()"
= text_field_tag "q[bill_address_firstname_start]", nil, size: 25
.field
= label_tag "q_bill_address_lastname_start", t(:last_name_begins_with)
= text_field_tag "q[bill_address_lastname_start]", nil, size: 25, "ng-model" => "q.bill_address_lastname_start", "ng-keypress" => "$event.keyCode === 13 && fetchResults()"
= text_field_tag "q[bill_address_lastname_start]", nil, size: 25
.omega.four.columns
.field.checkbox
%label
= check_box_tag "q[completed_at_not_null]", 1, true, {'ng-model' => 'q.completed_at_not_null'}
= check_box_tag "q[completed_at_not_null]", 1, true
= t(:show_only_complete_orders)
.field
= label_tag nil, t(:shipping_method)
%select2-watch-ng-model{'ng-model': 'q.shipping_method_id'}
= select_tag("q[shipping_method_id]",
options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method_names.#{s.name}"), s.id]}),
{include_blank: true, class: 'select2', 'ng-model': 'q.shipping_method_id'})
= select_tag(:shipping_method_id,
options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method_names.#{s.name}"), s.id]}),
{ include_blank: true, class: "primary", "data-controller": "tom-select" })
.field-block.alpha.eight.columns
= label_tag nil, t(:distributors)
%select2-watch-ng-model{'ng-model': 'q.distributor_id_in'}
= select_tag("q[distributor_id_in]",
options_for_select(Enterprise.is_distributor.managed_by(spree_current_user).map {|e| [e.name, e.id]}, params[:distributor_ids]),
{class: "select2 fullwidth", multiple: true, 'ng-model' => 'q.distributor_id_in'})
= select_tag("q[distributor_id_in]",
options_for_select(Enterprise.is_distributor.managed_by(spree_current_user).map {|e| [e.name, e.id]}, params[:distributor_ids]),
{ class: "fullwidth", multiple: true, data: { controller: "tom-select", "tom-select-options-value": { plugins: ['remove_button'], maxItems: nil } }})
.field-block.omega.eight.columns
= label_tag nil, t(:order_cycles)
%select2-watch-ng-model{'ng-model': 'q.order_cycle_id_in'}
= select_tag("q[order_cycle_id_in]",
options_for_select(OrderCycle.managed_by(spree_current_user).where('order_cycles.orders_close_at is not null').order('order_cycles.orders_close_at DESC').map {|oc| [oc.name, oc.id]}, params[:order_cycle_ids]),
{class: "select2 fullwidth", multiple: true, 'ng-model' => 'q.order_cycle_id_in'})
= select_tag("q[order_cycle_id_in]",
options_for_select(OrderCycle.managed_by(spree_current_user).where('order_cycles.orders_close_at is not null').order('order_cycles.orders_close_at DESC').map {|oc| [oc.name, oc.id]}, params[:order_cycle_ids]),
{ class: "fullwidth", multiple: true, data: { controller: "tom-select", "tom-select-options-value": { plugins: ['remove_button'], maxItems: nil } }})
.clearfix
.actions.filter-actions
%a.button.icon-search{'ng-click' => 'fetchResults()'}
%button{type: "submit", class: "button"}
%i.icon-search
= t(:filter_results)
%a.button{'ng-click' => 'clearFilters()', "id": "clear_filters_button"}
%button{"id": "clear_filters_button", type: "button", "data-controller": "search", "data-action": "click->search#reset" }
= t(:clear_filters)

View File

@@ -0,0 +1,30 @@
.row.index-controls
%div{ style: "display: flex; justify-content: space-between;" }
= render partial: "bulk_actions"
.per-page.right
= render partial: 'admin/shared/stimulus_page_controls', locals: { pagy: pagy }
%table#listing_orders.index.responsive{width: "100%" }
%colgroup
%col{style: "width: 3%"}
%thead
%tr
%th
%input#selectAll{ type: 'checkbox', data: { "checked-target": "all", action: "change->checked#toggleAll" } }
%th
= t(:products_distributor)
- columns = ['completed_at', 'number', 'state', 'payment_state', 'shipment_state', 'email', 'bill_address_lastname', 'total']
= render partial: "spree/admin/shared/stimulus_sortable_header", collection: columns, as: :column,
locals: { sorted: params.dig(:q, :s), default: "completed_at desc" }
%th.actions
%tbody
= render partial: "table_row", collection: orders, as: :order
- if pagy&.count&.positive?
= render partial: "admin/shared/stimulus_pagination", locals: { pagy: pagy }
- else
.no-objects-found= t('spree.admin.orders.index.no_orders_found')

View File

@@ -0,0 +1,48 @@
%tr{ id: dom_id(order), class: "state-#{order.state}" }
%td.align-center
%input{type: 'checkbox', value: order.id, name: 'order_ids[]', "data-checked-target": "checkbox", "data-action": "change->checked#toggleCheckbox" }
%td.align-center
= order.distributor.name
%td.align-center
= I18n.l(order.completed_at, format: '%B %d, %Y') if order.completed_at
%td
%a{ href: edit_admin_order_path(order) }
= order.number
- if order.special_instructions
%div
%br
%span.icon-warning-sign{'ofn-with-tip' => order.special_instructions.to_s }
= t('spree.admin.orders.index.note')
%td.align-center
%span.state{ class: order.state.to_s }
= t('js.admin.orders.order_state.' + order.state.to_s)
%td.align-center
- if order.payment_state
%span.state{class: 'order.payment_state'}
%a{href: spree.admin_order_payments_path(order) }
= t('js.admin.orders.payment_states.' + order.payment_state.to_s)
- if order.display_outstanding_balance
%span
= "(#{order.display_outstanding_balance})"
%td.align-center
- if order.shipment_state
%span.state{class: order.shipment_state.to_s}
= t('js.admin.orders.shipment_states.' + order.shipment_state.to_s)
%td
%a{ href: "mailto:#{order.email}", target: "_blank" }
= order.email
%td
= order.bill_address.full_name
%td.align-center
%span
= order.display_total
%td.actions
.flex
%div.row-loading-icons
- if local_assigns[:success]
%i.success.icon-ok-sign{"data-controller": "ephemeral"}
%a.icon_link.with-tip.icon-edit.no-text{href: edit_admin_order_path(order), 'ofn-with-tip' => t('spree.admin.orders.index.edit')}
- if order.ready_to_ship?
%button.icon-road.icon_link.with-tip.no-text{rel: 'nofollow', 'ofn-with-tip' => t('spree.admin.orders.index.ship')}
- if order.payment_required? && order.pending_payments.reject(&:requires_authorization?).any?
%button.icon-capture.icon_link.no-text{rel: 'nofollow', 'ofn-with-tip' => t('spree.admin.orders.index.capture')}

View File

@@ -9,120 +9,14 @@
= render partial: 'spree/admin/shared/order_sub_menu'
- content_for :main_ng_app_name do
= "ofn.admin"
- content_for :main_ng_ctrl_name do
= "ordersCtrl"
- content_for :table_filter_title do
= t(:search)
- content_for :table_filter do
= render partial: 'filters'
.row.index-controls{'ng-show' => '!RequestMonitor.loading && orders.length > 0'}
%div{style: "display: flex; justify-content: space-between;"}
.ofn-drop-down-with-prepend
.ofn-drop-down-prepend{"ng-class": "selected_orders.length == 0 ? 'disabled' : ''"}
{{ "spree.admin.orders.index.selected" | t:{count: selected_orders.length} }}
.ofn-drop-down{"ng-class": "selected_orders.length == 0 ? 'disabled' : ''"}
%span{ :class => 'icon-reorder' }
="#{t('admin.actions')}".html_safe
%span{ 'ng-class' => "expanded && 'icon-caret-up' || !expanded && 'icon-caret-down'" }
%div.menu{ 'ng-show' => "expanded" }
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "resend_confirmation" }
= t('.resend_confirmation')
- if Spree::Config[:enable_invoices?]
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "send_invoice" }
= t('.send_invoice')
%div.menu_item
%span.name.invoices-modal{'ng-controller' => 'bulkInvoiceCtrl', 'ng-click' => 'createBulkInvoice()' }
= t('.print_invoices')
%div.menu_item
%span.name{ "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "cancel_orders" }
= t('.cancel_orders')
= render partial: 'admin/shared/angular_per_page_controls', locals: { position: "right", model: "orders" }
%table#listing_orders.index.responsive{width: "100%", 'ng-init' => 'initialise()', 'ng-show' => "!RequestMonitor.loading && orders.length > 0" }
%colgroup
%col{style: "width: 3%"}
%thead
%tr
%th
%input#selectAll{type: 'checkbox', 'ng-change' => 'toggleAll()', 'ng-model' => 'select_all'}
%th
= t(:products_distributor)
%th
%a{'ng-click' => "sortOptions.toggle('completed_at')"}
= t(:completed_at, scope: 'activerecord.attributes.spree/order')
%span{'ng-show' => "sorting == 'completed_at asc'"}= "&#x25B2;".html_safe
%span{'ng-show' => "sorting == 'completed_at desc' || sorting === undefined"}= "&#x25BC;".html_safe
- ['number', 'state', 'payment_state', 'shipment_state', 'email', 'bill_address_lastname', 'total'].each do |column_name|
%th
= render partial: 'spree/admin/shared/sortable_header', locals: {column_name: column_name}
%th.actions
%tbody
%tr{ng: {repeat: 'order in orders track by order.id', class: {even: "'even'", odd: "'odd'"}}, 'ng-class' => "{'state-{{order.state}}': true, 'row-loading': rowStatus[order.id] == 'loading'}"}
%td.align-center
%input{type: 'checkbox', 'ng-model' => 'checkboxes[order.id]', 'ng-change' => 'toggleSelection(order.id)', value: '{{order.id}}', name: 'order_ids[]'}
%td.align-center
{{order.distributor_name}}
%td.align-center
{{order.completed_at}}
%td
%a{'ng-href' => '{{order.edit_path}}'}
{{order.number}}
%div{'ng-if' => 'order.special_instructions'}
%br
%span.icon-warning-sign{'ofn-with-tip' => "{{order.special_instructions}}"}
= t('.note')
%td.align-center
%span.state{'ng-class' => 'order.state'}
{{'js.admin.orders.order_state.' + order.state | t}}
%td.align-center
%span.state{'ng-class' => 'order.payment_state', 'ng-if' => 'order.payment_state'}
%a{'ng-href' => '{{order.payments_path}}' }
{{'js.admin.orders.payment_states.' + order.payment_state | t}}
%span{'ng-if' => 'order.display_outstanding_balance'}
({{order.display_outstanding_balance}})
%td.align-center
%span.state{'ng-class' => 'order.shipment_state', 'ng-if' => 'order.shipment_state'}
{{'js.admin.orders.shipment_states.' + order.shipment_state | t}}
%td
%a{ ng: { href: "mailto:{{order.email}}" } }
{{order.email}}
%td
{{order.full_name}}
%td.align-center
%span{'ng-bind-html' => 'order.display_total'}
%td.actions
%div.row-loading-icons
%div{ng: {show: 'rowStatus[order.id] == "loading"', cloak: true}, style: "width: 30px; height: 30px;"}
= render partial: "components/spinner"
%i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} }
%i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')}
%a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')}
%div{'ng-if' => 'order.ready_to_ship'}
%button.icon-road.icon_link.with-tip.no-text{'ng-click' => 'shipOrder(order)', rel: 'nofollow', 'ofn-with-tip' => t('.ship')}
%div{'ng-if' => 'order.ready_to_capture'}
%button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')}
.sixteen.columns.alpha#loading{ 'ng-show' => 'RequestMonitor.loading' }
= render partial: "components/admin_spinner"
%h1
= t('.loading')
%div{'ng-show' => "!RequestMonitor.loading && orders.length > 0" }
= render partial: 'admin/shared/angular_pagination'
.no-objects-found{'ng-show' => "!RequestMonitor.loading && orders.length == 0"}
= t('.no_orders_found')
#orders-index{"data-controller": "search checked"}
= render partial: "table", locals: { pagy: @pagy, orders: @orders }
= render 'spree/admin/shared/custom-confirm'

View File

@@ -0,0 +1,8 @@
%th
%a{ "data-action": "click->search#changeSorting", "data-column": "#{column}", "data-current": sorted.to_s }
= t("spree.admin.shared.sortable_header.#{column.to_s}")
- if sorted == "#{column} asc" || sorted.blank? && local_assigns[:default] == "#{column} asc"
= "&#x25B2;".html_safe
- if sorted == "#{column} desc" || sorted.blank? && local_assigns[:default] == "#{column} desc"
= "&#x25BC;".html_safe

View File

@@ -1,7 +1,7 @@
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path, icon: 'icon-dashboard'
= tab :products, :properties, :inventory, :product_import, :images, :variants, :product_properties, :group_buy_options, :seo, url: admin_products_path, icon: 'icon-th-large'
= tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh'
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path('q[s]' => 'completed_at desc'), icon: 'icon-shopping-cart'
= tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path, icon: 'icon-shopping-cart'
= tab :reports, url: main_app.admin_reports_path, icon: 'icon-file'
= tab :general_settings, :mail_methods, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path
= tab :enterprises, :enterprise_relationships, :vouchers, :oidc_settings, url: main_app.admin_enterprises_path

View File

@@ -6,9 +6,7 @@ export default class extends ApplicationController {
}
confirm() {
const send_cancellation_email = document.querySelector(
"#send_cancellation_email"
).checked;
const send_cancellation_email = document.querySelector("#send_cancellation_email").checked;
const restock_items = document.querySelector("#restock_items").checked;
const order_ids = [];
@@ -23,8 +21,7 @@ export default class extends ApplicationController {
send_cancellation_email: send_cancellation_email,
restock_items: restock_items,
};
this.stimulate("CancelOrdersReflex#confirm", params).then(() =>
window.location.reload()
);
this.stimulate("CancelOrdersReflex#confirm", params);
}
}

View File

@@ -1,19 +1,39 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["all", "checkbox"];
static targets = ["all", "checkbox", "disable"];
connect() {
this.toggleCheckbox()
this.toggleCheckbox();
}
toggleAll() {
this.checkboxTargets.forEach(checkbox => {
this.checkboxTargets.forEach((checkbox) => {
checkbox.checked = this.allTarget.checked;
});
this.#toggleDisabled();
}
toggleCheckbox() {
this.allTarget.checked = this.checkboxTargets.every(checkbox => checkbox.checked);
this.allTarget.checked = this.checkboxTargets.every((checkbox) => checkbox.checked);
this.#toggleDisabled();
}
// private
#toggleDisabled() {
if (!this.hasDisableTarget) {
return;
}
if (this.#noneChecked()) {
this.disableTargets.forEach((element) => element.classList.add("disabled"));
} else {
this.disableTargets.forEach((element) => element.classList.remove("disabled"));
}
}
#noneChecked() {
return this.checkboxTargets.every((checkbox) => !checkbox.checked);
}
}

View File

@@ -0,0 +1,16 @@
import { Controller } from "stimulus";
export default class extends Controller {
connect() {
setTimeout(this.fadeout, 1500);
}
fadeout = () => {
this.element.classList.add("animate-hide-500");
setTimeout(this.remove, 500);
};
remove = () => {
this.element.remove();
};
}

View File

@@ -0,0 +1,68 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["form"];
connect() {
this.#setup();
}
changePage(event) {
this.page.value = event.target.dataset.page;
this.submitSearch();
this.page.value = 1;
}
changePerPage(event) {
this.per_page.value = parseInt(event.target.value);
this.submitSearch();
}
changeSorting(event) {
let current = event.target.dataset.current;
let column = event.target.dataset.column;
this.sort.value = current === `${column} asc` ? `${column} desc` : `${column} asc`;
this.submitSearch();
}
submitSearch() {
this.form.requestSubmit();
}
reset() {
this.clearForm();
this.submitSearch();
}
clearForm() {
this.form.reset();
this.#clearCustomElements();
if (this.page) this.page.value = 1;
if (this.sort) this.sort.value = this.sort.dataset.default;
}
// private
#setup() {
if (this.hasFormTarget) {
this.form = this.formTarget;
this.form.controller = this;
} else {
this.form = document.querySelector("form[data-search-target=form]");
}
this.page = this.form.querySelector(".page");
this.per_page = this.form.querySelector(".per-page");
this.sort = this.form.querySelector(".sort");
}
#clearCustomElements() {
window.dispatchEvent(new CustomEvent("flatpickr:clear"));
this.form.querySelectorAll(".tomselected").forEach((select) => {
select.tomselect?.clear();
});
}
}

View File

@@ -10,6 +10,16 @@
}
}
@keyframes fade-out-hide {
0% {opacity: 1; visibility: visible;}
99% {opacity: 0; visibility: visible;}
100% {opacity: 0; visibility: hidden;}
}
.animate-hide-500 {
animation: fade-out-hide 0.5s;
}
// @-webkit-keyframes slideOutDown
// 0%
// -webkit-transform: translateY(0)

View File

@@ -1,6 +1,6 @@
input[type="submit"],
input[type="button"],
button,
button:not(.plain),
.button {
position: relative;
cursor: pointer;

View File

@@ -10,6 +10,10 @@
margin-right: 1em;
margin-left: 0;
}
.ts-control > * {
padding-right: 2.75em;
}
}
.per-page-feedback {

View File

@@ -1,5 +1,14 @@
.ts-wrapper {
min-height: initial;
}
.ts-dropdown {
margin-top: 0;
.option {
min-height: 2.25em;
display: block;
}
}
.ts-wrapper.single .ts-control,
@@ -45,6 +54,10 @@
}
}
.ts-wrapper .select-multiple {
cursor: pointer;
}
.ts-wrapper.dropdown-active.primary .ts-control {
background-color: $spree-green;
border-color: $spree-green;

View File

@@ -6,130 +6,156 @@
margin-left: 3px;
}
.ofn-drop-down:hover, .ofn-drop-down.expanded {
border: 1px solid #adadad;
color: #575757;
.ofn-drop-down {
.dropdown-content {
display: none;
}
.toggle-off {
display: none;
}
&:active:not(.disabled),
&:focus:not(.disabled) {
.dropdown-content {
display: inline-block;
}
.toggle-off {
display: inline-block;
}
.toggle-on {
display: none;
}
}
}
.ofn-drop-down:hover,
.ofn-drop-down.expanded {
border: 1px solid #adadad;
color: #575757;
}
@mixin ofn-drop-down-style {
padding: 7px 15px;
border-radius: 3px;
border: 1px solid #d4d4d4;
background-color: #f5f5f5;
display: block;
color: #828282;
cursor: pointer;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
padding: 7px 15px;
border-radius: 3px;
border: 1px solid #d4d4d4;
background-color: #f5f5f5;
display: block;
color: #828282;
cursor: pointer;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
margin-right: 10px;
&.disabled {
opacity: 0.5;
&:hover {
cursor: default;
border-color: #d4d4d4;
color: #828282;
}
}
&.disabled {
opacity: 0.5;
&:hover {
cursor: default;
border-color: #d4d4d4;
color: #828282;
}
}
}
.ofn-drop-down-with-prepend {
display: flex;
display: flex;
&.right {
float: right;
&.right {
float: right;
}
}
.ofn-drop-down {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.ofn-drop-down {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.ofn-drop-down-prepend {
@include ofn-drop-down-style;
.ofn-drop-down-prepend {
@include ofn-drop-down-style;
border-right: none;
margin-left: 0;
margin-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
cursor: default;
}
border-right: none;
margin-left: 0;
margin-right: 0;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
cursor: default;
}
}
.ofn-drop-down {
@include ofn-drop-down-style;
@include ofn-drop-down-style;
position: relative;
float: left;
position: relative;
float: left;
&.right {
float: right;
&.right {
float: right;
margin-right: 0px;
margin-left: 10px;
}
}
&:hover, &.expanded {
&:hover,
&.expanded {
border: 1px solid #adadad;
color: #575757;
}
> span {
width: auto;
text-transform: uppercase;
font-size: 85%;
font-weight: 600;
}
> span {
width: auto;
text-transform: uppercase;
font-size: 85%;
font-weight: 600;
}
.menu {
margin-top: 1px;
position: absolute;
float: none;
top:100%;
left: 0px;
padding: 5px 0px;
border: 1px solid #adadad;
background-color: #ffffff;
box-shadow: 1px 3px 10px #888888;
z-index: 100;
.menu {
margin-top: 1px;
position: absolute;
float: none;
top: 100%;
left: 0px;
padding: 5px 0px;
border: 1px solid #adadad;
background-color: #ffffff;
box-shadow: 1px 3px 10px #888888;
z-index: 100;
white-space: nowrap;
.filter {
padding-left: 5px;
padding-right: 5px;
position: relative;
> input[type="text"] {
border: 1px solid rgba(18, 18, 18, 0.1);
width: 100%;
padding-left: 30px;
padding-top: 10px;
padding-bottom: 10px;
font-size: 13px;
color:#454545;
}
.filter {
padding-left: 5px;
padding-right: 5px;
position: relative;
&:after {
content: "\f002";
font-family: FontAwesome;
position: absolute;
left: 15px;
top: 13px;
color:#454545;
}
}
> input[type="text"] {
border: 1px solid rgba(18, 18, 18, 0.1);
width: 100%;
padding-left: 30px;
padding-top: 10px;
padding-bottom: 10px;
font-size: 13px;
color: #454545;
}
.menu_item {
margin: 0px;
padding: 2px 10px;
color: #454545;
text-align: left;
&:after {
content: "\f002";
font-family: FontAwesome;
position: absolute;
left: 15px;
top: 13px;
color: #454545;
}
}
.menu_item {
margin: 0px;
padding: 2px 10px;
color: #454545;
text-align: left;
display: block;
.check {
@@ -146,78 +172,79 @@
padding: 0px 15px 0px 0px;
}
&.selected{
&.selected {
.check:before {
content: "\2713";
}
}
&.hidden {
display: none;
}
}
&.hidden {
display: none;
}
}
.menu_item:hover {
background-color: #ededed;
}
}
.menu_item:hover {
background-color: #ededed;
}
}
}
.ofn-drop-down-v2 {
border: 1px solid $pale-blue;
background-color: white;
padding: 0px;
&:hover {
border-color: $spree-blue;
}
border: 1px solid $pale-blue;
background-color: white;
padding: 0px;
.ofn-drop-down-label {
color: $color-3;
padding: 10px;
width: 235px;
display: flex;
justify-content: space-between;
&:hover {
border-color: $spree-blue;
}
&:hover {
color: $color-3;
}
.ofn-drop-down-label {
color: $color-3;
padding: 10px;
width: 235px;
display: flex;
justify-content: space-between;
.label {
padding-right: 10px;
}
&:hover {
color: $color-3;
}
.icon-caret-down, .icon-caret-up {
padding-right: 0px;
}
}
.label {
padding-right: 10px;
}
.menu {
width: 100%;
}
.icon-caret-down,
.icon-caret-up {
padding-right: 0px;
}
}
.menu_items {
max-height: 200px;
overflow-y: scroll;
.menu {
width: 100%;
}
.menu_item {
margin-bottom: 5px;
color: #454545;
font-weight: 400;
cursor: pointer;
padding-top: 4px;
padding-bottom: 5px;
text-transform: uppercase;
font-size: 85%;
}
}
.menu_items {
max-height: 200px;
overflow-y: scroll;
.menu_item {
margin-bottom: 5px;
color: #454545;
font-weight: 400;
cursor: pointer;
padding-top: 4px;
padding-bottom: 5px;
text-transform: uppercase;
font-size: 85%;
}
}
}
.ofn-drop-down.ofn-drop-down-v2 {
// Add very specific styling here for components that are in transition:
// ie. the ones using the two classes above
.ofn-drop-down-label {
padding-top: 7px;
padding-bottom: 7px;
}
// Add very specific styling here for components that are in transition:
// ie. the ones using the two classes above
.ofn-drop-down-label {
padding-top: 7px;
padding-bottom: 7px;
}
}

View File

@@ -1,12 +1,12 @@
$text-inputs:
"input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel]";
$text-inputs: "input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel]";
#{$text-inputs},
input[type="date"],
input[type="datetime"],
input[type="time"],
input[type="number"],
textarea, fieldset {
textarea,
fieldset {
@include border-radius($border-radius);
padding: 7px 10px;
border: 1px solid $color-txt-brd;
@@ -48,7 +48,9 @@ label {
}
}
.label-block label { display: block }
.label-block label {
display: block;
}
span.info {
font-style: italic;
@@ -63,7 +65,7 @@ span.info {
padding: 10px 0;
&.checkbox {
min-height: 73px;
min-height: 70px;
input[type="checkbox"] {
display: inline-block;
@@ -85,7 +87,6 @@ span.info {
display: inline-block;
padding-right: 10px;
label {
font-weight: normal;
text-transform: none;
@@ -171,14 +172,18 @@ fieldset {
display: inline-block;
}
button, .button, input[type="submit"], input[type="button"], span.or {
button,
.button,
input[type="submit"],
input[type="button"],
span.or {
@include border-radius($border-radius);
-webkit-box-shadow: 0 0 0 15px $color-1;
-moz-box-shadow: 0 0 0 15px $color-1;
-ms-box-shadow: 0 0 0 15px $color-1;
-o-box-shadow: 0 0 0 15px $color-1;
box-shadow: 0 0 0 15px $color-1;
-moz-box-shadow: 0 0 0 15px $color-1;
-ms-box-shadow: 0 0 0 15px $color-1;
-o-box-shadow: 0 0 0 15px $color-1;
box-shadow: 0 0 0 15px $color-1;
&:hover {
border-color: $color-1;
@@ -197,10 +202,10 @@ fieldset {
position: relative;
-webkit-box-shadow: 0 0 0 5px $color-1;
-moz-box-shadow: 0 0 0 5px $color-1;
-ms-box-shadow: 0 0 0 5px $color-1;
-o-box-shadow: 0 0 0 5px $color-1;
box-shadow: 0 0 0 5px $color-1;
-moz-box-shadow: 0 0 0 5px $color-1;
-ms-box-shadow: 0 0 0 5px $color-1;
-o-box-shadow: 0 0 0 5px $color-1;
box-shadow: 0 0 0 5px $color-1;
}
}
@@ -210,7 +215,8 @@ fieldset {
display: table;
width: 100%;
label, input {
label,
input {
display: table-cell !important;
}
input {
@@ -219,7 +225,7 @@ fieldset {
&.checkbox {
input {
width: auto !important
width: auto !important;
}
}
}
@@ -247,11 +253,12 @@ select {
align-items: center;
margin-top: 3px;
input, label {
input,
label {
cursor: pointer;
}
label {
margin: 0;
padding-left: .4rem;
padding-left: 0.4rem;
}
}

View File

@@ -4285,6 +4285,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
sortable_header:
name: "Name"
number: "Number"
completed_at: "Completed At"
state: "State"
payment_state: "Payment State"
shipment_state: "Shipment State"