Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg id="icon-tve-dash-notification" width="40" height="41" viewBox="0 0 40 41" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle opacity="0.7" cx="20" cy="20.7935" r="20"/>
<rect x="10" y="10.7935" width="20" height="20" rx="1"/>
<path d="M30 25.0793H23.5135C23.5135 25.0793 23.5135 27.9365 20.2703 27.9365C17.027 27.9365 17.027 25.0793 17.027 25.0793H10"/>
</svg>
<svg id="icon-tve-dash-tar" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="14" height="14" rx="1" stroke="#879198" stroke-width="1.5"/>
<path d="M15 11H10.4595C10.4595 11 10.4595 13 8.18919 13C5.91892 13 5.91892 11 5.91892 11H1" stroke="#879198" stroke-width="1.5"/>
</svg>
<svg id="icon-tvd-notification-cross" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8211 1.3415L10.6451 0.166504L5.98305 4.82484L1.32097 0.166504L0.14502 1.3415L4.80711 5.99984L0.14502 10.6582L1.32097 11.8332L5.98305 7.17484L10.6451 11.8332L11.8211 10.6582L7.159 5.99984L11.8211 1.3415Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-error" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.00006C6.47 2.00006 2 6.47006 2 12.0001C2 17.5301 6.47 22.0001 12 22.0001C17.53 22.0001 22 17.5301 22 12.0001C22 6.47006 17.53 2.00006 12 2.00006ZM14.59 8.00006L12 10.5901L9.41 8.00006L8 9.41006L10.59 12.0001L8 14.5901L9.41 16.0001L12 13.4101L14.59 16.0001L16 14.5901L13.41 12.0001L16 9.41006L14.59 8.00006ZM4 12.0001C4 16.4101 7.59 20.0001 12 20.0001C16.41 20.0001 20 16.4101 20 12.0001C20 7.59006 16.41 4.00006 12 4.00006C7.59 4.00006 4 7.59006 4 12.0001Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-info" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20ZM10 14.17L16.59 7.58L18 9L10 17L6 13L7.41 11.59L10 14.17Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-success" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM12 20C7.59 20 4 16.41 4 12C4 7.59 7.59 4 12 4C16.41 4 20 7.59 20 12C20 16.41 16.41 20 12 20ZM10 14.17L16.59 7.58L18 9L10 17L6 13L7.41 11.59L10 14.17Z" fill="currentColor"/>
</svg>
<svg id="icon-notification-type-warning" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.99 2.00012C6.47 2.00012 2 6.48012 2 12.0001C2 17.5201 6.47 22.0001 11.99 22.0001C17.52 22.0001 22 17.5201 22 12.0001C22 6.48012 17.52 2.00012 11.99 2.00012ZM13 13.0001V7.00012H11V13.0001H13ZM13 17.0001V15.0001H11V17.0001H13ZM4 12.0001C4 16.4201 7.58 20.0001 12 20.0001C16.42 20.0001 20 16.4201 20 12.0001C20 7.58012 16.42 4.00012 12 4.00012C7.58 4.00012 4 7.58012 4 12.0001Z" fill="currentColor"></path>
</svg>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
module.exports = Backbone.Collection.extend( {
/**
* helper function to get the last item of a collection
*
* @return Backbone.Model
*/
last: function () {
return this.at( this.size() - 1 );
}
} );

View File

@@ -0,0 +1,6 @@
var NotificationModel = require( './../models/Notification' );
module.exports = Backbone.Collection.extend({
model: NotificationModel,
});

View File

