mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-11 23:17:48 +00:00
12398: add slide-out animation
This commit is contained in:
@@ -12,8 +12,7 @@ class ConfirmModalComponent < ModalComponent
|
||||
confirm_button_class: :primary,
|
||||
confirm_button_text: I18n.t('js.admin.modals.confirm'),
|
||||
cancel_button_text: I18n.t('js.admin.modals.cancel'),
|
||||
actions_alignment_class: 'justify-space-around',
|
||||
confirm_submit_method: nil
|
||||
actions_alignment_class: 'justify-space-around'
|
||||
)
|
||||
super(id:, close_button: true)
|
||||
@confirm_actions = confirm_actions
|
||||
@@ -25,7 +24,6 @@ class ConfirmModalComponent < ModalComponent
|
||||
@confirm_button_text = confirm_button_text
|
||||
@cancel_button_text = cancel_button_text
|
||||
@actions_alignment_class = actions_alignment_class
|
||||
@confirm_submit_method = confirm_submit_method
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -7,9 +7,4 @@
|
||||
|
||||
%div{ class: "modal-actions #{@actions_alignment_class}" }
|
||||
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: @cancel_button_text, "data-action": "click->modal#close" }
|
||||
- # TODO: This if block needs to be removed when we completely get rid of Reflex
|
||||
- # The button's form action will be dynamically set when the modal is opened via modal-link-controller
|
||||
- if @confirm_submit_method
|
||||
= button_to @confirm_button_text, '', id: 'modal-confirm-button', method: @confirm_submit_method, data: { action: @confirm_actions }
|
||||
- else
|
||||
%input{ id: 'modal-confirm-button', class: "button icon-plus #{@confirm_button_class}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes }
|
||||
%input{ id: 'modal-confirm-button', class: "button icon-plus #{@confirm_button_class}", type: 'button', value: @confirm_button_text, "data-action": @confirm_actions, "data-reflex": @confirm_reflexes }
|
||||
|
||||
@@ -37,14 +37,16 @@ module Admin
|
||||
{ id: params[:id] }
|
||||
).find_product
|
||||
|
||||
status = :ok
|
||||
if @record.destroy
|
||||
flash[:success] = I18n.t('admin.products_v3.delete_product.success')
|
||||
else
|
||||
flash[:error] = I18n.t('admin.products_v3.delete_product.error')
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :destroy_product_variant }
|
||||
format.turbo_stream { render :destroy_product_variant, status: }
|
||||
end
|
||||
|
||||
# using flash with turbo stream doesn't clear it because the page is not refreshed.
|
||||
@@ -56,14 +58,16 @@ module Admin
|
||||
@record = Spree::Variant.active.find(params[:id])
|
||||
authorize! :delete, @record
|
||||
|
||||
status = :ok
|
||||
if VariantDeleter.new.delete(@record)
|
||||
flash[:success] = I18n.t('admin.products_v3.delete_variant.success')
|
||||
else
|
||||
flash[:error] = I18n.t('admin.products_v3.delete_variant.error')
|
||||
status = :internal_server_error
|
||||
end
|
||||
|
||||
respond_with do |format|
|
||||
format.turbo_stream { render :destroy_product_variant }
|
||||
format.turbo_stream { render :destroy_product_variant, status: }
|
||||
end
|
||||
|
||||
flash.discard
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
cancel_button_text: t("#{base_translation_key}.cancellation_text"),
|
||||
confirm_button_class: :red,
|
||||
actions_alignment_class: 'justify-end',
|
||||
confirm_reflexes: "click->products#delete_#{object_type}",
|
||||
confirm_actions: "click->modal#close",
|
||||
confirm_submit_method: :delete,
|
||||
controller: "products",
|
||||
confirm_actions: "click->products#delete_#{object_type} click->modal#close",
|
||||
)
|
||||
= render delete_modal do
|
||||
%h2.margin-bottom-20.black-text
|
||||
|
||||
@@ -43,5 +43,5 @@
|
||||
= link_to t('admin.products_page.actions.clone'), clone_admin_product_path(product), 'data-turbo': false
|
||||
%a{ "data-controller": "modal-link", "data-action": "click->modal-link#setModalDataSetOnConfirm click->modal-link#open",
|
||||
"data-modal-link-target-value": "product-delete-modal", "class": "delete",
|
||||
"data-modal-link-modal-dataset-value": {'data-path': admin_product_destroy_path(product)}.to_json }
|
||||
"data-modal-link-modal-dataset-value": {'data-delete-path': admin_product_destroy_path(product)}.to_json }
|
||||
= t('admin.products_page.actions.delete')
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
- if variant.product.variants.size > 1
|
||||
%a{ "data-controller": "modal-link", "data-action": "click->modal-link#setModalDataSetOnConfirm click->modal-link#open",
|
||||
"data-modal-link-target-value": "variant-delete-modal", "class": "delete",
|
||||
"data-modal-link-modal-dataset-value": {'data-path': admin_destroy_variant_path(variant)}.to_json }
|
||||
"data-modal-link-modal-dataset-value": {'data-delete-path': admin_destroy_variant_path(variant)}.to_json }
|
||||
= t('admin.products_page.actions.delete')
|
||||
- else
|
||||
%a{ 'data-action': "nested-form#remove", class: 'delete' }
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
- # @record can either be Product or Variant
|
||||
= turbo_stream.remove dom_id(@record)
|
||||
= render partial: "admin/shared/flashes", locals: { flashes: flash } if defined? flash
|
||||
- unless flash[:error]
|
||||
= turbo_stream.remove(dom_id(@record))
|
||||
-# Without +formats+ option here, by default render is trying to render the equivalant turbo stream
|
||||
-# It's strange that it works just fine if I remove the +unless+ above
|
||||
= render(partial: 'admin/shared/flashes', locals: { flashes: flash }, formats: [:html])
|
||||
|
||||
@@ -17,9 +17,6 @@ export default class extends Controller {
|
||||
const modalId = this.targetValue;
|
||||
const moodalConfirmButtonQuery = `#${modalId} #modal-confirm-button`;
|
||||
const confirmButton = document.querySelector(moodalConfirmButtonQuery);
|
||||
|
||||
this.#setPathToFormAction(confirmButton);
|
||||
|
||||
Object.keys(this.modalDatasetValue).forEach((datasetKey) => {
|
||||
confirmButton.setAttribute(datasetKey, this.modalDatasetValue[datasetKey]);
|
||||
});
|
||||
@@ -33,16 +30,4 @@ export default class extends Controller {
|
||||
getIdentifier() {
|
||||
return "modal";
|
||||
}
|
||||
|
||||
#setPathToFormAction(confirmButton) {
|
||||
const isSubmitButton = confirmButton.type === 'submit';
|
||||
const path = this.modalDatasetValue['data-path'];
|
||||
|
||||
if(isSubmitButton && path){
|
||||
const form = confirmButton.parentElement;
|
||||
form.setAttribute('action', path);
|
||||
|
||||
delete this.modalDatasetValue['data-path'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,14 @@ export default class extends ApplicationController {
|
||||
this.hideLoading();
|
||||
}
|
||||
|
||||
delete_product() {
|
||||
this.#deleteByRecordType('product');
|
||||
}
|
||||
|
||||
delete_variant() {
|
||||
this.#deleteByRecordType('variant');
|
||||
}
|
||||
|
||||
showLoading = () => {
|
||||
if (this.getLoadingController()) {
|
||||
this.getLoadingController().showLoading();
|
||||
@@ -39,4 +47,45 @@ export default class extends ApplicationController {
|
||||
"loading"
|
||||
));
|
||||
};
|
||||
|
||||
// +recordType+ can either be 'product' or 'variant'
|
||||
#deleteByRecordType(recordType) {
|
||||
const deletePath = document.querySelector(`#${recordType}-delete-modal #modal-confirm-button`).getAttribute('data-delete-path');
|
||||
const elementToBeRemoved = this.#getElementToBeRemoved(deletePath, recordType);
|
||||
|
||||
const handleSlideOutAnimationEnd = async () => {
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
|
||||
try {
|
||||
const response = await fetch(deletePath, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Accept: 'text/vnd.turbo-stream.html',
|
||||
'X-CSRF-Token': csrfToken,
|
||||
}
|
||||
});
|
||||
// need to render the turboStream message, that's why not throwing error here
|
||||
if(response.status === 500) elementToBeRemoved.classList.remove('slide-out');
|
||||
|
||||
const responseTurboStream = await response.text();
|
||||
Turbo.renderStreamMessage(responseTurboStream);
|
||||
} catch(error) {
|
||||
console.error(error.message);
|
||||
elementToBeRemoved.classList.remove('slide-out');
|
||||
}
|
||||
finally {
|
||||
elementToBeRemoved.removeEventListener('animationend', handleSlideOutAnimationEnd);
|
||||
}
|
||||
};
|
||||
|
||||
elementToBeRemoved.classList.add('slide-out');
|
||||
elementToBeRemoved.addEventListener('animationend', handleSlideOutAnimationEnd);
|
||||
};
|
||||
|
||||
#getElementToBeRemoved(path, recordType) {
|
||||
const recordId = path.substring(path.lastIndexOf('/') + 1);
|
||||
const elementDomId = `${recordType}_${recordId}`;
|
||||
|
||||
return document.getElementById(elementDomId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -413,4 +413,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideOutLeft {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
transform: translateX(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-out {
|
||||
animation: slideOutLeft 0.5s forwards;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user