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;
|
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
|
function channel_app_bootstrap(): void
|
||||||
{
|
{
|
||||||
static $booted = false;
|
static $booted = false;
|
||||||
@ -555,6 +723,8 @@ function channel_app_bootstrap(): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel_ensure_visible_test_rows($pdo);
|
||||||
|
|
||||||
$booted = true;
|
$booted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
clearAdvancedFiltersBtn: document.getElementById('clearAdvancedFiltersBtn'),
|
clearAdvancedFiltersBtn: document.getElementById('clearAdvancedFiltersBtn'),
|
||||||
applyAdvancedFiltersBtn: document.getElementById('applyAdvancedFiltersBtn'),
|
applyAdvancedFiltersBtn: document.getElementById('applyAdvancedFiltersBtn'),
|
||||||
selectPageBtn: document.getElementById('selectPageBtn'),
|
selectPageBtn: document.getElementById('selectPageBtn'),
|
||||||
|
saveCurrentViewBtn: document.getElementById('saveCurrentViewBtn'),
|
||||||
selectAllPageCheckbox: document.getElementById('selectAllPageCheckbox'),
|
selectAllPageCheckbox: document.getElementById('selectAllPageCheckbox'),
|
||||||
bulkEditBtn: document.getElementById('bulkEditBtn'),
|
bulkEditBtn: document.getElementById('bulkEditBtn'),
|
||||||
selectionBar: document.getElementById('selectionBar'),
|
selectionBar: document.getElementById('selectionBar'),
|
||||||
@ -142,6 +143,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
is_empty: 'is empty',
|
is_empty: 'is empty',
|
||||||
is_not_empty: 'is not 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) => {
|
const formatValue = (value) => {
|
||||||
if (value === null || value === undefined || value === '') return '—';
|
if (value === null || value === undefined || value === '') return '—';
|
||||||
@ -335,6 +343,48 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
elements.selectAllPageCheckbox.checked = allSelected;
|
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 rowClasses = (row) => {
|
||||||
const classes = ['channel-row'];
|
const classes = ['channel-row'];
|
||||||
if (Number(row.manually_edited) === 1) classes.push('row-manual');
|
if (Number(row.manually_edited) === 1) classes.push('row-manual');
|
||||||
@ -398,6 +448,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
elements.prevPageBtn.disabled = pagination.page <= 1;
|
elements.prevPageBtn.disabled = pagination.page <= 1;
|
||||||
elements.nextPageBtn.disabled = pagination.page >= pagination.pages;
|
elements.nextPageBtn.disabled = pagination.page >= pagination.pages;
|
||||||
updateSelectionUI();
|
updateSelectionUI();
|
||||||
|
updateSaveViewButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchChannels = async () => {
|
const fetchChannels = async () => {
|
||||||
@ -877,6 +928,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
notify('Current page selected.');
|
notify('Current page selected.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
elements.saveCurrentViewBtn?.addEventListener('click', () => {
|
||||||
|
exportCurrentView();
|
||||||
|
});
|
||||||
|
|
||||||
elements.clearSelectionBtn?.addEventListener('click', () => {
|
elements.clearSelectionBtn?.addEventListener('click', () => {
|
||||||
state.selectedIds.clear();
|
state.selectedIds.clear();
|
||||||
document.querySelectorAll('.row-checkbox').forEach(box => { box.checked = false; });
|
document.querySelectorAll('.row-checkbox').forEach(box => { box.checked = false; });
|
||||||
@ -1106,6 +1161,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
syncFilterForm();
|
syncFilterForm();
|
||||||
renderAdvancedFilters();
|
renderAdvancedFilters();
|
||||||
|
updateSaveViewButton();
|
||||||
renderHistoryEmpty('Click a row in Dataset to load its previous and current versions.');
|
renderHistoryEmpty('Click a row in Dataset to load its previous and current versions.');
|
||||||
refreshAll();
|
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>
|
||||||
<div class="d-flex flex-wrap gap-2 align-items-center">
|
<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="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>
|
<button class="btn btn-dark btn-sm" id="bulkEditBtn" data-bs-toggle="modal" data-bs-target="#bulkEditModal" disabled>Bulk edit (0)</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user