@@ -0,0 +1,46 @@
module.exports = Backbone.Model.extend({
idAttribute: 'id',
defaults: {
active: {},
dismissed: {},
},
getDate: function () {
if (this.has('start') && this.get('start')) {
let startDate = new Date(this.get('start'));
let currentDate = new Date(TD_Notification?.date_time_now);
let timeDiff = currentDate.getTime() - startDate.getTime();
// Convert the difference to months, days, hours, or minutes
let yearsDiff = Math.floor(timeDiff / (1000 * 3600 * 24 * 365));
if (yearsDiff > 0) {
return yearsDiff + (yearsDiff === 1 ? " year ago" : " years ago");
}
let monthsDiff = Math.floor(timeDiff / (1000 * 3600 * 24 * 30));
if (monthsDiff > 0) {
return monthsDiff + (monthsDiff === 1 ? " month ago" : " months ago");
}
let daysDiff = Math.floor(timeDiff / (1000 * 3600 * 24));
if (daysDiff > 0) {
return daysDiff + (daysDiff === 1 ? " day ago" : " days ago");
}
let hoursDiff = Math.floor(timeDiff / (1000 * 3600));
if (hoursDiff > 0) {
return hoursDiff + (hoursDiff === 1 ? " hour ago" : " hours ago");
}
let minsDiff = Math.floor(timeDiff / (1000 * 60));
if (minsDiff > 0) {
return minsDiff + (minsDiff === 1 ? " minute ago" : " minutes ago");
}
return "just now";
} else {
return "";
}
}
});

View File

@@ -0,0 +1,131 @@
TD_Notification = TD_Notification || {};
// Import necessary modules
const NotificationDrawer = require( './views/NotificationDrawer' );
const NotificationsList = require( './views/NotificationsList' );
const NotificationCollection = require( './collections/Notifications' );
const FooterView = require( './views/NotificationFooter' );
( function ( $ ) {
$(document).ready(function () {
// Initialize variables
let notificationType = 'Active';
let notificationData = [];
let notificationListView = null;
let footerView = null;
// Function to render the UI
const renderUI = function () {
// Filter data based on notification type
const filteredData = notificationType === 'Active' ? TD_Notification?.data?.active : TD_Notification?.data?.dismissed;
// Count dismissed and active notifications
const dismissedCount = TD_Notification?.data?.dismissed?.length;
const activeCount = TD_Notification?.data?.active?.length;
if ( activeCount <= 0 ) {
$('.notification-indicator').parent().remove();
}
// Create a new collection with filtered data
const collection = new NotificationCollection( filteredData );
// Render NotificationDrawer
const notificationDrawer = new NotificationDrawer( {
el: $( '.td-app-notification-counter' ),
collection: collection,
activeCount,
dismissedCount
} );
notificationDrawer.render();
// Render NotificationsList
notificationListView = new NotificationsList( {
el: $('.td-app-notification-holder'),
collection,
notificationType,
dismissedCount,
activeCount,
} );
notificationListView.render();
footerView = new FooterView({
el: $('.notification-footer'),
collection: collection,
notificationType: notificationType,
hideDismissAll: notificationType === 'Dismissed' || activeCount < 2,
});
footerView.render();
// Event handler for collection change
notificationListView.on( 'collectionChanged', function ( data ) {
notificationData = data.collection.toJSON();
renderUI(); // Re-render UI with updated data
} );
footerView.on( 'collectionChanged', function ( data ) {
notificationData = data.collection.toJSON();
renderUI(); // Re-render UI with updated data
} );
// Event handler for notification type change
notificationListView.on( 'notificationTypeChanged', function ( data ) {
notificationType = data?.notification_type ? data?.notification_type : 'Active';
renderUI(); // Re-render UI with updated notification type
} );
$('.tve-notification').last().css('border-bottom', 'none')
};
window.render_ui = renderUI;
// Check visibility every 100 milliseconds
const interval = setInterval(function () {
if ($('.td-app-notification-counter').is(':visible')) {
// Render the UI for the first time
renderUI();
clearInterval(interval);
}
}, 100);
// Initial check in case the element is already visible when the script runs
if ($('.td-app-notification-counter').is(':visible')) {
renderUI();
clearInterval(interval);
}
const checkEmptyOrNot = setInterval(function () {
if ($('.td-app-notification-wrapper').is(':empty')) {
renderUI();
} else {
clearInterval(checkEmptyOrNot);
}
}, 100);
// Function to close the notification drawer
const closeNotificationDrawer = function () {
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
};
// Event listener for Esc key press
$(document).on('keydown', function (e) {
if (e.key === 'Escape') {
closeNotificationDrawer();
}
});
const getUrlParameter = function(name) {
name = name.replace(/[\[\]]/g, '\\$&'); // Escape special characters for regex
const regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)');
const results = regex.exec(window.location.href);
if (!results) return null; // If no match is found
if (!results[2]) return ''; // If the parameter exists but no value is set
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
if ( getUrlParameter('notify') == 1 ) {
$( '.td-app-notification-overlay' ).removeClass( 'close' );
$( '.td-app-notification-drawer' ).addClass( 'open' );
}
});
} )( jQuery );

