Files
itflow/agent/modals/asset/asset_export.php
johnnyq 9ba21cf352 Assets: add NAS, UPS, PDU, Modem/ONT and NVR/DVR types from a new registry in functions/asset_type.php that sets each type's icon, tone, group, fields and details; the asset form shows only the fields a type uses (fields that already hold a value stay shown) and adds a Details section per type (CPU/RAM/storage, VM host/vCPUs, switch ports/SFP/PoE/management, NAS drives/capacity/RAID, UPS capacity/output/runtime/outlets/battery dates, PDU kind/outlets/input, modem circuit ID/ISP account, printer, phone, mobile, display, camera and NVR details) stored in a new asset_specs table (database 3.4.9); new or changed port and SFP counts add the missing interfaces, continuing the asset's numbering, skipping Wi-Fi, VLAN and management ports and never deleting any; the asset page and quick look show the details, a server or NAS lists the VMs that run on it, and Assigned and Warranty show only on types that use them; the list gets Servers & NAS and Power tabs, an optional Details column, a UPS battery badge, an Assigned picker only on assigned types, and New buttons named for what they add; nightly UPS Battery Due notifications at 45, 7 and 1 days as a Support notification; copy leaves out per-unit details, Transfer to Client carries details and interface types, export adds per-detail columns, import reads detail columns after the standard twelve (VM hosts by name, resolved after every row is in) and reports values it could not keep, and the API reads and writes asset_specs; racks, client portal, client export, overview, document templates and AI lists group the new types; fix asset import carrying physical location and notes into the next row, saving 0000-00-00 for a missing purchase date and warning on an unknown contact or location, save API and import types in the list's spelling, and keep interface types on transfer; changelog updated
2026-10-27 15:59:03 -04:00

178 lines
7.6 KiB
PHP

<?php
require_once '../../../includes/modal_header.php';
enforceUserPermission('module_support');
// Pre-filled from the assets page's current filters. Everything here is editable -
// the export runs whatever this form posts, not whatever the page happened to show.
$client_id = intval($_GET['client_id'] ?? 0);
if ($client_id) {
enforceClientAccess();
}
// Search Filter
$q_filter = $_GET['q'] ?? '';
// Type Filter
$type_filter = $_GET['type'] ?? '';
// Client Filter
$client_filter = intval($_GET['client'] ?? 0);
// Location Filter
$location_filter = intval($_GET['location'] ?? 0);
// Status Filter
$status_filter = trim(strip_tags((string) ($_GET['status'] ?? '')));
// Tags Filter
$tag_filter = (isset($_GET['tags']) && is_array($_GET['tags'])) ? array_map('intval', $_GET['tags']) : [];
// Expiring In Filter
$expire_filter = $_GET['expire_days'] ?? '';
// Archived Filter
$archived_filter = (isset($_GET['archived']) && $_GET['archived'] == 1) ? 1 : 0;
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-download me-2"></i>Export Assets</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<?php exportTabsNav(); ?>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<input type="hidden" name="client_id" value="<?= $client_id ?>">
<div class="modal-body">
<?php exportTabsFiltersOpen(); ?>
<div class="mb-3">
<label>Search</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-search"></i></span>
<input type="text" class="form-control" name="q" value="<?= stripslashes(escapeHtml($q_filter)) ?>" placeholder="Name, serial, IP, OS">
</div>
</div>
<div class="mb-3">
<label>Type</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
<select class="form-select select2" name="type">
<option value="">- All Types -</option>
<?php foreach (assetTypeTabs() as $tab_key => $tab) { ?>
<option <?php if ($type_filter === $tab_key) { echo "selected"; } ?> value="<?= $tab_key ?>"><?= escapeHtml($tab['label']) ?></option>
<?php } ?>
</select>
</div>
</div>
<?php if (!$client_id) { ?>
<div class="mb-3">
<label>Client</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
<select class="form-select select2" name="client">
<option value="">- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT client_id, client_name, client_abbreviation FROM clients WHERE EXISTS (SELECT 1 FROM assets WHERE asset_client_id = client_id)" . clientScopeSql('client_id') . " ORDER BY client_name ASC");
while ($row = mysqli_fetch_assoc($sql_clients_filter)) {
$filter_client_id = intval($row['client_id']);
$filter_client_name = escapeHtml($row['client_name']);
?>
<option <?php if ($client_filter == $filter_client_id) { echo "selected"; } ?> value="<?= $filter_client_id ?>"<?= selectOptionClient($row['client_id'], $row['client_name'], $row['client_abbreviation'] ?? '') ?>><?= $filter_client_name ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<?php if ($client_id) { ?>
<div class="mb-3">
<label>Location</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
<select class="form-select select2" name="location">
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT location_id, location_name FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
while ($row = mysqli_fetch_assoc($sql_locations_filter)) {
$filter_location_id = intval($row['location_id']);
$filter_location_name = escapeHtml($row['location_name']);
?>
<option <?php if ($location_filter == $filter_location_id) { echo "selected"; } ?> value="<?= $filter_location_id ?>"><?= $filter_location_name ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="mb-3">
<label>Status</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-circle"></i></span>
<select class="form-select select2" name="status">
<option value="">- All Statuses -</option>
<?= categoryFilterOptionsHtml('asset_status', $status_filter, "SELECT DISTINCT asset_status FROM assets WHERE asset_status IS NOT NULL AND asset_status <> ''" . ($client_id ? " AND asset_client_id = $client_id" : '') . clientScopeSql('asset_client_id')) ?>
</select>
</div>
</div>
<div class="mb-3">
<label>Tags</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-tags"></i></span>
<select class="form-select select2" name="tags[]" data-placeholder="- All Tags -" multiple>
<?= tagOptionsHtml('asset', $tag_filter) ?>
</select>
</div>
</div>
<div class="mb-3">
<label>Warranty Expiring In</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
<select class="form-select select2" name="expire_days">
<option value="">- Any -</option>
<option <?php if ($expire_filter === 'expired') { echo "selected"; } ?> value="expired">Expired</option>
<?php foreach ([7, 30, 45, 60, 90] as $expire_option) { ?>
<option <?php if ($expire_filter !== '' && $expire_filter == $expire_option) { echo "selected"; } ?> value="<?= $expire_option ?>"><?= $expire_option ?> Days</option>
<?php } ?>
</select>
</div>
</div>
<div class="mb-3">
<label>Archived</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-archive"></i></span>
<select class="form-select select2" name="archived">
<option <?php if (!$archived_filter) { echo "selected"; } ?> value="0">Active only</option>
<option <?php if ($archived_filter) { echo "selected"; } ?> value="1">Archived only</option>
</select>
</div>
</div>
<?php exportTabsColumns('assets'); ?>
</div>
<div class="modal-footer">
<?php renderExportButtons('export_assets'); ?>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';