v3
This commit is contained in:
parent
cc09913585
commit
1b3f6ab743
@ -378,6 +378,174 @@ function channel_import_workspace_csv(PDO $pdo, string $path): int
|
||||
return $imported;
|
||||
}
|
||||
|
||||
function channel_ensure_visible_test_rows(PDO $pdo): int
|
||||
{
|
||||
$targetCount = 1000;
|
||||
$baseDate = '2026-04-05';
|
||||
$rows = [
|
||||
[
|
||||
'upper_ch_ref' => 'A TEST LOGISTICS ALPHA',
|
||||
'country_iso' => 'US',
|
||||
'country_client' => 'Test Tenant',
|
||||
'sat_ref' => 'INTELSAT-TEST',
|
||||
'sat_tpinfo' => '11001/H/30000',
|
||||
'genre' => 'Test Feed',
|
||||
'type' => 'free',
|
||||
'resolution' => 'HD',
|
||||
'langue' => 'EN',
|
||||
'region' => 'North America',
|
||||
'groupe' => 'QA Samples',
|
||||
'active' => 1,
|
||||
'idtype' => 1,
|
||||
'six_id' => '199001',
|
||||
'sid' => '9901',
|
||||
'onid' => '91',
|
||||
'tid' => '401',
|
||||
'sat_in' => $baseDate,
|
||||
'sat_out' => null,
|
||||
'sat_update' => $baseDate,
|
||||
'sat_ch_client_upper' => 'A TEST LOGISTICS ALPHA',
|
||||
'sat_client' => 'QA Client',
|
||||
'counting' => 12,
|
||||
'lastview' => '2026-04-05 11:40:00',
|
||||
'manually_edited' => 0,
|
||||
'manually_edited_at' => null,
|
||||
'date_in' => $baseDate,
|
||||
'date_out' => null,
|
||||
],
|
||||
[
|
||||
'upper_ch_ref' => 'A TEST LOGISTICS BETA',
|
||||
'country_iso' => 'FR',
|
||||
'country_client' => 'Test Tenant',
|
||||
'sat_ref' => 'EUTELSAT-TEST',
|
||||
'sat_tpinfo' => '11002/V/30000',
|
||||
'genre' => 'Test Feed',
|
||||
'type' => 'payed',
|
||||
'resolution' => 'UHD',
|
||||
'langue' => 'FR',
|
||||
'region' => 'West Europe',
|
||||
'groupe' => 'QA Samples',
|
||||
'active' => 1,
|
||||
'idtype' => 1,
|
||||
'six_id' => '199002',
|
||||
'sid' => '9902',
|
||||
'onid' => '92',
|
||||
'tid' => '402',
|
||||
'sat_in' => $baseDate,
|
||||
'sat_out' => null,
|
||||
'sat_update' => $baseDate,
|
||||
'sat_ch_client_upper' => 'A TEST LOGISTICS BETA',
|
||||
'sat_client' => 'QA Client',
|
||||
'counting' => 18,
|
||||
'lastview' => '2026-04-05 11:41:00',
|
||||
'manually_edited' => 1,
|
||||
'manually_edited_at' => $baseDate,
|
||||
'date_in' => $baseDate,
|
||||
'date_out' => null,
|
||||
],
|
||||
[
|
||||
'upper_ch_ref' => 'A TEST FILTER GAMMA',
|
||||
'country_iso' => 'DE',
|
||||
'country_client' => 'Test Tenant',
|
||||
'sat_ref' => 'ASTRA-TEST',
|
||||
'sat_tpinfo' => '11003/H/30000',
|
||||
'genre' => 'QA Search',
|
||||
'type' => 'free',
|
||||
'resolution' => 'SD',
|
||||
'langue' => 'DE',
|
||||
'region' => 'DACH',
|
||||
'groupe' => 'QA Samples',
|
||||
'active' => 1,
|
||||
'idtype' => 1,
|
||||
'six_id' => '199003',
|
||||
'sid' => '9903',
|
||||
'onid' => '93',
|
||||
'tid' => '403',
|
||||
'sat_in' => $baseDate,
|
||||
'sat_out' => null,
|
||||
'sat_update' => $baseDate,
|
||||
'sat_ch_client_upper' => 'A TEST FILTER GAMMA',
|
||||
'sat_client' => 'QA Client',
|
||||
'counting' => 27,
|
||||
'lastview' => '2026-04-05 11:42:00',
|
||||
'manually_edited' => 0,
|
||||
'manually_edited_at' => null,
|
||||
'date_in' => $baseDate,
|
||||
'date_out' => null,
|
||||
],
|
||||
];
|
||||
|
||||
$countryPool = ['US', 'FR', 'DE', 'ES', 'IT', 'GB', 'CA', 'BR', 'AE', 'JP'];
|
||||
$satellitePool = ['INTELSAT-TEST', 'EUTELSAT-TEST', 'ASTRA-TEST', 'SES-TEST', 'HISPASAT-TEST'];
|
||||
$languagePool = ['EN', 'FR', 'DE', 'ES', 'IT', 'PT', 'AR', 'JP'];
|
||||
$regionPool = ['North America', 'West Europe', 'DACH', 'LATAM', 'MENA', 'APAC'];
|
||||
$resolutionPool = ['SD', 'HD', 'FHD', 'UHD'];
|
||||
|
||||
for ($i = 4; $i <= $targetCount; $i++) {
|
||||
$country = $countryPool[($i - 1) % count($countryPool)];
|
||||
$satellite = $satellitePool[($i - 1) % count($satellitePool)];
|
||||
$language = $languagePool[($i - 1) % count($languagePool)];
|
||||
$region = $regionPool[($i - 1) % count($regionPool)];
|
||||
$resolution = $resolutionPool[($i - 1) % count($resolutionPool)];
|
||||
$polarization = $i % 2 === 0 ? 'H' : 'V';
|
||||
$frequency = 11000 + (($i - 1) % 120);
|
||||
$symbolRate = 30000 + ((($i - 1) % 5) * 1000);
|
||||
$hour = intdiv(($i - 1) % 1440, 60);
|
||||
$minute = ($i - 1) % 60;
|
||||
$name = sprintf('A TEST LOGISTICS %04d', $i);
|
||||
|
||||
$rows[] = [
|
||||
'upper_ch_ref' => $name,
|
||||
'country_iso' => $country,
|
||||
'country_client' => 'Test Tenant',
|
||||
'sat_ref' => $satellite,
|
||||
'sat_tpinfo' => sprintf('%d/%s/%d', $frequency, $polarization, $symbolRate),
|
||||
'genre' => $i % 3 === 0 ? 'QA Search' : 'Test Feed',
|
||||
'type' => $i % 4 === 0 ? 'payed' : 'free',
|
||||
'resolution' => $resolution,
|
||||
'langue' => $language,
|
||||
'region' => $region,
|
||||
'groupe' => 'QA Samples',
|
||||
'active' => 1,
|
||||
'idtype' => 1,
|
||||
'six_id' => (string) (200000 + $i),
|
||||
'sid' => (string) (9900 + $i),
|
||||
'onid' => (string) (90 + (($i - 1) % 50)),
|
||||
'tid' => (string) (400 + $i),
|
||||
'sat_in' => $baseDate,
|
||||
'sat_out' => null,
|
||||
'sat_update' => $baseDate,
|
||||
'sat_ch_client_upper' => $name,
|
||||
'sat_client' => 'QA Client',
|
||||
'counting' => $i,
|
||||
'lastview' => sprintf('2026-04-05 %02d:%02d:00', $hour, $minute),
|
||||
'manually_edited' => $i % 10 === 0 ? 1 : 0,
|
||||
'manually_edited_at' => $i % 10 === 0 ? $baseDate : null,
|
||||
'date_in' => $baseDate,
|
||||
'date_out' => null,
|
||||
];
|
||||
}
|
||||
|
||||
$existingStmt = $pdo->query("SELECT upper_ch_ref FROM channels WHERE date_out IS NULL AND upper_ch_ref LIKE 'A TEST %'");
|
||||
$existingNames = [];
|
||||
foreach ($existingStmt->fetchAll(PDO::FETCH_COLUMN) as $existingName) {
|
||||
$existingNames[(string) $existingName] = true;
|
||||
}
|
||||
|
||||
$inserted = 0;
|
||||
foreach ($rows as $row) {
|
||||
if (isset($existingNames[$row['upper_ch_ref']])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
channel_insert($row, $pdo);
|
||||
$existingNames[$row['upper_ch_ref']] = true;
|
||||
$inserted++;
|
||||
}
|
||||
|
||||
return $inserted;
|
||||
}
|
||||
|
||||
function channel_app_bootstrap(): void
|
||||
{
|
||||
static $booted = false;
|
||||
@ -555,6 +723,8 @@ function channel_app_bootstrap(): void
|
||||
}
|
||||
}
|
||||
|
||||
channel_ensure_visible_test_rows($pdo);
|
||||
|
||||
$booted = true;
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
clearAdvancedFiltersBtn: document.getElementById('clearAdvancedFiltersBtn'),
|
||||
applyAdvancedFiltersBtn: document.getElementById('applyAdvancedFiltersBtn'),
|
||||
selectPageBtn: document.getElementById('selectPageBtn'),
|
||||
saveCurrentViewBtn: document.getElementById('saveCurrentViewBtn'),
|
||||
selectAllPageCheckbox: document.getElementById('selectAllPageCheckbox'),
|
||||
bulkEditBtn: document.getElementById('bulkEditBtn'),
|
||||
selectionBar: document.getElementById('selectionBar'),
|
||||
@ -142,6 +143,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
is_empty: 'is empty',
|
||||
is_not_empty: 'is not empty'
|
||||
};
|
||||
const exportFields = [
|
||||
'upper_ch_ref', 'country_iso', 'country_client', 'sat_ref', 'sat_tpinfo',
|
||||
'genre', 'type', 'resolution', 'langue', 'region', 'groupe', 'active',
|
||||
'idtype', 'six_id', 'sid', 'onid', 'tid', 'sat_in', 'sat_out',
|
||||
'sat_update', 'sat_ch_client_upper', 'sat_client', 'counting', 'lastview',
|
||||
'manually_edited_at'
|
||||
];
|
||||
|
||||
const formatValue = (value) => {
|
||||
if (value === null || value === undefined || value === '') return '—';
|
||||
@ -335,6 +343,48 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
elements.selectAllPageCheckbox.checked = allSelected;
|
||||
};
|
||||
|
||||
const csvCell = (value) => {
|
||||
const normalized = value === null || value === undefined ? '' : String(value);
|
||||
return `"${normalized.replaceAll('"', '""')}"`;
|
||||
};
|
||||
|
||||
const timestampForFilename = () => {
|
||||
const now = new Date();
|
||||
const pad = (part) => String(part).padStart(2, '0');
|
||||
return `${now.getUTCFullYear()}${pad(now.getUTCMonth() + 1)}${pad(now.getUTCDate())}-${pad(now.getUTCHours())}${pad(now.getUTCMinutes())}${pad(now.getUTCSeconds())}`;
|
||||
};
|
||||
|
||||
const updateSaveViewButton = () => {
|
||||
if (!elements.saveCurrentViewBtn) return;
|
||||
const count = state.currentRows.length;
|
||||
elements.saveCurrentViewBtn.disabled = count === 0;
|
||||
elements.saveCurrentViewBtn.textContent = count > 0 ? `Save visible page (${count})` : 'Save visible page';
|
||||
};
|
||||
|
||||
const exportCurrentView = () => {
|
||||
if (!state.currentRows.length) {
|
||||
notify('There is no visible row to save on this page yet.', 'danger');
|
||||
return;
|
||||
}
|
||||
|
||||
const headers = exportFields.map((field) => labels[field] || field);
|
||||
const rows = state.currentRows.map((row) => exportFields.map((field) => csvCell(row[field])));
|
||||
const csvLines = [headers.map(csvCell).join(','), ...rows.map((cells) => cells.join(','))];
|
||||
const csv = `${csvLines.join('\n')}`;
|
||||
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
const page = Number(state.filters.page || 1);
|
||||
|
||||
link.href = downloadUrl;
|
||||
link.download = `channels-visible-page-${page}-${timestampForFilename()}.csv`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
URL.revokeObjectURL(downloadUrl);
|
||||
notify(`Saved ${state.currentRows.length} visible row(s) from page ${page} as CSV.`);
|
||||
};
|
||||
|
||||
const rowClasses = (row) => {
|
||||
const classes = ['channel-row'];
|
||||
if (Number(row.manually_edited) === 1) classes.push('row-manual');
|
||||
@ -398,6 +448,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
elements.prevPageBtn.disabled = pagination.page <= 1;
|
||||
elements.nextPageBtn.disabled = pagination.page >= pagination.pages;
|
||||
updateSelectionUI();
|
||||
updateSaveViewButton();
|
||||
};
|
||||
|
||||
const fetchChannels = async () => {
|
||||
@ -877,6 +928,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
notify('Current page selected.');
|
||||
});
|
||||
|
||||
elements.saveCurrentViewBtn?.addEventListener('click', () => {
|
||||
exportCurrentView();
|
||||
});
|
||||
|
||||
elements.clearSelectionBtn?.addEventListener('click', () => {
|
||||
state.selectedIds.clear();
|
||||
document.querySelectorAll('.row-checkbox').forEach(box => { box.checked = false; });
|
||||
@ -1106,6 +1161,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
syncFilterForm();
|
||||
renderAdvancedFilters();
|
||||
updateSaveViewButton();
|
||||
renderHistoryEmpty('Click a row in Dataset to load its previous and current versions.');
|
||||
refreshAll();
|
||||
});
|
||||
|
||||
BIN
assets/pasted-20260405-114040-02cc2c16.png
Normal file
BIN
assets/pasted-20260405-114040-02cc2c16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 404 KiB |
@ -229,6 +229,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2 align-items-center">
|
||||
<button class="btn btn-outline-secondary btn-sm" id="selectPageBtn">Select page</button>
|
||||
<button class="btn btn-outline-secondary btn-sm" id="saveCurrentViewBtn">Save visible page</button>
|
||||
<button class="btn btn-dark btn-sm" id="bulkEditBtn" data-bs-toggle="modal" data-bs-target="#bulkEditModal" disabled>Bulk edit (0)</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user