Files
Umbra-Bookshelf/umbra-bookshelf/admin/js/umbra-bookshelf-admin.js
bdm 0bd78e587a Resolve the known issues; switch licence to GPL
Closes the three problems that blocked the consolidation and records the rest
as tasks.

Licence: GPLv2 or later (WordPress.org compatible)

  LICENSE is now the full GPLv2 text and NOTICE is gone (it was Apache
  specific). All 101 SPDX headers read GPL-2.0-or-later and every shipped
  header says "GPLv2 or later".

  This also fixes an inconsistency that predated the consolidation: the theme's
  style.css declared GPLv2 while its PHP files carried Apache headers.

  Old/ and archive/pre-umbra-releases/ keep their original Apache headers on
  purpose -- they are frozen snapshots, not shipped code.

Schema: the catalogue schema is canonical for bd_books and bd_series

  Adds Umbra_Schema_Migration. The catalogue and library modules previously
  both created those two tables with different columns, so whichever plugin
  activated first won and the other read and wrote against the wrong shape.

  The migration detects a library-shaped table, RENAMES it aside (never drops
  it), creates the canonical table and copies rows across:

    - book IDs preserved, keeping bd_book_meta, bd_reviews, bd_ratings and
      bd_review_shortlinks valid
    - title/slug/description resolved from the linked post
    - the library's single isbn/asin land on the ebook columns; amazon_asin is
      also set so existing product links keep working
    - series migrated first so books.series_id still resolves
    - post linkage rewritten as _bd_bookshelf_book_id (preserved meta key)
    - publish_date kept as _bd_bookshelf_publish_date (no catalogue column)
    - bd_ratings goodreads/amazon folded into rating_goodreads/rating_amazon
    - rows whose post is gone are skipped with a log line, not turned into
      unusable books
    - duplicate slugs de-duplicated, since catalogue slug is UNIQUE

  It runs before dbDelta, and on admin_init as well as activation, because
  plugin updates do not re-run activation hooks. Ordering matters: dbDelta adds
  columns but never drops them, so pointed at a library-shaped table it would
  graft on catalogue columns and leave a table satisfying neither schema.

  Umbra_Bookshelf_Helper_Install no longer creates bd_books or bd_series.

Scraping: Goodreads only, one implementation

  There were three Goodreads implementations and two Amazon ones; both library
  "scrapers" were empty stubs attached to cron events that fired on schedule to
  do nothing, and both real scraper classes were never called at all.

  Umbra_Amazon_Scraper is deleted and the duplicate HTML parsing is gone from
  Umbra_Rating_Sync, which now delegates to Umbra_Goodreads_Scraper. The two
  library stubs and their cron registrations are removed. One schedule
  survives: bd_bookshelf_sync_ratings, every 12 hours.

  The rating_amazon column is retained (it holds data and is populated during
  migration) and Amazon retail links are unaffected.

  A new rating fetch failure keeps the last known value instead of writing zero.
  The admin ratings notice no longer warns about Amazon scraping.

Umbra_SEO is now instantiated

  It registers its hooks from a constructor and the bootstrap never constructed
  it, so the class was dead code and no SEO output was produced. Its meta, Open
  Graph, Twitter card and sitemap hooks now attach. Completing SEO for generated
  book detail pages is docs/TASKS.md #2.

Assets that 404'd

  - assets/images/default-cover.png now holds a real 512x815 cover
    (WorkingTitleCover_512x815.png). The helper returned this path but the
    repository contained no images at all.
  - email/assets/js/admin.js is committed as an empty placeholder. It was
    enqueued on every email admin page but had never been committed.

Tests

  - tests/schema_migration_test.php: 42 checks against a real database, driven
    through the sqlite3 CLI on a throwaway file. Covers shape detection, row
    mapping, ID preservation, orphan handling, rating folding, idempotency and
    slug collisions.
  - tests/run_all.sh runs every suite.
  - The declared version is now checked against the plugin header rather than a
    literal, so a version bump cannot silently break the suite.