View File

@@ -0,0 +1,12 @@
/**
* Created by Russel Hussain on 4/29/2024.
*/
( function ( $ ) {
module.exports = Backbone.View.extend( {
render: function () {
return this;
}
} )
} )( jQuery );

View File

@@ -0,0 +1,47 @@
/**
* Created by Russel Hussain on 05/05/2024.
*/
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
notificationType: 'Active',
translate: TD_Notification.t,
initialize: function ( options ) {
if (options && options.notificationType) {
this.notificationType = options.notificationType;
}
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="no-notifications no-notifications-'+ theme_class +'">';
let notificationType = this.notificationType;
if ( notificationType === 'Active' ) {
html += '<img alt="Dannie the Detective" src="'+ TD_Notification?.image_url +'">' +
'<div class="great-scott great-scott-'+ theme_class +'">' + this.translate.no_new_title + '</div>' +
'<div class="no-new-notifications no-new-notification-'+ theme_class +'">' + this.translate.no_new + '</div>' +
'<span class="switch-notification-type toggle-to-dismissed switch-notification-type-'+ theme_class + '">' + this.translate.see_dismissed +'</span>';
}
if (notificationType === 'Dismissed') {
html += '<img alt="Dannie the Detective" src="'+ TD_Notification?.image_url +'">' +
'<div class="great-scott great-scott-'+ theme_class +'">' + this.translate.no_new_title + '</div>' +
'<div class="no-new-notifications no-new-notification-'+ theme_class +'">' + this.translate.no_dismissed + '</div>' +
'<span class="switch-notification-type toggle-to-active switch-notification-type-'+ theme_class +'">' + this.translate.see_new + '</span>';
}
html += '</div>';
return html;
}
} );
} )( jQuery );

View File

