This commit is contained in:
@@ -12205,6 +12205,91 @@ blockquote {
|
||||
font-family: "Gloria Hallelujah", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Toastify js 1.12.0
|
||||
* https://github.com/apvarun/toastify-js
|
||||
* @license MIT licensed
|
||||
*
|
||||
* Copyright (C) 2018 Varun A P
|
||||
*/
|
||||
.toastify {
|
||||
padding: 12px 20px;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
box-shadow: 0 3px 6px -1px rgba(0, 0, 0, 0.12), 0 10px 36px -4px rgba(77, 96, 232, 0.3);
|
||||
background: linear-gradient(135deg, #73a5ff, #5477f5);
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
max-width: calc(50% - 20px);
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
.toastify.on {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 1em;
|
||||
opacity: 0.4;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.toastify-right {
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.toastify-left {
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
.toastify-top {
|
||||
top: -150px;
|
||||
}
|
||||
|
||||
.toastify-bottom {
|
||||
bottom: -150px;
|
||||
}
|
||||
|
||||
.toastify-rounded {
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.toastify-avatar {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
margin: -7px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.toastify-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
max-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 360px) {
|
||||
.toastify-right,
|
||||
.toastify-left {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: -moz-fit-content;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
.chuck-norris-joke {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -768,26 +768,132 @@
|
||||
*/const NAME='toast';const DATA_KEY='bs.toast';const EVENT_KEY=`.${DATA_KEY}`;const EVENT_MOUSEOVER=`mouseover${EVENT_KEY}`;const EVENT_MOUSEOUT=`mouseout${EVENT_KEY}`;const EVENT_FOCUSIN=`focusin${EVENT_KEY}`;const EVENT_FOCUSOUT=`focusout${EVENT_KEY}`;const EVENT_HIDE=`hide${EVENT_KEY}`;const EVENT_HIDDEN=`hidden${EVENT_KEY}`;const EVENT_SHOW=`show${EVENT_KEY}`;const EVENT_SHOWN=`shown${EVENT_KEY}`;const CLASS_NAME_FADE='fade';const CLASS_NAME_HIDE='hide';// @deprecated - kept here only for backwards compatibility
|
||||
const CLASS_NAME_SHOW='show';const CLASS_NAME_SHOWING='showing';const DefaultType={animation:'boolean',autohide:'boolean',delay:'number'};const Default={animation:true,autohide:true,delay:5000};/**
|
||||
* Class definition
|
||||
*/class Toast extends BaseComponent{constructor(element,config){super(element,config);this._timeout=null;this._hasMouseInteraction=false;this._hasKeyboardInteraction=false;this._setListeners();}// Getters
|
||||
*/let Toast$1 = class Toast extends BaseComponent{constructor(element,config){super(element,config);this._timeout=null;this._hasMouseInteraction=false;this._hasKeyboardInteraction=false;this._setListeners();}// Getters
|
||||
static get Default(){return Default;}static get DefaultType(){return DefaultType;}static get NAME(){return NAME;}// Public
|
||||
show(){const showEvent=EventHandler.trigger(this._element,EVENT_SHOW);if(showEvent.defaultPrevented){return;}this._clearTimeout();if(this._config.animation){this._element.classList.add(CLASS_NAME_FADE);}const complete=()=>{this._element.classList.remove(CLASS_NAME_SHOWING);EventHandler.trigger(this._element,EVENT_SHOWN);this._maybeScheduleHide();};this._element.classList.remove(CLASS_NAME_HIDE);// @deprecated
|
||||
reflow(this._element);this._element.classList.add(CLASS_NAME_SHOW,CLASS_NAME_SHOWING);this._queueCallback(complete,this._element,this._config.animation);}hide(){if(!this.isShown()){return;}const hideEvent=EventHandler.trigger(this._element,EVENT_HIDE);if(hideEvent.defaultPrevented){return;}const complete=()=>{this._element.classList.add(CLASS_NAME_HIDE);// @deprecated
|
||||
this._element.classList.remove(CLASS_NAME_SHOWING,CLASS_NAME_SHOW);EventHandler.trigger(this._element,EVENT_HIDDEN);};this._element.classList.add(CLASS_NAME_SHOWING);this._queueCallback(complete,this._element,this._config.animation);}dispose(){this._clearTimeout();if(this.isShown()){this._element.classList.remove(CLASS_NAME_SHOW);}super.dispose();}isShown(){return this._element.classList.contains(CLASS_NAME_SHOW);}// Private
|
||||
_maybeScheduleHide(){if(!this._config.autohide){return;}if(this._hasMouseInteraction||this._hasKeyboardInteraction){return;}this._timeout=setTimeout(()=>{this.hide();},this._config.delay);}_onInteraction(event,isInteracting){switch(event.type){case 'mouseover':case 'mouseout':{this._hasMouseInteraction=isInteracting;break;}case 'focusin':case 'focusout':{this._hasKeyboardInteraction=isInteracting;break;}}if(isInteracting){this._clearTimeout();return;}const nextElement=event.relatedTarget;if(this._element===nextElement||this._element.contains(nextElement)){return;}this._maybeScheduleHide();}_setListeners(){EventHandler.on(this._element,EVENT_MOUSEOVER,event=>this._onInteraction(event,true));EventHandler.on(this._element,EVENT_MOUSEOUT,event=>this._onInteraction(event,false));EventHandler.on(this._element,EVENT_FOCUSIN,event=>this._onInteraction(event,true));EventHandler.on(this._element,EVENT_FOCUSOUT,event=>this._onInteraction(event,false));}_clearTimeout(){clearTimeout(this._timeout);this._timeout=null;}// Static
|
||||
static jQueryInterface(config){return this.each(function(){const data=Toast.getOrCreateInstance(this,config);if(typeof config==='string'){if(typeof data[config]==='undefined'){throw new TypeError(`No method named "${config}"`);}data[config](this);}});}}/**
|
||||
static jQueryInterface(config){return this.each(function(){const data=Toast.getOrCreateInstance(this,config);if(typeof config==='string'){if(typeof data[config]==='undefined'){throw new TypeError(`No method named "${config}"`);}data[config](this);}});}};/**
|
||||
* Data API implementation
|
||||
*/enableDismissTrigger(Toast);/**
|
||||
*/enableDismissTrigger(Toast$1);/**
|
||||
* jQuery
|
||||
*/defineJQueryPlugin(Toast);
|
||||
*/defineJQueryPlugin(Toast$1);
|
||||
|
||||
function getDefaultExportFromCjs (x) {
|
||||
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
||||
}
|
||||
|
||||
var toastify$1 = {exports: {}};
|
||||
|
||||
var toastify=toastify$1.exports;var hasRequiredToastify;function requireToastify(){if(hasRequiredToastify)return toastify$1.exports;hasRequiredToastify=1;(function(module){(function(root,factory){if(module.exports){module.exports=factory();}else {root.Toastify=factory();}})(toastify,function(global){// Object initialization
|
||||
var Toastify=function(options){// Returning a new init object
|
||||
return new Toastify.lib.init(options);},// Library version
|
||||
version="1.12.0";// Set the default global options
|
||||
Toastify.defaults={oldestFirst:true,text:"Toastify is awesome!",node:undefined,duration:3000,selector:undefined,callback:function(){},destination:undefined,newWindow:false,close:false,gravity:"toastify-top",positionLeft:false,position:'',backgroundColor:'',avatar:"",className:"",stopOnFocus:true,onClick:function(){},offset:{x:0,y:0},escapeMarkup:true,ariaLive:'polite',style:{background:''}};// Defining the prototype of the object
|
||||
Toastify.lib=Toastify.prototype={toastify:version,constructor:Toastify,// Initializing the object with required parameters
|
||||
init:function(options){// Verifying and validating the input object
|
||||
if(!options){options={};}// Creating the options object
|
||||
this.options={};this.toastElement=null;// Validating the options
|
||||
this.options.text=options.text||Toastify.defaults.text;// Display message
|
||||
this.options.node=options.node||Toastify.defaults.node;// Display content as node
|
||||
this.options.duration=options.duration===0?0:options.duration||Toastify.defaults.duration;// Display duration
|
||||
this.options.selector=options.selector||Toastify.defaults.selector;// Parent selector
|
||||
this.options.callback=options.callback||Toastify.defaults.callback;// Callback after display
|
||||
this.options.destination=options.destination||Toastify.defaults.destination;// On-click destination
|
||||
this.options.newWindow=options.newWindow||Toastify.defaults.newWindow;// Open destination in new window
|
||||
this.options.close=options.close||Toastify.defaults.close;// Show toast close icon
|
||||
this.options.gravity=options.gravity==="bottom"?"toastify-bottom":Toastify.defaults.gravity;// toast position - top or bottom
|
||||
this.options.positionLeft=options.positionLeft||Toastify.defaults.positionLeft;// toast position - left or right
|
||||
this.options.position=options.position||Toastify.defaults.position;// toast position - left or right
|
||||
this.options.backgroundColor=options.backgroundColor||Toastify.defaults.backgroundColor;// toast background color
|
||||
this.options.avatar=options.avatar||Toastify.defaults.avatar;// img element src - url or a path
|
||||
this.options.className=options.className||Toastify.defaults.className;// additional class names for the toast
|
||||
this.options.stopOnFocus=options.stopOnFocus===undefined?Toastify.defaults.stopOnFocus:options.stopOnFocus;// stop timeout on focus
|
||||
this.options.onClick=options.onClick||Toastify.defaults.onClick;// Callback after click
|
||||
this.options.offset=options.offset||Toastify.defaults.offset;// toast offset
|
||||
this.options.escapeMarkup=options.escapeMarkup!==undefined?options.escapeMarkup:Toastify.defaults.escapeMarkup;this.options.ariaLive=options.ariaLive||Toastify.defaults.ariaLive;this.options.style=options.style||Toastify.defaults.style;if(options.backgroundColor){this.options.style.background=options.backgroundColor;}// Returning the current object for chaining functions
|
||||
return this;},// Building the DOM element
|
||||
buildToast:function(){// Validating if the options are defined
|
||||
if(!this.options){throw "Toastify is not initialized";}// Creating the DOM object
|
||||
var divElement=document.createElement("div");divElement.className="toastify on "+this.options.className;// Positioning toast to left or right or center
|
||||
if(!!this.options.position){divElement.className+=" toastify-"+this.options.position;}else {// To be depreciated in further versions
|
||||
if(this.options.positionLeft===true){divElement.className+=" toastify-left";console.warn('Property `positionLeft` will be depreciated in further versions. Please use `position` instead.');}else {// Default position
|
||||
divElement.className+=" toastify-right";}}// Assigning gravity of element
|
||||
divElement.className+=" "+this.options.gravity;if(this.options.backgroundColor){// This is being deprecated in favor of using the style HTML DOM property
|
||||
console.warn('DEPRECATION NOTICE: "backgroundColor" is being deprecated. Please use the "style.background" property.');}// Loop through our style object and apply styles to divElement
|
||||
for(var property in this.options.style){divElement.style[property]=this.options.style[property];}// Announce the toast to screen readers
|
||||
if(this.options.ariaLive){divElement.setAttribute('aria-live',this.options.ariaLive);}// Adding the toast message/node
|
||||
if(this.options.node&&this.options.node.nodeType===Node.ELEMENT_NODE){// If we have a valid node, we insert it
|
||||
divElement.appendChild(this.options.node);}else {if(this.options.escapeMarkup){divElement.innerText=this.options.text;}else {divElement.innerHTML=this.options.text;}if(this.options.avatar!==""){var avatarElement=document.createElement("img");avatarElement.src=this.options.avatar;avatarElement.className="toastify-avatar";if(this.options.position=="left"||this.options.positionLeft===true){// Adding close icon on the left of content
|
||||
divElement.appendChild(avatarElement);}else {// Adding close icon on the right of content
|
||||
divElement.insertAdjacentElement("afterbegin",avatarElement);}}}// Adding a close icon to the toast
|
||||
if(this.options.close===true){// Create a span for close element
|
||||
var closeElement=document.createElement("button");closeElement.type="button";closeElement.setAttribute("aria-label","Close");closeElement.className="toast-close";closeElement.innerHTML="✖";// Triggering the removal of toast from DOM on close click
|
||||
closeElement.addEventListener("click",function(event){event.stopPropagation();this.removeElement(this.toastElement);window.clearTimeout(this.toastElement.timeOutValue);}.bind(this));//Calculating screen width
|
||||
var width=window.innerWidth>0?window.innerWidth:screen.width;// Adding the close icon to the toast element
|
||||
// Display on the right if screen width is less than or equal to 360px
|
||||
if((this.options.position=="left"||this.options.positionLeft===true)&&width>360){// Adding close icon on the left of content
|
||||
divElement.insertAdjacentElement("afterbegin",closeElement);}else {// Adding close icon on the right of content
|
||||
divElement.appendChild(closeElement);}}// Clear timeout while toast is focused
|
||||
if(this.options.stopOnFocus&&this.options.duration>0){var self=this;// stop countdown
|
||||
divElement.addEventListener("mouseover",function(event){window.clearTimeout(divElement.timeOutValue);});// add back the timeout
|
||||
divElement.addEventListener("mouseleave",function(){divElement.timeOutValue=window.setTimeout(function(){// Remove the toast from DOM
|
||||
self.removeElement(divElement);},self.options.duration);});}// Adding an on-click destination path
|
||||
if(typeof this.options.destination!=="undefined"){divElement.addEventListener("click",function(event){event.stopPropagation();if(this.options.newWindow===true){window.open(this.options.destination,"_blank");}else {window.location=this.options.destination;}}.bind(this));}if(typeof this.options.onClick==="function"&&typeof this.options.destination==="undefined"){divElement.addEventListener("click",function(event){event.stopPropagation();this.options.onClick();}.bind(this));}// Adding offset
|
||||
if(typeof this.options.offset==="object"){var x=getAxisOffsetAValue("x",this.options);var y=getAxisOffsetAValue("y",this.options);var xOffset=this.options.position=="left"?x:"-"+x;var yOffset=this.options.gravity=="toastify-top"?y:"-"+y;divElement.style.transform="translate("+xOffset+","+yOffset+")";}// Returning the generated element
|
||||
return divElement;},// Displaying the toast
|
||||
showToast:function(){// Creating the DOM object for the toast
|
||||
this.toastElement=this.buildToast();// Getting the root element to with the toast needs to be added
|
||||
var rootElement;if(typeof this.options.selector==="string"){rootElement=document.getElementById(this.options.selector);}else if(this.options.selector instanceof HTMLElement||typeof ShadowRoot!=='undefined'&&this.options.selector instanceof ShadowRoot){rootElement=this.options.selector;}else {rootElement=document.body;}// Validating if root element is present in DOM
|
||||
if(!rootElement){throw "Root element is not defined";}// Adding the DOM element
|
||||
var elementToInsert=Toastify.defaults.oldestFirst?rootElement.firstChild:rootElement.lastChild;rootElement.insertBefore(this.toastElement,elementToInsert);// Repositioning the toasts in case multiple toasts are present
|
||||
Toastify.reposition();if(this.options.duration>0){this.toastElement.timeOutValue=window.setTimeout(function(){// Remove the toast from DOM
|
||||
this.removeElement(this.toastElement);}.bind(this),this.options.duration);// Binding `this` for function invocation
|
||||
}// Supporting function chaining
|
||||
return this;},hideToast:function(){if(this.toastElement.timeOutValue){clearTimeout(this.toastElement.timeOutValue);}this.removeElement(this.toastElement);},// Removing the element from the DOM
|
||||
removeElement:function(toastElement){// Hiding the element
|
||||
// toastElement.classList.remove("on");
|
||||
toastElement.className=toastElement.className.replace(" on","");// Removing the element from DOM after transition end
|
||||
window.setTimeout(function(){// remove options node if any
|
||||
if(this.options.node&&this.options.node.parentNode){this.options.node.parentNode.removeChild(this.options.node);}// Remove the element from the DOM, only when the parent node was not removed before.
|
||||
if(toastElement.parentNode){toastElement.parentNode.removeChild(toastElement);}// Calling the callback function
|
||||
this.options.callback.call(toastElement);// Repositioning the toasts again
|
||||
Toastify.reposition();}.bind(this),400);// Binding `this` for function invocation
|
||||
}};// Positioning the toasts on the DOM
|
||||
Toastify.reposition=function(){// Top margins with gravity
|
||||
var topLeftOffsetSize={top:15,bottom:15};var topRightOffsetSize={top:15,bottom:15};var offsetSize={top:15,bottom:15};// Get all toast messages on the DOM
|
||||
var allToasts=document.getElementsByClassName("toastify");var classUsed;// Modifying the position of each toast element
|
||||
for(var i=0;i<allToasts.length;i++){// Getting the applied gravity
|
||||
if(containsClass(allToasts[i],"toastify-top")===true){classUsed="toastify-top";}else {classUsed="toastify-bottom";}var height=allToasts[i].offsetHeight;classUsed=classUsed.substr(9,classUsed.length-1);// Spacing between toasts
|
||||
var offset=15;var width=window.innerWidth>0?window.innerWidth:screen.width;// Show toast in center if screen with less than or equal to 360px
|
||||
if(width<=360){// Setting the position
|
||||
allToasts[i].style[classUsed]=offsetSize[classUsed]+"px";offsetSize[classUsed]+=height+offset;}else {if(containsClass(allToasts[i],"toastify-left")===true){// Setting the position
|
||||
allToasts[i].style[classUsed]=topLeftOffsetSize[classUsed]+"px";topLeftOffsetSize[classUsed]+=height+offset;}else {// Setting the position
|
||||
allToasts[i].style[classUsed]=topRightOffsetSize[classUsed]+"px";topRightOffsetSize[classUsed]+=height+offset;}}}// Supporting function chaining
|
||||
return this;};// Helper function to get offset.
|
||||
function getAxisOffsetAValue(axis,options){if(options.offset[axis]){if(isNaN(options.offset[axis])){return options.offset[axis];}else {return options.offset[axis]+'px';}}return '0px';}function containsClass(elem,yourClass){if(!elem||typeof yourClass!=="string"){return false;}else if(elem.className&&elem.className.trim().split(/\s+/gi).indexOf(yourClass)>-1){return true;}else {return false;}}// Setting up the prototype for the init object
|
||||
Toastify.lib.init.prototype=Toastify.lib;// Returning the Toastify function to be assigned to the window object/module
|
||||
return Toastify;});})(toastify$1);return toastify$1.exports;}
|
||||
|
||||
var toastifyExports = requireToastify();
|
||||
var Toastify = /*@__PURE__*/getDefaultExportFromCjs(toastifyExports);
|
||||
|
||||
const Toast=(text='',variant='primary')=>{const getColorByName=(variant='')=>{let color;switch(variant.trim().toLowerCase()){case 'primary':color='#0d6efd';break;case 'secondary':color='#6c757d';break;case 'warning':color='#ffc720';break;case 'success':color='#13653f';break;case 'info':color='#25cff2';break;case 'error':case 'danger':color='#a52834';break;case 'light':color='#babbbc';break;case 'dark':color='#373b3e';break;default:console.warn('variant not found');color='white';}return color;};const show=()=>{Toastify({text,duration:2000,className:variant,gravity:'top',// 'top' or 'bottom'
|
||||
position:'center',// `left`, `center` or `right`
|
||||
stopOnFocus:true,// Prevents dismissing of toast on hover
|
||||
style:{background:getColorByName(variant)}}).showToast();};return {show};};
|
||||
|
||||
// import 'bootstrap';
|
||||
// Factory Function
|
||||
const ProductManager=(el=null,options={})=>{// === DOM & VARS =======
|
||||
const module=el||document.querySelector('.product-manager')||console.warn('Product Manager Element not found');if(!module)return;const DOM={module,table:module.querySelector('.table-products'),tbody:module.querySelector('tbody'),inputName:module.querySelector('.input-product-name'),inputPrice:module.querySelector('.input-product-price'),btnAdd:module.querySelector('.button-product-add'),templateRow:module.querySelector('.template-row'),// Modal
|
||||
modalEdit:module.querySelector('.modal-edit'),formEdit:module.querySelector('.form-product-edit'),inputEditName:module.querySelector('.input-edit-name'),inputEditPrice:module.querySelector('.input-edit-price'),inputEditId:module.querySelector('.input-edit-id'),inputEditPosition:module.querySelector('.input-edit-position'),btnUpdate:module.querySelector('.button-product-update')};const SERVER_BASE_URL='http://127.0.0.1:8000';const bsModalEdit=new Modal(DOM.modalEdit,{backdrop:'static',keyboard:true});// console.log(DOM);
|
||||
const module=el||document.querySelector('.product-manager')||console.warn('Product Manager Element not found');if(!module)return;const DOM={module,table:module.querySelector('.table-products'),tbody:module.querySelector('tbody'),inputName:module.querySelector('.input-product-name'),inputPrice:module.querySelector('.input-product-price'),btnAdd:module.querySelector('.button-product-add'),templateRow:module.querySelector('.template-row'),// Modal Edit
|
||||
modalEdit:module.querySelector('.modal-edit'),formEdit:module.querySelector('.form-product-edit'),inputEditName:module.querySelector('.input-edit-name'),inputEditPrice:module.querySelector('.input-edit-price'),inputEditId:module.querySelector('.input-edit-id'),inputEditPosition:module.querySelector('.input-edit-position'),btnUpdate:module.querySelector('.button-product-update'),// Modal Delete
|
||||
modalDelete:module.querySelector('.modal-delete'),productName:module.querySelector('strong.product-name'),btnConfirmDelete:module.querySelector('.button-confirm-delete')};const SERVER_BASE_URL='http://127.0.0.1:8000';const bsModalEdit=new Modal(DOM.modalEdit,{backdrop:'static',keyboard:true});const bsModalDelete=new Modal(DOM.modalDelete,{backdrop:true,keyboard:true});// console.log(DOM);
|
||||
// === INIT =============
|
||||
const init=()=>{// Funktionsaufrufe zu beginn der Anwendung
|
||||
initProducts();DOM.btnAdd.disabled=true;// Event-Lauscher zu beginn der Anwendung
|
||||
DOM.btnAdd.addEventListener('click',onClickAdd);DOM.formEdit.addEventListener('submit',onSubmitEdit);window.addEventListener('keyup',onKeyUp);};// === EVENTHANDLER =====
|
||||
DOM.btnAdd.addEventListener('click',onClickAdd);DOM.btnConfirmDelete.addEventListener('click',onClickConfirmDelete);DOM.formEdit.addEventListener('submit',onSubmitEdit);window.addEventListener('keyup',onKeyUp);};// === EVENTHANDLER =====
|
||||
const onKeyUp=e=>{DOM.btnAdd.disabled=!(DOM.inputName.value!==''&&DOM.inputPrice.value!=='');// if (DOM.inputName.value !== '' && DOM.inputPrice.value !== '') {
|
||||
// DOM.btnAdd.disabled = false;
|
||||
// } else {
|
||||
@@ -795,16 +901,19 @@
|
||||
// }
|
||||
};const onClickAdd=e=>{const product={name:DOM.inputName.value,//
|
||||
price:Number(DOM.inputPrice.valueAsNumber)};// async API request
|
||||
createProduct(product).then(data=>{console.log(data);if(data.success){loadProducts();resetInputFields();disableNonFunctionalButtons();}});// addProduct(product);
|
||||
createProduct(product).then(data=>{console.log(data);if(data.success){Toast(data.msg,'success').show();loadProducts();resetInputFields();disableNonFunctionalButtons();}else {Toast(data.msg,'error').show();}});// addProduct(product);
|
||||
};const onSubmitEdit=e=>{e.preventDefault();// Standardverhalten unterbinden (Modal Form nicht versenden)
|
||||
const product={name:DOM.inputEditName.value,price:Number(Number(DOM.inputEditPrice.value).toFixed(2)),_id:DOM.inputEditId.value,position:parseInt(DOM.inputEditPosition.value)};// console.log(Object.fromEntries(new FormData(DOM.formEdit)));
|
||||
console.log(product);DOM.btnUpdate.querySelector('i').classList.add('fa-spin');// async Fetch Request
|
||||
updateProduct(product).then(data=>{console.log(data);if(data.success){DOM.btnUpdate.querySelector('i').classList.remove('fa-spin');resetInputFields();bsModalEdit.hide();loadProducts();}});};const onClickEdit=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];// btn.closest('tr'); // btn.parentNode.parentNode;
|
||||
console.log(product);const icon=DOM.btnUpdate.querySelector('i');icon.classList.add('fa-spin');// async Fetch Request
|
||||
updateProduct(product).then(data=>{console.log(data);if(data.success){Toast(data.msg,'success').show();icon.classList.remove('fa-spin');resetInputFields();loadProducts();bsModalEdit.hide();}else {Toast(data.msg,'error').show();}});};const onClickEdit=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];// btn.closest('tr'); // btn.parentNode.parentNode;
|
||||
const id=currentRow.dataset.id;// async API request
|
||||
fetchProduct(id).then(data=>{// console.log(data);
|
||||
showModalEdit(data);});};const onClickRemove=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];// btn.closest('tr'); // btn.parentNode.parentNode;
|
||||
currentRow.remove();// currentRow.parentNode.removeChild(currentRow); // IE11 support
|
||||
disableNonFunctionalButtons();};const onClickMoveUp=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];currentRow.previousElementSibling.before(currentRow);// DOM.tbody.insertBefore(currentRow, currentRow.previousElementSibling);
|
||||
const id=currentRow.dataset.id;const productName=currentRow.querySelector('.td-name').textContent.trim();console.log({id,productName});DOM.btnConfirmDelete.dataset.id=id;DOM.productName.textContent=productName;// currentRow.remove();
|
||||
// currentRow.parentNode.removeChild(currentRow); // IE11 support
|
||||
disableNonFunctionalButtons();};const onClickConfirmDelete=e=>{const btn=e.currentTarget;const id=btn.dataset.id;// async API request
|
||||
deleteProduct(id).then(data=>{// console.log(data);
|
||||
if(data.success){Toast(data.msg,'success').show();loadProducts();bsModalDelete.hide();}else {Toast(data.msg,'error').show();}});};const onClickMoveUp=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];currentRow.previousElementSibling.before(currentRow);// DOM.tbody.insertBefore(currentRow, currentRow.previousElementSibling);
|
||||
disableNonFunctionalButtons();};const onClickMoveDown=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];currentRow.nextElementSibling.after(currentRow);// DOM.tbody.insertBefore(currentRow, currentRow.nextElementSibling.nextElementSibling);
|
||||
disableNonFunctionalButtons();};const onMouseDownDrag=e=>{const btn=e.currentTarget;const currentRow=parents(btn,'tr')[0];// btn.closest('tr'); // btn.parentNode.parentNode;
|
||||
currentRow.draggable=true;// => <tr draggable="true" >...</tr>
|
||||
@@ -823,22 +932,27 @@
|
||||
// BRE(A)D - Add - hinzufügen eines neuen Produkts
|
||||
const createProduct=async product=>{try{const response=await fetch(`${SERVER_BASE_URL}/api/products`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(product)});// HTTP-Request URL
|
||||
if(!response.ok){throw new Error('Fetch went wrong.');}const data=await response.json();// HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
return data;}catch(error){console.error(error);throw error;}};// HTTP - Methode - GET
|
||||
return data;}catch(error){Toast(error.message||"Couldn't create product",'error').show();console.error(error);throw error;}};// HTTP - Methode - GET
|
||||
// C(R)UD - Read
|
||||
// (B)READ - Browse - auslesen aller Produkte
|
||||
const fetchProducts=async()=>{try{const response=await fetch(`${SERVER_BASE_URL}/api/products`);// HTTP-Request URL
|
||||
if(!response.ok){throw new Error('Fetch went wrong.');}const data=await response.json();// HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
return data;}catch(error){console.error(error);throw error;}};// HTTP - Methode - GET
|
||||
return data;}catch(error){Toast(error.message||"Couldn't get products",'error').show();console.error(error);throw error;}};// HTTP - Methode - GET
|
||||
// C(R)UD - Read
|
||||
// B(R)EAD - Read - auslesen eines Produkts
|
||||
const fetchProduct=async id=>{try{const response=await fetch(`${SERVER_BASE_URL}/api/products/${id}`);// HTTP-Request URL
|
||||
if(!response.ok){throw new Error('Fetch went wrong.');}const data=await response.json();// HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
return data;}catch(error){console.error(error);throw error;}};// HTTP - Methode - PUT
|
||||
return data;}catch(error){Toast(error.message||"Couldn't get product",'error').show();console.error(error);throw error;}};// HTTP - Methode - PUT
|
||||
// CR(U)D - Update
|
||||
// BR(E)AD - Edit - aktualisieren eines Produkts
|
||||
const updateProduct=async product=>{try{const response=await fetch(`${SERVER_BASE_URL}/api/products`,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(product)});// HTTP-Request URL
|
||||
if(!response.ok){throw new Error('Fetch went wrong.');}const data=await response.json();// HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
return data;}catch(error){console.error(error);throw error;}};// === FUNCTIONS ========
|
||||
return data;}catch(error){Toast(error.message||"Couldn't update product",'error').show();console.error(error);throw error;}};// HTTP - Methode - DELETE
|
||||
// CRU(D) - Delete
|
||||
// BREA(D) - Delete - löschen eines Produkts
|
||||
const deleteProduct=async id=>{try{const response=await fetch(`${SERVER_BASE_URL}/api/products/${id}`,{method:'DELETE'});// HTTP-Request URL
|
||||
if(!response.ok){throw new Error('Fetch went wrong.');}const data=await response.json();// HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
return data;}catch(error){Toast(error.message||"Couldn't delete product",'error').show();console.error(error);throw error;}};// === FUNCTIONS ========
|
||||
const initProducts=()=>{fetchProducts().then(products=>{products.forEach(addProduct);disableNonFunctionalButtons();});};const loadProducts=()=>{DOM.tbody.innerHTML='';fetchProducts().then(data=>{// TODO: add fade Animation
|
||||
data.forEach(addProduct);disableNonFunctionalButtons();});};const addProduct=product=>{const{name,price,_id:id}=product;// https://developer.mozilla.org/de/docs/Web/HTML/Reference/Elements/template#anwendungshinweise
|
||||
const trEl=DOM.templateRow.content.firstElementChild.cloneNode(true);const tdNameEl=trEl.querySelector('.td-name');const tdPriceEl=trEl.querySelector('.td-price');const btnDragEl=trEl.querySelector('.button-product-drag');const btnEditEl=trEl.querySelector('.button-product-edit');const btnRemoveEl=trEl.querySelector('.button-product-remove');const btnMoveUpEl=trEl.querySelector('.button-product-move-up');const btnMoveDownEl=trEl.querySelector('.button-product-move-down');// Drag 'n Drop hinzufügen.
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+32
-3
@@ -68,7 +68,10 @@
|
||||
<i class="fas fa-pen"></i>
|
||||
<span class="visually-hidden">Edit Product</span>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger button-product-remove">
|
||||
<button
|
||||
class="btn btn-sm btn-danger button-product-remove"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modal-product-delete">
|
||||
<i class="fas fa-trash-can"></i>
|
||||
<span class="visually-hidden">Remove Product</span>
|
||||
</button>
|
||||
@@ -85,8 +88,6 @@
|
||||
</template>
|
||||
|
||||
<!-- ▼ Modal Edit Product ▼ -->
|
||||
<!-- Button trigger modal -->
|
||||
|
||||
<div
|
||||
class="modal fade modal-edit"
|
||||
id="modal-product-edit"
|
||||
@@ -142,6 +143,34 @@
|
||||
</div>
|
||||
<!-- ▲ /Modal Edit Product ▲ -->
|
||||
|
||||
<!-- ▼ Delete Modal ▼ -->
|
||||
<div
|
||||
class="modal fade modal-delete"
|
||||
id="modal-product-delete"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modal-product-delete-label"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="modal-product-delete-label">Delete Product</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Do you really want to delete Product:<br />
|
||||
<strong class="product-name">{PRODUCT_NAME}</strong>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger button-confirm-delete">Confirm to delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ▲ /Delete Modal ▲ -->
|
||||
|
||||
<!-- ▼ Dialog Edit Product ▼ -->
|
||||
<!-- <button type="button" class="btn-solid theme-primary" data-bs-toggle="dialog" data-bs-target="#slideDownDialog">
|
||||
Slide down dialog
|
||||
|
||||
+74
-8
@@ -1,6 +1,6 @@
|
||||
import { parents } from '../utils/helpers.js';
|
||||
|
||||
import { Modal } from 'bootstrap';
|
||||
import Toast from './Toast';
|
||||
|
||||
//import * as bootstrap from 'bootstrap';
|
||||
// import 'bootstrap';
|
||||
@@ -22,7 +22,7 @@ const ProductManager = (el = null, options = {}) => {
|
||||
btnAdd: module.querySelector('.button-product-add'),
|
||||
templateRow: module.querySelector('.template-row'),
|
||||
|
||||
// Modal
|
||||
// Modal Edit
|
||||
modalEdit: module.querySelector('.modal-edit'),
|
||||
formEdit: module.querySelector('.form-product-edit'),
|
||||
inputEditName: module.querySelector('.input-edit-name'),
|
||||
@@ -30,6 +30,11 @@ const ProductManager = (el = null, options = {}) => {
|
||||
inputEditId: module.querySelector('.input-edit-id'),
|
||||
inputEditPosition: module.querySelector('.input-edit-position'),
|
||||
btnUpdate: module.querySelector('.button-product-update'),
|
||||
|
||||
// Modal Delete
|
||||
modalDelete: module.querySelector('.modal-delete'),
|
||||
productName: module.querySelector('strong.product-name'),
|
||||
btnConfirmDelete: module.querySelector('.button-confirm-delete'),
|
||||
};
|
||||
|
||||
const SERVER_BASE_URL = 'http://127.0.0.1:8000';
|
||||
@@ -39,6 +44,11 @@ const ProductManager = (el = null, options = {}) => {
|
||||
keyboard: true,
|
||||
});
|
||||
|
||||
const bsModalDelete = new Modal(DOM.modalDelete, {
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
});
|
||||
|
||||
// console.log(DOM);
|
||||
|
||||
// === INIT =============
|
||||
@@ -48,7 +58,7 @@ const ProductManager = (el = null, options = {}) => {
|
||||
DOM.btnAdd.disabled = true;
|
||||
// Event-Lauscher zu beginn der Anwendung
|
||||
DOM.btnAdd.addEventListener('click', onClickAdd);
|
||||
|
||||
DOM.btnConfirmDelete.addEventListener('click', onClickConfirmDelete);
|
||||
DOM.formEdit.addEventListener('submit', onSubmitEdit);
|
||||
window.addEventListener('keyup', onKeyUp);
|
||||
};
|
||||
@@ -73,9 +83,12 @@ const ProductManager = (el = null, options = {}) => {
|
||||
createProduct(product).then((data) => {
|
||||
console.log(data);
|
||||
if (data.success) {
|
||||
Toast(data.msg, 'success').show();
|
||||
loadProducts();
|
||||
resetInputFields();
|
||||
disableNonFunctionalButtons();
|
||||
} else {
|
||||
Toast(data.msg, 'error').show();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -95,16 +108,19 @@ const ProductManager = (el = null, options = {}) => {
|
||||
// console.log(Object.fromEntries(new FormData(DOM.formEdit)));
|
||||
|
||||
console.log(product);
|
||||
|
||||
DOM.btnUpdate.querySelector('i').classList.add('fa-spin');
|
||||
const icon = DOM.btnUpdate.querySelector('i');
|
||||
icon.classList.add('fa-spin');
|
||||
// async Fetch Request
|
||||
updateProduct(product).then((data) => {
|
||||
console.log(data);
|
||||
if (data.success) {
|
||||
DOM.btnUpdate.querySelector('i').classList.remove('fa-spin');
|
||||
Toast(data.msg, 'success').show();
|
||||
icon.classList.remove('fa-spin');
|
||||
resetInputFields();
|
||||
bsModalEdit.hide();
|
||||
loadProducts();
|
||||
bsModalEdit.hide();
|
||||
} else {
|
||||
Toast(data.msg, 'error').show();
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -124,12 +140,36 @@ const ProductManager = (el = null, options = {}) => {
|
||||
const onClickRemove = (e) => {
|
||||
const btn = e.currentTarget;
|
||||
const currentRow = parents(btn, 'tr')[0]; // btn.closest('tr'); // btn.parentNode.parentNode;
|
||||
const id = currentRow.dataset.id;
|
||||
const productName = currentRow.querySelector('.td-name').textContent.trim();
|
||||
|
||||
currentRow.remove();
|
||||
console.log({ id, productName });
|
||||
|
||||
DOM.btnConfirmDelete.dataset.id = id;
|
||||
DOM.productName.textContent = productName;
|
||||
|
||||
// currentRow.remove();
|
||||
// currentRow.parentNode.removeChild(currentRow); // IE11 support
|
||||
disableNonFunctionalButtons();
|
||||
};
|
||||
|
||||
const onClickConfirmDelete = (e) => {
|
||||
const btn = e.currentTarget;
|
||||
const id = btn.dataset.id;
|
||||
|
||||
// async API request
|
||||
deleteProduct(id).then((data) => {
|
||||
// console.log(data);
|
||||
if (data.success) {
|
||||
Toast(data.msg, 'success').show();
|
||||
loadProducts();
|
||||
bsModalDelete.hide();
|
||||
} else {
|
||||
Toast(data.msg, 'error').show();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onClickMoveUp = (e) => {
|
||||
const btn = e.currentTarget;
|
||||
const currentRow = parents(btn, 'tr')[0];
|
||||
@@ -218,6 +258,7 @@ const ProductManager = (el = null, options = {}) => {
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
Toast(error.message || "Couldn't create product", 'error').show();
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
@@ -237,6 +278,7 @@ const ProductManager = (el = null, options = {}) => {
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
Toast(error.message || "Couldn't get products", 'error').show();
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
@@ -256,6 +298,7 @@ const ProductManager = (el = null, options = {}) => {
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
Toast(error.message || "Couldn't get product", 'error').show();
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
@@ -281,6 +324,29 @@ const ProductManager = (el = null, options = {}) => {
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
Toast(error.message || "Couldn't update product", 'error').show();
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// HTTP - Methode - DELETE
|
||||
// CRU(D) - Delete
|
||||
// BREA(D) - Delete - löschen eines Produkts
|
||||
const deleteProduct = async (id) => {
|
||||
try {
|
||||
const response = await fetch(`${SERVER_BASE_URL}/api/products/${id}`, {
|
||||
method: 'DELETE',
|
||||
}); // HTTP-Request URL
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Fetch went wrong.');
|
||||
}
|
||||
const data = await response.json(); // HTTP-Response-Body in JS-Objekt geparsed -> Promise
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
Toast(error.message || "Couldn't delete product", 'error').show();
|
||||
console.error(error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import Toastify from 'toastify-js'; // das Modul wird vom node_modules Ordner ausgelesen und gebundlet. Funktioniert nur mit JS-Bundler (rollup/esbuild)
|
||||
|
||||
const Toast = (text = '', variant = 'primary') => {
|
||||
const getColorByName = (variant = '') => {
|
||||
let color;
|
||||
switch (variant.trim().toLowerCase()) {
|
||||
case 'primary':
|
||||
color = '#0d6efd';
|
||||
break;
|
||||
case 'secondary':
|
||||
color = '#6c757d';
|
||||
break;
|
||||
case 'warning':
|
||||
color = '#ffc720';
|
||||
break;
|
||||
case 'success':
|
||||
color = '#13653f';
|
||||
break;
|
||||
case 'info':
|
||||
color = '#25cff2';
|
||||
break;
|
||||
case 'error':
|
||||
case 'danger':
|
||||
color = '#a52834';
|
||||
break;
|
||||
case 'light':
|
||||
color = '#babbbc';
|
||||
break;
|
||||
case 'dark':
|
||||
color = '#373b3e';
|
||||
break;
|
||||
|
||||
default:
|
||||
console.warn('variant not found');
|
||||
color = 'white';
|
||||
}
|
||||
return color;
|
||||
};
|
||||
|
||||
const show = () => {
|
||||
Toastify({
|
||||
text,
|
||||
duration: 2000,
|
||||
className: variant,
|
||||
gravity: 'top', // 'top' or 'bottom'
|
||||
position: 'center', // `left`, `center` or `right`
|
||||
stopOnFocus: true, // Prevents dismissing of toast on hover
|
||||
style: {
|
||||
background: getColorByName(variant),
|
||||
},
|
||||
}).showToast();
|
||||
};
|
||||
|
||||
return {
|
||||
show,
|
||||
};
|
||||
};
|
||||
|
||||
export default Toast;
|
||||
+2
@@ -1,2 +1,4 @@
|
||||
// TODO: change with SASS FontAwesome Version
|
||||
@import 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.3.1/css/all.css';
|
||||
|
||||
@import 'toastify-1.12/toastify';
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*!
|
||||
* Toastify js 1.12.0
|
||||
* https://github.com/apvarun/toastify-js
|
||||
* @license MIT licensed
|
||||
*
|
||||
* Copyright (C) 2018 Varun A P
|
||||
*/
|
||||
|
||||
.toastify {
|
||||
padding: 12px 20px;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
box-shadow:
|
||||
0 3px 6px -1px rgba(0, 0, 0, 0.12),
|
||||
0 10px 36px -4px rgba(77, 96, 232, 0.3);
|
||||
background: -webkit-linear-gradient(315deg, #73a5ff, #5477f5);
|
||||
background: linear-gradient(135deg, #73a5ff, #5477f5);
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
transition: all 0.4s cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
max-width: calc(50% - 20px);
|
||||
z-index: 2147483647;
|
||||
}
|
||||
|
||||
.toastify.on {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast-close {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: 1em;
|
||||
opacity: 0.4;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.toastify-right {
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.toastify-left {
|
||||
left: 15px;
|
||||
}
|
||||
|
||||
.toastify-top {
|
||||
top: -150px;
|
||||
}
|
||||
|
||||
.toastify-bottom {
|
||||
bottom: -150px;
|
||||
}
|
||||
|
||||
.toastify-rounded {
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.toastify-avatar {
|
||||
width: 1.5em;
|
||||
height: 1.5em;
|
||||
margin: -7px 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.toastify-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
max-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 360px) {
|
||||
.toastify-right,
|
||||
.toastify-left {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
max-width: fit-content;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
"version": "0.0.1",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bootstrap": "^5.3.8"
|
||||
"bootstrap": "^5.3.8",
|
||||
"toastify-js": "^1.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^8.0.7",
|
||||
@@ -8981,6 +8982,12 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toastify-js": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz",
|
||||
"integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"vinyl-source-stream": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "^5.3.8"
|
||||
"bootstrap": "^5.3.8",
|
||||
"toastify-js": "^1.12.0"
|
||||
}
|
||||
}
|
||||
|
||||
+32
-3
@@ -106,7 +106,10 @@
|
||||
<i class="fas fa-pen"></i>
|
||||
<span class="visually-hidden">Edit Product</span>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-danger button-product-remove">
|
||||
<button
|
||||
class="btn btn-sm btn-danger button-product-remove"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modal-product-delete">
|
||||
<i class="fas fa-trash-can"></i>
|
||||
<span class="visually-hidden">Remove Product</span>
|
||||
</button>
|
||||
@@ -123,8 +126,6 @@
|
||||
</template>
|
||||
|
||||
<!-- ▼ Modal Edit Product ▼ -->
|
||||
<!-- Button trigger modal -->
|
||||
|
||||
<div
|
||||
class="modal fade modal-edit"
|
||||
id="modal-product-edit"
|
||||
@@ -180,6 +181,34 @@
|
||||
</div>
|
||||
<!-- ▲ /Modal Edit Product ▲ -->
|
||||
|
||||
<!-- ▼ Delete Modal ▼ -->
|
||||
<div
|
||||
class="modal fade modal-delete"
|
||||
id="modal-product-delete"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modal-product-delete-label"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="modal-product-delete-label">Delete Product</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>
|
||||
Do you really want to delete Product:<br />
|
||||
<strong class="product-name">{PRODUCT_NAME}</strong>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger button-confirm-delete">Confirm to delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ▲ /Delete Modal ▲ -->
|
||||
|
||||
<!-- ▼ Dialog Edit Product ▼ -->
|
||||
<!-- <button type="button" class="btn-solid theme-primary" data-bs-toggle="dialog" data-bs-target="#slideDownDialog">
|
||||
Slide down dialog
|
||||
|
||||
Reference in New Issue
Block a user