modificaciones de mejora
This commit is contained in:
+29
-6
@@ -26,25 +26,48 @@ func (OssApi) TableName() string {
|
||||
return "oss_api"
|
||||
}
|
||||
|
||||
// GetAllQrVcard obtiene todos los registros de QrVcard con paginación y búsqueda
|
||||
func GetAllOssApi(limit, offset int, search string) ([]OssApi, int64, error) {
|
||||
// GetAllOssApi obtiene todos los registros de OssApi con paginación, búsqueda, filtros y orden
|
||||
func GetAllOssApi(limit, offset int, search, provider, estado, sortBy, sortDir, dateFrom, dateTo string) ([]OssApi, int64, error) {
|
||||
var items []OssApi
|
||||
var total int64
|
||||
db := app.Http.Database.DB.Model(&OssApi{})
|
||||
|
||||
// Si se pasa un término de búsqueda, lo aplicamos en la consulta
|
||||
if search != "" {
|
||||
db = db.Where("name LIKE ?", "%"+search+"%")
|
||||
}
|
||||
if provider != "" {
|
||||
db = db.Where("provider = ?", provider)
|
||||
}
|
||||
if estado == "activo" {
|
||||
db = db.Where("is_active = ?", true)
|
||||
} else if estado == "inactivo" {
|
||||
db = db.Where("is_active = ?", false)
|
||||
}
|
||||
if dateFrom != "" {
|
||||
db = db.Where("created_at >= ?", dateFrom)
|
||||
}
|
||||
if dateTo != "" {
|
||||
db = db.Where("created_at <= ?", dateTo+" 23:59:59")
|
||||
}
|
||||
|
||||
// Contamos el total de registros
|
||||
if err := db.Count(&total).Error; err != nil {
|
||||
log.Printf("Error counting OssApi: %v", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Obtenemos los registros con paginación
|
||||
if err := db.Order("id DESC").Limit(limit).Offset(offset).Find(&items).Error; err != nil {
|
||||
allowedSorts := map[string]bool{
|
||||
"id": true, "name": true, "provider": true,
|
||||
"endpoint": true, "bucket_name": true, "region": true,
|
||||
"is_active": true, "created_at": true,
|
||||
}
|
||||
if !allowedSorts[sortBy] {
|
||||
sortBy = "id"
|
||||
}
|
||||
if sortDir != "asc" {
|
||||
sortDir = "desc"
|
||||
}
|
||||
|
||||
if err := db.Order(sortBy+" "+sortDir).Limit(limit).Offset(offset).Find(&items).Error; err != nil {
|
||||
log.Printf("Error retrieving OssApi: %v", err)
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -56,12 +56,28 @@
|
||||
<!-- Alerta de error -->
|
||||
<div x-show="errorMsg" class="mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-sm text-red-700" x-text="errorMsg"></div>
|
||||
|
||||
<!-- Barra de búsqueda (solo tab config) -->
|
||||
<div x-show="activeTab === 'config'" class="flex flex-col sm:flex-row gap-3 mb-5">
|
||||
<!-- Filtros (solo tab config) -->
|
||||
<div x-show="activeTab === 'config'" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-6 gap-3 mb-5">
|
||||
<input x-model="search" @keyup.enter="load()" type="text" placeholder="Buscar por nombre..."
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm flex-1 focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||
<select x-model="filtroProvider" @change="load()"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||
<option value="">Todos los proveedores</option>
|
||||
<option value="s3">S3 / MinIO</option>
|
||||
<option value="alibaba">Alibaba Cloud</option>
|
||||
</select>
|
||||
<select x-model="filtroEstado" @change="load()"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]">
|
||||
<option value="">Todos los estados</option>
|
||||
<option value="activo">Activo</option>
|
||||
<option value="inactivo">Inactivo</option>
|
||||
</select>
|
||||
<input x-model="dateFrom" @change="load()" type="date"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||
<input x-model="dateTo" @change="load()" type="date"
|
||||
class="border border-gray-300 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-[#8eb02f]" />
|
||||
<button @click="load()" :disabled="loading"
|
||||
class="flex items-center gap-2 px-4 py-2 rounded-lg border border-gray-300 text-sm hover:bg-gray-50 transition disabled:opacity-40">
|
||||
class="flex items-center justify-center gap-2 px-4 py-2 rounded-lg border border-gray-300 text-sm hover:bg-gray-50 transition disabled:opacity-40">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" :class="loading && 'animate-spin'" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"/>
|
||||
</svg>
|
||||
@@ -74,12 +90,24 @@
|
||||
<table class="table-auto w-full text-sm">
|
||||
<thead class="border-b border-gray-200 text-left text-xs font-semibold text-gray-500 uppercase">
|
||||
<tr>
|
||||
<th class="py-2 px-3">Nombre</th>
|
||||
<th class="py-2 px-3">Proveedor</th>
|
||||
<th class="py-2 px-3">Endpoint</th>
|
||||
<th class="py-2 px-3">Bucket</th>
|
||||
<th class="py-2 px-3">Región</th>
|
||||
<th class="py-2 px-3">Estado</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('name')">
|
||||
<span class="inline-flex items-center gap-1">Nombre <template x-if="sortBy === 'name'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('provider')">
|
||||
<span class="inline-flex items-center gap-1">Proveedor <template x-if="sortBy === 'provider'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('endpoint')">
|
||||
<span class="inline-flex items-center gap-1">Endpoint <template x-if="sortBy === 'endpoint'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('bucket_name')">
|
||||
<span class="inline-flex items-center gap-1">Bucket <template x-if="sortBy === 'bucket_name'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('region')">
|
||||
<span class="inline-flex items-center gap-1">Región <template x-if="sortBy === 'region'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 cursor-pointer select-none hover:text-gray-700" @click="sort('is_active')">
|
||||
<span class="inline-flex items-center gap-1">Estado <template x-if="sortBy === 'is_active'"><span x-text="sortDir === 'asc' ? '↑' : '↓'"></span></template></span>
|
||||
</th>
|
||||
<th class="py-2 px-3 text-right">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -374,6 +402,12 @@ function ossApiApp() {
|
||||
totalPages: 1,
|
||||
page: 1,
|
||||
search: '',
|
||||
filtroProvider: '',
|
||||
filtroEstado: '',
|
||||
dateFrom: '',
|
||||
dateTo: '',
|
||||
sortBy: 'id',
|
||||
sortDir: 'desc',
|
||||
loading: false,
|
||||
errorMsg: '',
|
||||
showModal: false,
|
||||
@@ -406,7 +440,16 @@ function ossApiApp() {
|
||||
this.loading = true;
|
||||
this.errorMsg = '';
|
||||
try {
|
||||
const params = new URLSearchParams({ page: this.page, search: this.search });
|
||||
const params = new URLSearchParams({
|
||||
page: this.page,
|
||||
search: this.search,
|
||||
provider: this.filtroProvider,
|
||||
estado: this.filtroEstado,
|
||||
date_from: this.dateFrom,
|
||||
date_to: this.dateTo,
|
||||
sort_by: this.sortBy,
|
||||
sort_dir: this.sortDir,
|
||||
});
|
||||
const res = await fetch(`/app/loadossapi?${params}`);
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || 'Error al cargar');
|
||||
@@ -420,6 +463,17 @@ function ossApiApp() {
|
||||
}
|
||||
},
|
||||
|
||||
sort(col) {
|
||||
if (this.sortBy === col) {
|
||||
this.sortDir = this.sortDir === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
this.sortBy = col;
|
||||
this.sortDir = 'asc';
|
||||
}
|
||||
this.page = 1;
|
||||
this.load();
|
||||
},
|
||||
|
||||
openAdd() {
|
||||
this.editItem = null;
|
||||
this.form = { name: '', provider: 'alibaba', endpoint: '', access_key_id: '', access_key_secret: '', bucket_name: '', region: '', is_active: true, notes: '' };
|
||||
|
||||
@@ -44,9 +44,17 @@ func GetOssApiConfigs(c *fiber.Ctx) error {
|
||||
}
|
||||
limit := 20
|
||||
offset := (page - 1) * limit
|
||||
search := c.Query("search", "")
|
||||
|
||||
items, total, err := models.GetAllOssApi(limit, offset, search)
|
||||
items, total, err := models.GetAllOssApi(
|
||||
limit, offset,
|
||||
c.Query("search", ""),
|
||||
c.Query("provider", ""),
|
||||
c.Query("estado", ""),
|
||||
c.Query("sort_by", "id"),
|
||||
c.Query("sort_dir", "desc"),
|
||||
c.Query("date_from", ""),
|
||||
c.Query("date_to", ""),
|
||||
)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user