Files
backPRO/templates/sites/dashboard.php
Jacek Pyziak e9a3602576 feat: Add SEMSTORM domain input and SEO panel links
- Added optional SEMSTORM domain input field in site creation and editing forms.
- Introduced SEO panel links in site dashboard and edit pages.
- Created a new cron job for SEMSTORM data synchronization.
- Implemented database migrations for cron logs and site SEO metrics.
- Developed SiteSeoSyncService to handle SEMSTORM data fetching and storage.
- Added logging functionality for cron events.
- Created a new LogController to display cron logs with filtering options.
- Added SEO statistics dashboard with visual representation of metrics.
- Implemented site SEO metrics model for data retrieval and manipulation.
2026-02-20 23:49:40 +01:00

287 lines
12 KiB
PHP

<div class="d-flex justify-content-between align-items-center mb-4">
<h2>WP Dashboard: <?= htmlspecialchars($site['name']) ?></h2>
<div class="d-flex gap-2">
<a href="/sites/<?= (int) $site['id'] ?>/seo" class="btn btn-outline-primary">
<i class="bi bi-graph-up me-1"></i>SEO Panel
</a>
<a href="/sites/<?= $site['id'] ?>/edit" class="btn btn-outline-secondary">
<i class="bi bi-pencil me-1"></i>Edytuj strone
</a>
<a href="/sites" class="btn btn-outline-dark">
<i class="bi bi-arrow-left me-1"></i>Lista stron
</a>
</div>
</div>
<div class="row g-4">
<div class="col-lg-7">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Permalinki</h5>
<?php if (!empty($permalinkStatus['success'])): ?>
<?php if (!empty($permalinkStatus['pretty_enabled'])): ?>
<span class="badge bg-success">Przyjazne linki ON</span>
<?php else: ?>
<span class="badge bg-warning text-dark">Przyjazne linki OFF</span>
<?php endif; ?>
<?php else: ?>
<span class="badge bg-secondary">Brak danych</span>
<?php endif; ?>
</div>
<div class="card-body">
<p class="mb-2">
<strong>Aktualna struktura:</strong>
<code><?= htmlspecialchars((string) ($permalinkStatus['permalink_structure'] ?? '')) ?: '(pusta)' ?></code>
</p>
<p class="text-muted small mb-4">
<?= htmlspecialchars((string) ($permalinkStatus['message'] ?? 'Brak informacji z WordPress.')) ?>
</p>
<form method="post" action="/sites/<?= $site['id'] ?>/dashboard/permalinks/enable" class="d-flex gap-2 flex-wrap" data-confirm="Usunac index.php ze struktury linkow permanentnych na tej stronie WordPress?">
<button
type="submit"
class="btn btn-primary"
>
<i class="bi bi-link-45deg me-1"></i>Usun index.php z permalinkow
</button>
<a href="/sites/<?= $site['id'] ?>/dashboard" class="btn btn-outline-secondary">
<i class="bi bi-arrow-clockwise me-1"></i>Odswiez status
</a>
</form>
</div>
</div>
<div class="card mt-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Motyw BackPRO News</h5>
<span class="badge bg-primary">Blog/Magazine</span>
</div>
<div class="card-body">
<p class="mb-2">
Lekki motyw inspirowany ukladem magazynowym.
</p>
<p class="small text-muted mb-3">
Strona glowna tworzy sekcje automatycznie z kategorii glownych (parent=0).
Jesli masz 10 kategorii glownych, pojawi sie 10 boksow. Jesli 2, pojawia sie 2.
</p>
<form method="post" action="/sites/<?= (int) $site['id'] ?>/dashboard/theme/install" data-confirm="Zainstalowac i aktywowac motyw BackPRO News na tej stronie?">
<button
type="submit"
class="btn btn-outline-primary"
>
<i class="bi bi-brush me-1"></i>Zainstaluj i aktywuj motyw
</button>
</form>
</div>
</div>
<div class="card border-danger mt-4">
<div class="card-header bg-danger-subtle d-flex justify-content-between align-items-center">
<h5 class="mb-0 text-danger">Reinstalacja WordPress</h5>
<span class="badge bg-danger">Operacja destrukcyjna</span>
</div>
<div class="card-body">
<p class="mb-2">
Reinstalacja usunie cala zawartosc z katalogu FTP strony i wyczysci cala baze danych WordPress.
</p>
<p class="small text-muted mb-3">
Nastepnie BackPRO zainstaluje WordPress na nowo z zapisanych danych tej strony i opcjonalnie ponownie opublikuje wszystkie wczesniej opublikowane artykuly z BackPRO.
</p>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="republishArticles" checked>
<label class="form-check-label" for="republishArticles">
Po reinstalacji opublikuj ponownie wczesniej wyslane artykuly
</label>
</div>
<button type="button" id="btnReinstallWp" class="btn btn-danger">
<i class="bi bi-arrow-repeat me-1"></i>Reinstaluj WordPress
</button>
</div>
</div>
<div id="reinstallProgressPanel" class="mt-4" style="display: none;">
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="bi bi-hourglass-split me-2"></i>Postep reinstalacji</h5>
</div>
<div class="card-body">
<div class="progress mb-3" style="height: 24px;">
<div id="reinstallProgressBar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" style="width: 0%;">0%</div>
</div>
<div id="reinstallProgressMessage" class="text-muted">Oczekiwanie na start...</div>
</div>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Plik serwisowy BackPRO</h5>
<?php
$localVersion = (string) ($remoteServiceStatus['local_version'] ?? 'brak');
$remoteVersion = (string) ($remoteServiceStatus['remote_version'] ?? 'brak');
$versionMatch = $localVersion !== '' && $remoteVersion !== '' && $localVersion === $remoteVersion;
?>
<?php if (!empty($remoteServiceStatus['success']) && $versionMatch): ?>
<span class="badge bg-success">Aktualny</span>
<?php elseif (!empty($remoteServiceStatus['success'])): ?>
<span class="badge bg-warning text-dark">Wymaga aktualizacji</span>
<?php else: ?>
<span class="badge bg-secondary">Brak odpowiedzi</span>
<?php endif; ?>
</div>
<div class="card-body">
<p class="mb-2"><strong>Wersja lokalna:</strong> <code><?= htmlspecialchars($localVersion) ?></code></p>
<p class="mb-2"><strong>Wersja na serwerze:</strong> <code><?= htmlspecialchars($remoteVersion) ?></code></p>
<p class="mb-3 small text-muted">
<?= htmlspecialchars((string) ($remoteServiceStatus['message'] ?? '')) ?>
</p>
<p class="mb-3 small">
<strong>Endpoint:</strong>
<code><?= htmlspecialchars((string) ($remoteServiceStatus['service_url'] ?? '')) ?></code>
</p>
<form method="post" action="/sites/<?= (int) $site['id'] ?>/dashboard/remote-service/update" data-confirm="Wymusic aktualizacje pliku backpro-remote-service.php na serwerze?">
<button
type="submit"
class="btn btn-outline-primary"
>
<i class="bi bi-arrow-repeat me-1"></i>Wymus aktualizacje pliku serwisowego
</button>
</form>
</div>
</div>
<div class="card">
<div class="card-header">
<h5 class="mb-0">Info techniczne</h5>
</div>
<div class="card-body">
<ul class="mb-0">
<li class="mb-2">BackPRO uzywa pliku serwisowego backpro-remote-service.php do zdalnych zmian.</li>
<li class="mb-2">Gdy pliku brak, system automatycznie probuje go wgrac przez FTP.</li>
<li class="mb-2">Wymagane sa dane FTP: host, port, user, haslo, ftp_path.</li>
<li>To miejsce jest przygotowane pod kolejne ustawienia WordPress (np. pluginy).</li>
</ul>
</div>
</div>
</div>
</div>
<script>
(function () {
var btn = document.getElementById('btnReinstallWp');
var republishCheckbox = document.getElementById('republishArticles');
var panel = document.getElementById('reinstallProgressPanel');
var bar = document.getElementById('reinstallProgressBar');
var message = document.getElementById('reinstallProgressMessage');
var intervalId = null;
function generateProgressId() {
var chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
var out = '';
for (var i = 0; i < 20; i++) {
out += chars.charAt(Math.floor(Math.random() * chars.length));
}
return out;
}
function setProgress(percent, text) {
var safe = Math.max(0, Math.min(100, parseInt(percent, 10) || 0));
bar.style.width = safe + '%';
bar.textContent = safe + '%';
message.textContent = text || '';
}
function pollStatus(progressId) {
fetch('/installer/status/' + progressId)
.then(function (r) { return r.json(); })
.then(function (data) {
if (!data || data.status === 'waiting') {
return;
}
setProgress(data.percent || 0, data.message || '');
})
.catch(function () {});
}
if (!btn) {
return;
}
btn.addEventListener('click', async function () {
var ok = await backproConfirm(
'To usunie wszystkie pliki z katalogu FTP i wyczysci baze danych WordPress. Czy na pewno kontynuowac?',
{
title: 'Reinstalacja WordPress',
confirmText: 'Tak, reinstaluj',
cancelText: 'Anuluj',
confirmClass: 'btn-danger'
}
);
if (!ok) {
return;
}
var progressId = generateProgressId();
var formData = new FormData();
formData.append('progress_id', progressId);
formData.append('republish_articles', republishCheckbox && republishCheckbox.checked ? '1' : '0');
btn.disabled = true;
panel.style.display = '';
setProgress(0, 'Uruchamianie reinstalacji...');
panel.scrollIntoView({ behavior: 'smooth', block: 'center' });
intervalId = setInterval(function () {
pollStatus(progressId);
}, 2000);
fetch('/sites/<?= (int) $site['id'] ?>/dashboard/reinstall', {
method: 'POST',
body: formData
})
.then(function (r) { return r.json(); })
.then(function (result) {
if (intervalId) {
clearInterval(intervalId);
}
bar.classList.remove('progress-bar-animated');
if (result && result.success) {
bar.classList.remove('bg-danger');
bar.classList.add('bg-success');
setProgress(100, result.message || 'Reinstalacja zakonczona.');
backproNotify(result.message || 'Reinstalacja zakonczona.', 'success');
setTimeout(function () {
window.location.reload();
}, 2500);
return;
}
bar.classList.add('bg-danger');
message.textContent = (result && result.message) ? result.message : 'Wystapil blad reinstalacji.';
backproNotify(message.textContent, 'danger');
btn.disabled = false;
})
.catch(function () {
if (intervalId) {
clearInterval(intervalId);
}
bar.classList.remove('progress-bar-animated');
bar.classList.add('bg-danger');
message.textContent = 'Blad polaczenia z serwerem.';
backproNotify(message.textContent, 'danger');
btn.disabled = false;
});
});
})();
</script>