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)} ${msdAjax.strings.posts}
${this.formatNumber(data.total_pages || 0)} ${msdAjax.strings.pages}
${msdAjax.strings.multisite_configuration}
${msdAjax.strings.installation_type}: ${this.escapeHtml(data.multisite_config?.installation_type_label || msdAjax.strings.unknown)}
${msdAjax.strings.network_admin_email}: ${this.escapeHtml(data.network_info?.network_admin_email || msdAjax.strings.not_set)}
${msdAjax.strings.site_upload_quota}: ${data.network_info?.blog_upload_space_formatted || msdAjax.strings.zero_mb}
${msdAjax.strings.max_upload_size}: ${data.network_info?.fileupload_maxk_formatted || msdAjax.strings.unknown}
${msdAjax.strings.default_language}: ${this.escapeHtml(data.network_info?.default_language || "en_US")}
${msdAjax.strings.registration}: ${this.escapeHtml(data.network_info?.registration_label || msdAjax.strings.unknown)}
`; $container.html(html); 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 += `

${msdAjax.strings.no_active_sites}

`; } else { html += '
'; sites.forEach((site) => { html += `
${this.escapeHtml(site.name)}
${this.escapeHtml(site.name)}
${site.users || 0} ${msdAjax.strings.users} ${site.last_activity_human || msdAjax.strings.no_activity}
`; }); html += "
"; } $container.html(html); }, renderStorageData($container, data) { let html = ``; if (!data || !data.sites || data.sites.length === 0) { html += `

${msdAjax.strings.no_storage_data}

`; } else { html += '
'; html += `
${msdAjax.strings.total_network_storage}: ${data.total_formatted || msdAjax.strings.zero_bytes}
`; if (data.summary) { html += `
${msdAjax.strings.top_5_sites_storage}
`; } 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 || msdAjax.strings.zero_bytes}
${site.usage_percentage || 0}%
`; }); html += "
"; } $container.html(html); }, renderVersionInfo($container, data) { let html = `

${this.escapeHtml(data.plugin_name || "WP Multisite Dashboard")}

${ data.update_available && data.update_info ? `
${msdAjax.strings.update_available.replace("{version}", this.escapeHtml(data.update_info.version))} ${data.update_info.details_url ? `${msdAjax.strings.view_details}` : ""}
` : "" }
${msdAjax.strings.plugin_version} ${this.escapeHtml(data.plugin_version || "")}
${msdAjax.strings.author_uri} ${this.escapeHtml(data.plugin_uri || "")}
${msdAjax.strings.required_php} ${this.escapeHtml(data.required_php || "")}
${msdAjax.strings.database_tables} ${data.database_status === "active" ? msdAjax.strings.check_mark : msdAjax.strings.warning_mark} ${data.database_status === "active" ? msdAjax.strings.activity_table_created : msdAjax.strings.activity_table_missing}
`; $container.html(html); }, renderCustomNews($container, news) { let html = ` `; if (!news || news.length === 0) { html += `

${msdAjax.strings.no_news_items}

${msdAjax.strings.configure_news_sources}

`; } 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(cleanTitle)}

${this.escapeHtml(cleanDescription)}

`; }); html += "
"; } html += `
`; $container.html(html); }, renderNetworkSettings($container, data) { let html = `
${msdAjax.strings.network}: ${this.escapeHtml(data.network_info?.network_name || msdAjax.strings.not_available)}
${msdAjax.strings.registration}: ${this.getRegistrationLabel(data.network_info?.registration || "none")}
${msdAjax.strings.upload_limit}: ${data.network_info?.blog_upload_space || 0} ${msdAjax.strings.mb}
${msdAjax.strings.active_plugins}: ${data.theme_plugin_settings?.network_active_plugins || 0}
${msdAjax.strings.network_themes}: ${data.theme_plugin_settings?.network_themes || 0}
${msdAjax.strings.settings} ${msdAjax.strings.sites} ${msdAjax.strings.users} ${msdAjax.strings.themes} ${msdAjax.strings.plugins} ${msdAjax.strings.updates}
`; $container.html(html); }, renderUserManagement($container, data) { let html = `
${data.total_users || 0} ${msdAjax.strings.users} (${data.super_admin_count || 0} ${msdAjax.strings.admins}) ${data.registration_status?.description || msdAjax.strings.unknown}
`; 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)}
${this.escapeHtml(user.display_name)}
`; }); } else { html += `
${msdAjax.strings.no_recent_registrations}
`; } html += "
"; if (data.pending_activations && data.pending_activations.length > 0) { html += `
${data.pending_activations.length} ${msdAjax.strings.pending_activations}
`; data.pending_activations.slice(0, 3).forEach((signup) => { html += `
${this.escapeHtml(signup.user_email)}
${msdAjax.strings.activate}
`; }); html += "
"; } html += "
"; $container.html(html); }, renderLastEdits($container, activities) { let html = ``; if (!activities || activities.length === 0) { html += `

${msdAjax.strings.no_recent_activity}

`; } 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 = `
${todos.length} ${msdAjax.strings.total}
${todos.filter((t) => t.completed).length} ${msdAjax.strings.done}
`; if (todos.length === 0) { html += `

${msdAjax.strings.no_todos}

`; } else { html += '
'; todos.forEach((todo) => { const completedClass = todo.completed ? "completed" : ""; const priorityLabel = msdAjax.strings[todo.priority + "_priority"] || todo.priority; html += `
${this.escapeHtml(todo.title)}
${todo.description ? `
${this.escapeHtml(todo.description)}
` : ""}
${priorityLabel} ${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(msdAjax.strings.title_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 || msdAjax.strings.failed_create_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 || msdAjax.strings.failed_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 || msdAjax.strings.failed_update_status, "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( msdAjax.strings.invalid_widget_id, "error", ); } return; } if (!confirm(msdAjax.strings.confirm_action)) { return; } $btn.prop("disabled", true).text(msdAjax.strings.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 || msdAjax.strings.action_completed, "success", ); this.loadWidget("user_management"); }, (error) => { window.MSD_Core.showNotice( error || msdAjax.strings.failed_user_action, "error", ); }, ).always(() => { $btn .prop("disabled", false) .text($btn.data("original-text") || msdAjax.strings.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 = `

${msdAjax.strings.unable_to_load}

`; $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(); });