Ajustes visualizacion

This commit is contained in:
Jorge Luis caudillo esparza
2026-09-29 09:38:51 -07:00
parent 78a6666e5a
commit a2bde9e920
27 changed files with 21206 additions and 750 deletions

View File

@@ -0,0 +1,43 @@
CAMBIO REQUERIDO EN Pages/Desarrolladores/DesarrolladorDetalle.aspx
El ZIP fuente SIG.Web(3).zip no contiene la carpeta Pages, por lo que no es seguro
inventar ni sobrescribir DesarrolladorDetalle.aspx.
El botón "Ver etapa" debe dejar de abrir el panel lateral y navegar a:
~/Pages/Fraccionamientos/EtapaDetalle.aspx?etapa={CveFraccionamientoEtapa}
Si actualmente es un LinkButton, reemplazar sólo esa acción por un HyperLink.
Ejemplo dentro del ItemTemplate:
<asp:HyperLink
ID="BtnVerEtapa"
runat="server"
CssClass="btn btn-circle btn-sm default sig-accion-icono"
ToolTip="Ver etapa"
aria-label="Ver etapa"
NavigateUrl='<%# ResolveUrl("~/Pages/Fraccionamientos/EtapaDetalle.aspx?etapa=" +
Convert.ToInt32(Eval("CveFraccionamientoEtapa")).ToString(
System.Globalization.CultureInfo.InvariantCulture)) %>'>
<i class="fa fa-eye" aria-hidden="true"></i>
</asp:HyperLink>
Si la URL se arma en code-behind, usar:
private string UrlDetalleEtapa(int cveFraccionamientoEtapa)
{
return ResolveUrl("~/Pages/Fraccionamientos/EtapaDetalle.aspx?etapa=" +
cveFraccionamientoEtapa.ToString(
System.Globalization.CultureInfo.InvariantCulture));
}
y asignar esa URL al HyperLink de Ver etapa.
Quitar del botón Ver etapa:
- CommandName usado sólo para abrir el panel.
- data-sig-panel-abrir.
- OnClientClick que abra el panel.
- cualquier llamada a SIGPanelLateral.abrir(...) asociada exclusivamente a Ver etapa.
No eliminar el UserControl DetalleEtapa.ascx: la nueva página lo reutiliza.

View File