Docs

  - KNOWN-ISSUES.md rewritten: three resolved, three remaining.
  - TASKS.md added: email admin behaviour, book detail page SEO, batching the
    rating sync, reclaiming legacy tables, reconciling the two book models,
    retiring the Old/ archive.
  - SPEC and ARCHITECTURE updated for schema ownership, the migration ordering
    constraint, and the single scraper.

Version 1.1.0.
2026-10-22 09:47:00 -07:00

850 lines
30 KiB
JavaScript

// Copyright 2026 Umbra Tools (umbratools.com)
// SPDX-License-Identifier: GPL-2.0-or-later
/**
* BD Bookshelf - Admin JavaScript
*
* @package Umbra_Bookshelf
*/
(function($) {
'use strict';
$(document).ready(function() {
// Initialize media uploader for book cover
initCoverUploader();
// Initialize media uploader for author photo
initAuthorPhotoUploader();
// Book form
$('#bd-bookshelf-book-form').on('submit', function(e) {
e.preventDefault();
saveBook();
});
// Delete book
$(document).on('click', '.bd-bookshelf-delete', function(e) {
e.preventDefault();
var bookId = $(this).data('id');
if (confirm('Are you sure you want to delete this book?')) {
deleteBook(bookId);
}
});
// Author Modal
initAuthorModal();
// Series Modal
initSeriesModal();
// Shortcode Modal
initShortcodeModal();
// Sites form
$('#bd-bookshelf-sites-form').on('submit', function(e) {
e.preventDefault();
saveSites();
});
// Settings form
$('#bd-bookshelf-settings-form').on('submit', function(e) {
e.preventDefault();
saveSettings();
});
// Import CSV form
$('#bd-bookshelf-import-csv-form').on('submit', function(e) {
e.preventDefault();
importCSV();
});
// Import Posts form
$('#bd-bookshelf-import-posts-form').on('submit', function(e) {
e.preventDefault();
importPosts();
});
// Manual sync
$('#bd-bookshelf-manual-sync').on('click', function() {
var btn = $(this);
btn.prop('disabled', true).text('Syncing...');
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_sync_ratings',
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
alert(response.data.message);
location.reload();
} else {
alert('Error: ' + response.data.message);
}
},
complete: function() {
btn.prop('disabled', false).text('Sync Now');
}
});
});
// Regenerate retail links
$('#bd-bookshelf-regenerate-links').on('click', function() {
var btn = $(this);
var bookId = btn.data('book-id');
btn.prop('disabled', true).text('Regenerating...');
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_regenerate_links',
book_id: bookId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
$('#bd-bookshelf-retail-links').html(response.data.html);
alert('Retail links regenerated!');
} else {
alert('Error: ' + response.data.message);
}
},
complete: function() {
btn.prop('disabled', false).text('Regenerate Links');
}
});
});
// Scan forms
initScanForms();
});
/**
* Initialize Scan Forms
*/
function initScanForms() {
// Goodreads scan
$('#bd-bookshelf-goodreads-scan-form').on('submit', function(e) {
e.preventDefault();
var authorId = $('#goodreads_author_id').val();
if (!authorId) {
alert('Please enter a Goodreads Author ID');
return;
}
scanAuthor('goodreads', authorId);
});
// Amazon scan
$('#bd-bookshelf-amazon-scan-form').on('submit', function(e) {
e.preventDefault();
var authorId = $('#amazon_author_id').val();
if (!authorId) {
alert('Please enter an Amazon Author ID');
return;
}
scanAuthor('amazon', authorId);
});
// Select all books
$(document).on('change', '#select-all-books', function() {
$('.book-checkbox').prop('checked', $(this).prop('checked'));
});
// Import selected books
$('#bd-bookshelf-import-selected').on('click', function() {
importSelectedBooks();
});
}
/**
* Scan author from source
*/
function scanAuthor(source, authorId) {
var action = source === 'goodreads' ? 'bd_bookshelf_scan_goodreads' : 'bd_bookshelf_scan_amazon';
$('#bd-bookshelf-scan-results').hide();
$('body').css('cursor', 'wait');
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: action,
author_id: authorId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
$('body').css('cursor', 'default');
if (response.success) {
displayScanResults(response.data);
} else {
alert('Error: ' + response.data.message);
}
},
error: function() {
$('body').css('cursor', 'default');
alert('An error occurred while scanning. Please try again.');
}
});
}
/**
* Display scan results
*/
function displayScanResults(data) {
var author = data.author;
var books = data.books;
var source = data.source;
// Show results section
$('#bd-bookshelf-scan-results').show();
// Display author info
var authorHtml = '<div class="bd-bookshelf-author-card">';
if (author.photo) {
authorHtml += '<img src="' + author.photo + '" style="width:100px;height:100px;border-radius:50%;margin-right:20px;float:left">';
}
authorHtml += '<h3>' + (author.name || 'Unknown Author') + '</h3>';
if (author.bio) {
authorHtml += '<p>' + author.bio.substring(0, 200) + '...</p>';
}
authorHtml += '<p><strong>Source:</strong> ' + source.charAt(0).toUpperCase() + source.slice(1) + '</p>';
authorHtml += '<p><strong>Books Found:</strong> ' + books.length + '</p>';
authorHtml += '<div style="clear:both"></div></div>';
$('#bd-bookshelf-author-info').html(authorHtml);
// Display books
var booksHtml = '';
books.forEach(function(book, index) {
booksHtml += '<tr>';
booksHtml += '<td><input type="checkbox" class="book-checkbox" value="' + index + '" checked></td>';
booksHtml += '<td>';
if (book.cover_image) {
booksHtml += '<img src="' + book.cover_image + '" style="width:60px;height:auto">';
}
booksHtml += '</td>';
booksHtml += '<td>' + (book.title || '') + '</td>';
booksHtml += '<td>' + (book.isbn || book.isbn13 || book.asin || '') + '</td>';
booksHtml += '<td>' + (book.rating || '0') + '/5</td>';
booksHtml += '<td>' + (book.published || '') + '</td>';
booksHtml += '<td>' + (book.description ? book.description.substring(0, 100) + '...' : '') + '</td>';
booksHtml += '</tr>';
// Store book data in hidden fields
booksHtml += '<input type="hidden" name="book_data[' + index + '][title]" value="' + (book.title || '').replace(/"/g, '&quot;') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][isbn]" value="' + (book.isbn || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][isbn13]" value="' + (book.isbn13 || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][cover_image]" value="' + (book.cover_image || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][rating]" value="' + (book.rating || '0') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][published]" value="' + (book.published || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][description]" value="' + (book.description || '').replace(/"/g, '&quot;') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][goodreads_id]" value="' + (book.goodreads_id || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][asin]" value="' + (book.asin || '') + '">';
booksHtml += '<input type="hidden" name="book_data[' + index + '][format]" value="' + (book.format || '') + '">';
});
$('#bd-bookshelf-books-list').html(booksHtml);
// Store author data
$('#bd-bookshelf-scan-results').data('author', author);
$('#bd-bookshelf-scan-results').data('source', source);
// Scroll to results
$('html, body').animate({
scrollTop: $('#bd-bookshelf-scan-results').offset().top
}, 500);
}
/**
* Import selected books
*/
function importSelectedBooks() {
var books = [];
var author = $('#bd-bookshelf-scan-results').data('author');
var source = $('#bd-bookshelf-scan-results').data('source');
$('.book-checkbox:checked').each(function() {
var index = $(this).val();
var bookData = {
title: $('input[name="book_data[' + index + '][title]"]').val(),
isbn: $('input[name="book_data[' + index + '][isbn]"]').val(),
isbn13: $('input[name="book_data[' + index + '][isbn13]"]').val(),
cover_image: $('input[name="book_data[' + index + '][cover_image]"]').val(),
rating: $('input[name="book_data[' + index + '][rating]"]').val(),
published: $('input[name="book_data[' + index + '][published]"]').val(),
description: $('input[name="book_data[' + index + '][description]"]').val(),
goodreads_id: $('input[name="book_data[' + index + '][goodreads_id]"]').val(),
asin: $('input[name="book_data[' + index + '][asin]"]').val() || '',
format: $('input[name="book_data[' + index + '][format]"]').val() || '',
};
books.push(bookData);
});
if (books.length === 0) {
alert('Please select at least one book to import');
return;
}
if (!confirm('Import ' + books.length + ' book(s)?')) {
return;
}
$('body').css('cursor', 'wait');
// Build form data manually for proper nested array handling
var formData = new FormData();
formData.append('action', 'bd_bookshelf_import_scraped');
formData.append('nonce', umbraBookshelfAdmin.nonce);
formData.append('source', source);
// Add author data
if (author) {
formData.append('author[name]', author.name || '');
formData.append('author[bio]', author.bio || '');
formData.append('author[photo]', author.photo || '');
formData.append('author[id]', author.id || '');
}
// Add books array
books.forEach(function(book, i) {
formData.append('books[' + i + '][title]', book.title || '');
formData.append('books[' + i + '][isbn]', book.isbn || '');
formData.append('books[' + i + '][isbn13]', book.isbn13 || '');
formData.append('books[' + i + '][cover_image]', book.cover_image || '');
formData.append('books[' + i + '][rating]', book.rating || '0');
formData.append('books[' + i + '][published]', book.published || '');
formData.append('books[' + i + '][description]', book.description || '');
formData.append('books[' + i + '][goodreads_id]', book.goodreads_id || '');
formData.append('books[' + i + '][asin]', book.asin || '');
formData.append('books[' + i + '][format]', book.format || '');
});
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
$('body').css('cursor', 'default');
if (response.success) {
alert(response.data.message);
if (response.data.imported > 0 || response.data.updated > 0) {
location.reload();
}
} else {
alert('Error: ' + response.data.message);
}
},
error: function() {
$('body').css('cursor', 'default');
alert('An error occurred while importing. Please try again.');
}
});
}
/**
* Initialize Cover Image Uploader
*/
function initCoverUploader() {
var coverFrame;
$('#cover-upload-btn').on('click', function(e) {
e.preventDefault();
if (coverFrame) {
coverFrame.open();
return;
}
coverFrame = wp.media({
title: umbraBookshelfAdmin.mediaTitle,
button: { text: umbraBookshelfAdmin.mediaButton },
multiple: false,
library: { type: 'image' }
});
coverFrame.on('select', function() {
var attachment = coverFrame.state().get('selection').first().toJSON();
var url = attachment.sizes && attachment.sizes.medium ? attachment.sizes.medium.url : attachment.url;
$('#cover_image').val(attachment.url);
$('#cover-preview').html('<img src="' + url + '" style="max-width:200px;height:auto">');
$('#cover-remove-btn').show();
});
coverFrame.open();
});
$('#cover-remove-btn').on('click', function(e) {
e.preventDefault();
$('#cover_image').val('');
$('#cover-preview').html('');
$(this).hide();
});
}
/**
* Initialize Author Photo Uploader
*/
function initAuthorPhotoUploader() {
var photoFrame;
$('#author-photo-btn').on('click', function(e) {
e.preventDefault();
if (photoFrame) {
photoFrame.open();
return;
}
photoFrame = wp.media({
title: 'Select Author Photo',
button: { text: 'Use This Photo' },
multiple: false,
library: { type: 'image' }
});
photoFrame.on('select', function() {
var attachment = photoFrame.state().get('selection').first().toJSON();
var url = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
$('#author_photo_url').val(attachment.url);
$('#author-photo-preview').html('<img src="' + url + '" style="max-width:100px;height:auto">');
$('#author-photo-remove').show();
});
photoFrame.open();
});
$('#author-photo-remove').on('click', function(e) {
e.preventDefault();
$('#author_photo_url').val('');
$('#author-photo-preview').html('');
$(this).hide();
});
}
/**
* Initialize Author Modal
*/
function initAuthorModal() {
// Open modal for new author
$('#bd-bookshelf-add-author').on('click', function() {
$('#author_id').val(0);
$('#author_display_name').val('');
$('#author_email').val('');
$('#author_website').val('');
$('#author_bio').val('');
$('#author_goodreads_id').val('');
$('#author_photo_url').val('');
$('#author-photo-preview').html('');
$('#author-photo-remove').hide();
$('#bd-bookshelf-author-modal-title').text('Add New Author');
$('#bd-bookshelf-author-modal').show();
});
// Edit author
$(document).on('click', '.bd-bookshelf-edit-author', function(e) {
e.preventDefault();
var authorId = $(this).data('id');
// Fetch author data
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_get_author',
id: authorId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
var author = response.data;
$('#author_id').val(author.id);
$('#author_display_name').val(author.display_name);
$('#author_email').val(author.email);
$('#author_website').val(author.website);
$('#author_bio').val(author.bio);
$('#author_goodreads_id').val(author.goodreads_author_id);
$('#author_photo_url').val(author.photo_url);
if (author.photo_url) {
$('#author-photo-preview').html('<img src="' + author.photo_url + '" style="max-width:100px;height:auto">');
$('#author-photo-remove').show();
} else {
$('#author-photo-preview').html('');
$('#author-photo-remove').hide();
}
$('#bd-bookshelf-author-modal-title').text('Edit Author');
$('#bd-bookshelf-author-modal').show();
}
}
});
});
// Delete author
$(document).on('click', '.bd-bookshelf-delete-author', function(e) {
e.preventDefault();
var authorId = $(this).data('id');
if (confirm('Are you sure you want to delete this author?')) {
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_delete_author',
id: authorId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
}
});
// Save author
$('#bd-bookshelf-author-form').on('submit', function(e) {
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_author',
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
});
// Close modal
$(document).on('click', '.bd-bookshelf-modal-close', function() {
$(this).closest('.bd-bookshelf-modal').hide();
});
}
/**
* Initialize Series Modal
*/
function initSeriesModal() {
// Open modal for new series
$('#bd-bookshelf-add-series').on('click', function() {
$('#series_id_input').val(0);
$('#series_name').val('');
$('#series_description').val('');
$('#bd-bookshelf-series-modal-title').text('Add New Series');
$('#bd-bookshelf-series-modal').show();
});
// Edit series
$(document).on('click', '.bd-bookshelf-edit-series', function(e) {
e.preventDefault();
var seriesId = $(this).data('id');
// Fetch series data
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_get_series',
id: seriesId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
var series = response.data;
$('#series_id_input').val(series.id);
$('#series_name').val(series.name);
$('#series_description').val(series.description);
$('#bd-bookshelf-series-modal-title').text('Edit Series');
$('#bd-bookshelf-series-modal').show();
}
}
});
});
// Delete series
$(document).on('click', '.bd-bookshelf-delete-series', function(e) {
e.preventDefault();
var seriesId = $(this).data('id');
if (confirm('Are you sure you want to delete this series? Books in this series will be unlinked.')) {
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_delete_series',
id: seriesId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
}
});
// Save series
$('#bd-bookshelf-series-form').on('submit', function(e) {
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_series',
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
});
}
/**
* Initialize Shortcode Modal
*/
function initShortcodeModal() {
// Open modal for new shortcode
$('#bd-bookshelf-add-shortcode').on('click', function() {
$('#shortcode_id').val(0);
$('#shortcode_slug').val('');
$('#shortcode_target').val('');
$('#shortcode_redirect').val('301');
$('#shortcode_description').val('');
$('#shortcode_slug').prop('readonly', false);
$('#bd-bookshelf-shortcode-modal-title').text('Add New Shortcode');
$('#bd-bookshelf-shortcode-modal').show();
});
// Edit shortcode
$(document).on('click', '.bd-bookshelf-edit-shortcode', function(e) {
e.preventDefault();
var shortcodeId = $(this).data('id');
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_get_shortcode',
id: shortcodeId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
var sc = response.data;
$('#shortcode_id').val(sc.id);
$('#shortcode_slug').val(sc.slug).prop('readonly', true);
$('#shortcode_target').val(sc.target_url);
$('#shortcode_redirect').val(sc.redirect_type);
$('#shortcode_description').val(sc.description);
$('#bd-bookshelf-shortcode-modal-title').text('Edit Shortcode');
$('#bd-bookshelf-shortcode-modal').show();
}
}
});
});
// Delete shortcode
$(document).on('click', '.bd-bookshelf-delete-shortcode', function(e) {
e.preventDefault();
var shortcodeId = $(this).data('id');
if (confirm('Are you sure you want to delete this shortcode?')) {
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_delete_shortcode',
id: shortcodeId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
}
});
// Save shortcode
$('#bd-bookshelf-shortcode-form').on('submit', function(e) {
e.preventDefault();
var data = $(this).serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_shortcode',
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
});
}
/**
* Save Book
*/
function saveBook() {
var form = $('#bd-bookshelf-book-form');
var data = form.serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_book',
success: function(response) {
if (response.success) {
alert('Book saved!');
if (!form.find('input[name="book_id"]').val() || form.find('input[name="book_id"]').val() === '0') {
window.location.href = window.location.href.split('&book_id=')[0] + '&book_id=' + response.data.id;
}
} else {
alert('Error: ' + response.data.message);
}
}
});
}
/**
* Delete Book
*/
function deleteBook(bookId) {
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: {
action: 'bd_bookshelf_delete_book',
id: bookId,
nonce: umbraBookshelfAdmin.nonce
},
success: function(response) {
if (response.success) {
location.reload();
} else {
alert('Error: ' + response.data.message);
}
}
});
}
/**
* Save Sites/Affiliate Codes
*/
function saveSites() {
var form = $('#bd-bookshelf-sites-form');
var data = form.serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_sites',
success: function(response) {
if (response.success) {
alert('Affiliate codes saved!');
} else {
alert('Error: ' + response.data.message);
}
}
});
}
/**
* Save Settings
*/
function saveSettings() {
var form = $('#bd-bookshelf-settings-form');
var data = form.serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_save_settings',
success: function(response) {
if (response.success) {
alert('Settings saved!');
} else {
alert('Error: ' + response.data.message);
}
}
});
}
/**
* Import CSV
*/
function importCSV() {
var form = $('#bd-bookshelf-import-csv-form');
var formData = new FormData(form[0]);
formData.append('action', 'bd_bookshelf_import_csv');
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
if (response.success) {
$('#bd-bookshelf-import-results').show();
$('#bd-bookshelf-import-message').text(response.data.message);
} else {
alert('Error: ' + response.data.message);
}
}
});
}
/**
* Import Posts
*/
function importPosts() {
var form = $('#bd-bookshelf-import-posts-form');
var data = form.serialize();
$.ajax({
url: umbraBookshelfAdmin.ajaxurl,
type: 'POST',
data: data + '&action=bd_bookshelf_import_posts',
success: function(response) {
if (response.success) {
alert(response.data.message);
} else {
alert('Error: ' + response.data.message);
}
}
});
}
})(jQuery);