POST
|
Hi @MK13 ,
This has been implemented. Please check out the $userInput profile variable which allows you to retrieve the geometry of the location the user clicked and drill down to provide information on other features from other layers in the pop-up.
https://developers.arcgis.com/arcade/profiles/popup/#profile-variables
... View more
10-18-2024
12:17 PM
|
2
|
1
|
212
|
BLOG
|
Hi @PROYECTOPIATER2022
It is possible to create interactivity between normal elements in a Dashboard and those that connect to data provided by an Arcade data expression. It all depends on the connection you can establish. Make sure you have some common fields between the two elements and define the action between them.
Español:
Es possible crear una acción entre un elemento definido basado en una capa y un elemento que tiene por debajo una expresión de datos de Arcade. Importante es contar con un campo en común para configurar la acción.
... View more
10-18-2024
12:14 PM
|
1
|
0
|
92
|
BLOG
|
Preguntas de selección múltiple en Survey123 Cuando en una encuesta usamos preguntas de tipo selección múltiple el resultado se guarda en un campo de texto donde los ítems seleccionados se separen con una coma. En el ejemplo abajo el resultado se almacena como “Reducción del CO2 emitido,Ahorro en costos de energía electrica”: Si visualizamos la información en un gráfico de barras el resultado puede verse así y no nos informe de manera fácil cual respuesta es más frecuente: Con una expresión de datos en Arcade es posible crear un conjunto de datos (featureset) en memoria y usar estos datos para un elemento en ArcGIS Dashboards. Al agregar un elemento de “Gráfico de serie” abre la ventana donde debemos seleccionar la capa para alimentar el elemento. En este caso seleccionamos “Nueva expresión de datos”: En el editor de Arcade se puede notar que para una expresión de datos no hay variables de perfil: Es necesario conectarnos a la capa de la encuesta, analizar los datos, crear un esquema para el resultado del análisis y, llenar el esquema y devolverlo como featureset. Una explicación de la expresión Arcade que se puede encontrar al final de este artículo: Línea 2: definir el portal donde están los datos Línea 3: definir una consultar para filtrar datos de interés Línea 4: acceder a la capa de la encuesta y filtrar los datos con la consulta definida Línea 6 a 22: crear un diccionario para almacenar los resultados, recorrer cada registro de la encuesta, separar los motivos de la respuesta de selección múltiple y almacenar el conteo de cada motivo. Línea 24 a 30: crear un esquema de datos con 2 campos y sin geometría. Un campo para registrar el motivo y otro campo para almacenar el conteo Línea 32 a 40: leer los resultados del diccionario y escribirlos al esquema de datos generado anteriormente Línea 43: Devolver el esquema (diccionario) como featureset Al ejecutar la expresión se obtiene un featureset con cada motivo separado y con su respectivo conteo: Así el gráfico que resulta es más fácil de interpretar: El código Arcade // 1: acceder a la capa de proyectos
var spx = Portal('https://utility-esri-co.maps.arcgis.com');
var sql = "Motivo <> ''";
var proyectos = Filter(FeatureSetByPortalItem(spx, 'bf4a31341a5d49be90de6ce471a0b647', 0, ["Motivo"], false), sql);
// 2: crear estadísticas por motivo
var dct = {};
var conteo = 0;
for (var proyecto in proyectos) {
var motivos = proyecto["Motivo"];
var lst = Split(motivos, ',');
for (var i in lst) {
var motivo = lst[i];
if (HasKey(dct, motivo)) {
conteo = dct[motivo]+1;
} else {
conteo = 1;
}
dct[motivo] = conteo;
}
}
Console(Text(dct));
// 3: crear esquema de datos para featureset el resultado
var Dict = {
'fields': [
{'name': 'Motivo', 'type': 'esriFieldTypeString' },
{'name': 'Conteo','type': 'esriFieldTypeInteger'}],
'geometryType': '',
'features': []};
// 4: llenar esquema con el resulatdo del análisis
var index = 0;
for (motivo in dct) {
Dict.features[index] = {
'attributes': {
'Motivo': motivo,
'Conteo': dct[motivo]
}}
index++; };
// 5: convertir a FeatureSet y devolver resultado
return FeatureSet(Text(Dict));
... View more
08-30-2024
04:09 PM
|
3
|
2
|
481
|
BLOG
|
Proporcionar más información Aunque es posible de crear visualización en la ventana emergente y proporcionar información más clara al usuario, a veces no es suficiente solamente proporcionar la información que tiene el feature que estamos consultando. Hay situaciones donde nos interesa conocer el indicador clave de rendimiento en relación con la vecindad y en relación con otros momentos en tiempo. Un ejemplo de esto podemos observar en este tablero donde representen SAIDI (duración de interrupciones de servicio por año) y SAIFI (cantidad de interrupciones de servicio al año): Fuente: https://storymaps.arcgis.com/stories/a944c3b67bed44d8adbfecc4b0748a0f En este ejemplo mediante un gráfico muestren el puntaje SAIDI en relación con los demás circuitos en la zona del servicio. Este indicador es un insumo importante para realizar inversiones en la red para mejorar la calidad del servicio. Para el caso de hoy usaremos los datos de cobertura de servicios de Colombia a nivel de municipio para conocer el grado de cobertura en relación con los municipios vecinos. Abajo un ejemplo de lo que se puede crear con Arcade: Con Arcade es posible realizar un análisis donde consultamos los municipios vecinos del municipio seleccionado y analizar la cobertura y generar una visualización atractiva brindando información adicional para el usuario. (Aunque este ejemplo va a utilizar información de entidades vecinos, también es posible realizar este tipo de análisis sobre información multitemporal para entender el rendimiento como función del tiempo). Para obtener los municipios vecinos, se puede aplicar un buffer pequeño al municipio inicial y seleccionar los municipios que intersecan con el buffer: Para agregar HTML a la ventana emergente, no se debe elegir la opción “Expresiones de atributos”, pero hacer clic en “Agregar contenido” y luego elegir “</> Arcade”: En el editor de Arcade se puede ver un ejemplo del formato para un gráfico que la expresión debe entregar: Es un diccionario, que contiene una serie de datos para definir los datos, los campos, colores, tipo de gráfico y títulos. Un gráfico requiere bastante información y dependiendo del tipo de gráfico, pero siempre los datos se entregan a la propiedad "attributes" como un diccionario, los campos a la propiedad "fields" y el tipo de gráfico a la propiedad "type". Una explicación del código Arcade: Línea 1: acceder al nombre del municipio seleccionado Línea 2: calcular un buffer de 25 metros alrededor del municipio seleccionado Línea 3 a 4: intersecar la capa de municipios con el buffer para tener la selección de municipios vecinos (incluyendo el municipio inicial) Línea 6 a 31: bucle por los municipios vecinos, calcular la cobertura de todos los servicios, registrar el resultado en un diccionario (municipio::cobertura). En este parte también se registren los colores, aunque este listado se va a modificar más adelante porque es necesario ordenar el diccionario de resultados. Línea 33 a 39: cambiar el formato del diccionario (municipio::cobertura) a un listado que se pueden ordenar por cobertura. Línea 41 a 48: función que permite ordenar listados (arrays) Línea 50: ordenar los municipios vecinos de cobertura máxima a cobertura mínima Línea 51 a 64: pasar el listado ordenado a un diccionario nuevamente (para el formato que requiere el gráfico) y crear una lista de colores según el municipio Línea 66 a 70: calcular estadísticas de cobertura y crear un texto para mostrar debajo del gráfico Línea 72 a 88: devolver el resultado (el gráfico, tipo “columnchart”), asignando el diccionario de datos a la propiedad “attributes”, el listado de campos (municipios) a la propiedad “fields” y el listado de colores a la propiedad “colors”. Es importante que el diccionario y las listas tienen el mismo orden para obtener el resultado deseado. El código Arcade (1) var mpio = $feature.MUNICIPIO;
var buf25m = Buffer($feature, 25, "meter");
var fs = Intersects($layer, buf25m);
var cnt = Count(fs);
var dct_score = {};
var flds = [];
var colors = [];
var ind = -1;
var i = 0
for (var f in fs) {
i += 1;
var place = f.MUNICIPIO; // "Zone " + Text(i, '00');
var current_mpio = f.MUNICIPIO;
var acue = f.P_ACUESI / (f.P_ACUENO + f.P_ACUESI) * 100.0;
var alca = f.P_ACUESI / (f.P_ACUENO + f.P_ACUESI) * 100.0;
var elec = f.P_ACUESI / (f.P_ACUENO + f.P_ACUESI) * 100.0;
var gasn = f.P_ACUESI / (f.P_ACUENO + f.P_ACUESI) * 100.0;
var tele = f.P_ACUESI / (f.P_ACUENO + f.P_ACUESI) * 100.0;
var score = Round((elec*5+acue*4+tele*3+alca*2+gasn)/15.0, 1);
dct_score[place] = score;
Push(flds, place);
if (current_mpio==mpio) {
var cob = score;
Push(colors, [255, 125, 175, 255])
ind = i;
} else {
Push(colors, [127, 127, 127, 127])
}
}
// create arr with dicts
var data = [];
var arr_score = [];
for (current_mpio in dct_score) {
Push(arr_score, {"NAME": current_mpio, "SCORE": dct_score[current_mpio]})
Push(data, dct_score[current_mpio]);
}
// sort the dct
function comparar(a,b){
if (a['SCORE']<b['SCORE'])
return 1;
if (a['SCORE']>b['SCORE'])
return -1;
return 0;
}
var arr_sorted = Sort(arr_score, comparar);
var flds2 = [];
var colors2 = [];
for (i in arr_sorted) {
var dct = arr_sorted[i];
current_mpio = dct["NAME"];
score = dct["SCORE"];
Push(flds2, current_mpio);
if (current_mpio == mpio) {
ind = i+1;
Push(colors2, [255, 125, 175, 255])
} else {
Push(colors2, [200, 200, 200, 255])
}
}
// stats
var minval = Min(data);
var maxval = Max(data);
var meanval = Mean(data);
var stats = 'Valor max: ' + maxval + '% | valor media: ' + Round(meanval, 1) + '% | valor min: ' + minval + '%';
return {
type: 'media',
title : 'Cobertura en ' + mpio + ' comparado con municipios vecinos',
description : 'Cobertura: ' + cob + '%, y la posición relativa es: ' + ind + '/' + cnt,
attributes : dct_score,
mediaInfos: [{
type : 'columnchart', //linechart | barchart | piechart | columnchart
title : '', //'Cobertura en relación con muncipios vecinos',
caption : stats, // 'Cobertura en relación con muncipios vecinos',
altText : 'Cobertura en relación con muncipios vecinos',
value : {
fields: flds2,
colors: colors2 //,
//normalizeField : '',
}
}]
} Abajo un ejemplo de usar un gráfico de torta usando los datos de iNaturalist (LivingAtlas) para mostrar las observaciones en un parque: El código Arcade (2) // colores por categoría
var dct_cols = {"Aves": [242, 223, 97, 255], "Plantae": [15, 153, 84, 255],
"Insecta": [170, 134, 49, 255], "Arachnida": [0, 0, 0, 255],
"Unknown": [234, 238, 234, 255], "Amphibia": [51, 119, 255, 255],
"Fungi": [82, 203, 163, 255], "Mollusca": [138, 86, 14, 255],
"Mammalia": [187, 84, 101, 255], "Actinopterygii": [102, 179, 255, 255],
"Protozoa": [161, 230, 230, 255], "Reptilia": [217, 193, 148, 255]};
// función para ordenar datos
function comparar(a,b){
if (a['Conteo']>b['Conteo'])
return -1;
if (a['Conteo']<b['Conteo'])
return 1;
return 0;
}
// acceso a los datos y obtener las observaciones en el parque seleccionado
var fs = FeatureSetByName($map, "Observations", ["taxon_category_name"], false);
var observaciones = Intersects(fs, $feature);
var parque = $feature.Nombre;
// crear diccionario con las observaciones por categoría
var dct_atts = {};
var arr_flds = [];
for (var obs in observaciones) {
var category = obs.taxon_category_name;
if (HasKey(dct_atts, category)) {
dct_atts[category] += 1;
} else {
dct_atts[category] = 1
Push(arr_flds, category);
}
}
//convertir diccionario con los resultados en un listado
var arr_atts = [];
for (category in dct_atts) {
Push(arr_atts, {'Category': category, 'Conteo': dct_atts[category]});
}
// ordenar el listado
var arr_atts2 = Sort(arr_atts, comparar);
// convertir listado a diccionario y crear listados de campos y colores
dct_atts = {};
arr_flds = [];
var arr_cols = [];
for (var i in arr_atts2) {
var dct_info = arr_atts2[i];
category = dct_info['Category'];
var conteo = dct_info['Conteo'];
dct_atts[category] = conteo;
Push(arr_flds, category)
Push(arr_cols, dct_cols[category]);
}
// devolver los datos en formato de gráfico de torta
return {
type: 'media',
title : 'Observaciones iNaturalist',
//description : 'Observaciones por categoría en ' + parque,
attributes : dct_atts,
mediaInfos: [{
type : 'piechart',
caption : 'Observaciones por categoría en parque ' + parque,
value : {
fields: arr_flds,
colors: arr_cols,
}
}]
}
... View more
08-30-2024
04:00 PM
|
2
|
0
|
291
|
BLOG
|
Proporcionar más información Aunque es posible de crear visualización en la ventana emergente y proporcionar información más clara al usuario, a veces no es suficiente solamente proporcionar la información que tiene el feature mismo. En el ejemplo abajo se muestren los cantones de Ecuador (Guayaquil está seleccionado) y por debajo las clases de susceptibilidad de incendios forestales. La ventana emergente solamente ofrece información de población y tamaño, pero si queremos conocer que porcentaje del cantón está tiene un riesgo muy alto tendríamos que estimarlo basado en lo que vemos: Con Arcade es posible realizar un análisis con otras capas y generar una visualización atractiva optimizando el entendimiento para el usuario. En el ejemplo abajo se generó una rampa con los mismos colores de las clases de riesgo al incendio forestal y aplicando un tamaño a cada clase que represente su porcentaje en el total: Cuando se hace clic en un polígono de un cantón, se toma esta geometría para realizar una consulta a la capa de riesgos de incendios forestales para obtener los polígonos de riesgos que están parcial o completamente contenidos en el polígono del cantón. Luego, para cada polígono de riesgo se cruce con el polígono del cantón para quedarse solamente con la parte del polígono de riesgo que está dentro del cantón. Con la información del feature se obtiene la clasificación de la susceptibilidad y la geometría del cruce nos dice el tamaño de la superficie: Es importante entender que las funciones “Intersects” y “Intersection” son diferentes. “Intersects” devuelve en este caso un featureset (selección de la capa de riesgos) y la función “Intersection” devuelve una geometría. Estas 2 operaciones son “costosos”, es decir, pueden consumir un tiempo considerable en caso de que la geometría es compleja o las capas tienen muchas entidades. Para agregar HTML a la ventana emergente, no se debe elegir la opción “Expresiones de atributos”, pero hacer clic en “Agregar contenido” y luego elegir “</> Arcade”: En el editor de Arcade se puede ver un ejemplo del formato que la expresión debe entregar: Es un diccionario, que indique que el tipo de información que genere es un texto y el texto es el HTML que la expresión debe generar. El HTML no es muy complejo y utilice un número de tags limitado. Tablas para alinear la información y presentar la rampa de colores (<table>, <tbody>, <tr> y <td>) Imágenes (<img>) Encabezado (<h3>) En las tables el uso de estilo CSS si es frecuente para obtener la visualización deseada. Al final de este documento pueden encontrar el código completo de Arcade usado para este ejemplo. Una explicación de la expresión Arcade: Línea 1: acceder a la capa de riesgos desde el mapa Línea 2: seleccionar los polígonos de riesgos que tiene traslapo con el cantón Línea 3: contar los polígonos de riesgos encontrados Línea 5 a 20: bucle por los polígonos de riesgo para determinar clase de riesgo y superficie y almacenar el resultado en un diccionario. Línea 22 a 28: calcular la superficie total Línea 30 a 34: determinar la superficie sin información de clase de riesgo Línea 36 a 43: diccionario de colores que coinciden con los colores usados en el mapa Línea 45 a 53: crear la table con el título y la imagen para incendios Línea 55 a 81: crear la tabla con los colores de riesgo y definir el ancho de cada celda según el análisis de clase de riesgo Línea 83 a 86: devolver el resultado (el html) El código Arcade var fs_incendios = FeatureSetByName($map, "Susceptibilidad Incendios Forestales", ["Ind_Suscep"], true);
var fs = Intersects(fs_incendios, $feature);
var cnt = Count(fs);
var dct = {};
if (cnt > 0) {
for (var f in fs) {
var fi = Intersection(f, $feature);
var clase = f["Ind_Suscep"];
var size = AreaGeodetic(fi, "square-kilometers");
if (HasKey(dct, clase)) {
dct[clase] += size;
} else {
dct[clase] = size;
}
}
Console(dct);
} else {
Console("sin incendios");
}
// area total
var areatot = AreaGeodetic($feature, "square-kilometers");
var areasum = 0;
for (clase in dct) {
size = dct[clase];
areasum += size;
}
var unk = areatot - areasum;
dct["Desconocido"] = unk;
Console($feature.NAME)
Console(areatot);
Console(unk);
// crear HTML
var dct_colores = {"Muy alta": "rgb(255, 127, 127)",
"Alta": "rgb(255, 212, 127)",
"Media": "rgb(255, 233, 191)",
"Baja": "rgb(255, 245, 222)",
"Muy baja": "rgb(203, 242, 127)",
"Desconocido": "rgb(192, 192, 192)"};
var html = "";
// Riesgo natural y condiciones tuberia
html += "<table style='width: 100%;border: 0px solid black;border-collapse: collapse;font-family: Segoe UI, Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;font-size: 11pt;'>";
html += "<tbody>";
html += " <tr valign='valign' style='background-color: rgb(255, 255, 255);'>"
html += " <td style='border: 0px solid rgb(255, 255, 255);background-color:rgb(255, 255, 255);text-align:left;height:60px;width:60px'><img src='https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/c2bab6080acb4f76a8e1e7aee73f9ca1/data' width='50' height='50'></td>";
html += " <td style='border: 0px solid rgb(255, 255, 255);padding-right: 5px;color:rgb(0, 0, 0);background-color:rgb(255, 255, 255);text-align:left;height:60px;width:250px'><h3>Riesgo de incendios</h3></td>";
html += " </tr>";
html += " </tbody>";
html += "</table>";
if (cnt > 0) {
html += "<table style='width: 100%;border: 0px solid black;border-collapse: collapse;font-family: Segoe UI, Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;font-size: 7pt;'>"
html += " <tbody>"
html += " <tr valign='valign' style='background-color: rgb(255, 255, 255);'>"
var arr = ["Muy alta", "Alta", "Media", "Baja", "Muy baja", "Desconocido"];
for (var i in arr) {
clase = arr[i];
if (HasKey(dct, clase)) {
size = dct[clase];
var porcentaje = Round(size / areatot * 100.0, 0)
if (porcentaje> 0) {
var bgcol = dct_colores[clase];
var txtclase = ""
if (porcentaje>10) {
txtclase = clase
}
html += " <td title='" + porcentaje + "% pasa por un riesgo de incendio " + clase + "' style='padding: 2px;padding-bottom: 5px;border: 1px solid rgb(0, 0, 0);padding-right: 1px;color:rgb(0, 0, 0);background-color:" + bgcol + ";text-align:center;height:20px;width:" + porcentaje + "%'>" + txtclase + "</td>";
}
}
}
html += " </tr>";
html += " </tbody>";
html += "</table>";
} else {
html += "<br/><i>Sin riesgo de incendios...</i>";
}
return {
type : 'text',
text : html
}
... View more
08-30-2024
03:47 PM
|
2
|
0
|
239
|
BLOG
|
Experiencia del usuario En muchos casos la costumbre es usar una visualización por defecto de los atributos en la ventana emergente, ¿pero con esto estamos entregando la mejor experiencia al usuario? Aprovechando Arcade es posible mejorar esta experiencia al usuario y brindar una visualización que no solamente sea más atractiva, pero también optimice la interpretación de los datos. Un ejemplo de los mismos datos se puede observar abajo: En este caso estamos usando una capa de municipios y para cada municipio tiene información sobre la cantidad de personas con acceso y sin acceso a los servicios públicos (acueducto, alcantarillado, electricidad, gas y telefonía). Con base en esto podemos calcular el porcentaje de cobertura para cada servicio: El cálculo es sencillo, pero para crear una visualización atractiva con los datos, debemos usar un elemento de Arcade que genere código HTML. La expresión de Arcade consiste en 2 partes; la configuración y el análisis donde se conecta a los datos, realicen los cálculos y genere el HTML basada en la configuración: Para agregar HTML a la ventana emergente, no se debe elegir la opción “Expresiones de atributos”, pero hacer clic en “Agregar contenido” y luego elegir “</> Arcade”: En el editor de Arcade se puede ver un ejemplo del formato que la expresión debe entregar: Es un diccionario, que indique que el tipo de información que genere es un texto y el texto es el HTML que la expresión debe generar. El HTML no es muy complejo y utilice un número de tags limitado. Tablas para alinear la información y presentar la rampa de colores (<table>, <tbody>, <tr> y <td>) Imágenes (<img>) Encabezado (<h3>) Negrilla (<b>) En las tables el uso de estilo CSS si es frecuente para obtener la visualización deseada. Al final de este documento pueden encontrar el código completo de Arcade usado para este ejemplo. Una explicación de la expresión Arcade: Línea 1 a 17, configuración de estilo CSS para las tablas Línea 20 a 59, listado de los servicios a graficar y un diccionario con información sobre nombres de campos con los datos y la imagen a usar en la ventana emergente. Estas imágenes fueron sacadas de Flaticon.com Línea 61 a 74, definición de la campa de colores (10 colores de verde a rojo) y crear una rampa invertida para ofrecer esta opción en la visualización. Línea 76 a 96, definición de variables Línea 98, inicio del bucle por los 5 servicios Línea 100, leer la configuración de campos, títulos e imagen para el servicio a procesar Línea 104 a 107, definición de la rampa de colores a usar para la visualización del servicio Línea 110 a 130, calcular la cobertura del servicio Línea 132 a 141, crear la tabla con el título y la imagen del servicio Línea 143 a 146, inicio de la tabla con la rampa Línea 148 a 178, crear las 10 celdas según la cobertura (0-10%, 10-20%, … , 90-100%), colocando el porcentaje en la celda que contiene este valor y dejando celdas de un rango mayor al porcentaje de cobertura en colores gris y blanco) Línea 184 a 187, donde se devuelve el código html para su representación. El código Arcade // configuración
var img_width = "50";
var img_height = "50";
var style_table1 = "width: 100%;border: 0px solid black;border-collapse: collapse;font-family: Segoe UI, Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;font-size: 11pt;";
var style_tbl1tr = "valign='valign' style='background-color: rgb(255, 255, 255);'";
var style_tbl1cell1 = "border: 0px solid rgb(255, 255, 255);background-color:rgb(255, 255, 255);text-align:left;height:60px;width:60px";
var style_tbl1cell2 = "border: 0px solid rgb(255, 255, 255);padding-right: 5px;color:rgb(0, 0, 0);background-color:rgb(255, 255, 255);text-align:left;height:60px;width:250px";
var style_table2 = "width: 100%;border: 0px solid black;border-collapse: collapse;font-family: Segoe UI, Tahoma, Verdana, Geneva, Arial, Helvetica, sans-serif;font-size: 9pt;";
var style_tbl2tr = "valign='valign' style='background-color: rgb(255, 255, 255);'";
var style_tbl2tdpart1 = "style='border: 1px solid ";
var style_tbl2tdpart2 = ";padding-right: 5px;color:rgb(0, 0, 0);background-color:";
var style_tbl2tdpart3 = ";text-align:center;height:25px;width:10%'";
var separation_between_data = "<br />";
var separation_after_header = ""; //"<br />";
var border_col_data = "rgb(0, 0, 0)";
var border_col_nodata = "rgb(200, 200, 200)";
var backgr_col_nodata = "rgb(255, 255, 255)";
// temas a tratar
var arr_info = ["Electricidad", "Acueducto", "Alcantarillado", "Gas Natural", "Telefonía"];
// info por tema
var dct_fieldinfo = {"Electricidad":
{"Title": "Cobertura de Electricidad",
"With": "P_ENERSI",
"Without": "P_ENERNO",
"NoData": "",
"img": "https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/817da1062ed643a39b0b721f7136f684/data",
"reverse": true},
"Acueducto":
{"Title": "Cobertura de Acueducto",
"With": "P_ACUESI",
"Without": "P_ACUENO",
"NoData": "",
"img": "https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/7c37c2849bbd475e94cb053d6081f641/data",
"reverse": true},
"Alcantarillado":
{"Title": "Cobertura de Alcantarillado",
"With": "P_ALCANSI",
"Without": "P_ALCANNO",
"NoData": "",
"img": "https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/015376acd80c41a4bf2fe6ac2bd53e92/data",
"reverse": true},
"Gas Natural":
{"Title": "Cobertura de Gas Natural",
"With": "P_GASNSI",
"Without": "P_GASNNO",
"NoData": "P_GASNNOIN",
"img": "https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/a9811a6c7e9c444381d1dad8d1f9894d/data",
"reverse": true},
"Telefonía":
{"Title": "Cobertura de Telefonía",
"With": "P_TELEFSI",
"Without": "P_TELEFNO",
"NoData": "P_TELEFNOI",
"img": "https://utility-esri-co.maps.arcgis.com/sharing/rest/content/items/c5b285416954406a9883748c6b30ddad/data",
"reverse": true},
};
// colores
var arr_rampcolors = ["rgb(113, 159, 102)",
"rgb(82, 186, 149)",
"rgb(128, 221, 164)",
"rgb(195, 255, 151)",
"rgb(235, 255, 100)",
"rgb(254, 233, 77)",
"rgb(252, 191, 76)",
"rgb(244, 136, 87)",
"rgb(210, 76, 76)",
"rgb(151, 76, 76)"];
// invertir colores (en caso que aplique)
var arr_rampcolorsrev = Reverse(arr_rampcolors);
var html = "";
Console($feature["MUNICIPIO"]);
Console($feature["DEPTO"]);
var conservicio = -1;
var sinservicio = -1;
var nodata = -1;
var score = -1;
var scoreint10 = -1;
var scoredec = -1;
var scoredectxt = "";
var servicio = "";
var info = {};
var img = "";
var title = "";
var i = 0;
var fld_nodata = "";
var fld_border_col = "";
var fld_backgr_col = "";
var fld_with = "";
var fld_without = "";
for (i in arr_info) {
servicio = arr_info[i];
info = dct_fieldinfo[servicio];
// construir titulo
img = info["img"]; // url de imagen
title = info["Title"]; // titulo del dato
var reverseramp = info["reverse"]; // no está implementado por el momento TODO
var use_ramp = arr_rampcolors;
if (reverseramp == true) {
use_ramp = arr_rampcolorsrev;
}
// calcular porcentaje
fld_with = info["With"];
fld_without = info["Without"];
fld_nodata = info["NoData"];
Console(fld_with);
Console(fld_without);
Console(fld_nodata);
conservicio = $feature[fld_with];
sinservicio = $feature[fld_without];
Console(conservicio);
Console(sinservicio);
if (fld_nodata == "") {
nodata = 0;
} else {
nodata = $feature[fld_nodata];
}
score = conservicio / (conservicio + sinservicio + nodata) * 100.0;
scoreint10 = Round(score/10, 0);
scoredec = Round(score, 2);
// tabla con datos a presentar
html += "<table style='" + style_table1 + "'>";
html += "<tbody>";
html += " <tr " + style_tbl1tr+ ">";
html += " <td style='" + style_tbl1cell1 + "'><img src='" + img + "' width='" + img_width + "' height='" + img_height + "'></td>";
html += " <td style='" + style_tbl1cell2 + "'><h3>" + title + "</h3></td>";
html += " </tr>";
html += " </tbody>";
html += "</table>";
html += separation_after_header;
// tabla con colores
html += "<table style='" + style_table2 + "'>";
html += "<tbody>";
html += " <tr " + style_tbl2tr + ">";
for (var j = 0; j < 10; j++) {
Console("j:" + j)
// construir tabla con colores
if (scoreint10 == j+1) {
// usar colores y texto
Console("usar colores y texto");
scoredectxt = scoredec;
fld_border_col = border_col_data;
fld_backgr_col = use_ramp[j];
} else if (scoreint10 > j+1) {
Console("usar colores sin texto");
// usar colores sin texto
scoredectxt = "";
fld_border_col = border_col_data;
fld_backgr_col = use_ramp[j];
} else {
// sin color y sin texto
Console("sin color y sin texto");
scoredectxt = "";
fld_border_col = border_col_nodata;
fld_backgr_col = backgr_col_nodata;
}
html += " <td "+ style_tbl2tdpart1 + fld_border_col + style_tbl2tdpart2 + fld_backgr_col + style_tbl2tdpart3 + "><b>" + scoredectxt + "</b></td>";
Console(" <td "+ style_tbl2tdpart1 + fld_border_col + style_tbl2tdpart2 + fld_backgr_col + style_tbl2tdpart3 + "><b>" + scoredectxt + "</b></td>")
}
html += " </tr>";
html += " </tbody>";
html += "</table>";
html += separation_between_data
}
Console("");
Console("");
Console(html);
return {
type : 'text',
text : html
}
... View more
08-30-2024
03:36 PM
|
2
|
0
|
260
|
BLOG
|
Usar Campos de tipo "DateOnly" en ArcGIS Dashboards En este blog compartiremos una manera de usar campos de fecha solamente (DateOnly) en un tablero de control (ArcGIS Dashboards). Nuevos tipos de campos Desde finales del año pasado contamos con nuevos tipos de campos en ArcGIS Online, pero el soporte para estos tipos de campos todavía no está en ArcGIS Dashboards. Más información sobre los nuevos campos: https://www.esri.com/arcgis-blog/products/arcgis-online/mapping/time-is-on-your-side-with-new-field-types-in-arcgis-online/ Al publicar un servicio desde ArcGIS Pro con estos nuevos tipos de campos en el esquema, genere un aviso indicando que el uso puede ser limitado y efectivamente eso es el caso para los tableros que configures en ArcGIS Dashboards. ¿Dónde están mis campo? Al publicar un conjunto de datos con campos de tipo fecha solamente ("DateOnly"), estos aparecen correctamente al explorar el servicio en ArcGIS Online: Pero en el momento de configurar alguna visualización como un gráfico de serie en ArcGIS Dashboards, se puede notar que estos campos no aparecen: Arcade al rescate Afortunadamente, es posible usar las expresiones de datos basadas en Arcade para crear en memoria un conjunto de datos con el esquema adaptado tal que ArcGIS Dashboard puede usar la fecha para crear la visualización deseada. Para conocer más acera de la creación de expresiones de datos con Arcade, puede consultar este página web: https://doc.arcgis.com/es/dashboards/latest/get-started/create-data-expressions.htm El concepto consiste en leer el featureset, modifcar el esquema, convertir la fecha, y convertir estos datos a un featureset en memoria. La gestión de fechas es algo que requiere un poco más de atención cuando se va a trabajar con expresiones de datos. No es posible escribir una fecha directamente a un campo de fecha, y es necesaria traducir la fecha a un epoch. Epoch o "Unix Time" se define como la cantidad de segundos transcurridos desde la medianoche UTC del 1 de enero de 1970, sin contar segundos intercalares. @DavidNyenhuis1 contestó a una pregunta en la comunidad compartiendo una manera para tomar un featureset y crear un "copia" en memoria con la posibilidad de modificar los datos en el proceso según la necesidad: https://community.esri.com/t5/arcgis-online-ideas/arcade-allow-date-values-in-date-fields/idc-p/1265782/highlight/true#M9860 Tomando esto como base se puede crear la solución que buscamos. Lo que es necesario es ajustar la expresión para modificar el esquema en el proceso. Abajo la expresión de datos con Arcade. La expresión es genérico aunque es necesario cambiar la referencia al featureset en la linea 40, conectando a su portal, especificando el ID del servicio y el índice de la capa a usar. // basado en:
// source: https://community.esri.com/t5/arcgis-online-ideas/arcade-allow-date-values-in-date-fields/idi-p/1204894
// de: David Nyenhuis
// Since a esriTypeDate can't take an Arcade Date, need to cast to EPOCH
// Pass in a feature
function CastDatesToEpoch(feat) {
var modifiedAttributes = {};
for (var att in feat) {
if(TypeOf(feat[att]) == 'Date') {
modifiedAttributes[att] = Number(feat[att])
Console('${feat[att]} is now ${Number(feat[att])}')
} else if(TypeOf(feat[att]) == 'DateOnly') {
modifiedAttributes[att] = Number(feat[att])
Console('${feat[att]} is now ${Number(feat[att])}')
}
else {
modifiedAttributes[att] = feat[att]
}
}
return modifiedAttributes
}
function ModifySchema(sch) {
var txt = Text(sch);
var sch2 = Dictionary(txt);
var lst_flds = sch2["fields"];
for (var i in lst_flds) {
var dct_fld = lst_flds[i];
if (dct_fld["type"] == "esriFieldTypeDateOnly") {
dct_fld["type"] = "esriFieldTypeDate";
}
lst_flds[i] = dct_fld;
}
sch2["fields"] = lst_flds
return sch2;
}
// get the layer
var fs = FeatureSetByPortalItem(Portal('https://utility-esri-co.maps.arcgis.com'), 'bf4a31341a5d49be90de6ce471a0b647', 0);
// Define a new dictionary feature set
var sch = Schema(fs);
var sch2 = ModifySchema(sch);
var dict = {
'fields': sch2.fields,
'geometryType': sch2.geometryType, // Can be esriGeometryNull, esriGeometryPoint, esriGeometryPolyline, esriGeometryPolygon;
'features': []
};
// Do something to each feature, like add a field, then add it to the dictionary
var index = 0;
for (var f in fs) {
// Add each feature to new dictionary and cast dates to EPOCH
dict.features[index] = {
'geometry': Geometry(f),
'attributes': CastDatesToEpoch(f)
}
index++;
}
// Convert dictionary to feature set.
return FeatureSet(Text(dict)); Al usar la expresión de datos como fuenta para crear por ejemplo un gráfico de serie ahora si aparecen los campos de las fechas: Resultado y aspectos para tener en cuenta Abajo se puede ver un ejemplo generado a partir de la expresión de datos que brinda acceso a a los campos de fecha: En caso de usar expresiones de datos es importante tener algunos aspectos en cuenta: Lo más importante es la experiencia del usuario final y para logar una buena experiencia del usuario el rendimiento del tablero debe ser bien. La expresión de datos que presentamos en este blog lea todo el featureset y lo replique en memoria. Esto funcione bien con una conjunto de datos de en este caso unos 1500 registros, pero si la capa es muy grande el usuario va a notar una reducción del rendimiento. Si la visualización no requiere todos los datos, aplique un filtro a los datos en el momento de leer la capa. Seguramente el soporte para estos nuevos campos va a aparecer en tiempo en las aplicaciones de ArcGIS. Si el objetivo es crear visualizaciones con base en fechas es mejor evitar el uso de estos campos en los conjuntos de datos hasta que se cuenta con soporte completa de estos campos. La expresión en este ejemplo solamente toma encuenta el caso de modificar un campo de solo fecha. No gestione campos de solo tiempo ni combine campos de solo fecha y solo tiempo en un campo de fecha.
... View more
06-28-2024
01:56 PM
|
1
|
0
|
344
|
POST
|
Hi @RaimonReventós , Almost a year ago I posted an idea (internally) with the title "Provide the location clicked in the pop-up to the Arcade expression". However, the idea is still open...
... View more
07-27-2022
02:21 PM
|
2
|
4
|
1944
|
DOC
|
Hi @Vanilla2020 , Have a look at the "GetFieldNamesOnPrivacy" function below: Function HasDomain(f, fldname) {
return Domain(f, fldname) != Null;
}
Function GetAlias(f, fldname) {
var esquema = Schema(f);
var flds = esquema["fields"];
for (var i in flds) {
var fldinfo = flds[i];
if (fldinfo["name"]==fldname) {
return fldinfo["alias"];
}
}
return fldname;
}
Function GetFieldNamesOnPrivacy(f) {
// privacy_level with values from 0 to 5)
// I want to display, say field_A, field_B, field_C, field_D
// for locations with privacy level larger than 2,
// while only field_A and field_B
var fldlst = [];
var level = f["privacy_level"];
if (level > 2) {
fldlst = ["field_A", "field_B"];
} else {
fldlst = ["field_A", "field_B", "field_C", "field_D"];
}
return fldlst;
}
var fs = FeatureSetByName($datastore, "_8_de_formulario");
var oid = $feature.objectid;
var sql = "OBJECTID = @oid";
var f = First(Filter(fs, sql));
// var excludeflds = ['globalid', 'objectid', 'prueba', "x_coord","y_coord","EditDate","Editor"];
var flds = GetFieldNamesOnPrivacy(f);
var info = [];
var atts = {};
for (var i in flds) {
var fldname = flds[i];
if (!IsEmpty(f[fldname])) {
var alias = GetAlias(f, fldname);
Push (info, {'fieldName': alias})
if (HasDomain(f, fldname)) {
atts[alias] = DomainName(f, fldname);
} else {
atts[alias] = f[fldname];
}
}
}
return {
type: 'fields',
title: 'Detalles de la actividad',
description : '(con Arcade)',
fieldInfos: info,
attributes : atts
}
... View more
07-27-2022
02:16 PM
|
0
|
0
|
9862
|
POST
|
Hi @AdamGebhart , I am glad that @KenBuja shared a good solution. Apart from the solution provided by Ken, there are many ways to do this. You can compare by exact date and time (probably the date has a time like 6 pm since it is stored as UTC date time and there is a difference between your local time zone and UTC): if ($feature.StatusDate == Date(2022, 11, 31, 18, 0, 0)) { ... } Another way (when the time does not matter) is to translate it to text and compare it as a string: if (Text($feature.StatusDate, "M/D/YY") == "12/31/22") { ... }
... View more
06-21-2022
01:27 PM
|
2
|
1
|
850
|
DOC
|
Hi @jschuckert , Good question... The FeatureSetByRelationshipName function is available in ArcGIS Online, but was not available in ArcGIS Enterprise at version 10.5.1. This might make the request to the server invalid or perhaps the response is not getting through correctly. Have you verified if there is something in the logs of ArcGIS Server?
... View more
06-21-2022
10:27 AM
|
0
|
0
|
5716
|
DOC
|
Hi @VanessaSimps , The comment above your comment explains just how to do that using the new Map Viewer and Arcade elements. Let me know if you have any questions on how to do this.
... View more
06-21-2022
10:14 AM
|
0
|
0
|
10117
|
POST
|
Hi @FredIausly1 , When I test with the TimeStamp() and Now() functions they return different results. The TimeStamp() will return the current date-time in UTC and Now() will return the current date-time in my Local time zone. You can use the ToLocal() and ToUTC() functions to switch between the time zones, but there is no function to automatically change to another time zone that is not UTC or Local. Be aware that the ToLocal and ToUTC functions will simply add or extract the number of hours difference between UTC and Local time zone indifferent is you provide a UTC or Local time. Also, in ArcGIS Online, date-time is stored in UTC and when you manually create a date it will be assumed to be in UTC. You can however use the DateAdd() function and add or subtract the number of hours to obtain the date-time in another time zone, but you should account for Daylight Saving Time depending on the date.
... View more
06-21-2022
10:12 AM
|
0
|
1
|
2182
|
POST
|
Hi @OliverSandoval_p , Sorry for the delay, but when I look at the distances that you get I wonder how big your feature is... Distances of 65M feet are about halfway around the globe. If I use Infinity or the searchDist as the initial minimum distance it will return the same result:
... View more
06-03-2022
10:41 AM
|
0
|
1
|
1404
|
POST
|
Hi @NCESOpen_Data , Sorry for the delay. In your case you can use something like: var txt = $feature["Your text field"];
if (Lower(txt) != 'unavailable') {
txt = Left(txt, Count(txt)-4);
}
return txt; A small example: var list = ['New Orleans, LA', 'Unavailable', 'Redlands, CA', 'Manhattan, NY'];
for (var i in list) {
var txt = list[i];
if (Lower(txt) != 'unavailable') {
txt = Left(txt, Count(txt)-4);
}
Console(txt);
} This will write to the console: New Orleans
Unavailable
Redlands
Manhattan
... View more
05-24-2022
03:43 PM
|
0
|
0
|
11347
|
Title | Kudos | Posted |
---|---|---|
1 | 05-30-2019 08:24 AM | |
1 | 05-29-2019 02:45 PM | |
1 | 10-18-2024 12:14 PM | |
2 | 10-18-2024 12:17 PM | |
2 | 08-30-2024 04:00 PM |
Online Status |
Offline
|
Date Last Visited |
10-18-2024
11:38 PM
|