This commit is contained in:
Jorge Luis caudillo esparza
2026-10-02 14:34:16 -07:00
parent c2f249c937
commit d2b7b982f3
6 changed files with 170 additions and 49 deletions

View File

@@ -135,3 +135,7 @@ Do not add the following until the user explicitly asks:
The starter must stay small and focused: commands, master page, login, contracts, dummy user session, bundle structure, copied assets, and centralized SQL foundation.
---
REGLA OBLIGATORIA: Nunca usar args.get_panelsUpdated() ni get_panelsUpdated() en JavaScript de WebForms/UpdatePanel de este proyecto; esa llamada rompe repetidamente el entorno. Para reinicializar después de postbacks parciales usar PageRequestManager.add_endRequest(function () { ... }) sin depender de args, o eventos delegados cuando corresponda.

View File

@@ -2,7 +2,6 @@ using System;
using System.Globalization;
using System.Web.UI.WebControls;
using SIG.Web.AppCode.Configuration;
using SIG.Web.AppCode.Infrastructure.WebForms;
using SIG.Web.AppCode.Security;
namespace SIG.Web.Pages.Clientes

View File

@@ -158,12 +158,13 @@
<ajax:TabPanel ID="PestanaDesarrollos" runat="server" HeaderText="Desarrollos">
<ContentTemplate>
<div class="desarrollador-formulario">
<div class="desarrollador-acciones">
<button type="button" class="btn blue" data-toggle="modal" data-target="#ModalFraccionamiento">
<i class="fa fa-plus" aria-hidden="true"></i>Agregar fraccionamiento
<i class="fa fa-plus" aria-hidden="true"></i>Agregar fraccionamiento
</button>
</div>
<asp:UpdatePanel ID="UpFraccionamientos" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<div class="table-responsive">
@@ -177,7 +178,7 @@
<asp:TemplateField HeaderText="Fraccionamiento / Etapa">
<ItemTemplate>
<asp:Panel runat="server"
Visible='<%# Convert.ToBoolean(Eval("EsFraccionamiento")) %>'>
Visible='<%# Convert.ToBoolean(Eval("EsFraccionamiento")) %>'>
<button type="button"
class="btn btn-circle btn-xs default sig-grid-alternar-grupo-accion desarrollador-accion-icono"
title="Mostrar u ocultar etapas"

View File

