Dateien nach „bavarian-rank-engine/assets“ hochladen

This commit is contained in:
Michael Fuchs 2026-02-22 10:05:30 +00:00
parent ea321ce43f
commit 8891b3743f
5 changed files with 413 additions and 0 deletions

View file

@ -0,0 +1,10 @@
.bre-settings h2 {
border-bottom: 1px solid #ddd;
padding-bottom: 5px;
margin-top: 30px;
}
.bre-provider-row { display: none; }
.bre-provider-row.active { display: table-row; }
.bre-test-result { margin-left: 10px; font-weight: bold; }
.bre-test-result.success { color: #46b450; }
.bre-test-result.error { color: #dc3232; }

View file

@ -0,0 +1,48 @@
/* global breAdmin */
jQuery( function ( $ ) {
function updateProviderRows() {
var active = $( '#bre-provider' ).val();
$( '.bre-provider-row' ).removeClass( 'active' );
$( '.bre-provider-row[data-provider="' + active + '"]' ).addClass( 'active' );
}
updateProviderRows();
$( '#bre-provider' ).on( 'change', updateProviderRows );
$( document ).on( 'click', '.bre-test-btn', function () {
var btn = $( this );
var providerId = btn.data( 'provider' );
var resultEl = $( '#test-result-' + providerId );
resultEl.removeClass( 'success error' ).text( 'Teste\u2026' );
btn.prop( 'disabled', true );
$.post( breAdmin.ajaxUrl, {
action: 'bre_test_connection',
nonce: breAdmin.nonce,
provider: providerId,
// api_key removed — server reads stored encrypted key
} ).done( function ( res ) {
if ( res.success ) {
resultEl.addClass( 'success' ).text( '\u2713 ' + res.data );
} else {
resultEl.addClass( 'error' ).text( '\u2717 ' + res.data );
}
} ).fail( function () {
resultEl.addClass( 'error' ).text( '\u2717 Netzwerkfehler' );
} ).always( function () {
btn.prop( 'disabled', false );
} );
} );
$( '#bre-reset-prompt' ).on( 'click', function () {
if ( ! confirm( 'Prompt wirklich zur\u00fccksetzen?' ) ) return;
$.post( breAdmin.ajaxUrl, {
action: 'bre_get_default_prompt',
nonce: breAdmin.nonce,
} ).done( function ( res ) {
if ( res.success ) {
$( 'textarea[name*="prompt"]' ).val( res.data );
}
} );
} );
} );

View file

@ -0,0 +1,221 @@
/* global breBulk */
jQuery( function ( $ ) {
var running = false;
var stopFlag = false;
var processed = 0;
var total = 0;
var failedItems = [];
if ( breBulk.isLocked ) {
showLockWarning( breBulk.lockAge );
}
loadStats();
function showLockWarning( age ) {
var msg = 'Ein Bulk-Prozess läuft bereits' + ( age ? ' (seit ' + age + 's)' : '' ) + '.';
$( '#bre-lock-warning' ).text( msg ).show();
$( '#bre-bulk-start' ).prop( 'disabled', true );
}
function hideLockWarning() {
$( '#bre-lock-warning' ).hide();
$( '#bre-bulk-start' ).prop( 'disabled', false );
}
function loadStats() {
$.post( breBulk.ajaxUrl, { action: 'bre_bulk_stats', nonce: breBulk.nonce } )
.done( function ( res ) {
if ( ! res.success ) return;
var html = '<strong>Posts ohne Meta-Beschreibung:</strong><ul>';
var t = 0;
$.each( res.data, function ( pt, count ) {
html += '<li>' + $( '<span>' ).text( pt ).html() + ': <strong>' + parseInt( count, 10 ) + '</strong></li>';
t += parseInt( count, 10 );
} );
html += '</ul><strong>Gesamt: ' + t + '</strong>';
total = t;
$( '#bre-bulk-stats' ).html( html );
updateCostEstimate();
} );
}
$( '#bre-bulk-limit, #bre-bulk-model, #bre-bulk-provider' ).on( 'change', updateCostEstimate );
function updateCostEstimate() {
var limit = parseInt( $( '#bre-bulk-limit' ).val(), 10 ) || 20;
var inputTokens = limit * 800;
var outputTokens = limit * 50;
var costHtml = '~' + inputTokens + ' Input-Token + ' + outputTokens + ' Output-Token';
var costData = breBulk.costs || {};
var provider = $( '#bre-bulk-provider' ).val();
var model = $( '#bre-bulk-model' ).val();
if ( costData[ provider ] && costData[ provider ][ model ] ) {
var c = costData[ provider ][ model ];
var inCost = ( inputTokens / 1000000 ) * parseFloat( c.input || 0 );
var outCost= ( outputTokens / 1000000 ) * parseFloat( c.output || 0 );
var total = inCost + outCost;
if ( total > 0 ) {
costHtml += ' ≈ $' + total.toFixed( 4 );
}
}
$( '#bre-cost-estimate' ).text( costHtml );
}
$( '#bre-bulk-start' ).on( 'click', function () {
if ( running ) return;
$.post( breBulk.ajaxUrl, { action: 'bre_bulk_status', nonce: breBulk.nonce } )
.done( function ( res ) {
if ( res.success && res.data.locked ) {
showLockWarning( res.data.lock_age );
return;
}
startRun();
} );
} );
function startRun() {
running = true;
stopFlag = false;
processed = 0;
failedItems = [];
$( '#bre-bulk-start' ).prop( 'disabled', true );
$( '#bre-bulk-stop' ).show();
$( '#bre-progress-wrap' ).show();
$( '#bre-bulk-log' ).show().html( '' );
$( '#bre-failed-summary' ).hide().html( '' );
hideLockWarning();
var limit = parseInt( $( '#bre-bulk-limit' ).val(), 10 ) || 20;
var provider = $( '#bre-bulk-provider' ).val();
var model = $( '#bre-bulk-model' ).val();
log( '▶ Start — max ' + limit + ' Posts, Provider: ' + provider );
runBatch( 'post', limit, provider, model, true );
}
$( '#bre-bulk-stop' ).on( 'click', function () {
stopFlag = true;
log( '⚠ Abbruch angefordert…', 'warn' );
releaseLock();
} );
function releaseLock() {
$.post( breBulk.ajaxUrl, { action: 'bre_bulk_release', nonce: breBulk.nonce } );
}
function runBatch( postType, remaining, provider, model, isFirst ) {
if ( stopFlag || remaining <= 0 ) {
finish();
return;
}
var batchSize = Math.min( 20, remaining );
var isLast = ( remaining - batchSize ) <= 0;
log( '↻ Verarbeite ' + batchSize + ' Posts… (' + remaining + ' verbleibend)' );
$.post( breBulk.ajaxUrl, {
action: 'bre_bulk_generate',
nonce: breBulk.nonce,
post_type: postType,
batch_size: batchSize,
provider: provider,
model: model,
is_first: isFirst ? 1 : 0,
is_last: isLast ? 1 : 0,
} ).done( function ( res ) {
if ( ! res.success ) {
if ( res.data && res.data.locked ) {
showLockWarning( res.data.lock_age );
finish();
return;
}
log( '✗ Fehler: ' + $( '<span>' ).text( ( res.data && res.data.message ) || 'Unbekannter Fehler' ).html(), 'error' );
finish();
return;
}
$.each( res.data.results, function ( i, item ) {
if ( item.success ) {
var note = item.attempts > 1 ? ' (Versuch ' + item.attempts + ')' : '';
log(
'✓ [' + item.id + '] ' +
$( '<span>' ).text( item.title ).html() + note +
'<br><small style="color:#9cdcfe;">' +
$( '<span>' ).text( item.description ).html() +
'</small>'
);
} else {
failedItems.push( item );
log(
'✗ [' + item.id + '] ' +
$( '<span>' ).text( item.title ).html() +
' — ' + $( '<span>' ).text( item.error ).html(),
'error'
);
}
processed++;
} );
updateProgress( processed, total );
var newRemaining = remaining - batchSize;
if ( res.data.remaining > 0 && ! stopFlag && newRemaining > 0 ) {
setTimeout( function () {
runBatch( postType, newRemaining, provider, model, false );
}, breBulk.rateDelay );
} else {
if ( isLast || res.data.remaining === 0 ) releaseLock();
finish();
}
} ).fail( function () {
log( '✗ Netzwerkfehler', 'error' );
releaseLock();
finish();
} );
}
function updateProgress( done, t ) {
var pct = t > 0 ? Math.round( ( done / t ) * 100 ) : 100;
$( '#bre-progress-bar' ).css( 'width', pct + '%' );
$( '#bre-progress-text' ).text( done + ' / ' + t + ' verarbeitet' );
}
/**
* Append a line to the log console.
* @param {string} msg Pre-escaped HTML string. User data MUST be escaped via
* $('<span>').text(val).html() before passing here.
* @param {string} type 'error' | 'warn' | undefined
*/
function log( msg, type ) {
var color = type === 'error' ? '#f48771' : type === 'warn' ? '#dcdcaa' : '#9cdcfe';
$( '#bre-bulk-log' ).append(
'<div style="color:' + color + ';margin-bottom:4px;">' + msg + '</div>'
);
var el = document.getElementById( 'bre-bulk-log' );
el.scrollTop = el.scrollHeight;
}
function finish() {
running = false;
$( '#bre-bulk-start' ).prop( 'disabled', false );
$( '#bre-bulk-stop' ).hide();
log( '— Fertig —' );
if ( failedItems.length > 0 ) {
var html = '<strong>⚠ ' + failedItems.length + ' Posts fehlgeschlagen:</strong><ul>';
$.each( failedItems, function ( i, item ) {
html += '<li>[' + item.id + '] ' +
$( '<span>' ).text( item.title ).html() +
': <em>' + $( '<span>' ).text( item.error ).html() + '</em></li>';
} );
html += '</ul>';
$( '#bre-failed-summary' ).html( html ).show();
}
loadStats();
}
} );

View file

@ -0,0 +1,32 @@
/* global jQuery, ajaxurl */
jQuery( function ( $ ) {
var $textarea = $( '#bre-meta-description' );
var $count = $( '#bre-meta-count' );
var $btn = $( '#bre-regen-meta' );
if ( ! $textarea.length ) return;
$textarea.on( 'input', function () {
$count.text( $( this ).val().length + ' / 160' );
} );
if ( ! $btn.length ) return;
$btn.on( 'click', function () {
$btn.prop( 'disabled', true ).text( '…' );
$.post( ajaxurl, {
action: 'bre_regen_meta',
nonce: $btn.data( 'nonce' ),
post_id: $btn.data( 'post-id' ),
} ).done( function ( res ) {
if ( res.success ) {
$textarea.val( res.data.description );
$count.text( res.data.description.length + ' / 160' );
} else {
alert( 'Fehler: ' + ( res.data || 'Unbekannt' ) );
}
} ).always( function () {
$btn.prop( 'disabled', false ).text( 'Mit KI neu generieren' );
} );
} );
} );

View file

@ -0,0 +1,102 @@
/* global jQuery, wp */
jQuery( function ( $ ) {
var $widget = $( '#bre-seo-widget' );
if ( ! $widget.length ) return;
var siteUrl = $widget.data( 'site-url' ) || window.location.origin;
var debounce = null;
function getContent() {
// Block editor
if ( window.wp && wp.data && wp.data.select( 'core/editor' ) ) {
try {
var blocks = wp.data.select( 'core/editor' ).getBlocks();
return blocks.map( function ( b ) {
return ( b.attributes && b.attributes.content ) ? b.attributes.content : '';
} ).join( ' ' );
} catch ( e ) { return ''; }
}
// Classic editor (TinyMCE or textarea)
if ( typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) {
return tinyMCE.activeEditor.getContent();
}
return $( '#content' ).val() || '';
}
function getTitle() {
if ( window.wp && wp.data && wp.data.select( 'core/editor' ) ) {
try {
return wp.data.select( 'core/editor' ).getEditedPostAttribute( 'title' ) || '';
} catch ( e ) { return ''; }
}
return $( '#title' ).val() || '';
}
function analyse() {
var content = getContent();
var title = getTitle();
var plain = content.replace( /<[^>]+>/g, ' ' ).replace( /\s+/g, ' ' ).trim();
var words = plain ? plain.split( /\s+/ ).length : 0;
var readMin = Math.max( 1, Math.ceil( words / 200 ) );
$( '#bre-title-stat' ).text( title.length + ' / 60' );
$( '#bre-words-stat' ).text( words.toLocaleString( 'de-DE' ) );
$( '#bre-read-stat' ).text( '~' + readMin + ' Min.' );
// Headings — count from HTML tags
var h = { h1: 0, h2: 0, h3: 0, h4: 0 };
( content.match( /<h([1-4])[\s>]/gi ) || [] ).forEach( function ( tag ) {
var level = 'h' + tag.replace( /<h/i, '' )[0];
if ( h[ level ] !== undefined ) h[ level ]++;
} );
var hParts = [];
[ 'h1', 'h2', 'h3', 'h4' ].forEach( function ( tag ) {
if ( h[ tag ] > 0 ) hParts.push( h[ tag ] + '× ' + tag.toUpperCase() );
} );
$( '#bre-headings-stat' ).text( hParts.length ? hParts.join( ' ' ) : 'Keine' );
// Links
var allLinks = content.match( /href="([^"]+)"/gi ) || [];
var siteHost = siteUrl.replace( /https?:\/\//, '' ).replace( /\/$/, '' );
var internal = 0;
var external = 0;
allLinks.forEach( function ( tag ) {
var href = ( tag.match( /href="([^"]+)"/ ) || [] )[1] || '';
if ( href.indexOf( '/' ) === 0 || href.indexOf( siteUrl ) === 0 || href.indexOf( siteHost ) !== -1 ) {
internal++;
} else if ( /^https?:\/\//.test( href ) ) {
external++;
}
} );
$( '#bre-links-stat' ).text( internal + ' intern ' + external + ' extern' );
// Warnings
var warnings = [];
if ( h.h1 === 0 ) warnings.push( '⚠ Keine H1-Überschrift' );
if ( h.h1 > 1 ) warnings.push( '⚠ Mehrere H1-Überschriften (' + h.h1 + ')' );
if ( internal === 0 && words > 50 ) warnings.push( '⚠ Keine internen Links' );
$( '#bre-seo-warnings' ).html( warnings.join( '<br>' ) );
}
function scheduledAnalyse() {
clearTimeout( debounce );
debounce = setTimeout( analyse, 500 );
}
// Block editor
if ( window.wp && wp.data ) {
wp.data.subscribe( scheduledAnalyse );
}
// Classic editor
$( document ).on( 'input change', '#content', scheduledAnalyse );
$( document ).on( 'tinymce-editor-init', function ( event, editor ) {
editor.on( 'KeyUp Change SetContent', scheduledAnalyse );
} );
$( '#title' ).on( 'input', scheduledAnalyse );
analyse();
} );