PluginProbe ʕ •ᴥ•ʔ
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets / 4.2.3
Widget Options – Advanced Conditional Visibility for Gutenberg Blocks & Classic Widgets v4.2.3
4.2.5 4.2.4 trunk 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.2 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8 3.8.1 3.8.10 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.8.8 3.8.9 3.8.9.1 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.5.1 4.0.6 4.0.6.1 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.2.0 4.2.1 4.2.2 4.2.3
widget-options / assets / js / widgetopts.migration.js
widget-options / assets / js Last commit date
bootstrap-multiselect.min.js 2 months ago jquery.liveFilter.js 2 months ago jquery.liveFilter.min.js 2 months ago jquery.widgetopts.beaver.js 2 months ago jquery.widgetopts.beaver.min.js 2 months ago select2-settings.js 2 months ago select2-settings.min.js 2 months ago select2.min.js 2 months ago settings.js 2 months ago settings.min.js 2 months ago widgetopts.global.js 2 months ago widgetopts.migration.js 2 months ago widgetopts.resize.js 2 months ago widgets.js 2 months ago widgets.min.js 2 months ago wpWidgetOpts.js 2 months ago wpWidgetOpts.min.js 2 months ago
widgetopts.migration.js
271 lines
1 /**
2 * Widget Options - Migration Page JS
3 *
4 * Handles scanning, rendering, migrating and deleting legacy display logic snippets.
5 */
6 (function ($) {
7 'use strict';
8
9 var config = window.widgetoptsMigration || {};
10 var items = [];
11
12 /**
13 * Escape HTML to prevent XSS
14 */
15 function esc(str) {
16 var div = document.createElement('div');
17 div.appendChild(document.createTextNode(str));
18 return div.innerHTML;
19 }
20
21 /**
22 * Show a notice on the migration page
23 */
24 function showNotice(message, type) {
25 var cls = 'widgetopts-migration-notice ' + (type || 'success');
26 $('#widgetopts-migration-notices').append(
27 '<div class="' + cls + '"><p>' + esc(message) + '</p></div>'
28 );
29 }
30
31 /**
32 * Type label mapping
33 */
34 function typeLabel(type) {
35 var map = {
36 classic_widget: 'Widget',
37 gutenberg: 'Block Editor',
38 elementor: 'Elementor',
39 beaver: 'Beaver',
40 siteorigin: 'SiteOrigin'
41 };
42 return map[type] || type;
43 }
44
45 /**
46 * Build a single table row for a scanned item
47 */
48 function buildRow(item, idx) {
49 var locations = '';
50 if (item.locations && item.locations.length) {
51 // Deduplicate locations: group by type+label, show count if > 1
52 var seen = {};
53 var unique = [];
54 $.each(item.locations, function (_, loc) {
55 var key = loc.type + '||' + loc.label;
56 if (seen[key]) {
57 seen[key].count++;
58 } else {
59 seen[key] = { type: loc.type, label: loc.label, count: 1 };
60 unique.push(seen[key]);
61 }
62 });
63
64 locations = '<ul class="widgetopts-locations-list">';
65 $.each(unique, function (_, loc) {
66 locations += '<li>'
67 + '<span class="widgetopts-loc-type widgetopts-loc-type-' + esc(loc.type) + '">'
68 + esc(typeLabel(loc.type))
69 + '</span> '
70 + esc(loc.label)
71 + (loc.count > 1 ? ' <span class="widgetopts-loc-count" style="display: none;">&times;' + loc.count + '</span>' : '')
72 + '</li>';
73 });
74 locations += '</ul>';
75 }
76
77 return '<tr data-hash="' + esc(item.hash) + '" data-idx="' + idx + '">'
78 + '<th scope="row" class="check-column"><input type="checkbox" class="widgetopts-row-cb" /></th>'
79 + '<td><code class="widgetopts-code-preview">' + esc(item.code) + '</code></td>'
80 + '<td><input type="text" class="widgetopts-name-input" value="' + esc(item.title) + '" /></td>'
81 + '<td>' + locations + '</td>'
82 + '<td><button type="button" class="button button-small button-delete widgetopts-delete-btn">'
83 + 'Delete</button></td>'
84 + '</tr>';
85 }
86
87 /**
88 * Render the scanned items into the table
89 */
90 function renderTable() {
91 var $tbody = $('#widgetopts-migration-tbody');
92 $tbody.empty();
93
94 if (!items.length) {
95 $('#widgetopts-migration-content').hide();
96 $('#widgetopts-migration-empty').show();
97 return;
98 }
99
100 $.each(items, function (idx, item) {
101 $tbody.append(buildRow(item, idx));
102 });
103
104 $('#widgetopts-migration-content').show();
105 $('#widgetopts-migration-empty').hide();
106 }
107
108 /**
109 * Perform the initial AJAX scan
110 */
111 function doScan() {
112 $('#widgetopts-migration-loading').show();
113 $('#widgetopts-migration-content').hide();
114 $('#widgetopts-migration-empty').hide();
115
116 $.post(config.ajaxurl, {
117 action: 'widgetopts_migration_scan',
118 nonce: config.nonce
119 }, function (response) {
120 $('#widgetopts-migration-loading').hide();
121 if (response.success && response.data && response.data.items) {
122 items = response.data.items;
123 renderTable();
124 } else {
125 showNotice(config.i18n.error, 'error');
126 }
127 }).fail(function () {
128 $('#widgetopts-migration-loading').hide();
129 showNotice(config.i18n.error, 'error');
130 });
131 }
132
133 /**
134 * Collect selected items (or all if allMode)
135 */
136 function collectItems(allMode) {
137 var collected = [];
138 $('#widgetopts-migration-tbody tr').each(function () {
139 var $row = $(this);
140 if (allMode || $row.find('.widgetopts-row-cb').is(':checked')) {
141 collected.push({
142 hash: $row.data('hash'),
143 title: $row.find('.widgetopts-name-input').val()
144 });
145 }
146 });
147 return collected;
148 }
149
150 /**
151 * Run migration AJAX
152 */
153 function doMigrate(selectedItems) {
154 if (!selectedItems.length) {
155 alert(config.i18n.selectAtLeast);
156 return;
157 }
158 if (!confirm(config.i18n.confirmMigrate)) {
159 return;
160 }
161
162 // Disable buttons
163 $('#widgetopts-migrate-all, #widgetopts-migrate-selected').prop('disabled', true).text(config.i18n.migrating);
164
165 $.post(config.ajaxurl, {
166 action: 'widgetopts_migration_migrate',
167 nonce: config.nonce,
168 items: selectedItems
169 }, function (response) {
170 $('#widgetopts-migrate-all, #widgetopts-migrate-selected').prop('disabled', false);
171 $('#widgetopts-migrate-all').text('Migrate All');
172 $('#widgetopts-migrate-selected').text('Migrate Selected');
173
174 if (response.success && response.data && response.data.results) {
175 var r = response.data.results;
176 var msg = config.i18n.migrationDone
177 + ' Snippets created: ' + r.snippets_created
178 + ', Widgets updated: ' + r.widgets_updated;
179 showNotice(msg, 'success');
180
181 if (r.errors && r.errors.length) {
182 $.each(r.errors, function (_, err) {
183 showNotice(err, 'error');
184 });
185 }
186
187 // Re-scan to refresh
188 doScan();
189 } else {
190 var errMsg = (response.data && response.data.message) ? response.data.message : config.i18n.error;
191 showNotice(errMsg, 'error');
192 }
193 }).fail(function () {
194 $('#widgetopts-migrate-all, #widgetopts-migrate-selected').prop('disabled', false);
195 $('#widgetopts-migrate-all').text('Migrate All');
196 $('#widgetopts-migrate-selected').text('Migrate Selected');
197 showNotice(config.i18n.error, 'error');
198 });
199 }
200
201 /**
202 * Delete a single legacy code entry
203 */
204 function doDelete($row) {
205 if (!confirm(config.i18n.confirmDelete)) {
206 return;
207 }
208
209 var hash = $row.data('hash');
210 $row.addClass('widgetopts-row-disabled');
211 $row.find('.widgetopts-delete-btn').prop('disabled', true).text(config.i18n.deleting);
212
213 $.post(config.ajaxurl, {
214 action: 'widgetopts_migration_delete',
215 nonce: config.nonce,
216 hash: hash
217 }, function (response) {
218 if (response.success) {
219 $row.fadeOut(300, function () {
220 $(this).remove();
221 // Remove from items array
222 items = items.filter(function (item) {
223 return item.hash !== hash;
224 });
225 if (!items.length) {
226 $('#widgetopts-migration-content').hide();
227 $('#widgetopts-migration-empty').show();
228 }
229 });
230 } else {
231 $row.removeClass('widgetopts-row-disabled');
232 $row.find('.widgetopts-delete-btn').prop('disabled', false).text('Delete');
233 var errMsg = (response.data && response.data.message) ? response.data.message : config.i18n.error;
234 showNotice(errMsg, 'error');
235 }
236 }).fail(function () {
237 $row.removeClass('widgetopts-row-disabled');
238 $row.find('.widgetopts-delete-btn').prop('disabled', false).text('Delete');
239 showNotice(config.i18n.error, 'error');
240 });
241 }
242
243 // DOM ready
244 $(function () {
245 // Initial scan
246 doScan();
247
248 // Select all toggle
249 $('#widgetopts-select-all').on('change', function () {
250 var checked = $(this).is(':checked');
251 $('#widgetopts-migration-tbody .widgetopts-row-cb').prop('checked', checked);
252 });
253
254 // Migrate All
255 $('#widgetopts-migrate-all').on('click', function () {
256 doMigrate(collectItems(true));
257 });
258
259 // Migrate Selected
260 $('#widgetopts-migrate-selected').on('click', function () {
261 doMigrate(collectItems(false));
262 });
263
264 // Delete button
265 $(document).on('click', '.widgetopts-delete-btn', function () {
266 doDelete($(this).closest('tr'));
267 });
268 });
269
270 })(jQuery);
271