@@ -0,0 +1,111 @@
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
render: function () {
this.$el.append( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="tve-notification notification-'+ theme_class +'">' +
'<div class="icon icon-'+ theme_class +'">' +
'<svg class="tve-circle-close type-' + this.model.get('type') + '" xmlns="http://www.w3.org/2000/svg">><use xlink:href="#icon-notification-type-' + this.model.get('type') + '"></use></svg>' +
'</div>' +
'<div class="body">' +
'<div class="title title-'+ theme_class +'">' +
'<div>' + this.model.get('title') + '</div>';
if (this.model.getDate()) {
html += '<div class="date date-'+ theme_class +'">' + this.model.getDate() + '</div>';
}
html += '</div>' +
'<div class="notification-content notification-content-'+ theme_class +'">' + this.addMediaPlayer(this.model.get('content')) + '</div>' +
'<div class="tvd-notification-actions">';
if ( this.model.get( 'button1_action' )) {
html += '<a type="button" class="tve-dash-button notify-primary notify-primary-'+ theme_class +'" href="' + this.model.get( 'button1_action' ) + '" target="_blank" rel="noopener noreferrer">' + this.model.get( 'button1_label' ) + '</a>';
}
if ( this.model.get( 'button2_action' ) ) {
html += '<a type="button" class="tve-dash-button notify-secondary notify-secondary-'+ theme_class +'" href="' + this.model.get( 'button2_action' ) + '" target="_blank" rel="noopener noreferrer">' + this.model.get( 'button2_label' ) + '</a>';
}
if ( this.model.get('dismissed') != 1 ) {
html += '<span class="dismiss-notification dismiss-notification-'+ theme_class +'" data-id="' + this.model.get('notification_id') + '">Dismiss</span>';
}
html += '</div>' +
'</div>' +
'</div>';
return html;
},
addMediaPlayer: function (content) {
content = content.replace(/&nbsp;/g, '<br>');
// Check for direct video links (mp4, webm, ogg)
const videoRegex = /(https?:\/\/\S+\.(mp4|webm|ogg))/gi;
if (videoRegex.test(content)) {
content = content.replace(videoRegex, (match, videoUrl) => {
return `<div class="notification-content-video-container"><video class="custom-video-player" controls>
<source src="${videoUrl}" type="video/mp4">
Your browser does not support the video tag.
</video></div>`;
});
}
// Check for YouTube links
const youtubeRegex = /(https?:\/\/(www\.)?youtube\.com\/watch\?v=[\w-]+|https?:\/\/youtu\.be\/[\w-]+)/gi;
if (youtubeRegex.test(content)) {
content = content.replace(youtubeRegex, (match, youtubeUrl) => {
const urlParams = new URLSearchParams(new URL(youtubeUrl).search);
const videoId = urlParams.get('v') || youtubeUrl.split('/').pop();
const embedUrl = `https://www.youtube.com/embed/${videoId}`;
return `<div class="notification-content-video-container"><iframe class="custom-iframe" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
});
}
const youtubeFigureRegex = /<figure[^>]*>\s*<div[^>]*>\s*(https?:\/\/(www\.)?youtube\.com\/watch\?v=[\w-]+|https?:\/\/youtu\.be\/[\w-]+)\s*<\/div>\s*<\/figure>/gi;
content = content.replace(youtubeFigureRegex, (match, youtubeUrl) => {
const urlParams = new URLSearchParams(new URL(youtubeUrl).search);
const videoId = urlParams.get('v') || youtubeUrl.split('/').pop();
const embedUrl = `https://www.youtube.com/embed/${videoId}`;
return `<div class="notification-content-video-container"><iframe class="custom-iframe" src="${embedUrl}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>`;
});
// Check for GIF images inside <a> tags
const gifInAnchorRegex = /<a[^>]*>\s*(https?:\/\/\S+\.(gif))\s*<\/a>/gi;
if (gifInAnchorRegex.test(content)) {
content = content.replace(gifInAnchorRegex, (match, gifUrl) => {
return `<div class="notification-content-image-container"><img class="custom-image-player" src="${gifUrl}" alt="GIF"></div>`;
});
}
// Check for image links (jpg, jpeg, png, gif)
const imageRegex = /(https?:\/\/\S+\.(jpg|jpeg|png|gif))/gi;
if (content.includes('<img')) {
return content;
}
if (imageRegex.test(content)) {
content = content.replace(imageRegex, (match, imageUrl) => {
return `<div class="notification-content-image-container"><img class="custom-image-player" src="${imageUrl}" alt="Image"></div>`;
});
}
const htmlTagRegex = /<\/?[a-z][\s\S]*>/i;
if (!htmlTagRegex.test(content)) {
content = content.replace(/\n/g, '<br>');
}
return content;
}
} );
} )( jQuery );

View File

@@ -0,0 +1,48 @@
(function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
dismissedCount: 0,
activeCount: 0,
events: {
'click .tvd-notifications-btn': 'open',
'click .td-app-notification-counter-holder': 'open',
'click .text-notify-t-automator': 'open',
},
initialize: function ( options ) {
$( window ).on('scroll', this.adjustDrawerPosition.bind(this));
$( document ).on('click', this.handleDocumentClick.bind(this));
if ( options ) {
this.activeCount = options.activeCount;
this.dismissedCount = options.dismissedCount;
}
},
adjustDrawerPosition: function () {
const scrollTop = $( window ).scrollTop();
const newTop = 124 + scrollTop + 'px';
this.$( '.td-app-notification-drawer' ).css( 'top', newTop );
},
render: function () {
this.$( '.td-app-notification-counter-holder' ).text( this.activeCount );
this.activeCount >= 1 ? this.$( '.td-app-notification-counter-holder' ).show() : this.$( '.td-app-notification-counter-holder' ).hide();
return this;
},
open: function () {
$( '.td-app-notification-overlay' ).removeClass( 'close' );
$( '.td-app-notification-drawer' ).addClass( 'open' );
},
handleDocumentClick: function (event) {
if ( $(event.target).closest('.td-app-notification-overlay.overlay').length) {
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
}
}
} );
} )( jQuery );

View File

