jQuery(document).ready(function($) {
'use strict';
const MSD_Widgets = {
init() {
this.loadAllWidgets();
this.bindEvents();
},
bindEvents() {
$(document)
.on('click', '.msd-user-action-btn', this.handleUserAction.bind(this))
.on('click', '.msd-todo-add-btn', this.showTodoForm.bind(this))
.on('click', '.msd-todo-checkbox', this.toggleTodoComplete.bind(this))
.on('click', '.msd-todo-edit', this.editTodo.bind(this))
.on('click', '.msd-todo-delete', this.deleteTodo.bind(this))
.on('click', '.msd-todo-save', this.saveTodo.bind(this))
.on('click', '.msd-todo-cancel', this.cancelTodoForm.bind(this));
},
loadAllWidgets() {
if (window.MSD_Core && window.MSD_Core.isRefreshing) return;
if (window.MSD_Core) {
window.MSD_Core.isRefreshing = true;
}
const widgets = ['network_overview', 'site_list', 'storage_data', 'version_info', 'custom_news', 'network_settings', 'user_management', 'last_edits', 'todo_items'];
widgets.forEach(widget => {
this.loadWidget(widget);
});
setTimeout(() => {
if (window.MSD_Core) {
window.MSD_Core.isRefreshing = false;
}
}, 1000);
},
loadWidget(widgetType) {
const $container = $(`[data-widget="${widgetType}"]`);
if ($container.length === 0) return;
const actionMap = {
network_overview: 'msd_get_network_overview',
site_list: 'msd_get_site_list',
storage_data: 'msd_get_storage_data',
version_info: 'msd_get_version_info',
custom_news: 'msd_get_custom_news',
network_settings: 'msd_get_network_settings',
user_management: 'msd_get_user_management',
last_edits: 'msd_get_last_edits',
todo_items: 'msd_get_todo_items'
};
const action = actionMap[widgetType];
if (!action) return;
if (window.MSD_Core) {
window.MSD_Core.makeAjaxRequest(action, {}, (response) => {
this.renderWidget(widgetType, $container, response.data);
if (window.MSD_Core) {
window.MSD_Core.retryCount = 0;
}
}, (error) => {
this.handleWidgetError($container, error, widgetType);
});
}
},
renderWidget(widgetType, $container, data) {
const renderers = {
network_overview: this.renderNetworkOverview,
site_list: this.renderQuickSites,
storage_data: this.renderStorageData,
version_info: this.renderVersionInfo,
custom_news: this.renderCustomNews,
network_settings: this.renderNetworkSettings,
user_management: this.renderUserManagement,
last_edits: this.renderLastEdits,
todo_items: this.renderTodoItems
};
const renderer = renderers[widgetType];
if (renderer) {
renderer.call(this, $container, data);
$container.addClass('fade-in');
}
},
renderNetworkOverview($container, data) {
const html = `
${this.formatNumber(data.total_posts || 0)}
Posts
${this.formatNumber(data.total_pages || 0)}
Pages
Installation Type:
${this.escapeHtml(data.multisite_config?.installation_type_label || 'Unknown')}
Network Admin Email:
${this.escapeHtml(data.network_info?.network_admin_email || 'Not set')}
Site Upload Quota:
${data.network_info?.blog_upload_space_formatted || '0 MB'}
Max Upload Size:
${data.network_info?.fileupload_maxk_formatted || 'Unknown'}
Default Language:
${this.escapeHtml(data.network_info?.default_language || 'en_US')}
Registration:
${this.escapeHtml(data.network_info?.registration_label || 'Unknown')}
`;
$container.html(html);
// 重新初始化 sortable 功能
setTimeout(() => {
if (window.MSD_Modals && window.MSD_Modals.initSortable) {
window.MSD_Modals.initSortable();
}
}, 100);
},
renderQuickSites($container, sites) {
let html = '';
if (!sites || sites.length === 0) {
html += '';
} else {
html += '';
sites.forEach(site => {
html += `
${this.escapeHtml(site.name)}
${site.users || 0} users
${site.last_activity_human || 'No activity'}
`;
});
html += '
';
}
$container.html(html);
},
renderStorageData($container, data) {
let html = '';
if (!data || !data.sites || data.sites.length === 0) {
html += 'No storage data available.
';
} else {
html += '';
html += `
Total Network Storage: ${data.total_formatted || '0 B'}
`;
if (data.summary) {
html += `
Top 5 sites by storage usage
`;
}
html += '
';
html += '';
data.sites.forEach(site => {
const fillWidth = Math.min(site.usage_percentage || 0, 100);
const fillClass = this.getStorageStatusClass(site.status);
html += `
${this.escapeHtml(site.name)}
${this.escapeHtml(site.domain)}
${site.storage_formatted || '0 B'}
${site.usage_percentage || 0}%
`;
});
html += '
';
}
$container.html(html);
},
renderVersionInfo($container, data) {
let html = `
${data.update_available && data.update_info ? `
Version ${this.escapeHtml(data.update_info.version)} available!
${data.update_info.details_url ? `
View Details` : ''}
` : ''}
Plugin Version
${this.escapeHtml(data.plugin_version || '')}
Required PHP
${this.escapeHtml(data.required_php || '')}
Database Tables
${data.database_status === 'active' ? '✓' : '⚠'} ${this.escapeHtml(data.database_message || 'Unknown')}
`;
$container.html(html);
},
renderCustomNews($container, news) {
let html = `
`;
if (!news || news.length === 0) {
html += `
No news items available.
Configure news sources to see updates.
`;
} else {
html += '';
news.forEach(item => {
const date = item.date ? this.formatNewsDate(item.date) : '';
const cleanTitle = this.decodeHtmlEntities(item.title || '');
const cleanDescription = this.decodeHtmlEntities(item.description || '');
html += `
${this.escapeHtml(item.source || '')}
${date}
${this.escapeHtml(cleanDescription)}
`;
});
html += '
';
}
html += `
`;
$container.html(html);
},
renderNetworkSettings($container, data) {
let html = `
Network:
${this.escapeHtml(data.network_info?.network_name || 'N/A')}
Registration:
${this.getRegistrationLabel(data.network_info?.registration || 'none')}
Upload Limit:
${data.network_info?.blog_upload_space || 0} MB
Active Plugins:
${data.theme_plugin_settings?.network_active_plugins || 0}
Network Themes:
${data.theme_plugin_settings?.network_themes || 0}
`;
$container.html(html);
},
renderUserManagement($container, data) {
let html = `
`;
if (data.recent_registrations && data.recent_registrations.length > 0) {
data.recent_registrations.slice(0, 5).forEach(user => {
const statusClass = this.getUserStatusClass(user.status);
html += `
${this.escapeHtml(user.display_name)}
${user.registered_ago} • ${user.sites_count} sites
${this.getUserStatusLabel(user.status)}
Edit
`;
});
} else {
html += '
No recent registrations
';
}
html += '
';
if (data.pending_activations && data.pending_activations.length > 0) {
html += `
`;
data.pending_activations.slice(0, 3).forEach(signup => {
html += `
${this.escapeHtml(signup.user_email)}
Activate
`;
});
html += '
';
}
html += '
';
$container.html(html);
},
renderLastEdits($container, activities) {
let html = '';
if (!activities || activities.length === 0) {
html += 'No recent network activity found.
';
} else {
html += '';
activities.forEach(activity => {
const truncatedContent = activity.content ? this.truncateText(activity.content, 30) : '';
html += `
${this.escapeHtml(activity.site_name)}
${activity.date_human}
${truncatedContent ? `
${this.escapeHtml(truncatedContent)}
` : ''}
`;
});
html += '
';
}
$container.html(html);
},
renderTodoItems($container, todos) {
let html = `
`;
if (todos.length === 0) {
html += `
No todos yet. Click "Add Todo" to get started!
`;
} else {
html += '
';
todos.forEach(todo => {
const completedClass = todo.completed ? 'completed' : '';
html += `
${this.escapeHtml(todo.title)}
${todo.description ? `
${this.escapeHtml(todo.description)}
` : ''}
${todo.priority}
${todo.created_at_human}
`;
});
html += '
';
}
html += `
`;
$container.html(html);
},
showTodoForm() {
$('#msd-todo-form').addClass('active');
$('#msd-todo-title').focus();
},
cancelTodoForm() {
$('#msd-todo-form').removeClass('active');
this.clearTodoForm();
},
clearTodoForm() {
$('#msd-todo-title').val('');
$('#msd-todo-description').val('');
$('#msd-todo-priority').val('medium');
$('#msd-todo-form').removeData('edit-id');
},
saveTodo() {
const title = $('#msd-todo-title').val().trim();
if (!title) {
if (window.MSD_Core) {
window.MSD_Core.showNotice('Title is required', 'error');
}
return;
}
const data = {
title: title,
description: $('#msd-todo-description').val().trim(),
priority: $('#msd-todo-priority').val()
};
const editId = $('#msd-todo-form').data('edit-id');
const action = editId ? 'msd_update_todo_item' : 'msd_save_todo_item';
if (editId) {
data.id = editId;
}
if (window.MSD_Core) {
window.MSD_Core.makeAjaxRequest(action, data, (response) => {
window.MSD_Core.showNotice(response.data.message, 'success');
this.cancelTodoForm();
this.loadWidget('todo_items');
}, (error) => {
window.MSD_Core.showNotice(error || 'Failed to save todo', 'error');
});
}
},
editTodo(e) {
const $item = $(e.currentTarget).closest('.msd-todo-item');
const id = $item.data('id');
const title = $item.find('.msd-todo-title').text();
const description = $item.find('.msd-todo-description').text();
$('#msd-todo-title').val(title);
$('#msd-todo-description').val(description);
$('#msd-todo-form').data('edit-id', id).addClass('active');
$('#msd-todo-title').focus();
},
deleteTodo(e) {
if (!confirm(msdAjax.strings.confirm_delete)) {
return;
}
const $item = $(e.currentTarget).closest('.msd-todo-item');
const id = $item.data('id');
if (window.MSD_Core) {
window.MSD_Core.makeAjaxRequest('msd_delete_todo_item', { id }, (response) => {
window.MSD_Core.showNotice(response.data.message, 'success');
this.loadWidget('todo_items');
}, (error) => {
window.MSD_Core.showNotice(error || 'Failed to delete todo', 'error');
});
}
},
toggleTodoComplete(e) {
const $item = $(e.currentTarget).closest('.msd-todo-item');
const id = $item.data('id');
if (window.MSD_Core) {
window.MSD_Core.makeAjaxRequest('msd_toggle_todo_complete', { id }, (response) => {
this.loadWidget('todo_items');
}, (error) => {
window.MSD_Core.showNotice(error || 'Failed to update todo', 'error');
});
}
},
handleUserAction(e) {
e.preventDefault();
const $btn = $(e.currentTarget);
const action = $btn.data('action');
const userId = $btn.data('user-id');
if (!action || !userId) {
if (window.MSD_Core) {
window.MSD_Core.showNotice('Invalid action or user ID', 'error');
}
return;
}
if (!confirm('Are you sure you want to perform this action?')) {
return;
}
$btn.prop('disabled', true).text('Processing...');
if (window.MSD_Core) {
window.MSD_Core.makeAjaxRequest('msd_manage_user_action', {
user_action: action,
user_id: userId
}, (response) => {
window.MSD_Core.showNotice(response.data.message || 'Action completed successfully', 'success');
this.loadWidget('user_management');
}, (error) => {
window.MSD_Core.showNotice(error || 'Action failed', 'error');
}).always(() => {
$btn.prop('disabled', false).text($btn.data('original-text') || 'Action');
});
}
},
handleWidgetError($container, error, widgetType) {
if (window.MSD_Core) {
window.MSD_Core.retryCount++;
if (window.MSD_Core.retryCount <= window.MSD_Core.maxRetries) {
setTimeout(() => {
this.loadWidget(widgetType);
}, 2000 * window.MSD_Core.retryCount);
return;
}
}
const html = `
Unable to load data
`;
$container.html(html);
},
formatNumber: window.MSD_Core ? window.MSD_Core.formatNumber : function(num) { return num.toString(); },
escapeHtml: window.MSD_Core ? window.MSD_Core.escapeHtml : function(text) { return text; },
decodeHtmlEntities: window.MSD_Core ? window.MSD_Core.decodeHtmlEntities : function(text) { return text; },
truncateText: window.MSD_Core ? window.MSD_Core.truncateText : function(text, maxLength) { return text; },
getDefaultFavicon: window.MSD_Core ? window.MSD_Core.getDefaultFavicon : function() { return ''; },
getDefaultAvatar: window.MSD_Core ? window.MSD_Core.getDefaultAvatar : function() { return ''; },
formatNewsDate: window.MSD_Core ? window.MSD_Core.formatNewsDate : function(date) { return date; },
getUserStatusClass: window.MSD_Core ? window.MSD_Core.getUserStatusClass : function(status) { return status; },
getUserStatusLabel: window.MSD_Core ? window.MSD_Core.getUserStatusLabel : function(status) { return status; },
getRegistrationLabel: window.MSD_Core ? window.MSD_Core.getRegistrationLabel : function(reg) { return reg; },
getStorageStatusClass: window.MSD_Core ? window.MSD_Core.getStorageStatusClass : function(status) { return status; }
};
window.MSD_Widgets = MSD_Widgets;
MSD_Widgets.init();
});