Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - API+APP - Posibilidad de crear tramos #254

Open
wants to merge 33 commits into
base: reporting
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f87513a
Primer avance de la función de rangos
ronaldchavezjortilles Oct 30, 2024
c10c824
Ajustes de solo números y signos . : ,
ronaldchavezjortilles Oct 31, 2024
a3abc34
Control del input para solo recibir números, '.', ',' y ':'
ronaldchavezjortilles Oct 31, 2024
3e12925
El último caracter debe ser número
ronaldchavezjortilles Oct 31, 2024
fe8cd67
Nueva rama actual de range, según reunión
ronaldchavezjortilles Nov 5, 2024
8acd12d
Range front end diseño nuevo
ronaldchavezjortilles Nov 5, 2024
09001e6
Cuando se selecciona el rango, se selecciona la agregación none
ronaldchavezjortilles Nov 6, 2024
780a0e8
Interactividad de los rangos y las agregaciones funcional
ronaldchavezjortilles Nov 6, 2024
e038f2f
Frontend rango - margenes listos
ronaldchavezjortilles Nov 6, 2024
ef90983
String de rangos listo
ronaldchavezjortilles Nov 6, 2024
ff3b318
Frontend terminado
ronaldchavezjortilles Nov 6, 2024
62ee7ca
Llegada de rangos al Backend
ronaldchavezjortilles Nov 6, 2024
8c1502f
Primera versión de la tarea de Rangos
ronaldchavezjortilles Nov 7, 2024
d65cb74
Corrección de la generación del query en el Backend
ronaldchavezjortilles Nov 8, 2024
499e6ed
Backend funcional y limpieza de código
ronaldchavezjortilles Nov 8, 2024
5bc7a1d
issue en los rangos, resuelto
ronaldchavezjortilles Nov 8, 2024
0487ba6
Internacionalización de la primera versión de rangos terminada
ronaldchavezjortilles Nov 8, 2024
e50ea0a
Ajustes de los rangos, acordados en la reunión con SinergiaDA
ronaldchavezjortilles Nov 18, 2024
0fe86b7
formato
jortilles Nov 19, 2024
4a43b4a
Falta revisar la ordenacion
jortilles Dec 16, 2024
e259fac
Genaración del rangesOrderExpression para el ordenamiento
ronaldchavezjortilles Dec 19, 2024
8eeb8e2
Ordenamiento listo
ronaldchavezjortilles Dec 19, 2024
534fc3a
Ajuste de ordenation_type = No
ronaldchavezjortilles Dec 20, 2024
38b6944
Agregación de números negativos y correcciones de texto
ronaldchavezjortilles Dec 30, 2024
4c3e598
Identificación de valores del rango
ronaldchavezjortilles Dec 30, 2024
3e4ed89
Seleccion de valores negativos, exclusivamente para los rangos
ronaldchavezjortilles Dec 31, 2024
77176db
Limpieza de codigo y agregado de comentarios
ronaldchavezjortilles Dec 31, 2024
9b65a4a
Solo se mostrara el rango para los campos que originalmente han sido …
ronaldchavezjortilles Jan 10, 2025
9086745
Limitar un solo rango por consulta
ronaldchavezjortilles Jan 14, 2025
074343d
Se añadio la propiedad hasOwnProperty
ronaldchavezjortilles Jan 14, 2025
6b29b6c
Generando la query de ceros y nulos para la query
ronaldchavezjortilles Jan 15, 2025
ee8f263
SDA#51 finalizado
ronaldchavezjortilles Jan 16, 2025
d61029b
agregado de salto de linea a la query
ronaldchavezjortilles Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export class MySqlBuilderService extends QueryBuilderService {
let o = tables.filter(table => table.name === origin).map(table => { return table.query ? table.query : table.name })[0];
let myQuery = `SELECT ${columns.join(', ')} \nFROM ${o}`;


/** SI ES UN SELECT PARA UN SELECTOR VOLDRÉ VALORS ÚNICS */
if (forSelector === true) {
myQuery = `SELECT DISTINCT ${columns.join(', ')} \nFROM ${o}`;
Expand Down Expand Up @@ -55,16 +54,22 @@ export class MySqlBuilderService extends QueryBuilderService {
const orderColumns = this.queryTODO.fields.map(col => {
let out;

console.log('EL col >>>>>> ',col)

if (col.ordenation_type !== 'No' && col.ordenation_type !== undefined) {
out = `\`${col.display_name}\` ${col.ordenation_type}`
} else {
out = false;
}
if( col.rangesOrderExpression && col.rangesOrderExpression != undefined && col.ordenation_type !== 'No'){
out = `${col.rangesOrderExpression} ${col.ordenation_type}`
}

return out;
}).filter(e => e !== false);

const order_columns_string = orderColumns.join(',');

if (order_columns_string.length > 0) {
myQuery = `${myQuery}\norder by ${order_columns_string}`;
} else if (forSelector === true) {
Expand Down
74 changes: 70 additions & 4 deletions eda/eda_api/lib/services/query-builder/query-builder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ export abstract class QueryBuilderService {
/** joins per els value list */
let valueListJoins = [];

//console.log(this.queryTODO);

if (!this.queryTODO.queryMode || this.queryTODO.queryMode == 'EDA') {
/** Reviso si cap columna de la consulta es un multivalueliest..... */
this.queryTODO.fields.forEach( e=>{
Expand Down Expand Up @@ -114,7 +112,8 @@ export abstract class QueryBuilderService {

/** ..........................PER ELS VALUE LISTS................................ */


// Verificando el Rango, si existe agrega los cambios sino el this.queryTODO queda igual.
this.queryTODO = this.verifyRange(this.queryTODO);
const filterTables = this.queryTODO.filters.map(filter => filter.filter_table);

// Afegim a dest les taules dels filtres
Expand Down Expand Up @@ -319,10 +318,78 @@ export abstract class QueryBuilderService {
this.query = this.normalQuery(columns, origin, dest, joinTree, grouping, filters, havingFilters, tables,
this.queryTODO.queryLimit, this.queryTODO.joinType, valueListJoins, this.dataModel.ds.connection.schema,
this.dataModel.ds.connection.database, this.queryTODO.forSelector);

return this.query;
}
}

public verifyRange(queryTODO: any){
// let columnRange = queryTODO.fields.find( c => c.ranges.length!==0);

queryTODO.fields.forEach( (fieldsColumn:any, j: number) => {

if(fieldsColumn.ranges===undefined) {

queryTODO.fields[j]=fieldsColumn;
} else {

if(fieldsColumn.ranges.length===0){
queryTODO.fields[j]=fieldsColumn;
} else {

fieldsColumn.computed_column = 'computed';
fieldsColumn.column_type = 'text';

let columna = `${fieldsColumn.table_id}.${fieldsColumn.column_name}`

let SQLexpression = "CASE\n";

// Primer caso: menor que el primer valor del rango
SQLexpression += `\tWHEN ${columna} < ${fieldsColumn.ranges[0]} THEN '< ${fieldsColumn.ranges[0]}'\n`;

// Casos intermedios: entre cada par de valores en el rango
for (let i = 0; i < fieldsColumn.ranges.length - 1; i++) {
const lower = fieldsColumn.ranges[i];
const upper = fieldsColumn.ranges[i + 1] - 1;
SQLexpression += `\tWHEN ${columna} >= ${lower} AND ${columna} <= ${upper} THEN ' ${lower} - ${upper}'\n`;
}

// Último caso: mayor o igual al último valor del rango
SQLexpression += `\tWHEN ${columna} >= ${fieldsColumn.ranges[fieldsColumn.ranges.length - 1]} THEN '>= ${fieldsColumn.ranges[fieldsColumn.ranges.length - 1]}'\n`;
SQLexpression += "END";

fieldsColumn.SQLexpression = SQLexpression;

// GENERANDO LA ORDENACIÓN
let rangesOrderExpression = "CASE\n";
let rangesOrderExpressionNumber = 1;

// Primer caso:
rangesOrderExpression += `\tWHEN ${columna} < ${fieldsColumn.ranges[0]} THEN ${rangesOrderExpressionNumber}\n`;

// Casos intermedios:
for(let i = 0; i<fieldsColumn.ranges.length - 1; i++) {
rangesOrderExpressionNumber += 1;
const lower = fieldsColumn.ranges[i];
const upper = fieldsColumn.ranges[i + 1] - 1;
rangesOrderExpression += `\tWHEN ${columna} >= ${lower} AND ${columna} <= ${upper} THEN ${rangesOrderExpressionNumber}\n`;
}

// Ultimo caso:
rangesOrderExpression += `\tWHEN ${columna} >= ${fieldsColumn.ranges[fieldsColumn.ranges.length - 1]} THEN ${rangesOrderExpressionNumber + 1}\n`;
rangesOrderExpression += "END";
fieldsColumn.rangesOrderExpression = rangesOrderExpression;

queryTODO[j] = fieldsColumn;
}

}

})

return queryTODO
}

public buildGraph() {
const graph = [];
//No fa falta treure les relacions ocultes per que les poso al array no_relations en guardar-ho
Expand Down Expand Up @@ -496,7 +563,6 @@ export abstract class QueryBuilderService {
}



/** esto se usa para las consultas que hacemos a bbdd para generar el modelo */
public simpleQuery(columns: string[], origin: string) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ <h4 i18n="@@agregacionesH4">
</h4>
<hr>

<div class="aggregation-list">
<div class="aggregation-list" >
<div class="aggregation-box" *ngFor="let aggregation of aggregationsTypes"
(click)="addAggregation(aggregation)"
(click)="allowedAggregations && addAggregation(aggregation)"
[ngStyle]="{'cursor': !allowedAggregations ? 'not-allowed' : 'pointer'}"
[ngClass]="aggregation.selected === true ? 'aggregation-active' : ''">

<span>{{getAggName(aggregation.value)}}</span>

<span>{{getAggName(aggregation.value)}}</span>
</div>
</div>

Expand Down Expand Up @@ -328,6 +327,61 @@ <h6 i18n="@@cumulativeSum">Suma acumulativa</h6>

</ng-container>

<ng-container *ngIf="(selectedColumn.column_type === 'numeric') || (selectedColumn.column_type === 'text' && this.ranges.length!==0)">

<h4 i18n="@@dateFormatH4"> Formato </h4>

<hr>

<div style="margin: 10px 0;">

<div>
<h5 i18n="@@rangesExpresionH5" style="margin-top: 5px; font-size: 1.2rem; display: inline;">Rangos: </h5>
<span>
<i class="pi pi-info-circle"
style="cursor: pointer; margin-top: -5px; font-size: 1.2rem;"
[pTooltip]="ptooltipViewTextRanges">
</i>
</span>
</div>

<input
type="text"
style="font-size: 1rem;"
[(ngModel)]="rangeString"
[disabled]="showRange"
(input)="validateInput($event)">

</div>

<p-button
(onClick)="addRange(rangeString)"
label="Añadir Rango"
[disabled]="((!rangeString || rangeString.length === 0)) || showRange"
i18n-label="@@addRange"
>
</p-button>

<div *ngIf="showRange" class="col-12 foot-card" style="margin-top: 5px;">

<p-scrollPanel [style]="{width: '100%', height: '160px'}" styleClass="custombar1">

<ng-container *ngIf="showRange">

<b i18n="@@rangeDescriptionB" class="mr-2" style="margin: 2px; font-size: 1.1rem;">
• Rango:
<i class="ui-dropdown-clear-icon pi pi-times pointer"(click)="removeRange()"></i>
</b>
<div *ngIf="showRange" class="d-flex align-items-center" [innerHTML]="selectedRange" style="font-size: 1rem; padding: 10px 40px 5px 30px;"></div>

</ng-container>

</p-scrollPanel>

</div>

</ng-container>

</ng-container>

</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as _ from 'lodash';

import { aggTypes } from 'app/config/aggretation-types';


@Component({
selector: 'app-column-dialog',
templateUrl: './column-dialog.component.html',
Expand Down Expand Up @@ -57,6 +58,17 @@ export class ColumnDialogComponent extends EdaDialogAbstract {
public cumulativeSumTooltip: string = $localize`:@@cumulativeSumTooltip:Si activas ésta función se calculará la suma acumulativa
para los campos numéricos que eligas. Sólo se puede activar si la fecha está agregada por mes, semana o dia.`


public ranges: number[] = [];
public rangeString: string;
public selectedRange: string = '';
public showRange: boolean = false;
public allowedAggregations: boolean = true;
public ptooltipViewTextRanges: string = $localize`:@@ptooltipViewTextRanges:Al configurar un Rango las agregaciones quedarán bloqueadas, Ejemplo de un rango válido - 12:18:50:100 `;
public rangeDescriptionNumberError: string = $localize`:@@rangeDescriptionNumberError:El correcto orden de los límites del rango van de menor a mayor`;
public rangeDescriptionCharacterError: string = $localize`:@@rangeDescriptionCharacterError:El último caracter del rango debe ser un número`;


constructor(
private dashboardService: DashboardService,
private chartUtils: ChartUtilsService,
Expand All @@ -83,8 +95,9 @@ export class ColumnDialogComponent extends EdaDialogAbstract {
const title = this.selectedColumn.display_name.default;
const col = $localize`:@@col:Atributo`, from = $localize`:@@table:de la entidad`;
this.dialog.title = `${col} ${title} ${from} ${this.controller.params.table}`;

this.carregarValidacions();
this.verifyRange();

const columnType = this.selectedColumn.column_type;

Expand Down Expand Up @@ -620,4 +633,97 @@ export class ColumnDialogComponent extends EdaDialogAbstract {
onClose(event: EdaDialogCloseEvent, response?: any): void {
return this.controller.close(event, response);
}

addRange(rangeString: string) {

const regexNumber = /^[0-9]/;

if(regexNumber.test(rangeString[rangeString.length-1])){

const ranges = rangeString.split(":")
.map(item => parseFloat(item.replace(",", ".")));

for (let i = 0; i < ranges.length-1; i++) {
// Verificar si el número actual es menor o igual al anterior
if (ranges[i] >= ranges[i + 1]) {
this.ranges=[];
// console.log('El correcto orden de los límites del rango van de menor a mayor')
this.alertService.addError('El correcto orden de los límites del rango van de menor a mayor');
return;
}
}

this.ranges = ranges
this.showRange = true;
this.selectedRange = this.generarStringRango(this.ranges); // extraemos el rango seleccionado
this.rangeString = '';
this.allowedAggregations = false;

// Selección de Rango, genera que la agregación sea 'none'
const selectionAggregationRange = { value: 'none', display_name: 'No', selected: 'true' };
this.addAggregation(selectionAggregationRange);

// Encuentra la columna de turno y agrega el rango
const addAggr = this.findColumn(this.selectedColumn, this.controller.params.currentQuery);
addAggr.column_type = 'text';
addAggr.ranges = this.ranges;
}
else {
// console.log('El último caracter del rango debe ser un número')
this.alertService.addError('El último caracter del rango debe ser un número');
return;
}

}

removeRange() {
this.selectedRange='';
this.showRange=false;
this.allowedAggregations = true;
const addAggr = this.findColumn(this.selectedColumn, this.controller.params.currentQuery);
addAggr.column_type = 'numeric';
this.selectedColumn.column_type = 'numeric';
this.rangeString = this.ranges.join(':');
addAggr.ranges = [];
}

generarStringRango(rango: number[]): string {
let resultado = "";

// Agregamos la primera condición
resultado += `< ${rango[0]}<br>`;

// Creamos las condiciones intermedias
for (let i = 0; i < rango.length - 1; i++) {
resultado += `${rango[i]} - ${rango[i + 1] - 1}<br>`;
}

// Agregamos la última condición
resultado += `>= ${rango[rango.length - 1]}`;

return resultado;
}

verifyRange() {

if(this.selectedColumn.ranges !== undefined){

if(this.selectedColumn.ranges.length !==0){
this.allowedAggregations = false;
this.showRange = true;
this.ranges = this.selectedColumn.ranges;
this.selectedRange = this.generarStringRango(this.ranges);
}
}
}

validateInput(event: Event): void {
const inputElement = event.target as HTMLInputElement;
const validCharacters = /[1234567890.,:-]*/g;
inputElement.value = inputElement.value.match(validCharacters)?.join('') || '';
// Si el input inicia con (. , :) no se habilitara el botón del rango ni se agregará el signo en el input. Se debe empezar con un número o con un signo (-) y un número para los negativos.
if(inputElement.value=== '.' || inputElement.value===',' || inputElement.value===':') inputElement.value = '';
this.rangeString = inputElement.value; // Se actualiza ngModel
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ export class EdaBlankPanelComponent implements OnInit {
*/

public buildGlobalconfiguration(panelContent: any) {

const modeSQL = panelContent.query.query.modeSQL;
const queryMode = this.selectedQueryMode;
/*SDA CUSTOM*/ this.showHiddenColumn = true;
Expand All @@ -447,11 +448,13 @@ export class EdaBlankPanelComponent implements OnInit {
this.rootTable = this.tables.find((t) => t.table_name == this.rootTable);
// Assert Relation Tables
const currentQuery = panelContent.query.query.fields;

for (const column of currentQuery) {
PanelInteractionUtils.assertTable(this, column);
}

PanelInteractionUtils.handleCurrentQuery2(this);

this.reloadTablesData();
PanelInteractionUtils.loadTableNodes(this);
this.userSelectedTable = undefined;
Expand All @@ -469,6 +472,7 @@ export class EdaBlankPanelComponent implements OnInit {
}
}


this.queryLimit = panelContent.query.query.queryLimit;
PanelInteractionUtils.handleFilters(this, panelContent.query.query);
PanelInteractionUtils.handleFilterColumns(this, panelContent.query.query.filters, panelContent.query.query.fields);
Expand All @@ -488,6 +492,7 @@ export class EdaBlankPanelComponent implements OnInit {
* Updates panel content with actual state
*/
public savePanel() {

this.panel.title = this.pdialog.getTitle();

if (this.panel?.content) {
Expand Down
Loading