@@ -0,0 +1,73 @@
( function ( $ ) {
const BaseView = require( './Base' );
module.exports = BaseView.extend( {
hideDismissAll: false,
events: {
'click .dismiss-all': 'dismissAll',
},
initialize: function ( options ) {
if ( options && options.hideDismissAll ) {
this.hideDismissAll = options.hideDismissAll;
}
this.listenTo( this.collection, 'change:dismiss-all', this.collectionChanged );
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
let html = '<div class="pagination pagination-'+ theme_class +'"></div>' +
'<div class="dismiss-all dismiss-all-'+ theme_class +'">';
if ( !this.hideDismissAll ) {
html += '<span class="dismiss-all dismiss-all-'+ theme_class +'">Dismiss All</span>';
}
html += '</div>';
return html;
},
dismissAll: function () {
this.collection.each(function (item) {
const index = TD_Notification.data.active.findIndex(notification => notification.notification_id == item.get('notification_id'));
if (index !== -1) {
TD_Notification.data.active.splice(index, 1);
}
TD_Notification.data.dismissed.unshift(item.toJSON());
});
this.collectionChanged();
this.dismissAllNotification();
},
dismissAllNotification: function () {
$.ajax( {
type: 'POST',
url: TD_Notification.baseUrl + '/dismiss-all',
headers: {
'X-WP-Nonce': TD_Notification?.dismiss_nonce // Pass the nonce in the headers
},
success: function (response) {
// Handle success response
},
error: function (xhr, status, error) {
console.error('Error marking notification as read:', error);
}
} );
},
collectionChanged: function () {
this.trigger( 'collectionChanged', { notification_type: 'Active', collection: this.collection } );
}
});
} )( jQuery );

View File

@@ -0,0 +1,75 @@
( function ( $ ) {
let BaseView = require( './Base' );
module.exports = BaseView.extend( {
data: {
notification_type: 'Active',
notification_number: 0,
active_count: 0,
dismissed_count: 0
},
events: {
'click .toggle-to-dismissed': 'toggleNotification',
'click .toggle-to-active': 'toggleNotification'
},
initialize: function ( options ) {
if ( options ) {
this.data.active_count = options.activeCount;
this.data.dismissed_count = options.dismissedCount;
this.data.notification_type = options.notificationType;
}
if ( this.data.notification_type === 'Dismissed' ) {
this.collection.each( function ( item ) {
if ( item.get( 'dismissed' ) == 0 ) {
item.set( 'dismissed', 1 );
}
});
}
this.data.notification_number = this.collection.length;
},
render: function () {
this.$el.html( this.getHtml() );
return this;
},
getHtml: function () {
let html = '';
let theme_class = TD_Notification.notify_class ? TD_Notification.notify_class : '';
if ( this.data.notification_type === 'Active' ) {
html += '<span class="tvd-notification-number notification-number-'+ theme_class +'">(' + this.data.notification_number + ') New Notifications</span>';
} else if ( this.data.notification_type === 'Dismissed' ) {
html += '<span class="tvd-notification-number notification-number-'+ theme_class +'"> (' + this.data.notification_number + ') Notifications</span>';
}
html += '<div class="toggle-notifications">';
//If current tab is active and no of dismissed notification is zero, no need to show
if ( this.data.notification_type === 'Active' && this.data.dismissed_count > 0 ) {
html += '<span class="toggle-to-dismissed toggle-notifications toggle-'+ theme_class +'">Dismissed Notifications</span>';
}
//If Current tab is Dismissed should have option to go to active notification
if ( this.data.notification_type === 'Dismissed' ) {
html += '<span class="toggle-to-active toggle-notifications toggle-'+ theme_class +'">Active Notifications</span>';
}
html += '</div>';
html += '<span class="tvd-close-notification-drawer close-notification-'+ theme_class +'">';
html += '<svg class="icon-tve-dash-notification-cross"><use xlink:href="#icon-tvd-notification-cross"></use></svg>';
html += '</span>';
return html;
},
toggleNotification: function ( event ) {
const notificationType = $( event.currentTarget ).hasClass( 'toggle-to-dismissed' ) ? 'Dismissed' : 'Active';
if (this.data.notification_type !== notificationType) {
this.data.notification_type = notificationType;
this.trigger('notificationTypeChanged', { notification_type: notificationType });
}
event.stopPropagation();
}
} );
} )( jQuery );

View File

