- Implemented a new logs page with filters for level, source, and date range. - Added a data table to display logs with pagination and sorting capabilities. - Created backend functionality to fetch logs data based on filters. - Introduced a new Logs class for handling log data operations. - Added a new database migration for the logs table. - Enhanced UI with custom checkbox styles for better user experience. - Updated navigation to include a link to the logs page.
398 lines
10 KiB
JavaScript
398 lines
10 KiB
JavaScript
/**
|
|
* AdsProDialog - własny system dialogów (zamiennik jquery-confirm)
|
|
* API kompatybilne z jquery-confirm: $.confirm(options), $.alert(options)
|
|
*/
|
|
(function( $ )
|
|
{
|
|
'use strict';
|
|
|
|
var dialogCounter = 0;
|
|
var activeDialogs = [];
|
|
|
|
function AdsProDialog( options )
|
|
{
|
|
this.id = ++dialogCounter;
|
|
this.options = $.extend( {}, AdsProDialog.defaults, options );
|
|
this.$el = null;
|
|
this.$box = null;
|
|
this.$content = null;
|
|
this._closed = false;
|
|
this._autoCloseTimer = null;
|
|
this._init();
|
|
}
|
|
|
|
AdsProDialog.defaults = {
|
|
title: '',
|
|
content: '',
|
|
type: '',
|
|
theme: '',
|
|
buttons: {},
|
|
closeIcon: false,
|
|
closeIconClass: 'fa-solid fa-xmark',
|
|
columnClass: '',
|
|
boxWidth: '',
|
|
useBootstrap: true,
|
|
draggable: false,
|
|
autoClose: '',
|
|
onContentReady: null,
|
|
onClose: null,
|
|
onOpen: null
|
|
};
|
|
|
|
AdsProDialog.prototype = {
|
|
|
|
_init: function()
|
|
{
|
|
this._buildDOM();
|
|
this._bindEvents();
|
|
this._appendToBody();
|
|
this._applyAutoClose();
|
|
this._triggerContentReady();
|
|
this._focusInitialElement();
|
|
activeDialogs.push( this );
|
|
},
|
|
|
|
_buildDOM: function()
|
|
{
|
|
var o = this.options;
|
|
var typeClass = o.type ? ' adspro-dialog-type-' + o.type : '';
|
|
|
|
var sizeStyle = '';
|
|
var sizeClass = '';
|
|
if ( !o.useBootstrap && o.boxWidth )
|
|
{
|
|
sizeStyle = 'max-width:' + o.boxWidth + ';width:100%;';
|
|
}
|
|
else if ( o.columnClass )
|
|
{
|
|
sizeClass = ' ' + o.columnClass.replace( /col-md-offset-\d+/g, '' ).trim();
|
|
}
|
|
|
|
var html =
|
|
'<div class="adspro-dialog" data-dialog-id="' + this.id + '">' +
|
|
'<div class="adspro-dialog-bg"></div>' +
|
|
'<div class="adspro-dialog-scrollpane">' +
|
|
'<div class="adspro-dialog-center' + sizeClass + '">' +
|
|
'<div class="adspro-dialog-box jconfirm-box' + typeClass + '" style="' + sizeStyle + '" tabindex="-1">' +
|
|
this._buildCloseIcon( o ) +
|
|
this._buildHeader( o ) +
|
|
'<div class="adspro-dialog-content-pane">' +
|
|
'<div class="adspro-dialog-content">' + o.content + '</div>' +
|
|
'</div>' +
|
|
this._buildButtons( o ) +
|
|
'<div class="adspro-dialog-loading" style="display:none;">' +
|
|
'<div class="adspro-dialog-spinner"></div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
|
|
this.$el = $( html );
|
|
this.$box = this.$el.find( '.adspro-dialog-box' );
|
|
this.$content = this.$el.find( '.adspro-dialog-content' );
|
|
},
|
|
|
|
_buildCloseIcon: function( o )
|
|
{
|
|
if ( !o.closeIcon ) return '';
|
|
var iconClass = o.closeIconClass || 'fa-solid fa-xmark';
|
|
return '<div class="adspro-dialog-close-icon"><i class="' + iconClass + '"></i></div>';
|
|
},
|
|
|
|
_buildHeader: function( o )
|
|
{
|
|
if ( !o.title ) return '';
|
|
return '<div class="adspro-dialog-title-c">' +
|
|
'<span class="adspro-dialog-title">' + o.title + '</span>' +
|
|
'</div>';
|
|
},
|
|
|
|
_buildButtons: function( o )
|
|
{
|
|
if ( !o.buttons || $.isEmptyObject( o.buttons ) ) return '';
|
|
|
|
var html = '<div class="adspro-dialog-buttons">';
|
|
var self = this;
|
|
|
|
$.each( o.buttons, function( key, btnDef )
|
|
{
|
|
if ( typeof btnDef === 'function' )
|
|
{
|
|
btnDef = { action: btnDef };
|
|
o.buttons[ key ] = btnDef;
|
|
}
|
|
|
|
var text = btnDef.text || key.charAt( 0 ).toUpperCase() + key.slice( 1 );
|
|
var btnClass = btnDef.btnClass || 'btn-default';
|
|
var isEnter = ( btnDef.keys && btnDef.keys.indexOf( 'enter' ) !== -1 );
|
|
|
|
html += '<button type="button" class="adspro-dialog-btn btn ' + btnClass + '"' +
|
|
' data-btn-key="' + key + '"' +
|
|
( isEnter ? ' data-enter-key="true"' : '' ) +
|
|
'>' + text + '</button>';
|
|
});
|
|
|
|
html += '</div>';
|
|
return html;
|
|
},
|
|
|
|
_bindEvents: function()
|
|
{
|
|
var self = this;
|
|
var o = this.options;
|
|
|
|
// Backdrop click
|
|
this.$el.find( '.adspro-dialog-bg' ).on( 'click', function()
|
|
{
|
|
self.close();
|
|
});
|
|
|
|
// Close icon
|
|
this.$el.find( '.adspro-dialog-close-icon' ).on( 'click', function()
|
|
{
|
|
self.close();
|
|
});
|
|
|
|
// Buttons
|
|
this.$el.find( '.adspro-dialog-btn' ).each( function()
|
|
{
|
|
var $btn = $( this );
|
|
var key = $btn.data( 'btn-key' );
|
|
var btnDef = o.buttons[ key ];
|
|
|
|
// Referencje do buttonów (kompatybilność z $$formSubmit itp.)
|
|
self[ '$$' + key ] = $btn;
|
|
|
|
$btn.on( 'click', function()
|
|
{
|
|
if ( typeof btnDef === 'function' )
|
|
{
|
|
btnDef.call( self );
|
|
self.close();
|
|
return;
|
|
}
|
|
if ( btnDef && typeof btnDef.action === 'function' )
|
|
{
|
|
var result = btnDef.action.call( self );
|
|
if ( result !== false )
|
|
{
|
|
self.close();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.close();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Keyboard
|
|
$( document ).on( 'keydown.adspro-dialog-' + this.id, function( e )
|
|
{
|
|
if ( self._closed ) return;
|
|
if ( activeDialogs[ activeDialogs.length - 1 ] !== self ) return;
|
|
|
|
if ( e.key === 'Escape' )
|
|
{
|
|
e.preventDefault();
|
|
self.close();
|
|
}
|
|
if ( e.key === 'Enter' )
|
|
{
|
|
if ( $( e.target ).is( '.adspro-dialog-btn, textarea, select, input' ) ) return;
|
|
var $enterBtn = self.$el.find( '.adspro-dialog-btn[data-enter-key="true"]' );
|
|
if ( $enterBtn.length )
|
|
{
|
|
e.preventDefault();
|
|
$enterBtn.trigger( 'click' );
|
|
}
|
|
}
|
|
});
|
|
|
|
// Draggable
|
|
if ( o.draggable && $.fn.draggable )
|
|
{
|
|
this.$box.draggable({
|
|
handle: '.adspro-dialog-title-c',
|
|
cursor: 'move'
|
|
});
|
|
this.$el.find( '.adspro-dialog-title-c' ).css( 'cursor', 'move' );
|
|
}
|
|
},
|
|
|
|
_appendToBody: function()
|
|
{
|
|
var baseZIndex = 99000 + ( this.id * 10 );
|
|
this.$el.css( 'z-index', baseZIndex );
|
|
$( 'body' ).append( this.$el );
|
|
|
|
var self = this;
|
|
requestAnimationFrame( function()
|
|
{
|
|
self.$el.addClass( 'adspro-dialog-open' );
|
|
});
|
|
|
|
if ( typeof this.options.onOpen === 'function' )
|
|
{
|
|
this.options.onOpen.call( this );
|
|
}
|
|
},
|
|
|
|
_applyAutoClose: function()
|
|
{
|
|
var ac = this.options.autoClose;
|
|
if ( !ac ) return;
|
|
|
|
var parts = ac.split( '|' );
|
|
if ( parts.length !== 2 ) return;
|
|
|
|
var ms = parseInt( parts[ 1 ], 10 );
|
|
var self = this;
|
|
this._autoCloseTimer = setTimeout( function()
|
|
{
|
|
if ( !self._closed ) self.close();
|
|
}, ms );
|
|
},
|
|
|
|
_triggerContentReady: function()
|
|
{
|
|
if ( typeof this.options.onContentReady === 'function' )
|
|
{
|
|
this.options.onContentReady.call( this );
|
|
}
|
|
},
|
|
|
|
_focusInitialElement: function()
|
|
{
|
|
var self = this;
|
|
|
|
setTimeout( function()
|
|
{
|
|
if ( self._closed ) return;
|
|
if ( $( document.activeElement ).closest( self.$el ).length ) return;
|
|
|
|
var $focusTarget = self.$el.find( '[autofocus]:visible:not(:disabled):first' );
|
|
if ( !$focusTarget.length )
|
|
{
|
|
$focusTarget = self.$el.find( '.adspro-dialog-content input:visible:not(:disabled):first, .adspro-dialog-content select:visible:not(:disabled):first, .adspro-dialog-content textarea:visible:not(:disabled):first' ).first();
|
|
}
|
|
if ( !$focusTarget.length )
|
|
{
|
|
$focusTarget = self.$el.find( '.adspro-dialog-btn[data-enter-key="true"]:visible:not(:disabled):first' );
|
|
}
|
|
if ( !$focusTarget.length )
|
|
{
|
|
$focusTarget = self.$el.find( '.adspro-dialog-btn:visible:not(:disabled):first' );
|
|
}
|
|
if ( !$focusTarget.length )
|
|
{
|
|
$focusTarget = self.$box;
|
|
}
|
|
|
|
if ( $focusTarget.length )
|
|
{
|
|
$focusTarget.trigger( 'focus' );
|
|
}
|
|
}, 20 );
|
|
},
|
|
|
|
// --- Metody publiczne ---
|
|
|
|
close: function()
|
|
{
|
|
if ( this._closed ) return;
|
|
this._closed = true;
|
|
|
|
if ( this._autoCloseTimer ) clearTimeout( this._autoCloseTimer );
|
|
$( document ).off( 'keydown.adspro-dialog-' + this.id );
|
|
|
|
var self = this;
|
|
this.$el.removeClass( 'adspro-dialog-open' );
|
|
this.$el.addClass( 'adspro-dialog-closing' );
|
|
|
|
setTimeout( function()
|
|
{
|
|
self.$el.remove();
|
|
var idx = activeDialogs.indexOf( self );
|
|
if ( idx > -1 ) activeDialogs.splice( idx, 1 );
|
|
if ( typeof self.options.onClose === 'function' )
|
|
{
|
|
self.options.onClose.call( self );
|
|
}
|
|
}, 250 );
|
|
},
|
|
|
|
showLoading: function( showContent )
|
|
{
|
|
this.$el.find( '.adspro-dialog-loading' ).show();
|
|
if ( !showContent )
|
|
{
|
|
this.$el.find( '.adspro-dialog-content-pane' ).css( 'opacity', '0.3' );
|
|
}
|
|
this.$el.find( '.adspro-dialog-buttons' ).css({
|
|
'pointer-events': 'none',
|
|
'opacity': '0.5'
|
|
});
|
|
},
|
|
|
|
hideLoading: function()
|
|
{
|
|
this.$el.find( '.adspro-dialog-loading' ).hide();
|
|
this.$el.find( '.adspro-dialog-content-pane' ).css( 'opacity', '' );
|
|
this.$el.find( '.adspro-dialog-buttons' ).css({
|
|
'pointer-events': '',
|
|
'opacity': ''
|
|
});
|
|
},
|
|
|
|
setContent: function( html )
|
|
{
|
|
this.$content.html( html );
|
|
},
|
|
|
|
setTitle: function( title )
|
|
{
|
|
this.$el.find( '.adspro-dialog-title' ).html( title );
|
|
}
|
|
};
|
|
|
|
// --- Rejestracja globalna ---
|
|
|
|
$.confirm = function( options )
|
|
{
|
|
return new AdsProDialog( options );
|
|
};
|
|
|
|
$.alert = function( options )
|
|
{
|
|
if ( typeof options === 'string' )
|
|
{
|
|
options = {
|
|
title: '',
|
|
content: options,
|
|
buttons: { ok: { text: 'OK', btnClass: 'btn-blue' } }
|
|
};
|
|
}
|
|
|
|
if ( !options.buttons )
|
|
{
|
|
options.buttons = { ok: { text: 'OK', btnClass: 'btn-blue' } };
|
|
}
|
|
|
|
return new AdsProDialog( options );
|
|
};
|
|
|
|
$.dialog = function( options )
|
|
{
|
|
options = options || {};
|
|
options.closeIcon = true;
|
|
if ( !options.buttons )
|
|
{
|
|
options.buttons = {};
|
|
}
|
|
return new AdsProDialog( options );
|
|
};
|
|
|
|
})( jQuery );
|