@@ -1,36 +1,69 @@
(function (window, document, $) {
'use strict';
if (window.SIGLotesEtapa) { return; }
if (window.SIGLotesEtapa) {
return;
}
function init(context) {
var $ctx = $(context || document);
$ctx.find('.sig-lotes-etapa .select2me').each(function () {
var $el = $(this);
if (!$el.hasClass('select2-hidden-accessible')) {
$el.select2({ width: '100%' });
if (typeof $el.select2 !== 'function') {
return;
}
/*
* Compatible con el Select2 que ya usa la plataforma.
* No reinicializa controles que ya tienen Select2.
*/
if ($el.data('select2') ||
$el.hasClass('select2-hidden-accessible')) {
return;
}
$el.select2({
width: '100%'
});
});
$ctx.find('.sig-lotes-etapa .btn-group.open').removeClass('open');
$ctx.find('.sig-lotes-etapa .btn-group.open')
.removeClass('open');
}
$(function () { init(document); });
$(function () {
init(document);
});
/*
* WebForms / UpdatePanel
*
* REGLA DEL PROYECTO:
* No inspeccionar paneles actualizados; usar endRequest.
*
* Después de cualquier postback parcial simplemente revisamos
* los controles de Lotes. init() ya evita reinicializar Select2.
*/
if (window.Sys &&
Sys.WebForms &&
Sys.WebForms.PageRequestManager) {
if (window.Sys && Sys.WebForms && Sys.WebForms.PageRequestManager) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm._sigLotesEtapaRegistrado) {
prm.add_endRequest(function (sender, args) {
var panels = args.get_panelsUpdated();
if (!panels || !panels.length) {
init(document);
return;
}
for (var i = 0; i < panels.length; i++) {
init(panels[i]);
}
prm.add_endRequest(function () {
init(document);
});
prm._sigLotesEtapaRegistrado = true;
}
}
window.SIGLotesEtapa = { inicializar: init };
window.SIGLotesEtapa = {
inicializar: init
};
}(window, document, jQuery));

View File

@@ -48,7 +48,7 @@
CommandName="EliminarTipo"
CommandArgument='<%# Container.DataItemIndex %>'
CausesValidation="false"
OnClientClick="return confirm('¿Eliminar este tipo de vivienda?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Eliminar este tipo de vivienda?');">
Eliminar
</asp:LinkButton>
</ItemTemplate>
@@ -77,7 +77,7 @@
CssClass="btn default"
CausesValidation="false"
OnClick="LimpiarLotes_Click"
OnClientClick="return confirm('Se eliminarán sólo lotes NO aprobados y NO bloqueados. ¿Continuar?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, 'Se eliminarán sólo lotes NO aprobados y NO bloqueados. ¿Continuar?');">
<i class="fa fa-trash"></i> Limpiar lotes
</asp:LinkButton>
<asp:LinkButton ID="BtnAbrirGis" runat="server"
@@ -157,7 +157,7 @@
CommandName="Eliminar"
CommandArgument='<%# Eval("CveFraccionamientoLote") %>'
CausesValidation="false"
OnClientClick="return confirm('¿Eliminar este lote?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Eliminar este lote?');">
<i class="fa fa-trash"></i> Eliminar
</asp:LinkButton>
</li>
@@ -169,7 +169,7 @@
CommandName="CambiarAprobacion"
CommandArgument='<%# Eval("CveFraccionamientoLote") %>'
CausesValidation="false"
OnClientClick="return confirm('¿Confirmar cambio de aprobación del lote?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Confirmar cambio de aprobación del lote?');">
<i class="fa fa-check-circle"></i>
<%# Convert.ToBoolean(Eval("Aprobado")) ? "Desaprobar lote" : "Aprobar lote" %>
</asp:LinkButton>
@@ -179,7 +179,7 @@
CommandName="CambiarBloqueo"
CommandArgument='<%# Eval("CveFraccionamientoLote") %>'
CausesValidation="false"
OnClientClick="return confirm('¿Confirmar cambio de bloqueo del lote?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Confirmar cambio de bloqueo del lote?');">
<i class="fa fa-lock"></i>
<%# Convert.ToBoolean(Eval("Bloqueado")) ? "Desbloquear lote" : "Bloquear lote" %>
</asp:LinkButton>
@@ -197,7 +197,7 @@
CommandName="CambiarAgua"
CommandArgument='<%# Eval("CveFraccionamientoLote") %>'
CausesValidation="false"
OnClientClick="return confirm('¿Confirmar cambio de autorización de agua potable?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Confirmar cambio de autorización de agua potable?');">
<i class="fa fa-tint"></i>
<%# Convert.ToBoolean(Eval("AguaPotableAutorizada")) ? "Desautorizar agua potable" : "Autorizar agua potable" %>
</asp:LinkButton>
@@ -207,7 +207,7 @@
CommandName="CambiarDrenaje"
CommandArgument='<%# Eval("CveFraccionamientoLote") %>'
CausesValidation="false"
OnClientClick="return confirm('¿Confirmar cambio de autorización de drenaje?');">
OnClientClick="return window.SIGAlerts.confirmPostBack(this, '¿Confirmar cambio de autorización de drenaje?');">
<i class="fa fa-random"></i>
<%# Convert.ToBoolean(Eval("DrenajeAutorizado")) ? "Desautorizar drenaje" : "Autorizar drenaje" %>
</asp:LinkButton>
@@ -294,7 +294,10 @@
OnClick="DescargarPlantilla_Click">
<i class="fa fa-download"></i> Descargar plantilla
</asp:LinkButton>
<asp:FileUpload ID="ArchivoExcel" runat="server" CssClass="form-control" />
<input id="ArchivoExcel"
runat="server"
type="hidden"
class="ADSdropzoneLocal" />
<asp:Button ID="BtnCargarExcel" runat="server"
Text="Cargar Excel" CssClass="btn btn-success"
OnClick="CargarExcel_Click" />
@@ -412,7 +415,10 @@
Se registra también en Documentos de la etapa. Si está aprobado no debe poder reemplazarse.
</p>
<div class="form-group">
<asp:FileUpload ID="ArchivoGis" runat="server" CssClass="form-control" />
<input id="ArchivoGis"
runat="server"
type="hidden"
class="ADSdropzoneLocal" />
</div>
<div class="form-group">
<label>Nota</label>

View File

@@ -8,6 +8,7 @@ using System.Web.UI;
using System.Web.UI.WebControls;
using ClosedXML.Excel;
using SIG.Web.AppCode.Configuration;
using SIG.Web.AppCode.Infrastructure.WebForms;
using SIG.Web.AppCode.Models.Common;
using SIG.Web.AppCode.Models.Fraccionamientos;
using SIG.Web.AppCode.Session;
@@ -62,6 +63,28 @@ namespace SIG.Web.UserControl
sm.RegisterPostBackControl(BtnCargarExcel);
sm.RegisterPostBackControl(BtnSubirGis);
}
/*
* REGLA DEL PROYECTO:
* Las cargas de archivos usan siempre ADSdropzoneLocal.
* No usar asp:FileUpload.
*
* Se configura en cada request para que el input real generado
* conserve el name esperado por CargaArchivoWebHelper.
*/
CargaArchivoWebHelper.Configurar(
ArchivoExcel,
".xlsx",
null,
1,
"Arrastra aquí la plantilla .xlsx o haz clic para seleccionarla.");
CargaArchivoWebHelper.Configurar(
ArchivoGis,
".gis",
30,
1,
"Arrastra aquí el archivo .gis o haz clic para seleccionarlo.");
}
@@ -589,13 +612,26 @@ namespace SIG.Web.UserControl
protected void CargarExcel_Click(object sender, EventArgs e)
{
if (!ArchivoExcel.HasFile)
var archivoExcel =
CargaArchivoWebHelper.ObtenerArchivo(Page, ArchivoExcel);
if (archivoExcel == null)
{
MostrarModal("ModalAgregarLotes");
Alertar("Seleccione un archivo Excel.");
return;
}
if (!string.Equals(
Path.GetExtension(archivoExcel.FileName),
".xlsx",
StringComparison.OrdinalIgnoreCase))
{
MostrarModal("ModalAgregarLotes");
Alertar("El archivo seleccionado debe tener extensión .xlsx.");
return;
}
var tipos = AppServices.ServicioFraccionamiento.ListarTiposVivienda(
Usuario.CveUsuario, Usuario.NombreDominio);
@@ -615,7 +651,7 @@ namespace SIG.Web.UserControl
var lotes = new List<ModeloLoteFraccionamiento>();
using (var wb = new XLWorkbook(ArchivoExcel.PostedFile.InputStream))
using (var wb = new XLWorkbook(archivoExcel.InputStream))
{
var ws = wb.Worksheet("Lotes");
int fila = 2;
@@ -691,19 +727,53 @@ namespace SIG.Web.UserControl
protected void AbrirGis_Click(object sender, EventArgs e)
{
TxtNotaGis.Text = "";
TxtNotaGis.Text = string.Empty;
/*
* Se conserva el mismo control genérico ADSdropzoneLocal.
* La configuración se vuelve a aplicar al abrir el modal
* para que el UpdatePanel renderice los data-* correctos.
*/
CargaArchivoWebHelper.Configurar(
ArchivoGis,
".gis",
30,
1,
"Arrastra aquí el archivo .gis o haz clic para seleccionarlo.");
MostrarModal("ModalGisEtapa");
}
protected void SubirGis_Click(object sender, EventArgs e)
{
if (!ArchivoGis.HasFile)
var archivoGis =
CargaArchivoWebHelper.ObtenerArchivo(Page, ArchivoGis);
if (archivoGis == null)
{
MostrarModal("ModalGisEtapa");
Alertar("Seleccione el Archivo GIS de la Etapa.");
return;
}
if (!string.Equals(
Path.GetExtension(archivoGis.FileName),
".gis",
StringComparison.OrdinalIgnoreCase))
{
MostrarModal("ModalGisEtapa");
Alertar("El archivo seleccionado debe tener extensión .gis.");
return;
}
const long tamanoMaximoGis = 30L * 1024L * 1024L;
if (archivoGis.ContentLength > tamanoMaximoGis)
{
MostrarModal("ModalGisEtapa");
Alertar("El archivo GIS no puede exceder 30 MB.");
return;
}
var ctx = AppServices.TramiteDocumentoService.GetUploadContext(
CveFraccionamientoActual, 0, CveTipoDocumentoGis,
Usuario.CveUsuario, Usuario.NombreDominio, CveEtapaActual);
@@ -725,10 +795,10 @@ namespace SIG.Web.UserControl
var r = AppServices.TramiteDocumentoService.Upload(
CveFraccionamientoActual, 0, CveTipoDocumentoGis,
ArchivoGis.FileName,
ArchivoGis.PostedFile.ContentType,
ArchivoGis.PostedFile.InputStream,
ArchivoGis.PostedFile.ContentLength,
archivoGis.FileName,
archivoGis.ContentType,
archivoGis.InputStream,
archivoGis.ContentLength,
TxtNotaGis.Text,
Usuario.CveUsuario,
Usuario.NombreDominio,
@@ -778,30 +848,38 @@ namespace SIG.Web.UserControl
private void MostrarModal(string id)
{
ScriptManager.RegisterStartupScript(
this, GetType(), "show-" + id + "-" + Guid.NewGuid(),
"$('#" + id + "').modal('show');", true);
PageScriptRegistrar.RegistraScript(
Page,
"jQuery('#" +
HttpUtility.JavaScriptStringEncode(id ?? string.Empty) +
"').modal('show')",
"LotesMostrarModal");
}
private void CerrarModal(string id)
{
ScriptManager.RegisterStartupScript(
this, GetType(), "hide-" + id + "-" + Guid.NewGuid(),
"$('#" + id + "').modal('hide');", true);
PageScriptRegistrar.RegistraScript(
Page,
"jQuery('#" +
HttpUtility.JavaScriptStringEncode(id ?? string.Empty) +
"').modal('hide')",
"LotesCerrarModal");
}
private void Alertar(string mensaje)
{
string js = "if(window.SIGAlerts&&SIGAlerts.alert){SIGAlerts.alert(" +
"'" + HttpUtility.JavaScriptStringEncode(mensaje ?? "") + "');}" +
"else{alert('" + HttpUtility.JavaScriptStringEncode(mensaje ?? "") + "');}";
ScriptManager.RegisterStartupScript(
this, GetType(), "alert-" + Guid.NewGuid(), js, true);
PageAlertManager.Alert(
Page,
mensaje ?? "No fue posible completar la operación.",
TipoMensaje.MsgAdvertencia);
}
private void Toast(string mensaje)
{
Alertar(mensaje);
PageAlertManager.Alert(
Page,
mensaje ?? string.Empty,
TipoMensaje.ToastExito);
}
private static int? EnteroNullable(string value)