@@ -1,4 +1,4 @@
using System.Web.Optimization;
using System.Web.Optimization;
using System.Web.UI;
namespace SIG.Web.AppCode.Configuration
@@ -59,6 +59,7 @@ namespace SIG.Web.AppCode.Configuration
"~/Scripts/SigPdfDrawer.js",
"~/Scripts/PanelLateral.js",
"~/Scripts/DocumentosEtapa.js",
"~/Scripts/SigVisualizadorArchivo.js",
"~/Scripts/Visitas.js",
"~/Scripts/PagosConvenios.js",
"~/Scripts/custom.js",
@@ -125,6 +126,7 @@ namespace SIG.Web.AppCode.Configuration
"~/Styles/SigPdfViewer.css",
"~/Styles/SigPdfDrawer.css",
"~/Styles/PanelLateral.css",
"~/Styles/SigVisualizadorArchivo.css",
"~/Styles/DetalleEtapa.css",
"~/Styles/DocumentosEtapa.css",
"~/Styles/Archivos.css",

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Globalization;
using System.IO;
using System.Web;
@@ -7,6 +7,7 @@ using SIG.Web.AppCode.Configuration;
using SIG.Web.AppCode.Models.Common;
using SIG.Web.AppCode.Models.Documentos;
using SIG.Web.AppCode.Session;
using SIG.Web.AppCode.SigControls;
namespace SIG.Web.Pages.Fraccionamientos
{
@@ -24,9 +25,9 @@ namespace SIG.Web.Pages.Fraccionamientos
if (currentUser == null)
{
context.Response.StatusCode = 401;
context.Response.ContentType = "text/plain";
context.Response.Write(
RespondError(
context,
401,
"Su sesión no está disponible. Inicie sesión nuevamente.");
return;
}
@@ -41,9 +42,10 @@ namespace SIG.Web.Pages.Fraccionamientos
context.Request.QueryString["documento"],
out documentRequestId))
{
context.Response.StatusCode = 400;
context.Response.ContentType = "text/plain";
context.Response.Write("El documento solicitado no es válido.");
RespondError(
context,
400,
"El documento solicitado no es válido.");
return;
}
@@ -58,9 +60,9 @@ namespace SIG.Web.Pages.Fraccionamientos
result.Data == null ||
result.Data.Content == null)
{
context.Response.StatusCode = 404;
context.Response.ContentType = "text/plain";
context.Response.Write(
RespondError(
context,
404,
result == null ||
string.IsNullOrWhiteSpace(result.UserMessage)
? "No se encontró el documento."
@@ -69,21 +71,68 @@ namespace SIG.Web.Pages.Fraccionamientos
}
TramiteDocumentoFileModel file = result.Data;
bool visualizar = string.Equals(
context.Request.QueryString["vista"],
"1",
StringComparison.Ordinal);
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.TrySkipIisCustomErrors = true;
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
context.Response.ContentType =
string.IsNullOrWhiteSpace(file.ContentType)
string nombreArchivo = SanitizeFileName(file.NombreArchivo);
string tipoContenido = string.IsNullOrWhiteSpace(file.ContentType)
? MimeMapping.GetMimeMapping(nombreArchivo)
: file.ContentType;
if (visualizar &&
SigVisualizadorArchivoOfficeConverter.EsArchivoOffice(
nombreArchivo,
tipoContenido))
{
SigVisualizadorArchivoOfficeResultado conversion;
string error;
using (file.Content)
{
if (!SigVisualizadorArchivoOfficeConverter.IntentarConvertir(
file.Content,
nombreArchivo,
out conversion,
out error))
{
RespondError(
context,
415,
string.IsNullOrWhiteSpace(error)
? "No fue posible generar la vista previa del archivo de Office."
: error);
return;
}
}
using (conversion)
using (var contenidoPdf = new FileStream(
conversion.RutaPdf,
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
PrepareResponse(
context,
"application/pdf",
false,
Path.GetFileNameWithoutExtension(nombreArchivo) + ".pdf");
contenidoPdf.CopyTo(context.Response.OutputStream);
}
context.ApplicationInstance.CompleteRequest();
return;
}
PrepareResponse(
context,
string.IsNullOrWhiteSpace(tipoContenido)
? "application/octet-stream"
: file.ContentType;
context.Response.AddHeader(
"Content-Disposition",
"attachment; filename=\"" +
SanitizeFileName(file.NombreArchivo) +
"\"");
: tipoContenido,
!visualizar,
nombreArchivo);
using (file.Content)
{
@@ -93,6 +142,37 @@ namespace SIG.Web.Pages.Fraccionamientos
context.ApplicationInstance.CompleteRequest();
}
private static void PrepareResponse(
HttpContext context,
string contentType,
bool download,
string fileName)
{
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.TrySkipIisCustomErrors = true;
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetNoStore();
context.Response.ContentType = contentType;
context.Response.AddHeader(
"Content-Disposition",
(download ? "attachment" : "inline") +
"; filename=\"" + SanitizeFileName(fileName) + "\"");
}
private static void RespondError(
HttpContext context,
int statusCode,
string message)
{
context.Response.Clear();
context.Response.StatusCode = statusCode;
context.Response.TrySkipIisCustomErrors = true;
context.Response.ContentType = "text/plain; charset=utf-8";
context.Response.Write(message);
context.ApplicationInstance.CompleteRequest();
}
private static UserSessionModel GetCurrentUser()
{
return AppServices.UserContext != null &&

View File

@@ -0,0 +1,388 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace SIG.Web.AppCode.SigControls
{
[ToolboxData("<{0}:SigVisualizadorArchivo runat=server></{0}:SigVisualizadorArchivo>")]
public sealed class SigVisualizadorArchivo : WebControl
{
private const string ClaveSesionPrefijo = "SigVisualizadorArchivo:";
[Category("SIG")]
public string Titulo
{
get { return Convert.ToString(ViewState["Titulo"]); }
set { ViewState["Titulo"] = value; }
}
[Category("SIG")]
public string Descripcion
{
get { return Convert.ToString(ViewState["Descripcion"]); }
set { ViewState["Descripcion"] = value; }
}
[Category("SIG")]
public string NombreArchivo
{
get { return Convert.ToString(ViewState["NombreArchivo"]); }
set { ViewState["NombreArchivo"] = value; }
}
[Category("SIG")]
public string TipoContenido
{
get { return Convert.ToString(ViewState["TipoContenido"]); }
set { ViewState["TipoContenido"] = value; }
}
[Category("SIG")]
public string RutaWeb
{
get { return Convert.ToString(ViewState["RutaWeb"]); }
set
{
ViewState["RutaWeb"] = value;
if (!string.IsNullOrWhiteSpace(value))
{
ViewState["RutaFisica"] = null;
}
}
}
[Category("SIG")]
public string RutaDescargaWeb
{
get { return Convert.ToString(ViewState["RutaDescargaWeb"]); }
set { ViewState["RutaDescargaWeb"] = value; }
}
[Category("SIG")]
public string RutaFisica
{
get { return Convert.ToString(ViewState["RutaFisica"]); }
set
{
ViewState["RutaFisica"] = value;
if (!string.IsNullOrWhiteSpace(value))
{
ViewState["RutaWeb"] = null;
ViewState["RutaDescargaWeb"] = null;
}
}
}
[Category("SIG")]
[DefaultValue(true)]
public bool PermitirDescarga
{
get { return ViewState["PermitirDescarga"] as bool? ?? true; }
set { ViewState["PermitirDescarga"] = value; }
}
[Category("SIG")]
[DefaultValue(true)]
public bool PermitirExpandir
{
get { return ViewState["PermitirExpandir"] as bool? ?? true; }
set { ViewState["PermitirExpandir"] = value; }
}
[Browsable(false)]
public bool ActivoInicial
{
get { return ViewState["ActivoInicial"] as bool? ?? false; }
private set { ViewState["ActivoInicial"] = value; }
}
private string TokenRutaFisica
{
get { return Convert.ToString(ViewState["TokenRutaFisica"]); }
set { ViewState["TokenRutaFisica"] = value; }
}
public void Mostrar(
string titulo,
string descripcion,
string nombreArchivo,
string rutaWeb,
string tipoContenido = null,
string rutaDescargaWeb = null)
{
Titulo = titulo;
Descripcion = descripcion;
NombreArchivo = nombreArchivo;
TipoContenido = tipoContenido;
RutaWeb = rutaWeb;
RutaDescargaWeb = rutaDescargaWeb;
ActivoInicial = !string.IsNullOrWhiteSpace(rutaWeb);
}
public void MostrarRutaFisica(
string titulo,
string descripcion,
string nombreArchivo,
string rutaFisica,
string tipoContenido = null)
{
Titulo = titulo;
Descripcion = descripcion;
NombreArchivo = nombreArchivo;
TipoContenido = tipoContenido;
RutaFisica = rutaFisica;
ActivoInicial = !string.IsNullOrWhiteSpace(rutaFisica);
}
public void Limpiar()
{
Titulo = null;
Descripcion = null;
NombreArchivo = null;
TipoContenido = null;
RutaWeb = null;
RutaDescargaWeb = null;
RutaFisica = null;
ActivoInicial = false;
}
protected override void OnPreRender(EventArgs argumentos)
{
base.OnPreRender(argumentos);
if (!string.IsNullOrWhiteSpace(RutaFisica))
{
RegistrarRutaFisicaEnSesion();
}
}
protected override void Render(HtmlTextWriter writer)
{
string rutaVisualizacion;
string rutaDescarga;
ResolverRutas(out rutaVisualizacion, out rutaDescarga);
writer.AddAttribute(HtmlTextWriterAttribute.Id, ClientID);
writer.AddAttribute(HtmlTextWriterAttribute.Class, CombinarClases(CssClass, "sig-visualizador-archivo"));
writer.AddAttribute("data-sig-visualizador-archivo", "1");
writer.AddAttribute("data-sig-visualizador-activo-inicial", ActivoInicial ? "1" : "0");
AgregarAtributo(writer, "data-sig-visualizador-titulo-inicial", Titulo);
AgregarAtributo(writer, "data-sig-visualizador-descripcion-inicial", Descripcion);
AgregarAtributo(writer, "data-sig-visualizador-nombre-inicial", NombreArchivo);
AgregarAtributo(writer, "data-sig-visualizador-tipo-contenido-inicial", TipoContenido);
AgregarAtributo(writer, "data-sig-visualizador-url-inicial", rutaVisualizacion);
AgregarAtributo(writer, "data-sig-visualizador-url-descarga-inicial", rutaDescarga);
writer.AddAttribute("data-sig-visualizador-permitir-descarga", PermitirDescarga ? "1" : "0");
writer.AddAttribute("data-sig-visualizador-permitir-expandir", PermitirExpandir ? "1" : "0");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
RenderEncabezado(writer, rutaDescarga);
RenderContenido(writer);
writer.RenderEndTag();
}
private void RenderEncabezado(HtmlTextWriter writer, string rutaDescarga)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-encabezado");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-datos");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-titulo");
writer.AddAttribute("data-sig-visualizador-titulo", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.WriteEncodedText(Titulo ?? string.Empty);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-descripcion");
writer.AddAttribute("data-sig-visualizador-descripcion", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.WriteEncodedText(Descripcion ?? string.Empty);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-nombre");
writer.AddAttribute("data-sig-visualizador-nombre", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.WriteEncodedText(NombreArchivo ?? string.Empty);
writer.RenderEndTag();
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-acciones");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "btn btn-sm default sig-visualizador-archivo-descargar");
writer.AddAttribute(HtmlTextWriterAttribute.Title, "Descargar archivo");
writer.AddAttribute("aria-label", "Descargar archivo");
writer.AddAttribute("data-sig-visualizador-descargar", "1");
if (!string.IsNullOrWhiteSpace(rutaDescarga))
{
writer.AddAttribute(HtmlTextWriterAttribute.Href, rutaDescarga);
}
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.Write("<i class=\"fa fa-download\" aria-hidden=\"true\"></i><span>Descargar</span>");
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "btn btn-sm default sig-visualizador-archivo-expandir");
writer.AddAttribute(HtmlTextWriterAttribute.Title, "Expandir visor");
writer.AddAttribute("aria-label", "Expandir visor");
writer.AddAttribute("data-sig-visualizador-expandir", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Button);
writer.Write("<i class=\"fa fa-expand\" aria-hidden=\"true\"></i>");
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Type, "button");
writer.AddAttribute(HtmlTextWriterAttribute.Class, "btn btn-sm default sig-visualizador-archivo-cerrar");
writer.AddAttribute(HtmlTextWriterAttribute.Title, "Cerrar visor");
writer.AddAttribute("aria-label", "Cerrar visor");
writer.AddAttribute("data-sig-visualizador-cerrar", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Button);
writer.Write("<i class=\"fa fa-times\" aria-hidden=\"true\"></i>");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
private static void RenderContenido(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-cuerpo");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-pdf");
writer.AddAttribute("data-sig-visualizador-pdf", "1");
writer.AddAttribute(HtmlTextWriterAttribute.Title, "Vista previa del documento PDF");
writer.RenderBeginTag(HtmlTextWriterTag.Iframe);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-imagen");
writer.AddAttribute("data-sig-visualizador-imagen", "1");
writer.AddAttribute(HtmlTextWriterAttribute.Alt, "Vista previa del archivo");
writer.RenderBeginTag(HtmlTextWriterTag.Img);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-texto");
writer.AddAttribute("data-sig-visualizador-texto", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Pre);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-gis");
writer.AddAttribute("data-sig-visualizador-gis", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-mensaje");
writer.AddAttribute("data-sig-visualizador-mensaje", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-mensaje-icono");
writer.RenderBeginTag(HtmlTextWriterTag.I);
writer.RenderEndTag();
writer.AddAttribute(HtmlTextWriterAttribute.Class, "sig-visualizador-archivo-mensaje-texto");
writer.AddAttribute("data-sig-visualizador-mensaje-texto", "1");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.WriteEncodedText("Seleccione un archivo para visualizarlo.");
writer.RenderEndTag();
writer.RenderEndTag();
writer.RenderEndTag();
}
private void RegistrarRutaFisicaEnSesion()
{
if (Page == null || Page.Session == null)
{
return;
}
string rutaCompleta;
try
{
rutaCompleta = Path.GetFullPath(RutaFisica);
}
catch
{
return;
}
if (string.IsNullOrWhiteSpace(TokenRutaFisica))
{
TokenRutaFisica = Guid.NewGuid().ToString("N");
}
Page.Session[ClaveSesionPrefijo + TokenRutaFisica] = new SigVisualizadorArchivoSesion
{
RutaFisica = rutaCompleta,
NombreArchivo = string.IsNullOrWhiteSpace(NombreArchivo)
? Path.GetFileName(rutaCompleta)
: Path.GetFileName(NombreArchivo),
TipoContenido = string.IsNullOrWhiteSpace(TipoContenido)
? MimeMapping.GetMimeMapping(rutaCompleta)
: TipoContenido
};
}
private void ResolverRutas(out string rutaVisualizacion, out string rutaDescarga)
{
rutaVisualizacion = ResolverRutaCliente(RutaWeb);
rutaDescarga = ResolverRutaCliente(
string.IsNullOrWhiteSpace(RutaDescargaWeb)
? RutaWeb
: RutaDescargaWeb);
if (string.IsNullOrWhiteSpace(RutaFisica) || string.IsNullOrWhiteSpace(TokenRutaFisica))
{
return;
}
string baseHandler = ResolveClientUrl("~/SigVisualizadorArchivo.ashx?token=" +
HttpUtility.UrlEncode(TokenRutaFisica));
rutaVisualizacion = baseHandler;
rutaDescarga = baseHandler + "&descargar=1";
}
private string ResolverRutaCliente(string ruta)
{
if (string.IsNullOrWhiteSpace(ruta))
{
return string.Empty;
}
if (Uri.IsWellFormedUriString(ruta, UriKind.Absolute))
{
return ruta;
}
return ResolveClientUrl(ruta);
}
private static void AgregarAtributo(HtmlTextWriter writer, string nombre, string valor)
{
if (!string.IsNullOrWhiteSpace(valor))
{
writer.AddAttribute(nombre, valor);
}
}
private static string CombinarClases(string clase1, string clase2)
{
return ((clase1 ?? string.Empty) + " " + (clase2 ?? string.Empty)).Trim();
}
}
[Serializable]
internal sealed class SigVisualizadorArchivoSesion
{
public string RutaFisica { get; set; }
public string NombreArchivo { get; set; }
public string TipoContenido { get; set; }
}
}

View File

@@ -0,0 +1,162 @@
using System;
using System.IO;
using System.Web;
using System.Web.SessionState;
namespace SIG.Web.AppCode.SigControls
{
public sealed class SigVisualizadorArchivoHandler : IHttpHandler, IRequiresSessionState
{
private const string ClaveSesionPrefijo = "SigVisualizadorArchivo:";
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext contexto)
{
string token = contexto.Request.QueryString["token"];
if (string.IsNullOrWhiteSpace(token) || contexto.Session == null)
{
ResponderError(contexto, 400, "El archivo solicitado no es válido.");
return;
}
var archivo = contexto.Session[ClaveSesionPrefijo + token] as SigVisualizadorArchivoSesion;
if (archivo == null || string.IsNullOrWhiteSpace(archivo.RutaFisica))
{
ResponderError(contexto, 404, "El archivo ya no está disponible.");
return;
}
string rutaCompleta;
try
{
rutaCompleta = Path.GetFullPath(archivo.RutaFisica);
}
catch
{
ResponderError(contexto, 404, "El archivo ya no está disponible.");
return;
}
if (!File.Exists(rutaCompleta))
{
ResponderError(contexto, 404, "El archivo ya no está disponible.");
return;
}
bool descargar = string.Equals(
contexto.Request.QueryString["descargar"],
"1",
StringComparison.Ordinal);
string nombreArchivo = LimpiarNombreArchivo(
string.IsNullOrWhiteSpace(archivo.NombreArchivo)
? Path.GetFileName(rutaCompleta)
: archivo.NombreArchivo);
string tipoContenido = string.IsNullOrWhiteSpace(archivo.TipoContenido)
? MimeMapping.GetMimeMapping(nombreArchivo)
: archivo.TipoContenido;
if (!descargar &&
SigVisualizadorArchivoOfficeConverter.EsArchivoOffice(
nombreArchivo,
tipoContenido))
{
SigVisualizadorArchivoOfficeResultado conversion;
string error;
if (!SigVisualizadorArchivoOfficeConverter.IntentarConvertir(
rutaCompleta,
nombreArchivo,
out conversion,
out error))
{
ResponderError(
contexto,
415,
string.IsNullOrWhiteSpace(error)
? "No fue posible generar la vista previa del archivo de Office."
: error);
return;
}
using (conversion)
using (var contenidoPdf = new FileStream(
conversion.RutaPdf,
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
PrepararRespuesta(
contexto,
"application/pdf",
false,
Path.GetFileNameWithoutExtension(nombreArchivo) + ".pdf");
contenidoPdf.CopyTo(contexto.Response.OutputStream);
}
contexto.ApplicationInstance.CompleteRequest();
return;
}
PrepararRespuesta(
contexto,
string.IsNullOrWhiteSpace(tipoContenido)
? "application/octet-stream"
: tipoContenido,
descargar,
nombreArchivo);
using (var contenido = new FileStream(
rutaCompleta,
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
contenido.CopyTo(contexto.Response.OutputStream);
}
contexto.ApplicationInstance.CompleteRequest();
}
private static void PrepararRespuesta(
HttpContext contexto,
string tipoContenido,
bool descargar,
string nombreArchivo)
{
contexto.Response.Clear();
contexto.Response.ClearHeaders();
contexto.Response.TrySkipIisCustomErrors = true;
contexto.Response.Cache.SetCacheability(HttpCacheability.NoCache);
contexto.Response.Cache.SetNoStore();
contexto.Response.ContentType = tipoContenido;
contexto.Response.AddHeader(
"Content-Disposition",
(descargar ? "attachment" : "inline") +
"; filename=\"" + LimpiarNombreArchivo(nombreArchivo) + "\"");
}
private static void ResponderError(HttpContext contexto, int codigo, string mensaje)
{
contexto.Response.Clear();
contexto.Response.StatusCode = codigo;
contexto.Response.TrySkipIisCustomErrors = true;
contexto.Response.ContentType = "text/plain; charset=utf-8";
contexto.Response.Write(mensaje);
contexto.ApplicationInstance.CompleteRequest();
}
private static string LimpiarNombreArchivo(string nombreArchivo)
{
return Path.GetFileName(string.IsNullOrWhiteSpace(nombreArchivo) ? "archivo" : nombreArchivo)
.Replace("\"", string.Empty)
.Replace("\r", string.Empty)
.Replace("\n", string.Empty);
}
}
}

View File

@@ -0,0 +1,409 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Globalization;
using System.IO;
namespace SIG.Web.AppCode.SigControls
{
internal static class SigVisualizadorArchivoOfficeConverter
{
private static readonly HashSet<string> ExtensionesOffice =
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
".doc",
".docx",
".docm",
".dot",
".dotx",
".dotm",
".rtf",
".xls",
".xlsx",
".xlsm",
".xlsb",
".xlt",
".xltx",
".xltm",
".ppt",
".pptx",
".pptm",
".pps",
".ppsx",
".ppsm",
".pot",
".potx",
".potm",
".odt",
".ods",
".odp"
};
public static bool EsArchivoOffice(string nombreArchivo, string tipoContenido)
{
string extension = Path.GetExtension(nombreArchivo ?? string.Empty);
if (!string.IsNullOrWhiteSpace(extension) && ExtensionesOffice.Contains(extension))
{
return true;
}
string tipo = (tipoContenido ?? string.Empty).ToLowerInvariant();
return tipo.Contains("officedocument") ||
tipo.Contains("msword") ||
tipo.Contains("ms-excel") ||
tipo.Contains("ms-powerpoint") ||
tipo.Contains("opendocument");
}
public static bool IntentarConvertir(
Stream contenido,
string nombreArchivo,
out SigVisualizadorArchivoOfficeResultado resultado,
out string error)
{
resultado = null;
error = null;
if (contenido == null)
{
error = "El archivo no contiene datos para generar la vista previa.";
return false;
}
string extension = NormalizarExtension(nombreArchivo);
if (!ExtensionesOffice.Contains(extension))
{
error = "El tipo de archivo de Office no está soportado para vista previa.";
return false;
}
string directorioTrabajo = CrearDirectorioTrabajo();
string rutaEntrada = Path.Combine(directorioTrabajo, "entrada" + extension);
try
{
if (contenido.CanSeek)
{
contenido.Position = 0;
}
using (var archivoEntrada = new FileStream(
rutaEntrada,
FileMode.Create,
FileAccess.Write,
FileShare.None))
{
contenido.CopyTo(archivoEntrada);
}
return IntentarConvertirRuta(
rutaEntrada,
directorioTrabajo,
out resultado,
out error);
}
catch (Exception ex)
{
EliminarDirectorio(directorioTrabajo);
error = "No fue posible preparar el archivo de Office para vista previa. " + ex.Message;
return false;
}
}
public static bool IntentarConvertir(
string rutaFisica,
string nombreArchivo,
out SigVisualizadorArchivoOfficeResultado resultado,
out string error)
{
resultado = null;
error = null;
if (string.IsNullOrWhiteSpace(rutaFisica) || !File.Exists(rutaFisica))
{
error = "El archivo ya no está disponible.";
return false;
}
string extension = NormalizarExtension(nombreArchivo);
if (!ExtensionesOffice.Contains(extension))
{
extension = Path.GetExtension(rutaFisica) ?? string.Empty;
}
if (!ExtensionesOffice.Contains(extension))
{
error = "El tipo de archivo de Office no está soportado para vista previa.";
return false;
}
string directorioTrabajo = CrearDirectorioTrabajo();
string rutaEntrada = Path.Combine(directorioTrabajo, "entrada" + extension);
try
{
File.Copy(rutaFisica, rutaEntrada, true);
return IntentarConvertirRuta(
rutaEntrada,
directorioTrabajo,
out resultado,
out error);
}
catch (Exception ex)
{
EliminarDirectorio(directorioTrabajo);
error = "No fue posible preparar el archivo de Office para vista previa. " + ex.Message;
return false;
}
}
private static bool IntentarConvertirRuta(
string rutaEntrada,
string directorioTrabajo,
out SigVisualizadorArchivoOfficeResultado resultado,
out string error)
{
resultado = null;
error = null;
string ejecutable = ResolverLibreOffice();
if (string.IsNullOrWhiteSpace(ejecutable))
{
EliminarDirectorio(directorioTrabajo);
error = "La vista previa de Office requiere LibreOffice en el servidor.";
return false;
}
string directorioSalida = Path.Combine(directorioTrabajo, "salida");
string directorioPerfil = Path.Combine(directorioTrabajo, "perfil");
Directory.CreateDirectory(directorioSalida);
Directory.CreateDirectory(directorioPerfil);
string perfilUri = new Uri(
directorioPerfil.TrimEnd(Path.DirectorySeparatorChar) +
Path.DirectorySeparatorChar).AbsoluteUri.TrimEnd('/');
var inicio = new ProcessStartInfo
{
FileName = ejecutable,
Arguments =
"-env:UserInstallation=\"" + perfilUri + "\" " +
"--headless --nologo --nodefault --nolockcheck --nofirststartwizard " +
"--convert-to pdf --outdir \"" + directorioSalida + "\" \"" + rutaEntrada + "\"",
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
try
{
using (Process proceso = Process.Start(inicio))
{
if (proceso == null)
{
EliminarDirectorio(directorioTrabajo);
error = "No fue posible iniciar LibreOffice para generar la vista previa.";
return false;
}
int segundos = ResolverTimeoutSegundos();
if (!proceso.WaitForExit(segundos * 1000))
{
try
{
proceso.Kill();
}
catch
{
// El proceso puede haber terminado entre la espera y el intento de cancelación.
}
EliminarDirectorio(directorioTrabajo);
error = "La generación de la vista previa de Office excedió el tiempo permitido.";
return false;
}
if (proceso.ExitCode != 0)
{
EliminarDirectorio(directorioTrabajo);
error = "LibreOffice no pudo convertir el archivo para vista previa.";
return false;
}
}
string rutaPdf = Path.Combine(directorioSalida, "entrada.pdf");
if (!File.Exists(rutaPdf))
{
string[] pdfs = Directory.GetFiles(directorioSalida, "*.pdf", SearchOption.TopDirectoryOnly);
rutaPdf = pdfs.Length > 0 ? pdfs[0] : null;
}
if (string.IsNullOrWhiteSpace(rutaPdf) || !File.Exists(rutaPdf))
{
EliminarDirectorio(directorioTrabajo);
error = "LibreOffice terminó la conversión sin generar el PDF de vista previa.";
return false;
}
resultado = new SigVisualizadorArchivoOfficeResultado(
directorioTrabajo,
rutaPdf);
return true;
}
catch (Exception ex)
{
EliminarDirectorio(directorioTrabajo);
error = "No fue posible generar la vista previa de Office. " + ex.Message;
return false;
}
}
private static string NormalizarExtension(string nombreArchivo)
{
string extension = Path.GetExtension(nombreArchivo ?? string.Empty);
return string.IsNullOrWhiteSpace(extension)
? string.Empty
: extension.ToLowerInvariant();
}
private static string CrearDirectorioTrabajo()
{
string raiz = Path.Combine(
Path.GetTempPath(),
"SIGVisualizadorArchivo");
Directory.CreateDirectory(raiz);
string directorio = Path.Combine(
raiz,
Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(directorio);
return directorio;
}
private static int ResolverTimeoutSegundos()
{
int segundos;
string configurado = ConfigurationManager.AppSettings[
"SigVisualizadorArchivoOfficeTimeoutSeconds"];
if (!int.TryParse(
configurado,
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out segundos) ||
segundos < 10 ||
segundos > 300)
{
segundos = 90;
}
return segundos;
}
private static string ResolverLibreOffice()
{
string configurado = ConfigurationManager.AppSettings[
"SigVisualizadorArchivoLibreOfficePath"];
if (!string.IsNullOrWhiteSpace(configurado) && File.Exists(configurado))
{
return Path.GetFullPath(configurado);
}
var candidatos = new List<string>();
AgregarCandidatoPrograma(candidatos, Environment.GetEnvironmentVariable("ProgramFiles"));
AgregarCandidatoPrograma(candidatos, Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
string path = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
foreach (string directorio in path.Split(Path.PathSeparator))
{
if (!string.IsNullOrWhiteSpace(directorio))
{
candidatos.Add(Path.Combine(directorio.Trim(), "soffice.exe"));
}
}
foreach (string candidato in candidatos)
{
try
{
if (File.Exists(candidato))
{
return Path.GetFullPath(candidato);
}
}
catch
{
// Continuar con el siguiente candidato.
}
}
return null;
}
private static void AgregarCandidatoPrograma(
ICollection<string> candidatos,
string carpetaProgramas)
{
if (string.IsNullOrWhiteSpace(carpetaProgramas))
{
return;
}
candidatos.Add(Path.Combine(
carpetaProgramas,
"LibreOffice",
"program",
"soffice.exe"));
}
internal static void EliminarDirectorio(string directorio)
{
if (string.IsNullOrWhiteSpace(directorio))
{
return;
}
try
{
if (Directory.Exists(directorio))
{
Directory.Delete(directorio, true);
}
}
catch
{
// La limpieza no debe romper la respuesta del visor.
}
}
}
internal sealed class SigVisualizadorArchivoOfficeResultado : IDisposable
{
private bool disposed;
public SigVisualizadorArchivoOfficeResultado(
string directorioTrabajo,
string rutaPdf)
{
DirectorioTrabajo = directorioTrabajo;
RutaPdf = rutaPdf;
}
public string DirectorioTrabajo { get; private set; }
public string RutaPdf { get; private set; }
public void Dispose()
{
if (disposed)
{
return;
}
disposed = true;
SigVisualizadorArchivoOfficeConverter.EliminarDirectorio(
DirectorioTrabajo);
}
}
}

View File

@@ -0,0 +1,412 @@
{
"type": "FeatureCollection",
"name": "Etapa1_10_lotes",
"crs": {
"type": "name",
"properties": {
"name": "EPSG:4326"
}
},
"features": [
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-1",
"Tipo": "Lote",
"Calle": "Calle Demo 1",
"Catastro": "CAT-001",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9555,
29.09
],
[
-110.95532,
29.09
],
[
-110.95532,
29.090139999999998
],
[
-110.9555,
29.090139999999998
],
[
-110.9555,
29.09
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-2",
"Tipo": "Lote",
"Calle": "Calle Demo 1",
"Catastro": "CAT-002",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9553,
29.09
],
[
-110.95512,
29.09
],
[
-110.95512,
29.090139999999998
],
[
-110.9553,
29.090139999999998
],
[
-110.9553,
29.09
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-3",
"Tipo": "Lote",
"Calle": "Calle Demo 1",
"Catastro": "CAT-003",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9551,
29.09
],
[
-110.95492,
29.09
],
[
-110.95492,
29.090139999999998
],
[
-110.9551,
29.090139999999998
],
[
-110.9551,
29.09
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-4",
"Tipo": "Lote",
"Calle": "Calle Demo 1",
"Catastro": "CAT-004",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9549,
29.09
],
[
-110.95472,
29.09
],
[
-110.95472,
29.090139999999998
],
[
-110.9549,
29.090139999999998
],
[
-110.9549,
29.09
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-5",
"Tipo": "Lote",
"Calle": "Calle Demo 1",
"Catastro": "CAT-005",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9547,
29.09
],
[
-110.95452,
29.09
],
[
-110.95452,
29.090139999999998
],
[
-110.9547,
29.090139999999998
],
[
-110.9547,
29.09
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-6",
"Tipo": "Lote",
"Calle": "Calle Demo 2",
"Catastro": "CAT-006",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9555,
29.09016
],
[
-110.95532,
29.09016
],
[
-110.95532,
29.0903
],
[
-110.9555,
29.0903
],
[
-110.9555,
29.09016
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-7",
"Tipo": "Lote",
"Calle": "Calle Demo 2",
"Catastro": "CAT-007",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9553,
29.09016
],
[
-110.95512,
29.09016
],
[
-110.95512,
29.0903
],
[
-110.9553,
29.0903
],
[
-110.9553,
29.09016
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-8",
"Tipo": "Lote",
"Calle": "Calle Demo 2",
"Catastro": "CAT-008",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9551,
29.09016
],
[
-110.95492,
29.09016
],
[
-110.95492,
29.0903
],
[
-110.9551,
29.0903
],
[
-110.9551,
29.09016
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-9",
"Tipo": "Lote",
"Calle": "Calle Demo 2",
"Catastro": "CAT-009",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9549,
29.09016
],
[
-110.95472,
29.09016
],
[
-110.95472,
29.0903
],
[
-110.9549,
29.0903
],
[
-110.9549,
29.09016
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Etapa": "Etapa 1",
"Nombre": "Umbrella-10",
"Tipo": "Lote",
"Calle": "Calle Demo 2",
"Catastro": "CAT-010",
"MetrosCuadrados": 200.0,
"Duplicador": 1,
"Estatus": "Activa"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-110.9547,
29.09016
],
[
-110.95452,
29.09016
],
[
-110.95452,
29.0903
],
[
-110.9547,
29.0903
],
[
-110.9547,
29.09016
]
]
]
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -1,48 +1,36 @@
<%@ Page Title="Detalle de desarrollador" Language="C#" MasterPageFile="~/Site.master"
<%@ Page Title="Detalle de desarrollador" Language="C#" MasterPageFile="~/Site.master"
AutoEventWireup="true" CodeFile="DesarrolladorDetalle.aspx.cs"
Inherits="SIG.Web.Pages.Desarrolladores.DesarrolladorDetalle" %>
<%@ Register TagPrefix="sig" TagName="CapturaEtapas" Src="~/UserControl/CapturaEtapas.ascx" %>
<%@ Register TagPrefix="sig" TagName="DetalleEtapa" Src="~/UserControl/DetalleEtapa.ascx" %>
<%@ Register TagPrefix="sig" TagName="ConveniosListado" Src="~/UserControl/ConveniosListado.ascx" %>
<asp:Content ID="ContenidoEncabezado" ContentPlaceHolderID="H" runat="server">
<style>
.desarrollador-panel-etapa {
width: min(1200px, 96vw);
}
.desarrollador-formulario {
padding: 20px 0;
}
.desarrollador-pie {
padding: 15px 20px;
border-top: 1px solid #e7ecf1;
text-align: right;
}
.desarrollador-acciones {
margin-bottom: 15px;
}
.desarrollador-listado > tbody > tr.desarrollador-grupo {
position: relative;
height: 50px;
}
.desarrollador-listado > tbody > tr.desarrollador-grupo > td:first-child {
display: block;
position: absolute;
left: 0;
right: 0;
top: 0;
min-height: 50px;
.desarrollador-listado > tbody > tr.desarrollador-grupo > td {
background: #edf4f8;
padding: 10px 12px;
box-sizing: border-box;
}
.desarrollador-listado > tbody > tr.desarrollador-grupo > td.desarrollador-celda-oculta-grupo {
display: none;
}
.desarrollador-cabecera {
display: flex;
align-items: center;
gap: 12px;
}
.desarrollador-descripcion {
flex: 1;
display: flex;
@@ -50,14 +38,22 @@
align-items: center;
gap: 8px 20px;
}
.desarrollador-alternar {
background: transparent;
}
.desarrollador-credenciales {
overflow-wrap: anywhere;
padding: 15px;
background: #f1f8ff;
}
.sig-columna-acciones {
width: 1%;
white-space: nowrap;
text-align: center;
}
</style>
</asp:Content>
<asp:Content ID="ContenidoAcciones" ContentPlaceHolderID="A" runat="server">
@@ -75,27 +71,8 @@
OnConsultar="BuscarDesarrolladores" OnSeleccionCambiada="SeleccionarDesarrollador" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpAbrirEtapa" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:LinkButton ID="BtnAbrirEtapa" runat="server" CssClass="hidden"
CausesValidation="false" OnClick="AbrirEtapa_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Panel ID="PanelDetalleEtapa" runat="server" CssClass="sig_panel_lateral sig_panel_derecho desarrollador-panel-etapa"
role="dialog" aria-modal="true" aria-hidden="true" tabindex="-1" aria-label="Detalle de etapa">
<div class="sig_panel_contenido">
<div class="sig_panel_cabecera">
<h4>Detalle de etapa</h4>
<button type="button" class="btn default" data-sig-panel-cerrar="">Cerrar</button>
</div>
<div class="sig_panel_cuerpo">
<sig:DetalleEtapa ID="DetalleEtapa" runat="server" OnCambiado="Etapa_Cambiada" />
</div>
</div>
</asp:Panel>
<asp:Panel ID="PnlDetalle" runat="server" Visible="false">
<ajax:TabContainer ID="PestanasDesarrollador" runat="server" ActiveTabIndex="0">
<ajax:TabContainer ID="PestanasDesarrollador" runat="server" ActiveTabIndex="1">
<ajax:TabPanel ID="PestanaDatos" runat="server" HeaderText="Datos generales">
<ContentTemplate>
<asp:UpdatePanel ID="UpDatos" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
@@ -177,7 +154,8 @@
<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">
@@ -225,13 +203,14 @@
HeaderStyle-CssClass="sig-columna-acciones"
ItemStyle-CssClass="sig-columna-acciones">
<ItemTemplate>
<asp:LinkButton runat="server"
CssClass="btn btn-circle btn-sm blue sig-accion-icono"
CommandName="VerEtapa" CausesValidation="false"
ToolTip="Ver etapa" aria-label="Ver etapa"
<asp:HyperLink runat="server"
CssClass="btn btn-circle btn-sm primary sig-accion-icono"
ToolTip="Ver etapa"
aria-label="Ver etapa"
NavigateUrl='<%# ObtenerUrlEtapa(Eval("CveFraccionamientoEtapa")) %>'
Visible='<%# !Convert.ToBoolean(Eval("EsFraccionamiento")) %>'>
<i class="fa fa-eye" aria-hidden="true"></i>
</asp:LinkButton>
<i class="fa fa-eye" aria-hidden="true"></i>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
@@ -310,7 +289,8 @@
<h4 id="TituloModalEtapa" class="modal-title">Agregar etapa</h4>
</div>
<div class="modal-body">
<p>Fraccionamiento: <strong><asp:Literal ID="LitFraccionamientoEtapa" runat="server" Mode="Encode" /></strong></p>
<p>Fraccionamiento: <strong>
<asp:Literal ID="LitFraccionamientoEtapa" runat="server" Mode="Encode" /></strong></p>
<p class="help-block">Fideicomiso se heredará de la última etapa creada. Podrá editarlo en el detalle de la etapa.</p>
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="TxtEtapa" Text="Etapa" />

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Web.UI;
@@ -16,28 +16,6 @@ namespace SIG.Web.Pages.Desarrolladores
{
public partial class DesarrolladorDetalle : ClsPaginaBase
{
#region Propiedades
private int CveClienteActual
{
get { return ViewState["CveClienteActual"] as int? ?? 0; }
set { ViewState["CveClienteActual"] = value; }
}
private int CveFraccionamientoEtapaActual
{
get { return ViewState["CveFraccionamientoEtapaActual"] as int? ?? 0; }
set { ViewState["CveFraccionamientoEtapaActual"] = value; }
}
private bool AsociadoCanadeviActual
{
get { return ViewState["AsociadoCanadeviActual"] as bool? ?? false; }
set { ViewState["AsociadoCanadeviActual"] = value; }
}
#endregion
protected void Fraccionamientos_FilaEnlazada(object origen, GridViewRowEventArgs argumentos)
{
if (argumentos.Row.RowType != DataControlRowType.DataRow)
@@ -52,11 +30,10 @@ namespace SIG.Web.Pages.Desarrolladores
if (desarrollo.EsFraccionamiento)
{
argumentos.Row.CssClass = "desarrollador-grupo";
argumentos.Row.Cells[0].ColumnSpan = GvFraccionamientos.Columns.Count;
for (int indice = 1; indice < argumentos.Row.Cells.Count; indice++)
{
argumentos.Row.Cells[indice].CssClass =
(argumentos.Row.Cells[indice].CssClass +
" desarrollador-celda-oculta-grupo").Trim();
argumentos.Row.Cells[indice].Visible = false;
}
}
}
@@ -69,16 +46,6 @@ namespace SIG.Web.Pages.Desarrolladores
fila.Ubicacion, fila.HectareasFraccionamiento, fila.NumeroEtapas, fila.Estatus);
}
protected void AbrirEtapa_Click(object origen, EventArgs argumentos)
{
int clave;
if (int.TryParse(Request.Form["__EVENTARGUMENT"], out clave))
{
DetalleEtapa.Cargar(clave);
RegistraScript("SIGPanelLateral.abrir('" + PanelDetalleEtapa.ClientID + "');");
}
}
protected void Etapa_Cambiada(object origen, EventArgs argumentos)
{
CargarFraccionamientos();
@@ -119,6 +86,24 @@ namespace SIG.Web.Pages.Desarrolladores
}
}
private int CveClienteActual
{
get { return ViewState["CveClienteActual"] as int? ?? 0; }
set { ViewState["CveClienteActual"] = value; }
}
private int CveFraccionamientoEtapaActual
{
get { return ViewState["CveFraccionamientoEtapaActual"] as int? ?? 0; }
set { ViewState["CveFraccionamientoEtapaActual"] = value; }
}
private bool AsociadoCanadeviActual
{
get { return ViewState["AsociadoCanadeviActual"] as bool? ?? false; }
set { ViewState["AsociadoCanadeviActual"] = value; }
}
protected void Page_Load(object origen, EventArgs argumentos)
{
if (!IsPostBack)
@@ -145,12 +130,6 @@ namespace SIG.Web.Pages.Desarrolladores
CargarEstatus();
BuscadorDesarrolladores.SelectedValue = cveCliente.ToString(CultureInfo.InvariantCulture);
BuscadorDesarrolladores.Text = consulta.Data.RFC + " - " + consulta.Data.Nombre;
int etapa;
if (int.TryParse(Request.QueryString["etapa"], out etapa))
{
DetalleEtapa.Cargar(etapa);
RegistraScript("SIGPanelLateral.abrir('" + PanelDetalleEtapa.ClientID + "');");
}
}
ConfigurarCanadevi(AsociadoCanadeviActual);
@@ -159,24 +138,6 @@ namespace SIG.Web.Pages.Desarrolladores
protected override void OnPreRender(EventArgs argumentos)
{
base.OnPreRender(argumentos);
var administrador = ScriptManager.GetCurrent(Page);
string destinoPostback = Request.Form["__EVENTTARGET"] ?? string.Empty;
bool postbackDelDetalle = destinoPostback.StartsWith(DetalleEtapa.UniqueID + "$", StringComparison.Ordinal);
foreach (string claveFormulario in Request.Form.AllKeys)
{
if (claveFormulario != null &&
claveFormulario.StartsWith(DetalleEtapa.UniqueID + "$", StringComparison.Ordinal) &&
Request.Form[claveFormulario] != null &&
(claveFormulario.EndsWith("$GuardarArchivo", StringComparison.Ordinal) ||
claveFormulario.EndsWith("$GuardarDocumento", StringComparison.Ordinal)))
{
postbackDelDetalle = true;
}
}
if (IsPostBack && administrador != null && !administrador.IsInAsyncPostBack && postbackDelDetalle)
{
RegistraScript("SIGPanelLateral.abrir('" + PanelDetalleEtapa.ClientID + "');");
}
var sitio = Master as SIG.Web.Site;
if (sitio != null)
{
@@ -268,8 +229,7 @@ namespace SIG.Web.Pages.Desarrolladores
protected void Fraccionamientos_Comando(object origen, GridViewCommandEventArgs argumentos)
{
if ((argumentos.CommandName != "AgregarEtapa" && argumentos.CommandName != "VerEtapa") ||
!ValidarDesarrollador())
if (argumentos.CommandName != "AgregarEtapa" || !ValidarDesarrollador())
{
return;
}
@@ -289,19 +249,6 @@ namespace SIG.Web.Pages.Desarrolladores
}
CveFraccionamientoEtapaActual = cveFraccionamiento;
if (argumentos.CommandName == "VerEtapa")
{
int clave = Convert.ToInt32(
GvFraccionamientos.DataKeys[fila.RowIndex].Values["CveFraccionamientoEtapa"]);
if (clave > 0)
{
DetalleEtapa.Cargar(clave);
RegistraScript("SIGPanelLateral.abrir('" + PanelDetalleEtapa.ClientID + "');");
}
return;
}
LitFraccionamientoEtapa.Text = fraccionamiento.Fraccionamiento;
TxtEtapa.Text = string.Empty;
TxtHectareasEtapa.Text = string.Empty;
@@ -380,6 +327,15 @@ namespace SIG.Web.Pages.Desarrolladores
Convert.ToInt32(clave).ToString(CultureInfo.InvariantCulture));
}
protected string ObtenerUrlEtapa(object clave)
{
int cveEtapa = Convert.ToInt32(clave);
return cveEtapa <= 0
? string.Empty
: ResolveUrl("~/Pages/Fraccionamientos/EtapaDetalle.aspx?etapa=" +
cveEtapa.ToString(CultureInfo.InvariantCulture));
}
private void CargarFraccionamientos()
{
var resultado = AppServices.ServicioFraccionamiento.ListarDesarrollos(

View File

@@ -1,4 +1,9 @@
<%@ Page Title="Detalle de etapa" Language="C#" MasterPageFile="~/Site.master"
AutoEventWireup="true" CodeFile="EtapaDetalle.aspx.cs"
Inherits="SIG.Web.Pages.Fraccionamientos.EtapaDetalle" %>
<asp:Content ID="Contenido" ContentPlaceHolderID="C" runat="server" />
<%@ Register TagPrefix="sig" TagName="DetalleEtapa" Src="~/UserControl/DetalleEtapa.ascx" %>
<asp:Content ID="ContenidoPrincipal" ContentPlaceHolderID="C" runat="server">
<sig:DetalleEtapa ID="DetalleEtapa" runat="server" />
</asp:Content>

View File

@@ -1,8 +1,7 @@
using System;
using System.Globalization;
using SIG.Web.AppCode.Configuration;
using SIG.Web.AppCode.Security;
using SIG.Web.AppCode.Infrastructure.WebForms;
using SIG.Web.AppCode.Security;
using SIG.Web.AppCode.Session;
namespace SIG.Web.Pages.Fraccionamientos
{
@@ -10,23 +9,48 @@ namespace SIG.Web.Pages.Fraccionamientos
{
protected void Page_Load(object origen, EventArgs argumentos)
{
int clave;
if (!int.TryParse(Request.QueryString["etapa"], out clave))
if (IsPostBack)
{
return;
}
int cveEtapa;
if (!int.TryParse(Request.QueryString["etapa"], out cveEtapa) || cveEtapa <= 0)
{
Alert("Seleccione una etapa válida.", TipoMensaje.MsgAdvertencia);
return;
}
var consulta = AppServices.ServicioFraccionamiento.ObtenerEtapa(
clave, CurrentUser.CveUsuario, CurrentUser.NombreDominio);
if (!consulta.Success || consulta.Data == null)
DetalleEtapa.Cargar(cveEtapa);
}
protected override void OnPreRender(EventArgs argumentos)
{
base.OnPreRender(argumentos);
var sitio = Master as SIG.Web.Site;
if (sitio == null)
{
Alert(consulta.UserMessage, TipoMensaje.MsgAdvertencia);
return;
}
Response.Redirect(ResolveUrl("~/Pages/Desarrolladores/DesarrolladorDetalle.aspx") +
"?cveCliente=" + consulta.Data.CveCliente.ToString(CultureInfo.InvariantCulture) +
"&etapa=" + clave.ToString(CultureInfo.InvariantCulture), false);
Context.ApplicationInstance.CompleteRequest();
sitio.SetPageNavigation("Detalle de etapa", new[]
{
new BreadcrumbItemModel
{
Texto = "Inicio",
Url = "~/Inicio.aspx"
},
new BreadcrumbItemModel
{
Texto = "Desarrolladores",
Url = "~/Pages/Desarrolladores/Desarrolladores.aspx"
},
new BreadcrumbItemModel
{
Texto = "Detalle de etapa"
}
});
}
}
}

View File

@@ -0,0 +1,7 @@
namespace SIG.Web.Pages.Fraccionamientos
{
public partial class EtapaDetalle
{
protected global::SIG.Web.UserControl.DetalleEtapa UcDetalleEtapa;
}
}

View File

@@ -133,6 +133,7 @@
<Content Include="Pages\Desarrolladores\FacturasCfdi.aspx" />
<Content Include="Pages\Fraccionamientos\Fraccionamientos.aspx" />
<Content Include="Pages\Fraccionamientos\FraccionamientoDetalle.aspx" />
<Content Include="Pages\Fraccionamientos\EtapaDetalle.aspx" />
<Content Include="Pages\Fraccionamientos\PlantillaLotes.ashx" />
<Content Include="Pages\Fraccionamientos\FraccionamientoGis.ashx" />
<Content Include="Site.master" />

BIN
SIG.Web/SIG.Web.zip Normal file

Binary file not shown.

View File

@@ -1,44 +1,543 @@
(function (ventana, documento) {
(function (ventana, documento) {
"use strict";
function inicializar(raiz) {
var cortinas = raiz.querySelectorAll("[data-sig-documentos-cortina]:not([data-sig-documentos-inicializada])");
var menuAbierto = null;
var botonMenuAbierto = null;
var origenMenuAbierto = null;
var eventosMenuRegistrados = false;
function inicializarCortinas(raiz) {
var cortinas = raiz.querySelectorAll(
"[data-sig-documentos-cortina]:not([data-sig-documentos-inicializada])"
);
Array.prototype.forEach.call(cortinas, function (cortina) {
var clave = "documentos-etapa:" + ventana.location.pathname + ":" + cortina.id + ":" +
var clave =
"documentos-etapa:" +
ventana.location.pathname +
":" +
cortina.id +
":" +
cortina.getAttribute("data-sig-documentos-cortina");
try {
var guardado = ventana.sessionStorage.getItem(clave);
if (guardado !== null && cortina.getAttribute("data-sig-documentos-fija") !== "1") {
if (
guardado !== null &&
cortina.getAttribute("data-sig-documentos-fija") !== "1"
) {
cortina.open = guardado === "1";
}
} catch (error) {
// Las cortinas siguen funcionando si el navegador limita el almacenamiento.
}
cortina.addEventListener("toggle", function () {
try {
ventana.sessionStorage.setItem(clave, cortina.open ? "1" : "0");
ventana.sessionStorage.setItem(
clave,
cortina.open ? "1" : "0"
);
} catch (error) {
// No se requiere almacenamiento para abrir o cerrar la cortina.
}
});
cortina.setAttribute("data-sig-documentos-inicializada", "1");
cortina.setAttribute(
"data-sig-documentos-inicializada",
"1"
);
});
}
if (ventana.SIGDocumentosEtapaRegistrado) {
function cerrarMenuAcciones() {
if (!menuAbierto) {
return;
}
if (botonMenuAbierto) {
botonMenuAbierto.setAttribute(
"aria-expanded",
"false"
);
}
menuAbierto.classList.remove(
"sig-menu-acciones-flotante"
);
menuAbierto.removeAttribute("style");
if (
origenMenuAbierto &&
origenMenuAbierto.parentNode
) {
origenMenuAbierto.appendChild(menuAbierto);
} else if (menuAbierto.parentNode) {
menuAbierto.parentNode.removeChild(menuAbierto);
}
menuAbierto = null;
botonMenuAbierto = null;
origenMenuAbierto = null;
}
function obtenerFormulario() {
return documento.querySelector("form");
}
function posicionarMenu(menu, boton) {
var margen = 6;
var separacion = 4;
var rectangulo = boton.getBoundingClientRect();
var anchoVentana =
ventana.innerWidth ||
documento.documentElement.clientWidth;
var altoVentana =
ventana.innerHeight ||
documento.documentElement.clientHeight;
/*
* IMPORTANTE:
*
* Bootstrap puede dejar:
*
* right: 0;
*
* en dropdown-menu-right.
*
* Como este menú se mueve temporalmente al FORM,
* si dejamos left y right al mismo tiempo el menú
* puede estirarse prácticamente a todo el ancho.
*/
menu.style.position = "fixed";
menu.style.display = "block";
menu.style.visibility = "hidden";
menu.style.left = "0px";
menu.style.right = "auto";
menu.style.top = "0px";
menu.style.bottom = "auto";
/*
* El menú debe mantener un ancho compacto.
*/
menu.style.width = "auto";
menu.style.minWidth = "190px";
menu.style.maxWidth = "260px";
menu.style.boxSizing = "border-box";
/*
* Si la ventana es pequeña, permitimos scroll
* dentro del propio menú.
*/
menu.style.maxHeight =
Math.max(
80,
altoVentana - (margen * 2)
) + "px";
menu.style.overflowY = "auto";
menu.style.overflowX = "hidden";
/*
* Después de establecer el ancho correcto
* podemos medirlo.
*/
var anchoMenu = menu.offsetWidth;
var altoMenu = menu.offsetHeight;
var espacioAbajo =
altoVentana -
rectangulo.bottom -
margen;
var espacioArriba =
rectangulo.top -
margen;
var arriba;
/*
* Primero intentamos abrir hacia abajo.
*/
if (altoMenu <= espacioAbajo) {
arriba =
rectangulo.bottom +
separacion;
}
/*
* Si no cabe abajo pero sí arriba,
* abrimos arriba.
*/
else if (altoMenu <= espacioArriba) {
arriba =
rectangulo.top -
altoMenu -
separacion;
}
/*
* Si no cabe completo en ningún lado,
* utilizamos el lado con más espacio.
*/
else if (espacioAbajo >= espacioArriba) {
arriba =
rectangulo.bottom +
separacion;
menu.style.maxHeight =
Math.max(
80,
espacioAbajo - separacion
) + "px";
}
else {
menu.style.maxHeight =
Math.max(
80,
espacioArriba - separacion
) + "px";
altoMenu = Math.min(
menu.offsetHeight,
Math.max(
80,
espacioArriba - separacion
)
);
arriba =
rectangulo.top -
altoMenu -
separacion;
}
/*
* Alineamos el borde derecho del menú
* con el borde derecho del botón.
*/
var izquierda =
rectangulo.right -
anchoMenu;
/*
* Protección del borde izquierdo.
*/
if (izquierda < margen) {
izquierda = margen;
}
/*
* Protección del borde derecho.
*/
if (
izquierda + anchoMenu >
anchoVentana - margen
) {
izquierda = Math.max(
margen,
anchoVentana -
anchoMenu -
margen
);
}
/*
* Protección vertical.
*/
arriba = Math.max(
margen,
Math.min(
arriba,
altoVentana -
margen
)
);
menu.style.left =
izquierda + "px";
/*
* Reafirmamos right:auto porque Bootstrap
* puede traer right:0 desde dropdown-menu-right.
*/
menu.style.right = "auto";
menu.style.top =
arriba + "px";
menu.style.visibility =
"visible";
}
function abrirMenuAcciones(boton) {
var contenedor =
boton.closest(
".sig-menu-acciones"
);
var formulario =
obtenerFormulario();
var menu;
if (
!contenedor ||
!formulario
) {
return;
}
menu =
contenedor.querySelector(
".sig-menu-acciones-lista"
);
if (!menu) {
return;
}
/*
* Si pulsamos nuevamente el mismo botón,
* cerramos el menú.
*/
if (menuAbierto === menu) {
cerrarMenuAcciones();
return;
}
cerrarMenuAcciones();
menuAbierto = menu;
botonMenuAbierto = boton;
origenMenuAbierto = contenedor;
/*
* Sacamos temporalmente el menú del contenedor
* que tiene overflow/scroll.
*
* Así table-responsive no puede cortarlo.
*/
formulario.appendChild(menu);
menu.classList.add(
"sig-menu-acciones-flotante"
);
boton.setAttribute(
"aria-expanded",
"true"
);
posicionarMenu(
menu,
boton
);
}
function registrarEventosMenuAcciones() {
if (eventosMenuRegistrados) {
return;
}
eventosMenuRegistrados = true;
documento.addEventListener(
"click",
function (evento) {
var boton =
evento.target.closest(
".sig-menu-acciones-boton"
);
if (boton) {
evento.preventDefault();
evento.stopPropagation();
abrirMenuAcciones(
boton
);
return;
}
if (
menuAbierto &&
!evento.target.closest(
".sig-menu-acciones-lista"
)
) {
cerrarMenuAcciones();
}
}
);
documento.addEventListener(
"sigvisualizadorabierto",
function (evento) {
var layout =
evento.target.closest(
".sig-documentos-layout"
);
if (!layout) {
return;
}
layout.classList.add(
"sig-documentos-visor-activo"
);
layout.classList.remove(
"sig-documentos-visor-expandido"
);
cerrarMenuAcciones();
}
);
documento.addEventListener(
"sigvisualizadorcerrado",
function (evento) {
var layout =
evento.target.closest(
".sig-documentos-layout"
);
if (!layout) {
return;
}
layout.classList.remove(
"sig-documentos-visor-activo"
);
layout.classList.remove(
"sig-documentos-visor-expandido"
);
}
);
documento.addEventListener(
"sigvisualizadorexpandido",
function (evento) {
var layout =
evento.target.closest(
".sig-documentos-layout"
);
if (!layout) {
return;
}
layout.classList.toggle(
"sig-documentos-visor-expandido",
!!(
evento.detail &&
evento.detail.expandido
)
);
}
);
documento.addEventListener(
"keydown",
function (evento) {
if (evento.key === "Escape") {
cerrarMenuAcciones();
}
}
);
/*
* Si cambia el scroll, cerramos.
*
* Esto evita que el menú flotante quede
* separado del botón que lo abrió.
*/
documento.addEventListener(
"scroll",
cerrarMenuAcciones,
true
);
ventana.addEventListener(
"resize",
cerrarMenuAcciones
);
/*
* Antes de un async postback devolvemos
* el menú a su lugar original.
*/
if (
ventana.Sys &&
ventana.Sys.WebForms &&
ventana.Sys.WebForms.PageRequestManager
) {
ventana.Sys.WebForms
.PageRequestManager
.getInstance()
.add_beginRequest(function () {
cerrarMenuAcciones();
});
}
}
function inicializar(raiz) {
inicializarCortinas(raiz);
registrarEventosMenuAcciones();
}
if (
ventana.SIGDocumentosEtapaRegistrado
) {
return;
}
ventana.SIGDocumentosEtapaRegistrado = true;
if (documento.readyState === "loading") {
documento.addEventListener("DOMContentLoaded", function () {
inicializar(documento);
});
ventana.SIGDocumentosEtapaRegistrado =
true;
if (
documento.readyState === "loading"
) {
documento.addEventListener(
"DOMContentLoaded",
function () {
inicializar(
documento
);
}
);
} else {
inicializar(documento);
inicializar(
documento
);
}
if (ventana.Sys && ventana.Sys.Application) {
ventana.Sys.Application.add_load(function () {
inicializar(documento);
});
/*
* Volver a inicializar después de cada
* partial postback de WebForms.
*/
if (
ventana.Sys &&
ventana.Sys.Application
) {
ventana.Sys.Application.add_load(
function () {
inicializar(
documento
);
}
);
}
}(window, document));
}(window, document));

View File

@@ -0,0 +1,767 @@
(function (ventana, documento) {
"use strict";
var eventosRegistrados = false;
var espacioSvg = "http://www.w3.org/2000/svg";
function texto(elemento, valor) {
if (!elemento) {
return;
}
elemento.textContent = valor || "";
elemento.style.display = valor ? "" : "none";
}
function extension(nombreArchivo) {
var nombre = (nombreArchivo || "").toLowerCase();
var indice = nombre.lastIndexOf(".");
return indice >= 0 ? nombre.substring(indice + 1) : "";
}
function detectarTipo(nombreArchivo, tipoContenido) {
var tipo = (tipoContenido || "").toLowerCase();
var ext = extension(nombreArchivo);
if (tipo === "application/pdf" || ext === "pdf") {
return "pdf";
}
if (tipo.indexOf("image/") === 0 ||
["jpg", "jpeg", "png", "gif", "bmp", "webp", "svg"].indexOf(ext) >= 0) {
return "imagen";
}
if (ext === "gis" || ext === "geojson") {
return "gis";
}
if (["txt", "log", "csv", "xml", "json"].indexOf(ext) >= 0 ||
tipo.indexOf("text/") === 0 ||
tipo.indexOf("application/json") === 0 ||
tipo.indexOf("application/xml") === 0 ||
tipo.indexOf("text/xml") === 0) {
return "texto";
}
if (["doc", "docx", "docm", "dot", "dotx", "dotm", "rtf", "xls", "xlsx", "xlsm", "xlsb", "xlt", "xltx", "xltm", "ppt", "pptx", "pptm", "pps", "ppsx", "ppsm", "pot", "potx", "potm", "odt", "ods", "odp"].indexOf(ext) >= 0 ||
tipo.indexOf("officedocument") >= 0 ||
tipo.indexOf("msword") >= 0 ||
tipo.indexOf("ms-excel") >= 0 ||
tipo.indexOf("ms-powerpoint") >= 0 ||
tipo.indexOf("opendocument") >= 0) {
return "office";
}
return "no-compatible";
}
function emitir(control, nombreEvento, detalle) {
var evento;
if (typeof ventana.CustomEvent === "function") {
evento = new CustomEvent(nombreEvento, {
bubbles: true,
detail: detalle || {}
});
} else {
evento = documento.createEvent("CustomEvent");
evento.initCustomEvent(nombreEvento, true, false, detalle || {});
}
control.dispatchEvent(evento);
}
function abortarSolicitud(control) {
if (control && control._sigVisualizadorSolicitud) {
try {
control._sigVisualizadorSolicitud.abort();
} catch (error) {
// La solicitud pudo haber terminado antes de cancelarse.
}
control._sigVisualizadorSolicitud = null;
}
}
function liberarObjectUrl(control) {
if (control && control._sigVisualizadorObjectUrl) {
try {
ventana.URL.revokeObjectURL(control._sigVisualizadorObjectUrl);
} catch (error) {
// La limpieza del object URL no debe interrumpir el visor.
}
control._sigVisualizadorObjectUrl = null;
}
}
function limpiarVista(control) {
var pdf;
var imagen;
var textoPlano;
var gis;
var mensaje;
if (!control) {
return;
}
abortarSolicitud(control);
liberarObjectUrl(control);
pdf = control.querySelector("[data-sig-visualizador-pdf]");
imagen = control.querySelector("[data-sig-visualizador-imagen]");
textoPlano = control.querySelector("[data-sig-visualizador-texto]");
gis = control.querySelector("[data-sig-visualizador-gis]");
mensaje = control.querySelector("[data-sig-visualizador-mensaje]");
if (pdf) {
pdf.removeAttribute("src");
pdf.style.display = "none";
}
if (imagen) {
imagen.removeAttribute("src");
imagen.style.display = "none";
}
if (textoPlano) {
textoPlano.textContent = "";
textoPlano.style.display = "none";
}
if (gis) {
while (gis.firstChild) {
gis.removeChild(gis.firstChild);
}
gis.style.display = "none";
}
if (mensaje) {
mensaje.style.display = "none";
}
}
function mostrarMensaje(control, icono, mensaje) {
var contenedor = control.querySelector("[data-sig-visualizador-mensaje]");
var iconoElemento = contenedor ?
contenedor.querySelector(".sig-visualizador-archivo-mensaje-icono") : null;
var textoElemento = control.querySelector("[data-sig-visualizador-mensaje-texto]");
if (!contenedor) {
return;
}
if (iconoElemento) {
iconoElemento.className = "sig-visualizador-archivo-mensaje-icono fa " + icono;
}
if (textoElemento) {
textoElemento.textContent = mensaje;
}
contenedor.style.display = "flex";
}
function aplicarAcciones(control, datos) {
var descargar = control.querySelector("[data-sig-visualizador-descargar]");
var expandir = control.querySelector("[data-sig-visualizador-expandir]");
var permitirDescarga = control.getAttribute("data-sig-visualizador-permitir-descarga") !== "0";
var permitirExpandir = control.getAttribute("data-sig-visualizador-permitir-expandir") !== "0";
if (descargar) {
descargar.style.display = permitirDescarga && datos.urlDescarga ? "" : "none";
if (datos.urlDescarga) {
descargar.setAttribute("href", datos.urlDescarga);
} else {
descargar.removeAttribute("href");
}
}
if (expandir) {
expandir.style.display = permitirExpandir ? "" : "none";
}
}
function crearSolicitud(control, url, tipoRespuesta, alCompletar, alError) {
var solicitud = new XMLHttpRequest();
control._sigVisualizadorSolicitud = solicitud;
solicitud.open("GET", url, true);
solicitud.withCredentials = true;
if (tipoRespuesta) {
solicitud.responseType = tipoRespuesta;
}
solicitud.onreadystatechange = function () {
if (solicitud.readyState !== 4) {
return;
}
if (control._sigVisualizadorSolicitud === solicitud) {
control._sigVisualizadorSolicitud = null;
}
if (solicitud.status >= 200 && solicitud.status < 300) {
alCompletar(solicitud);
return;
}
alError(solicitud);
};
solicitud.onerror = function () {
if (control._sigVisualizadorSolicitud === solicitud) {
control._sigVisualizadorSolicitud = null;
}
alError(solicitud);
};
solicitud.send();
return solicitud;
}
function mostrarPdf(control, url) {
var pdf = control.querySelector("[data-sig-visualizador-pdf]");
if (!pdf) {
return;
}
pdf.setAttribute("src", url);
pdf.style.display = "block";
}
function mostrarImagen(control, datos) {
var imagen = control.querySelector("[data-sig-visualizador-imagen]");
if (!imagen) {
return;
}
imagen.setAttribute("src", datos.url);
imagen.setAttribute(
"alt",
datos.titulo || datos.nombreArchivo || "Vista previa del archivo");
imagen.style.display = "block";
}
function cargarOffice(control, datos) {
mostrarMensaje(
control,
"fa-spinner fa-spin",
"Generando vista previa del archivo de Office...");
crearSolicitud(
control,
datos.url,
"blob",
function (solicitud) {
var tipo = (solicitud.getResponseHeader("Content-Type") || "").toLowerCase();
var blob = solicitud.response;
if (!blob || tipo.indexOf("application/pdf") < 0) {
mostrarMensaje(
control,
"fa-file-o",
"No fue posible generar la vista previa de este archivo de Office. Puede descargar el archivo original.");
return;
}
limpiarVista(control);
control._sigVisualizadorObjectUrl = ventana.URL.createObjectURL(blob);
mostrarPdf(control, control._sigVisualizadorObjectUrl);
},
function () {
mostrarMensaje(
control,
"fa-file-o",
"No fue posible generar la vista previa de este archivo de Office. Puede descargar el archivo original.");
});
}
function normalizarTextoVistaPrevia(nombreArchivo, contenido) {
var ext = extension(nombreArchivo);
var valor = String(contenido || "").replace(/^\uFEFF/, "");
if (ext === "json") {
try {
return JSON.stringify(JSON.parse(valor), null, 2);
} catch (error) {
return valor;
}
}
return valor;
}
function cargarTexto(control, datos) {
mostrarMensaje(
control,
"fa-spinner fa-spin",
"Cargando vista previa del archivo...");
crearSolicitud(
control,
datos.url,
"text",
function (solicitud) {
var pre = control.querySelector("[data-sig-visualizador-texto]");
if (!pre) {
return;
}
limpiarVista(control);
pre.textContent = normalizarTextoVistaPrevia(
datos.nombreArchivo,
solicitud.responseText);
pre.style.display = "block";
},
function () {
mostrarMensaje(
control,
"fa-file-text-o",
"No fue posible cargar la vista previa del archivo de texto. Puede descargar el archivo.");
});
}
function esNumero(valor) {
return typeof valor === "number" && isFinite(valor);
}
function recorrerCoordenadas(valor, callback) {
var indice;
if (!Array.isArray(valor)) {
return;
}
if (valor.length >= 2 && esNumero(valor[0]) && esNumero(valor[1])) {
callback(valor[0], valor[1]);
return;
}
for (indice = 0; indice < valor.length; indice++) {
recorrerCoordenadas(valor[indice], callback);
}
}
function obtenerNombreFeature(feature, indice) {
var propiedades = feature && feature.properties ? feature.properties : {};
return propiedades.Nombre ||
propiedades.nombre ||
propiedades.Numero ||
propiedades.numero ||
propiedades.Lote ||
propiedades.lote ||
(feature && feature.id !== undefined && feature.id !== null
? String(feature.id)
: "Polígono " + (indice + 1));
}
function validarGeoJson(valor) {
var features;
var validas = [];
if (!valor || valor.type !== "FeatureCollection" || !Array.isArray(valor.features)) {
throw new Error("El archivo GIS no contiene un GeoJSON FeatureCollection válido.");
}
features = valor.features;
features.forEach(function (feature) {
var geometria = feature && feature.geometry;
if (!geometria) {
return;
}
if (geometria.type === "Polygon" || geometria.type === "MultiPolygon") {
validas.push(feature);
}
});
if (!validas.length) {
throw new Error("El archivo GIS no contiene geometrías Polygon o MultiPolygon para visualizar.");
}
return validas;
}
function crearProyeccion(features, ancho, alto, margen) {
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
features.forEach(function (feature) {
recorrerCoordenadas(feature.geometry.coordinates, function (x, y) {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
});
});
if (!isFinite(minX) || !isFinite(minY) || !isFinite(maxX) || !isFinite(maxY)) {
throw new Error("No fue posible obtener coordenadas válidas del archivo GIS.");
}
var rangoX = Math.max(maxX - minX, 0.0000001);
var rangoY = Math.max(maxY - minY, 0.0000001);
var escala = Math.min(
(ancho - (margen * 2)) / rangoX,
(alto - (margen * 2)) / rangoY);
var anchoDibujo = rangoX * escala;
var altoDibujo = rangoY * escala;
var offsetX = (ancho - anchoDibujo) / 2;
var offsetY = (alto - altoDibujo) / 2;
return function (x, y) {
return {
x: offsetX + ((x - minX) * escala),
y: alto - offsetY - ((y - minY) * escala)
};
};
}
function anilloAPath(anillo, proyectar) {
var partes = [];
(anillo || []).forEach(function (coordenada, indice) {
if (!Array.isArray(coordenada) || coordenada.length < 2 ||
!esNumero(coordenada[0]) || !esNumero(coordenada[1])) {
return;
}
var punto = proyectar(coordenada[0], coordenada[1]);
partes.push((indice === 0 ? "M" : "L") + punto.x.toFixed(2) + " " + punto.y.toFixed(2));
});
if (partes.length) {
partes.push("Z");
}
return partes.join(" ");
}
function geometriaAPath(geometria, proyectar) {
var partes = [];
var poligonos;
if (geometria.type === "Polygon") {
poligonos = [geometria.coordinates];
} else if (geometria.type === "MultiPolygon") {
poligonos = geometria.coordinates;
} else {
return "";
}
poligonos.forEach(function (poligono) {
(poligono || []).forEach(function (anillo) {
var path = anilloAPath(anillo, proyectar);
if (path) {
partes.push(path);
}
});
});
return partes.join(" ");
}
function centroFeature(feature, proyectar) {
var sumaX = 0;
var sumaY = 0;
var total = 0;
recorrerCoordenadas(feature.geometry.coordinates, function (x, y) {
var punto = proyectar(x, y);
sumaX += punto.x;
sumaY += punto.y;
total++;
});
return total > 0
? { x: sumaX / total, y: sumaY / total }
: null;
}
function renderizarGis(control, valor) {
var contenedor = control.querySelector("[data-sig-visualizador-gis]");
var features = validarGeoJson(valor);
var ancho = 1000;
var alto = 650;
var margen = 35;
var proyectar = crearProyeccion(features, ancho, alto, margen);
var svg;
if (!contenedor) {
return;
}
limpiarVista(control);
svg = documento.createElementNS(espacioSvg, "svg");
svg.setAttribute("viewBox", "0 0 " + ancho + " " + alto);
svg.setAttribute("role", "img");
svg.setAttribute("aria-label", "Vista previa del archivo GIS");
svg.setAttribute("class", "sig-visualizador-archivo-gis-svg");
features.forEach(function (feature, indice) {
var pathTexto = geometriaAPath(feature.geometry, proyectar);
var path;
var centro;
var etiqueta;
if (!pathTexto) {
return;
}
path = documento.createElementNS(espacioSvg, "path");
path.setAttribute("d", pathTexto);
path.setAttribute("class", "sig-visualizador-archivo-gis-poligono");
path.setAttribute("fill-rule", "evenodd");
etiqueta = documento.createElementNS(espacioSvg, "title");
etiqueta.textContent = obtenerNombreFeature(feature, indice);
path.appendChild(etiqueta);
svg.appendChild(path);
centro = centroFeature(feature, proyectar);
if (centro && features.length <= 150) {
etiqueta = documento.createElementNS(espacioSvg, "text");
etiqueta.setAttribute("x", centro.x.toFixed(2));
etiqueta.setAttribute("y", centro.y.toFixed(2));
etiqueta.setAttribute("class", "sig-visualizador-archivo-gis-etiqueta");
etiqueta.textContent = obtenerNombreFeature(feature, indice);
svg.appendChild(etiqueta);
}
});
contenedor.appendChild(svg);
contenedor.style.display = "flex";
}
function cargarGis(control, datos) {
mostrarMensaje(
control,
"fa-spinner fa-spin",
"Cargando vista previa GIS...");
crearSolicitud(
control,
datos.url,
"text",
function (solicitud) {
try {
var contenido = String(solicitud.responseText || "").replace(/^\uFEFF/, "");
renderizarGis(control, JSON.parse(contenido));
} catch (error) {
mostrarMensaje(
control,
"fa-map-o",
error && error.message
? error.message
: "No fue posible interpretar el archivo GIS. Puede descargar el archivo.");
}
},
function () {
mostrarMensaje(
control,
"fa-map-o",
"No fue posible cargar el archivo GIS. Puede descargar el archivo.");
});
}
function mostrar(control, datos) {
var tipo;
if (!control || !datos || !datos.url) {
return;
}
control.classList.add("sig-visualizador-archivo-activo");
control.classList.remove("sig-visualizador-archivo-expandido");
texto(control.querySelector("[data-sig-visualizador-titulo]"), datos.titulo);
texto(control.querySelector("[data-sig-visualizador-descripcion]"), datos.descripcion);
texto(control.querySelector("[data-sig-visualizador-nombre]"), datos.nombreArchivo);
aplicarAcciones(control, datos);
limpiarVista(control);
tipo = detectarTipo(datos.nombreArchivo, datos.tipoContenido);
if (tipo === "pdf") {
mostrarPdf(control, datos.url);
} else if (tipo === "imagen") {
mostrarImagen(control, datos);
} else if (tipo === "office") {
cargarOffice(control, datos);
} else if (tipo === "gis") {
cargarGis(control, datos);
} else if (tipo === "texto") {
cargarTexto(control, datos);
} else {
mostrarMensaje(
control,
"fa-file-o",
"Archivo no soportado para visualización. Puede descargarlo.");
}
emitir(control, "sigvisualizadorabierto", {
tipo: tipo,
nombreArchivo: datos.nombreArchivo || ""
});
}
function cerrar(control) {
if (!control) {
return;
}
limpiarVista(control);
control.classList.remove("sig-visualizador-archivo-activo");
control.classList.remove("sig-visualizador-archivo-expandido");
emitir(control, "sigvisualizadorcerrado", {});
}
function alternarExpandido(control) {
var expandido;
var boton;
var icono;
if (!control) {
return;
}
expandido = !control.classList.contains("sig-visualizador-archivo-expandido");
control.classList.toggle("sig-visualizador-archivo-expandido", expandido);
boton = control.querySelector("[data-sig-visualizador-expandir]");
icono = boton ? boton.querySelector("i") : null;
if (boton) {
boton.setAttribute("title", expandido ? "Restaurar visor" : "Expandir visor");
boton.setAttribute("aria-label", expandido ? "Restaurar visor" : "Expandir visor");
}
if (icono) {
icono.className = "fa " + (expandido ? "fa-compress" : "fa-expand");
}
emitir(control, "sigvisualizadorexpandido", {
expandido: expandido
});
}
function obtenerDatosDisparador(disparador) {
return {
titulo: disparador.getAttribute("data-sig-visualizador-titulo") || "",
descripcion: disparador.getAttribute("data-sig-visualizador-descripcion") || "",
nombreArchivo: disparador.getAttribute("data-sig-visualizador-nombre") || "",
tipoContenido: disparador.getAttribute("data-sig-visualizador-tipo-contenido") || "",
url: disparador.getAttribute("data-sig-visualizador-url") || disparador.getAttribute("href") || "",
urlDescarga: disparador.getAttribute("data-sig-visualizador-url-descarga") || disparador.getAttribute("href") || ""
};
}
function encontrarVisualizador(disparador) {
var destino = disparador.getAttribute("data-sig-visualizador-destino");
var contexto;
if (destino) {
return documento.getElementById(destino);
}
contexto = disparador.closest("[data-sig-visualizador-contexto]");
return contexto ? contexto.querySelector("[data-sig-visualizador-archivo]") : null;
}
function inicializarControl(control) {
var activoInicial;
if (!control || control.getAttribute("data-sig-visualizador-inicializado") === "1") {
return;
}
control.setAttribute("data-sig-visualizador-inicializado", "1");
activoInicial = control.getAttribute("data-sig-visualizador-activo-inicial") === "1";
if (activoInicial) {
mostrar(control, {
titulo: control.getAttribute("data-sig-visualizador-titulo-inicial") || "",
descripcion: control.getAttribute("data-sig-visualizador-descripcion-inicial") || "",
nombreArchivo: control.getAttribute("data-sig-visualizador-nombre-inicial") || "",
tipoContenido: control.getAttribute("data-sig-visualizador-tipo-contenido-inicial") || "",
url: control.getAttribute("data-sig-visualizador-url-inicial") || "",
urlDescarga: control.getAttribute("data-sig-visualizador-url-descarga-inicial") || ""
});
}
}
function inicializar(raiz) {
var controles = (raiz || documento).querySelectorAll(
"[data-sig-visualizador-archivo]:not([data-sig-visualizador-inicializado='1'])"
);
Array.prototype.forEach.call(controles, inicializarControl);
}
function registrarEventos() {
if (eventosRegistrados) {
return;
}
eventosRegistrados = true;
documento.addEventListener("click", function (evento) {
var disparador = evento.target.closest("[data-sig-visualizador-abrir]");
var cerrarBoton = evento.target.closest("[data-sig-visualizador-cerrar]");
var expandirBoton = evento.target.closest("[data-sig-visualizador-expandir]");
var control;
if (disparador) {
control = encontrarVisualizador(disparador);
if (!control) {
return;
}
evento.preventDefault();
mostrar(control, obtenerDatosDisparador(disparador));
return;
}
if (cerrarBoton) {
evento.preventDefault();
cerrar(cerrarBoton.closest("[data-sig-visualizador-archivo]"));
return;
}
if (expandirBoton) {
evento.preventDefault();
alternarExpandido(expandirBoton.closest("[data-sig-visualizador-archivo]"));
}
});
}
ventana.SIGVisualizadorArchivo = {
inicializar: inicializar,
mostrar: mostrar,
cerrar: cerrar,
alternarExpandido: alternarExpandido
};
registrarEventos();
if (documento.readyState === "loading") {
documento.addEventListener("DOMContentLoaded", function () {
inicializar(documento);
});
} else {
inicializar(documento);
}
if (ventana.Sys && ventana.Sys.Application) {
ventana.Sys.Application.add_load(function () {
inicializar(documento);
});
}
}(window, document));

View File

@@ -0,0 +1 @@
<%@ WebHandler Language="C#" Class="SIG.Web.AppCode.SigControls.SigVisualizadorArchivoHandler" %>

View File

@@ -1,9 +1,16 @@
.etapa-seccion {
.etapa-seccion {
padding: 20px 0;
}
.etapa-accion {
padding-top: 24px;
}
.etapa-contexto {
margin-bottom: 20px;
.sig-etapa-detalle-pagina {
width: 100%;
min-width: 0;
}
.sig-etapa-detalle-pagina .sig-documentos-layout {
width: 100%;
}

View File

@@ -1,4 +1,5 @@
.sig-documentos-etapa > .btn {
.sig-documentos-etapa > .btn,
.sig-documentos-listado > .btn {
margin-bottom: 16px;
}
.sig-documentos-cortina {
@@ -29,3 +30,112 @@
color: #c0392b;
font-weight: 600;
}
/* ============================================================
MENÚ FLOTANTE DE ACCIONES
============================================================ */
.sig-menu-acciones {
display: inline-block;
position: relative;
}
.sig-menu-acciones-boton {
width: 28px;
height: 28px;
padding: 0;
line-height: 26px;
text-align: center;
}
.sig-menu-acciones-lista {
display: none;
}
.sig-menu-acciones-lista.sig-menu-acciones-flotante {
display: block;
min-width: 210px;
max-width: calc(100vw - 12px);
margin: 0;
overflow-x: hidden;
overflow-y: auto;
z-index: 10060;
}
.sig-menu-acciones-lista > li > a {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 14px;
white-space: nowrap;
}
.sig-menu-acciones-lista > li > a > i {
width: 18px;
flex: 0 0 18px;
text-align: center;
}
.sig-menu-acciones-lista > li > a > span {
min-width: 0;
}
/* ============================================================
LAYOUT DOCUMENTOS + VISUALIZADOR
============================================================ */
.sig-documentos-layout {
min-width: 0;
}
.sig-documentos-listado,
.sig-documentos-visualizador {
min-width: 0;
}
.sig-documentos-visualizador {
display: none;
}
.sig-documentos-layout.sig-documentos-visor-activo {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
align-items: start;
}
.sig-documentos-layout.sig-documentos-visor-activo .sig-documentos-visualizador {
display: block;
}
.sig-documentos-layout.sig-documentos-visor-expandido {
grid-template-columns: minmax(0, 1fr);
}
.sig-documentos-layout.sig-documentos-visor-expandido .sig-documentos-listado {
display: none;
}
.sig-documentos-layout.sig-documentos-visor-expandido .sig-documentos-visualizador {
width: 100%;
}
.sig-documentos-layout.sig-documentos-visor-activo .sig-documentos-listado > .table-responsive {
max-height: calc(100vh - 315px);
}
@media (max-width: 991px) {
.sig-documentos-layout.sig-documentos-visor-activo {
display: block;
}
.sig-documentos-layout.sig-documentos-visor-activo .sig-documentos-listado {
display: none;
}
.sig-documentos-layout.sig-documentos-visor-activo .sig-documentos-visualizador {
display: block;
width: 100%;
}
}

View File

@@ -0,0 +1,210 @@
.sig-visualizador-archivo {
display: none;
min-width: 0;
border: 1px solid #e1e5ec;
background: #fff;
}
.sig-visualizador-archivo.sig-visualizador-archivo-activo {
display: flex;
flex-direction: column;
}
.sig-visualizador-archivo-encabezado {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
padding: 12px 14px;
border-bottom: 1px solid #e7ecf1;
background: #f8f9fb;
}
.sig-visualizador-archivo-datos {
min-width: 0;
flex: 1;
}
.sig-visualizador-archivo-titulo {
color: #333;
font-size: 15px;
font-weight: 600;
line-height: 1.35;
overflow-wrap: anywhere;
}
.sig-visualizador-archivo-descripcion {
margin-top: 3px;
color: #667;
font-size: 13px;
line-height: 1.35;
overflow-wrap: anywhere;
}
.sig-visualizador-archivo-nombre {
margin-top: 3px;
color: #8a8a8a;
font-size: 12px;
line-height: 1.35;
overflow-wrap: anywhere;
}
.sig-visualizador-archivo-acciones {
display: flex;
align-items: center;
flex: 0 0 auto;
gap: 5px;
}
.sig-visualizador-archivo-acciones .btn {
min-width: 32px;
padding-left: 8px;
padding-right: 8px;
}
.sig-visualizador-archivo-descargar {
display: inline-flex;
align-items: center;
gap: 6px;
}
.sig-visualizador-archivo-cuerpo {
position: relative;
display: flex;
align-items: stretch;
justify-content: center;
min-height: 460px;
height: calc(100vh - 300px);
max-height: 820px;
overflow: auto;
background: #eef1f5;
}
.sig-visualizador-archivo-pdf,
.sig-visualizador-archivo-imagen,
.sig-visualizador-archivo-texto,
.sig-visualizador-archivo-gis,
.sig-visualizador-archivo-mensaje {
display: none;
}
.sig-visualizador-archivo-pdf {
width: 100%;
height: 100%;
min-height: 460px;
border: 0;
background: #fff;
}
.sig-visualizador-archivo-imagen {
align-self: flex-start;
max-width: 100%;
max-height: 100%;
margin: auto;
object-fit: contain;
}
.sig-visualizador-archivo-texto {
box-sizing: border-box;
width: 100%;
min-height: 460px;
margin: 0;
padding: 16px;
overflow: auto;
border: 0;
background: #fff;
color: #2f353b;
font-family: Consolas, "Courier New", monospace;
font-size: 13px;
line-height: 1.45;
text-align: left;
white-space: pre;
tab-size: 4;
}
.sig-visualizador-archivo-gis {
box-sizing: border-box;
width: 100%;
min-height: 460px;
padding: 12px;
align-items: center;
justify-content: center;
overflow: auto;
background: #f4f6f8;
}
.sig-visualizador-archivo-gis-svg {
display: block;
width: 100%;
min-width: 520px;
height: auto;
max-height: 100%;
background: #fff;
border: 1px solid #d9dfe5;
}
.sig-visualizador-archivo-gis-poligono {
fill: rgba(53, 152, 220, 0.18);
stroke: #2f7ca8;
stroke-width: 1.5;
vector-effect: non-scaling-stroke;
}
.sig-visualizador-archivo-gis-poligono:hover {
fill: rgba(53, 152, 220, 0.30);
}
.sig-visualizador-archivo-gis-etiqueta {
fill: #34495e;
font-size: 12px;
font-family: Arial, sans-serif;
text-anchor: middle;
dominant-baseline: middle;
pointer-events: none;
}
.sig-visualizador-archivo-mensaje {
width: 100%;
min-height: 320px;
padding: 30px;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 12px;
color: #6f7b86;
text-align: center;
}
.sig-visualizador-archivo-mensaje-icono {
font-size: 48px;
}
.sig-visualizador-archivo-mensaje-texto {
max-width: 480px;
font-size: 14px;
line-height: 1.5;
}
.sig-visualizador-archivo.sig-visualizador-archivo-expandido .sig-visualizador-archivo-cuerpo {
height: calc(100vh - 225px);
max-height: none;
}
@media (max-width: 767px) {
.sig-visualizador-archivo-encabezado {
flex-direction: column;
}
.sig-visualizador-archivo-acciones {
width: 100%;
justify-content: flex-end;
}
.sig-visualizador-archivo-cuerpo,
.sig-visualizador-archivo-pdf,
.sig-visualizador-archivo-texto,
.sig-visualizador-archivo-gis {
min-height: 420px;
height: 65vh;
}
}

View File

@@ -20,9 +20,6 @@
<asp:UpdatePanel ID="UpContexto" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
<ContentTemplate>
<asp:Panel ID="PnlDetalle" runat="server" Visible="false">
<div class="etapa-contexto">
<asp:Literal ID="LitContexto" runat="server" Mode="Encode" />
</div>
<ajax:TabContainer ID="PestanasEtapa" runat="server" ActiveTabIndex="0">
<ajax:TabPanel ID="PestanaDatos" runat="server" HeaderText="Datos de la etapa">
<ContentTemplate>

View File

@@ -83,7 +83,7 @@ namespace SIG.Web.UserControl
_etapa = consulta.Data;
PnlDetalle.Visible = true;
LitContexto.Text = desarrollador.Data.Nombre + " / Etapa: " + _etapa.Etapa;
string descripcionEtapa = desarrollador.Data.Nombre + " / Etapa: " + _etapa.Etapa;
UcSupervisiones.CveFraccionamiento = _etapa.CveFraccionamiento;
UcSupervisiones.CveFraccionamientoEtapa = CveEtapaActual;
@@ -101,7 +101,7 @@ namespace SIG.Web.UserControl
UcConvenios.Cargar(new FiltroConvenios { CveFraccionamientoEtapa = CveEtapaActual });
CargarCondiciones();
BuscadorEtapas.SelectedValue = CveEtapaActual.ToString(CultureInfo.InvariantCulture);
BuscadorEtapas.Text = LitContexto.Text;
BuscadorEtapas.Text = descripcionEtapa;
}
}
@@ -367,8 +367,7 @@ namespace SIG.Web.UserControl
if (accion == "EnviarRevision")
{
return CurrentUser.EsDesarrollador &&
tramite.PuedeCambiarEstatus &&
return tramite.PuedeCambiarEstatus &&
tramite.EsEstatusCliente &&
!tramite.EsEstatusOk;
}

View File

@@ -1,624 +1,290 @@
<%@ Control Language="C#" AutoEventWireup="false" CodeFile="DocumentosEtapa.ascx.cs"
<%@ Control Language="C#" AutoEventWireup="false" CodeFile="DocumentosEtapa.ascx.cs"
Inherits="SIG.Web.UserControl.DocumentosEtapa" %>
<asp:UpdatePanel ID="Listado" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<div class="sig-documentos-etapa">
<asp:LinkButton
ID="SolicitarDocumento"
runat="server"
Text="Solicitar documento"
CssClass="btn blue"
CausesValidation="false"
OnClick="AbrirSolicitud" />
<div class="sig-documentos-etapa" data-sig-visualizador-contexto>
<div class="sig-documentos-layout">
<div class="sig-documentos-listado" data-sig-documentos-listado>
<asp:LinkButton ID="SolicitarDocumento" runat="server" Text="Solicitar documento"
CssClass="btn blue" CausesValidation="false" OnClick="AbrirSolicitud" />
<asp:Literal
ID="MensajeVacio"
runat="server"
Mode="Encode" />
<asp:Literal ID="MensajeVacio" runat="server" Mode="Encode" />
<div class="table-responsive">
<asp:GridView
ID="Documentos"
runat="server"
AutoGenerateColumns="false"
GridLines="None"
CssClass="table table-hover Widthall sig-grid-agrupado"
DataKeyNames="CveFraccionamientoEtapa,CveTipoDocumento,CveDocumentoSolicitud,EsGrupo"
OnRowDataBound="EnlazarFilaDocumento"
OnRowCommand="ComandoDocumento"
EmptyDataText="No hay documentos para mostrar.">
<Columns>
<asp:TemplateField
HeaderStyle-CssClass="sig-grid-columna-grupo"
ItemStyle-CssClass="sig-grid-columna-grupo">
<ItemTemplate>
<button
type="button"
class="sig-grid-alternar-grupo"
aria-expanded="true">
<span class="sig-grid-grupo-titulo">
<%#: Eval("TituloGrupo") %>
<div class="table-responsive">
<asp:GridView ID="Documentos" runat="server"
AutoGenerateColumns="false"
GridLines="None"
CssClass="table table-hover Widthall sig-grid-agrupado"
DataKeyNames="CveFraccionamientoEtapa,CveTipoDocumento,CveDocumentoSolicitud,EsGrupo"
OnRowDataBound="EnlazarFilaDocumento"
OnRowCommand="ComandoDocumento"
EmptyDataText="No hay documentos para mostrar.">
<Columns>
<asp:TemplateField HeaderStyle-CssClass="sig-grid-columna-grupo"
ItemStyle-CssClass="sig-grid-columna-grupo">
<ItemTemplate>
<button type="button" class="sig-grid-alternar-grupo" aria-expanded="true">
<span class="sig-grid-grupo-titulo"><%#: Eval("TituloGrupo") %></span>
<i class="fa fa-chevron-up sig-grid-icono-agrupacion" aria-hidden="true"></i>
</button>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="TipoDocumento" HeaderText="Documento"
ItemStyle-CssClass="sig-grid-columna-dato-principal" />
<asp:BoundField DataField="Responsable" HeaderText="Responsable" />
<asp:CheckBoxField DataField="EsRequerido" HeaderText="Requerido" />
<asp:BoundField DataField="EstadoDocumento" HeaderText="Estado" />
<asp:TemplateField HeaderText="Aprobado">
<ItemTemplate>
<%#: TextoAprobacion(Container.DataItem) %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Vencimiento">
<ItemTemplate>
<span class='<%# FechaExpirada(Container.DataItem) ? "sig-documentos-fecha-vencida" : "" %>'>
<%#: TextoFechaVencimiento(Container.DataItem) %>
</span>
<i
class="fa fa-chevron-up sig-grid-icono-agrupacion"
aria-hidden="true">
</i>
</button>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField
DataField="TipoDocumento"
HeaderText="Documento"
ItemStyle-CssClass="sig-grid-columna-dato-principal" />
<asp:BoundField
DataField="Responsable"
HeaderText="Responsable" />
<asp:CheckBoxField
DataField="EsRequerido"
HeaderText="Requerido" />
<asp:BoundField
DataField="EstadoDocumento"
HeaderText="Estado" />
<asp:TemplateField HeaderText="Aprobado">
<ItemTemplate>
<%#: TextoAprobacion(Container.DataItem) %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Vencimiento">
<ItemTemplate>
<span class='<%# FechaExpirada(Container.DataItem)
? "sig-documentos-fecha-vencida"
: "" %>'>
<%#: TextoFechaVencimiento(Container.DataItem) %>
</span>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField
DataField="Nota"
HeaderText="Nota / motivo" />
<asp:TemplateField
HeaderText="Acciones"
HeaderStyle-CssClass="sig-columna-acciones"
ItemStyle-CssClass="sig-columna-acciones">
<ItemTemplate>
<asp:PlaceHolder
runat="server"
Visible='<%#
MostrarAccion(Container.DataItem, "Descargar") ||
MostrarAccion(Container.DataItem, "AdministrarGis") ||
MostrarAccion(Container.DataItem, "Cargar") ||
MostrarAccion(Container.DataItem, "Aprobar") ||
MostrarAccion(Container.DataItem, "CancelarDocumento") ||
MostrarAccion(Container.DataItem, "QuitarRequerido") ||
MostrarAccion(Container.DataItem, "ActivarRequerido") ||
MostrarAccion(Container.DataItem, "EditarVencimiento") ||
MostrarAccion(Container.DataItem, "Eliminar")
%>'>
<div class="dropdown">
<button
type="button"
class="btn btn-circle btn-sm default dropdown-toggle sig-accion-icono"
data-toggle="dropdown"
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Nota" HeaderText="Nota / motivo" />
<asp:TemplateField HeaderText="Acciones"
HeaderStyle-CssClass="sig-columna-acciones"
ItemStyle-CssClass="sig-columna-acciones">
<ItemTemplate>
<asp:Panel runat="server"
CssClass="sig-menu-acciones"
Visible='<%# MostrarAccion(Container.DataItem, "Ver") || MostrarAccion(Container.DataItem, "AdministrarGis") || MostrarAccion(Container.DataItem, "Cargar") || MostrarAccion(Container.DataItem, "Aprobar") || MostrarAccion(Container.DataItem, "CancelarDocumento") || MostrarAccion(Container.DataItem, "QuitarRequerido") || MostrarAccion(Container.DataItem, "ActivarRequerido") || MostrarAccion(Container.DataItem, "EditarVencimiento") || MostrarAccion(Container.DataItem, "Eliminar") %>'>
<button type="button"
class="btn btn-circle btn-sm default sig-accion-icono sig-menu-acciones-boton"
title="Acciones"
aria-label="Acciones"
aria-haspopup="true"
aria-expanded="false">
<i
class="fa fa-ellipsis-v"
aria-hidden="true">
</i>
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<asp:PlaceHolder
runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "Descargar") %>'>
<li>
<asp:HyperLink
runat="server"
ToolTip="Descargar"
aria-label="Descargar"
NavigateUrl='<%# UrlDocumento(
ClaveDocumento(Container.DataItem)) %>'>
<i
class="fa fa-download"
aria-hidden="true">
</i>
Descargar
</asp:HyperLink>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<ul class="dropdown-menu dropdown-menu-right sig-menu-acciones-lista"
role="menu">
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "Ver") %>'>
<asp:HyperLink runat="server"
ToolTip="Ver archivo"
aria-label="Ver archivo"
NavigateUrl='<%# UrlDocumento(ClaveDocumento(Container.DataItem)) %>'
data-sig-visualizador-abrir="1"
data-sig-visualizador-destino='<%# VisualizadorDocumento.ClientID %>'
data-sig-visualizador-titulo='<%# Eval("TipoDocumento") %>'
data-sig-visualizador-descripcion='<%# Eval("TipoTramite") %>'
data-sig-visualizador-nombre='<%# Eval("NombreArchivo") %>'
data-sig-visualizador-url='<%# UrlDocumentoVista(ClaveDocumento(Container.DataItem)) %>'
data-sig-visualizador-url-descarga='<%# UrlDocumento(ClaveDocumento(Container.DataItem)) %>'>
<i class="fa fa-eye" aria-hidden="true"></i>
<span>Ver</span>
</asp:HyperLink>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "AdministrarGis") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="AdministrarGis"
CausesValidation="false"
ToolTip="Administrar GIS"
aria-label="Administrar GIS">
<i
class="fa fa-map-marker"
aria-hidden="true">
</i>
Administrar GIS
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="AdministrarGis"
CausesValidation="false"
ToolTip="Administrar GIS"
aria-label="Administrar GIS">
<i class="fa fa-map-marker" aria-hidden="true"></i>
<span>Administrar GIS</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "Cargar") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="Cargar"
CausesValidation="false"
ToolTip="Cargar / renovar"
aria-label="Cargar / renovar">
<i
class="fa fa-upload"
aria-hidden="true">
</i>
Cargar / renovar
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="Cargar"
CausesValidation="false"
ToolTip="Cargar / renovar"
aria-label="Cargar / renovar">
<i class="fa fa-upload" aria-hidden="true"></i>
<span>Cargar / renovar</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "Aprobar") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="Aprobar"
CausesValidation="false"
ToolTip="Aprobar"
aria-label="Aprobar">
<i
class="fa fa-check"
aria-hidden="true">
</i>
Aprobar
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="Aprobar"
CausesValidation="false"
ToolTip="Aprobar"
aria-label="Aprobar">
<i class="fa fa-check" aria-hidden="true"></i>
<span>Aprobar</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "CancelarDocumento") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="CancelarDocumento"
CausesValidation="false"
ToolTip="Cancelar documento"
aria-label="Cancelar documento">
<i
class="fa fa-ban"
aria-hidden="true">
</i>
Cancelar documento
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="CancelarDocumento"
CausesValidation="false"
ToolTip="Cancelar documento"
aria-label="Cancelar documento">
<i class="fa fa-ban" aria-hidden="true"></i>
<span>Cancelar documento</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "QuitarRequerido") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="QuitarRequerido"
CausesValidation="false"
ToolTip="Quitar requerido"
aria-label="Quitar requerido">
<i
class="fa fa-times"
aria-hidden="true">
</i>
Quitar requerido
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="QuitarRequerido"
CausesValidation="false"
ToolTip="Quitar requerido"
aria-label="Quitar requerido">
<i class="fa fa-times" aria-hidden="true"></i>
<span>Quitar requerido</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "ActivarRequerido") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="ActivarRequerido"
CausesValidation="false"
ToolTip="Marcar como requerido"
aria-label="Marcar como requerido">
<i
class="fa fa-check"
aria-hidden="true">
</i>
Marcar como requerido
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="ActivarRequerido"
CausesValidation="false"
ToolTip="Marcar como requerido"
aria-label="Marcar como requerido">
<i class="fa fa-check" aria-hidden="true"></i>
<span>Marcar como requerido</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "EditarVencimiento") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="EditarVencimiento"
CausesValidation="false"
ToolTip="Editar fecha de vencimiento"
aria-label="Editar fecha de vencimiento">
<i
class="fa fa-calendar"
aria-hidden="true">
</i>
Editar vencimiento
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:PlaceHolder
runat="server"
<asp:LinkButton runat="server"
CommandName="EditarVencimiento"
CausesValidation="false"
ToolTip="Editar fecha de vencimiento"
aria-label="Editar fecha de vencimiento">
<i class="fa fa-calendar" aria-hidden="true"></i>
<span>Editar vencimiento</span>
</asp:LinkButton>
</li>
<li runat="server"
Visible='<%# MostrarAccion(Container.DataItem, "Eliminar") %>'>
<li>
<asp:LinkButton
runat="server"
CommandName="Eliminar"
CausesValidation="false"
ToolTip="Eliminar"
aria-label="Eliminar"
OnClientClick="return confirm('¿Eliminar la versión vigente? Los trámites que la requieren quedarán pendientes.');">
<i
class="fa fa-trash"
aria-hidden="true">
</i>
Eliminar
</asp:LinkButton>
</li>
</asp:PlaceHolder>
<asp:LinkButton runat="server"
CommandName="Eliminar"
CausesValidation="false"
ToolTip="Eliminar"
aria-label="Eliminar"
OnClientClick="return confirm('¿Eliminar la versión vigente? Los trámites que la requieren quedarán pendientes.');">
<i class="fa fa-trash" aria-hidden="true"></i>
<span>Eliminar</span>
</asp:LinkButton>
</li>
</ul>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
</div>
</div>
</asp:PlaceHolder>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<div class="sig-documentos-visualizador" data-sig-documentos-visualizador>
<sig:SigVisualizadorArchivo
ID="VisualizadorDocumento"
runat="server"
PermitirDescarga="true"
PermitirExpandir="true" />
</div>
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
<div
id="ModalDocumento"
runat="server"
class="modal fade"
tabindex="-1"
role="dialog">
<div id="ModalDocumento" runat="server" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<asp:UpdatePanel
ID="Formulario"
runat="server"
UpdateMode="Conditional"
ChildrenAsTriggers="true">
<asp:UpdatePanel ID="Formulario" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<div class="modal-content">
<div class="modal-header">
<button
type="button"
class="close"
data-dismiss="modal"
aria-label="Cerrar">
</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Cerrar"></button>
<h4>
<asp:Literal
ID="TituloFormulario"
runat="server"
Mode="Encode" />
</h4>
<asp:Literal ID="TituloFormulario" runat="server" Mode="Encode" /></h4>
</div>
<div class="modal-body">
<asp:Panel
ID="CamposSolicitud"
runat="server">
<asp:Panel ID="CamposSolicitud" runat="server">
<div class="form-group">
<asp:Label
runat="server"
AssociatedControlID="EtapaSolicitud"
Text="Etapa" />
<asp:DropDownList
ID="EtapaSolicitud"
runat="server"
CssClass="form-control select2me"
AutoPostBack="true"
OnSelectedIndexChanged="CambiarEtapaSolicitud" />
<asp:Label runat="server" AssociatedControlID="EtapaSolicitud" Text="Etapa" />
<asp:DropDownList ID="EtapaSolicitud" runat="server" CssClass="form-control select2me"
AutoPostBack="true" OnSelectedIndexChanged="CambiarEtapaSolicitud" />
</div>
<div class="form-group">
<asp:Label
runat="server"
AssociatedControlID="TramiteSolicitud"
Text="Trámite asociado (opcional)" />
<asp:DropDownList
ID="TramiteSolicitud"
runat="server"
CssClass="form-control select2me"
AutoPostBack="true"
OnSelectedIndexChanged="CambiarTramiteSolicitud" />
<asp:Label runat="server" AssociatedControlID="TramiteSolicitud" Text="Trámite asociado (opcional)" />
<asp:DropDownList ID="TramiteSolicitud" runat="server" CssClass="form-control select2me"
AutoPostBack="true" OnSelectedIndexChanged="CambiarTramiteSolicitud" />
</div>
<div class="form-group">
<asp:Label
runat="server"
AssociatedControlID="TipoDocumentoSolicitud"
Text="Tipo de documento" />
<asp:DropDownList
ID="TipoDocumentoSolicitud"
runat="server"
CssClass="form-control select2me" />
<asp:Label runat="server" AssociatedControlID="TipoDocumentoSolicitud" Text="Tipo de documento" />
<asp:DropDownList ID="TipoDocumentoSolicitud" runat="server" CssClass="form-control select2me" />
</div>
<asp:CheckBox
ID="TieneVigenciaSolicitud"
runat="server"
Text="Tiene vigencia" />
<asp:CheckBox ID="TieneVigenciaSolicitud" runat="server" Text="Tiene vigencia" />
</asp:Panel>
<asp:Panel
ID="CamposArchivo"
runat="server">
<asp:Panel ID="CamposArchivo" runat="server">
<p>
<asp:Literal
ID="ReglasArchivo"
runat="server"
Mode="Encode" />
<asp:Literal ID="ReglasArchivo" runat="server" Mode="Encode" />
</p>
<div class="form-group">
<label>Archivo</label>
<input
id="Archivo"
runat="server"
type="hidden"
<input id="Archivo" runat="server" type="hidden"
class="ADSdropzoneLocal" />
</div>
<div class="form-group">
<asp:Label
runat="server"
AssociatedControlID="FechaDocumento"
Text="Fecha del documento" />
<asp:TextBox
ID="FechaDocumento"
runat="server"
TextMode="Date"
CssClass="form-control" />
<asp:Label runat="server" AssociatedControlID="FechaDocumento" Text="Fecha del documento" />
<asp:TextBox ID="FechaDocumento" runat="server" TextMode="Date" CssClass="form-control" />
</div>
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="FechaVencimiento" Text="Fecha de vencimiento" />
<asp:TextBox ID="FechaVencimiento" runat="server" TextMode="Date" CssClass="form-control" />
</div>
</asp:Panel>
<asp:Label
runat="server"
AssociatedControlID="FechaVencimiento"
<asp:Panel ID="CamposVencimiento" runat="server">
<div class="form-group">
<asp:Label runat="server" AssociatedControlID="FechaVencimientoEdicion"
Text="Fecha de vencimiento" />
<asp:TextBox
ID="FechaVencimiento"
runat="server"
TextMode="Date"
CssClass="form-control" />
<asp:TextBox ID="FechaVencimientoEdicion" runat="server"
TextMode="Date" CssClass="form-control" />
<p class="help-block">Puede dejarla vacía. Si el documento requiere vigencia, deberá capturarla antes de aprobarlo.</p>
</div>
</asp:Panel>
<asp:Panel
ID="CamposVencimiento"
runat="server">
<div class="form-group">
<asp:Label
runat="server"
AssociatedControlID="FechaVencimientoEdicion"
Text="Fecha de vencimiento" />
<asp:TextBox
ID="FechaVencimientoEdicion"
runat="server"
TextMode="Date"
CssClass="form-control" />
<p class="help-block">
Puede dejarla vacía. Si el documento requiere vigencia,
deberá capturarla antes de aprobarlo.
</p>
</div>
<asp:Panel ID="CamposNota" runat="server">
<asp:Label runat="server" AssociatedControlID="Nota" Text="Nota / motivo" />
<asp:TextBox ID="Nota" runat="server" TextMode="MultiLine" Rows="3" CssClass="form-control" />
</asp:Panel>
<asp:Panel
ID="CamposNota"
runat="server">
<asp:Label
runat="server"
AssociatedControlID="Nota"
Text="Nota / motivo" />
<asp:TextBox
ID="Nota"
runat="server"
TextMode="MultiLine"
Rows="3"
CssClass="form-control" />
</asp:Panel>
</div>
<div class="modal-footer">
<button
type="button"
class="btn default"
data-dismiss="modal">
Cerrar
</button>
<asp:Button
ID="GuardarArchivo"
runat="server"
Text="Guardar archivo"
CssClass="btn blue"
CausesValidation="false"
OnClick="GuardarCarga" />
<asp:Button
ID="GuardarSolicitud"
runat="server"
Text="Solicitar"
CssClass="btn blue"
CausesValidation="false"
OnClick="GuardarRequerimiento" />
<asp:Button
ID="GuardarVencimiento"
runat="server"
Text="Guardar vencimiento"
CssClass="btn blue"
CausesValidation="false"
OnClick="GuardarFechaVencimiento" />
<asp:Button
ID="GuardarCancelacion"
runat="server"
Text="Cancelar documento"
CssClass="btn red"
CausesValidation="false"
OnClick="CancelarDocumento" />
<button type="button" class="btn default" data-dismiss="modal">Cerrar</button>
<asp:Button ID="GuardarArchivo" runat="server" Text="Guardar archivo" CssClass="btn blue"
CausesValidation="false" OnClick="GuardarCarga" />
<asp:Button ID="GuardarSolicitud" runat="server" Text="Solicitar" CssClass="btn blue"
CausesValidation="false" OnClick="GuardarRequerimiento" />
<asp:Button ID="GuardarVencimiento" runat="server" Text="Guardar vencimiento" CssClass="btn blue"
CausesValidation="false" OnClick="GuardarFechaVencimiento" />
<asp:Button ID="GuardarCancelacion" runat="server" Text="Cancelar documento" CssClass="btn red"
CausesValidation="false" OnClick="CancelarDocumento" />
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</div>

View File

@@ -278,6 +278,16 @@ namespace SIG.Web.UserControl
get { return Documento == null ? string.Empty : Documento.TipoDocumento; }
}
public string TipoTramite
{
get { return Documento == null ? string.Empty : (Documento.TipoTramite ?? string.Empty); }
}
public string NombreArchivo
{
get { return Documento == null ? string.Empty : (Documento.NombreArchivo ?? string.Empty); }
}
public string Responsable
{
get { return Documento == null ? string.Empty : Documento.Responsable; }
@@ -382,6 +392,7 @@ namespace SIG.Web.UserControl
switch (accion)
{
case "Ver":
case "Descargar":
return documento.TieneArchivo;
case "AdministrarGis":
@@ -416,6 +427,11 @@ namespace SIG.Web.UserControl
"?fraccionamiento=" + CveFraccionamientoActual + "&documento=" + Convert.ToInt32(clave);
}
protected string UrlDocumentoVista(object clave)
{
return UrlDocumento(clave) + "&vista=1";
}
protected string UrlEtapa(object clave)
{
return ResolveUrl("~/Pages/Fraccionamientos/FraccionamientoDetalle.aspx") +

View File

@@ -25,6 +25,8 @@
<add key="EmailFrom" value="notificaciones@sig.adssistemas.mx" />
<add key="EmailFromDisplayName" value="Agua de Hermosillo" />
<add key="CredencialPacProfactPruebas" value="mvpNUXmQfK8=" />
<add key="GoogleMapsApiKey" value="TU_API_KEY" />
<add key="GoogleMapsEnabled" value="true" />
<!-- reCAPTCHA v2: al desactivarlo no se muestra ni se valida. La clave secreta nunca se envía al navegador. -->
<add key="RecaptchaEnabled" value="true" />
<add key="RecaptchaSiteKey" value="6LeVOFQtAAAAAOxZKnBiKFlnMnd90aR1PwJmUGgJ" />