@@ -0,0 +1,149 @@
(function ( $ ) {
let BaseView = require('./Base');
let HeaderView = require('./NotificationHeader');
let FooterView = require('./NotificationFooter');
let NotificationView = require('./NotificationController');
let NoNotificationView = require('./NoNotification');
module.exports = BaseView.extend( {
headerView: null,
hideDismissAll: false,
notificationType: 'Active',
dismissedCount: 0,
activeCount: 0,
events: {
'click .tvd-close-notification-drawer': 'close',
'click .dismiss-notification': 'dismiss',
'click .switch-notification-type': 'toggleNotification',
},
initialize: function ( options ) {
if ( options ) {
this.activeCount = options.activeCount;
this.dismissedCount = options.dismissedCount;
this.hideDismissAll = options.notificationType === 'Dismissed' || this.activeCount < 2;
this.notificationType = options.notificationType;
}
this.listenTo( this.collection, 'change:dismiss', this.collectionChanged );
},
render: function () {
this.renderHeader();
const $wrapperContainer = this.$('.td-app-notification-wrapper');
if (this.collection.length > 0) {
$wrapperContainer.html('<div class="tvd-notifications-list"></div>');
this.renderList();
} else {
$wrapperContainer.empty();
new NoNotificationView( {
el: $wrapperContainer,
notificationType: this.notificationType
} ).render();
}
if ($wrapperContainer.find('.notification-footer').length === 0) {
this.renderFooter();
}
return this;
},
renderHeader: function () {
this.headerView = new HeaderView( {
el: this.$( '.td-app-notification-header' ),
collection: this.collection,
activeCount: this.activeCount,
dismissedCount: this.dismissedCount,
notificationType: this.notificationType
} ).render();
this.listenTo( this.headerView, 'notificationTypeChanged', this.notificationTypeChanged );
},
renderList: function () {
const $listContainer = this.$( '.tvd-notifications-list' );
$listContainer.empty();
// Instantiate NotificationView outside the loop
const notificationViews = this.collection.map(function(model) {
return new NotificationView({
model: model
});
});
// Render each NotificationView instance within the loop
notificationViews.forEach(function(notificationView) {
$listContainer.append(notificationView.render().el);
});
},
renderFooter: function () {
const $notificationFooter = $( '.notification-footer' );
$notificationFooter.empty();
new FooterView({
el: $notificationFooter,
collection: this.collection,
notificationType: this.notificationType,
hideDismissAll: this.hideDismissAll,
}).render();
},
toggleNotification: function ( event ) {
const notificationType = $( event.currentTarget ).hasClass( 'toggle-to-dismissed' ) ? 'Dismissed' : 'Active';
this.trigger('notificationTypeChanged', { notification_type: notificationType });
},
dismiss: function ( event ) {
event.preventDefault();
let notification_id = $( event.currentTarget ).data( 'id' );
let item = this.collection.findWhere( { notification_id: String(notification_id) } );
if ( item ) {
this.collection.remove(item);
const index = TD_Notification.data.active.findIndex(notification => notification.notification_id== notification_id);
if (index !== -1) {
TD_Notification.data.active.splice(index, 1);
}
TD_Notification.data.dismissed.unshift(item.toJSON());
this.dismissNotification( notification_id );
this.collectionChanged();
}
},
dismissNotification: function ( remoteId ) {
$.ajax( {
type: 'POST',
url: TD_Notification.baseUrl + '/dismiss',
headers: {
'X-WP-Nonce': TD_Notification?.dismiss_nonce // Pass the nonce in the headers
},
data: {
notification_id: remoteId,
},
success: function ( response ) {
// Handle success response
},
error: function (xhr, status, error) {
console.error('Error marking notification as read:', error);
}
} );
},
close: function () {
const notificationType = 'Active';
this.trigger('notificationTypeChanged', { notification_type: notificationType });
$( '.td-app-notification-overlay' ).addClass( 'close' );
$( '.td-app-notification-drawer' ).removeClass( 'open' );
},
collectionChanged: function () {
this.trigger( 'collectionChanged', { notification_type: 'Active', collection: this.collection } );
},
notificationTypeChanged: function ( data ) {
this.trigger( 'notificationTypeChanged', data );
}
} );
} )( jQuery );