PluginProbe ʕ •ᴥ•ʔ
Admin Help Docs / trunk
Admin Help Docs vtrunk
2.0.1.1 trunk 1.4.3.2 2.0.0 2.0.0.1 2.0.0.2 2.0.1
admin-help-docs / inc / tabs / js / import.js
admin-help-docs / inc / tabs / js Last commit date
admin-menu.js 3 months ago documentation.js 3 months ago import.js 3 months ago settings.js 3 months ago support.js 3 months ago
import.js
298 lines
1 jQuery( document ).ready( function( $ ) {
2
3 // Dirty state tracking
4 const saveReminder = $( '#helpdocs-save-reminder' );
5 let isDirty = false;
6
7 function markDirty() {
8 if ( ! isDirty ) {
9 isDirty = true;
10 saveReminder.fadeIn( 150 );
11 }
12 }
13
14 $( window ).on( 'beforeunload', function( e ) {
15 if( isDirty ){
16 e.preventDefault();
17 e.returnValue = '';
18 return '';
19 }
20 });
21
22 $( document ).on( 'change input', '#helpdocs_import_active, #helpdocs_import_title, #helpdocs_website_url, #helpdocs_imports_table input[type="checkbox"]', function() {
23 markDirty();
24 });
25
26 // Hide the "Don't forget to activate" notice when the toggle is changed
27 $( '#helpdocs_import_active' ).on( 'change', function() {
28 const isActive = $( this ).is( ':checked' );
29 $( '#helpdocs-inactive-notice' ).toggle( ! isActive );
30 } );
31
32 // Saving
33 const saveButton = $( '#header_btn_save_import_settings' );
34 const urlInput = $( '#helpdocs_website_url' );
35
36 function validateSave() {
37 if ( urlInput.val().trim() === '' ) {
38 saveButton.prop( 'disabled', true );
39 } else {
40 saveButton.prop( 'disabled', false );
41 }
42 }
43
44 validateSave();
45
46 urlInput.on( 'input change', function() {
47 validateSave();
48 });
49
50 function startSavingTitle() {
51 let dots = 0;
52
53 document.title = helpdocs_import.saving_text; // immediate first update
54
55 setInterval( function() {
56 dots = (dots + 1) % 4; // cycles 0 → 3
57 document.title = helpdocs_import.saving_text + '.'.repeat(dots);
58 }, 500 );
59 }
60
61 function showSaving() {
62 saveButton.prop( 'disabled', true ).html( '<span class="dashicons dashicons-update spin"></span> ' + helpdocs_import.saving_text + '...' );
63 }
64
65 function saveSettings() {
66 if ( saveButton.prop( 'disabled' ) ) {
67 return;
68 }
69
70 startSavingTitle();
71 showSaving();
72 isDirty = false;
73 $( '#helpdocs_import_form' ).submit();
74 }
75
76 saveButton.on( 'click', saveSettings );
77
78 $( document ).on( 'keydown', function( e ) {
79 if ( ( e.ctrlKey || e.metaKey ) && e.key.toLowerCase() === 's' ) {
80 e.preventDefault();
81 saveSettings();
82 }
83 } );
84
85 const successMsg = $( '#helpdocs-saved-success' );
86 if ( successMsg.is( ':visible' ) ) {
87 setTimeout( function() {
88 successMsg.fadeOut( 500 );
89 }, 5000 );
90
91 const url = new URL( window.location.href );
92 if ( url.searchParams.has( 'import-updated' ) ) {
93 url.searchParams.delete( 'import-updated' );
94 window.history.replaceState( {}, document.title, url.pathname + url.search + url.hash );
95 }
96 }
97
98 // Select All Buttons
99 $( '.helpdocs-select-all-toggle' ).on( 'click', function( e ) {
100 e.preventDefault();
101 const type = $( this ).data( 'type' ); // 'feed' or 'toc'
102 const checkboxes = $( '.' + type + '-checkbox' );
103
104 // Determine if we should check all or uncheck all
105 const anyUnchecked = checkboxes.filter( ':not(:checked)' ).length > 0;
106
107 checkboxes.prop( 'checked', anyUnchecked );
108 markDirty();
109 } );
110
111 // "Feed All" and "TOC All" Logic
112 const feedAll = $( '#helpdocs_all' );
113 const tocAll = $( '#helpdocs_all_tocs' );
114 const tocAllWrap = $( '#helpdocs_all_tocs_container' );
115 const table = $( '#helpdocs_imports_table' );
116
117 function syncTableState() {
118 const isFeedAllChecked = feedAll.is( ':checked' );
119 const isTocAllChecked = tocAll.is( ':checked' );
120 const feedCheckboxes = table.find( '.feed-checkbox' );
121 const tocCheckboxes = table.find( '.toc-checkbox' );
122
123 if ( isFeedAllChecked ) {
124 feedCheckboxes.each( function() {
125 const cb = $( this );
126 if ( undefined === cb.data( 'prev-state' ) ) {
127 cb.data( 'prev-state', cb.is( ':checked' ) );
128 }
129 } );
130
131 tocAllWrap.css( 'display', 'inline-flex' );
132 feedCheckboxes.prop( 'checked', true ).prop( 'disabled', true );
133 $( '.helpdocs-select-all-toggle' ).prop( 'disabled', true ).css( 'opacity', '0.5' );
134
135 if ( isTocAllChecked ) {
136 tocCheckboxes.prop( 'checked', true ).prop( 'disabled', true );
137 } else {
138 tocCheckboxes.prop( 'disabled', true );
139 }
140 } else {
141 tocAllWrap.hide();
142 $( '.helpdocs-select-all-toggle' ).prop( 'disabled', false ).css( 'opacity', '1' );
143
144 feedCheckboxes.each( function() {
145 const cb = $( this );
146 const prev = cb.data( 'prev-state' );
147 if ( undefined !== prev ) {
148 cb.prop( 'checked', prev );
149 }
150 cb.prop( 'disabled', false );
151 } );
152
153 feedCheckboxes.removeData( 'prev-state' );
154 tocCheckboxes.prop( 'disabled', false );
155 }
156 }
157
158 syncTableState();
159
160 feedAll.on( 'change', function() {
161 syncTableState();
162 } );
163
164 tocAll.on( 'change', function() {
165 if ( ! $( this ).is( ':checked' ) && feedAll.is( ':checked' ) ) {
166 table.find( '.toc-checkbox' ).prop( 'checked', false );
167 }
168 syncTableState();
169 } );
170
171 // Trigger "Fetch" on Enter key in the URL field
172 $( '#helpdocs_website_url' ).on( 'keydown', function( e ) {
173 if ( e.key === 'Enter' ) {
174 e.preventDefault(); // Stop the form from saving
175 $( '#helpdocs_fetch_remote_docs' ).trigger( 'click' );
176 }
177 } );
178
179 // Toggle API Key Visibility
180 $( document ).on( 'click', '.helpdocs-toggle-visibility', function() {
181 const $input = $( '#helpdocs_api_key' );
182 const type = $input.attr( 'type' ) === 'password' ? 'text' : 'password';
183 $input.attr( 'type', type );
184 $( this ).toggleClass( 'dashicons-visibility dashicons-hidden' );
185 } );
186
187 // Fetch Remote Docs
188 $( '#helpdocs_fetch_remote_docs' ).on( 'click', function( e ) {
189 e.preventDefault();
190
191 const $btn = $( this );
192 const originalText = $btn.text();
193 let url = $( '#helpdocs_website_url' ).val().trim();
194 const apiKey = $( '#helpdocs_api_key' ).val().trim();
195
196 if ( ! url ) {
197 alert( 'Please enter a URL first.' );
198 return;
199 }
200
201 if ( ! /^https?:\/\//i.test( url ) ) {
202 url = 'https://' + url;
203 $( '#helpdocs_website_url' ).val( url );
204 }
205
206 // Reset UI state before fetching
207 $btn.addClass( 'disabled thinking' ).text( helpdocs_import.fetching_text );
208 $( '#helpdocs_api_error, #helpdocs_connection_error, #helpdocs_no_docs_found' ).hide();
209
210 $.post( ajaxurl, {
211 action: 'helpdocs_fetch_remote_docs',
212 nonce: helpdocs_import.fetch_nonce,
213 url: url,
214 api_key: apiKey // Pass the key to PHP
215 }, function( response ) {
216 if ( response.success ) {
217 // Handle specific error codes returned in response.data
218 if ( response.data.error === 'unauthorized' ) {
219 $( '#helpdocs_api_error' ).fadeIn();
220 $( '#helpdocs_remote_docs_wrapper' ).hide();
221 } else if ( response.data.error === 'connection_failed' ) {
222 $( '#helpdocs_connection_error' ).fadeIn();
223 $( '#helpdocs_remote_docs_wrapper' ).hide();
224 } else {
225 // Success: Update the table
226 $( '#helpdocs_imports_table tbody' ).html( response.data.html );
227
228 const count = response.data.count;
229 const itemText = count === 1 ? ' item' : ' items';
230 $( '.displaying-num' ).text( count + itemText );
231
232 const $notice = $( '#helpdocs_version_notice' );
233 if ( response.data.version === 'v1' ) {
234 $notice.fadeIn();
235 } else {
236 $notice.hide();
237 }
238
239 $( '#helpdocs_remote_docs_wrapper' ).fadeIn();
240 }
241 } else {
242 // General failure (no docs or server error)
243 $( '#helpdocs_remote_docs_wrapper' ).hide();
244 $( '#helpdocs_no_docs_found' ).fadeIn();
245
246 if ( response.data !== 'No documents found at this URL.' && ! response.data.error ) {
247 alert( response.data );
248 }
249 }
250 $btn.removeClass( 'disabled thinking' ).text( originalText );
251 } );
252 } );
253
254 // Import Individual Docs
255 $( document ).on( 'click', '.helpdocs-clone-individual', function( e ) {
256 e.preventDefault();
257 const $btn = $( this );
258 const originalText = $btn.text();
259 const docId = $btn.data( 'id' );
260 const importId = $( '#helpdocs_imports_table' ).data( 'import-id' );
261 const websiteUrl = $( '#helpdocs_website_url' ).val();
262 const apiKey = $( '#helpdocs_api_key' ).val().trim();
263
264 if ( $btn.hasClass( 'updating-message' ) ) return;
265
266 $btn.addClass( 'updating-message' ).addClass( 'thinking' ).text( helpdocs_import.importing_text );
267
268 $.ajax( {
269 url: ajaxurl,
270 type: 'POST',
271 data: {
272 action: 'helpdocs_import_individual_doc',
273 nonce: helpdocs_import.clone_nonce,
274 doc_id: docId,
275 import_id: importId,
276 website_url: websiteUrl,
277 api_key: apiKey
278 },
279 success: function( response ) {
280 if ( response.success ) {
281 $btn.removeClass( 'button-secondary updating-message thinking' )
282 .addClass( 'button-disabled' )
283 .text( helpdocs_import.imported_text )
284 .prop( 'disabled', true );
285 } else {
286 alert( response.data || helpdocs_import.error_text );
287 $btn.removeClass( 'updating-message thinking' ).text( originalText );
288 }
289 },
290 error: function( xhr, status, error ) {
291 console.error( xhr.responseText );
292 alert( helpdocs_import.error_text + ' (Status: ' + status + ')' );
293 $btn.removeClass( 'updating-message thinking' ).text( originalText );
294 }
295 } );
296 } );
297
298 } );