dc/client/src/app/query/query.component.ts
2023-08-03 17:56:34 +02:00

1098 lines
30 KiB
TypeScript

import { Subscription } from 'rxjs'
import {
Component,
AfterViewInit,
AfterContentInit,
OnDestroy,
ChangeDetectorRef,
LOCALE_ID,
Input
} from '@angular/core'
import { SasStoreService } from '../services/sas-store.service'
import { globals } from '../_globals'
import { EventService } from '../services/event.service'
import { registerLocaleData } from '@angular/common'
import localeEnGB from '@angular/common/locales/en-GB'
import { HelperService } from '../services/helper.service'
import { QueryClause } from '../models/TableData'
import { PublicGetcolvalsSASResponse } from '../models/sas/public-getcolvals.model'
import { QueryDateTime } from './models/QueryDateTime.model'
import { isSpecialMissing } from '@sasjs/utils/input/validators'
import { get } from 'lodash-es'
import { OnLoadingMoreEvent } from '../shared/autocomplete/autocomplete.component'
registerLocaleData(localeEnGB)
@Component({
selector: 'app-query',
templateUrl: './query.component.html',
styleUrls: ['./query.component.scss'],
providers: [{ provide: LOCALE_ID, useValue: 'en-GB' }]
})
export class QueryComponent
implements AfterViewInit, AfterContentInit, OnDestroy
{
@Input() caching: boolean = true
@Input() viewboxId: number | undefined
private rows_increment: number = 100
private initial_rows: number = 1000
private columnsSub: Subscription | undefined
private valuesSub: Subscription | undefined
private _removeQry: Subscription | undefined
public cols: Array<any> | undefined
public libds: string | undefined
public variable: string | undefined
public value: string | undefined
public operator: string | undefined
public vals: Array<any> | undefined
public innerWidth: any
public noBorder: any
public clauseAmt: Array<any> = ['']
public numOperators: Array<any> = [
'=',
'<',
'>',
'<=',
'>=',
'BETWEEN',
'IN',
'NOT IN',
'NE'
]
public charOperators: Array<any> = [
'=',
'<',
'>',
'<=',
'>=',
'CONTAINS',
'IN',
'NOT IN',
'NE'
// "LIKE",
// "BEGINS_WITH",
]
public logic: string | undefined
public notIn: boolean = false
public notArr: boolean = true
public wasBetween: boolean = false
public whereClauseLoading: boolean = false
public dynamicWhereClause: boolean = true
public usePickers: boolean = false
private queryObj: {
elements: any[]
clauseLogic?: string
invalidClause?: boolean
} = {
elements: [
{
logic: null,
type: null,
ddtype: null,
variable: null,
operator: null,
value: null,
startrow: 0,
rows: 0,
nobs: 0,
values: <
{
formatted: any
unformatted: any
}[]
>[],
operators: []
}
],
clauseLogic: '',
invalidClause: false
}
public selVar: any = {
index: null,
format: null,
type: null
}
public inObj: Array<any> = [
{
checked: false,
value: null
}
]
public groupLogic: string = 'AND'
public clauses: any = {
queryObj: [this.queryObj],
clauseLogic: [],
groupLogic: this.groupLogic
}
public whereString: string | undefined
public val: any
public whereClause: string | undefined
public logicOperators: Array<string> = ['AND', 'OR']
/**
* Temporary values array used in pickers
* because they need particular format to work
* before sending values to backend, values are parsed
*/
public queryDateTime: QueryDateTime[] = []
public currentClauseIndex: number = -1
public currentQueryIndex: number = -1
public pendingINValuesSet: {
clauseIndex: number
queryIndex: number
} | null = null
constructor(
private sasStoreService: SasStoreService,
private eventService: EventService,
private helperService: HelperService,
private cdf: ChangeDetectorRef
) {
this.innerWidth = window.screen.width
if (this.innerWidth > 768) {
this.noBorder = 'border-left: 2px solid gray;'
}
}
/**
* Gets and sets temporary values selected with DATETIME or TIME picker
* Those values are used for picker to work with format it lieks
* Later before sending values to backend, values are parsed
*/
getQueryDateTime(clauseIndex: number, queryIndex: number): QueryDateTime {
let existingQueryDateTime = this.queryDateTime.find(
(x) => x.clauseIndex === clauseIndex && x.queryIndex === queryIndex
)
if (!existingQueryDateTime) {
const lastIndex =
this.queryDateTime.push({
clauseIndex,
queryIndex,
date: '',
time: ''
}) - 1
existingQueryDateTime = this.queryDateTime[lastIndex]
}
return existingQueryDateTime
}
/**
* When toggling pickers feature we reset the temp picker values array
*/
usePickersChange() {
this.queryDateTime = []
}
/**
* Resets all variables used for filtering
*/
public resetFilter() {
this.whereString = undefined
this.whereClause = undefined
this.queryObj = {
elements: [
{
logic: null,
type: null,
ddtype: null,
variable: null,
operator: null,
value: null,
values: [],
operators: []
}
]
}
this.clauses = {
queryObj: [this.queryObj],
clauseLogic: [],
groupLogic: this.groupLogic
}
this.whereClauseFn(true)
}
/**
* `Globals` are used to store filtering state (variables) as a caching feature
* until browser reloads
*/
public setToGlobals() {
if (!this.caching) return
let objPath = ''
if (globals.rootParam === 'home' || globals.rootParam === 'editor') {
if (this.viewboxId) {
objPath = `viewboxes.${this.viewboxId}`
} else {
objPath = 'editor'
}
} else if (globals.rootParam === 'view') {
objPath = 'viewer'
}
get(globals, objPath).filter.groupLogic = this.groupLogic
if (typeof this.whereClause === 'string') {
get(globals, objPath).filter.whereClause = this.whereClause
}
if (typeof this.libds === 'string') {
get(globals, objPath).filter.libds = this.libds
}
get(globals, objPath).filter.clauses = this.clauses
console.log('globals', globals)
}
/**
* `Globals` are used to store filtering state (variables) as a caching feature
* until browser reloads
*/
public getFromGlobals() {
if (!this.caching) return
let objPath = ''
if (globals.rootParam === 'home' || globals.rootParam === 'editor') {
if (this.viewboxId) {
objPath = `viewboxes.${this.viewboxId}`
} else {
objPath = 'editor'
}
} else if (globals.rootParam === 'view') {
objPath = 'viewer'
}
if (get(globals, objPath).filter.cols.length > 0) {
this.cols = JSON.parse(JSON.stringify(get(globals, objPath).filter.cols))
}
if (get(globals, objPath).filter.vals.length > 0) {
this.vals = JSON.parse(JSON.stringify(get(globals, objPath).filter.vals))
}
if (get(globals, objPath).filter.groupLogic !== '') {
this.groupLogic = get(globals, objPath).filter.groupLogic
this.whereClause = get(globals, objPath).filter.whereClause
this.libds = get(globals, objPath).filter.libds
this.clauses = get(globals, objPath).filter.clauses
this.whereClauseFn()
}
}
/**
* Sets filtering multiple caluses group logic (and / or)
*
* @param groupLogic to set
*/
public setGroupLogic(groupLogic: any) {
this.groupLogic = groupLogic
this.clauses.groupLogic = groupLogic
this.whereClauseFn()
this.setToGlobals()
}
public dateChange(
pickerValue: any,
query: any,
queryIndex: number,
clauseIndex: number,
queryValueIndex?: number
) {
let valueInDays = this.helperService.convertJsDateToSasDate(pickerValue)
if (query.operator === 'BETWEEN' && queryValueIndex !== undefined) {
this.clauses.queryObj[clauseIndex].elements[queryIndex].value[
queryValueIndex
] = valueInDays
}
this.setVariableValues(valueInDays, queryIndex, clauseIndex)
}
public dateTimeChange(
query: any,
queryIndex: number,
clauseIndex: number,
queryValueIndex?: number
) {
const queryDateTime = this.getQueryDateTime(clauseIndex, queryIndex)
if (queryDateTime.date === '') {
if (query.value === '') return
queryDateTime.date = query.value.split(':')[0]
}
const dateHours = parseInt(queryDateTime.time.split(':')[0])
const dateMinutes = parseInt(queryDateTime.time.split(':')[1])
const dateSeconds = parseInt(queryDateTime.time.split(':')[2]) || 0
let dateObject = new Date(queryDateTime.date)
let dateTimeObject = new Date(
dateObject.getFullYear(),
dateObject.getMonth(),
dateObject.getDate(),
dateHours,
dateMinutes,
dateSeconds
)
let valueInSeconds = this.helperService.convertJsDateToSasDate(
dateTimeObject,
'seconds'
)
if (query.operator === 'BETWEEN' && queryValueIndex !== undefined) {
this.clauses.queryObj[clauseIndex].elements[queryIndex].value[
queryValueIndex
] = valueInSeconds
}
this.setVariableValues(valueInSeconds, queryIndex, clauseIndex)
}
public timeChange(
time: any,
query: any,
ind: number,
clauseIndex: number,
queryValueIndex?: number
) {
time = time.target.value
let hours = parseInt(time.split(':')[0])
let minutes = parseInt(time.split(':')[1])
let seconds = parseInt(time.split(':')[2]) || 0
let hourSeconds = hours * 60 * 60
let minuteSeconds = minutes * 60
let inputValue = hourSeconds + minuteSeconds + seconds
if (query.operator === 'BETWEEN' && queryValueIndex !== undefined) {
this.clauses.queryObj[clauseIndex].elements[ind].value[queryValueIndex] =
inputValue
}
this.setVariableValues(inputValue, ind, clauseIndex)
}
/**
* Takes the clause object, removes current clause and makes new array (table)
* ready to be sent to SAS
*/
public dynamicWhereClauseCreator(groupIndex: number, clauseIndex: number) {
let dynamicWhereClauseTable: QueryClause[] = []
if (
this.clauses.queryObj.length > 1 ||
this.clauses.queryObj[groupIndex].elements.length > 1
) {
for (
let groupInd = 0;
groupInd < this.clauses.queryObj.length;
groupInd++
) {
for (
let clauseInd = 0;
clauseInd < this.clauses.queryObj[groupInd].elements.length;
clauseInd++
) {
if (groupInd === groupIndex && clauseInd === clauseIndex) continue
if (
[null, undefined].includes(
this.clauses.queryObj[groupInd].elements[clauseInd].variable
) ||
[null, undefined].includes(
this.clauses.queryObj[groupInd].elements[clauseInd].operator
) ||
[null, undefined].includes(
this.clauses.queryObj[groupInd].elements[clauseInd].value
)
)
continue
let rawValue = ''
const operator =
this.clauses.queryObj[groupInd].elements[clauseInd].operator
const variable =
this.clauses.queryObj[groupInd].elements[clauseInd].variable
if (operator === 'BETWEEN') {
rawValue = `${this.clauses.queryObj[groupInd].elements[clauseInd].value[0]} AND ${this.clauses.queryObj[groupInd][clauseInd].value[1]}`
} else if (operator === 'IN' || operator === 'NOT IN') {
this.clauses.queryObj[groupInd][clauseInd].value.forEach(
(element: any) => {
if (element.checked) {
let value = element.val
if (typeof value === 'string' && !isSpecialMissing(value)) {
if (rawValue.length > 0) {
rawValue += `,'${value}'`
} else {
rawValue = `('${value}'`
}
} else {
if (rawValue.length > 0) {
rawValue += `,${value}`
} else {
rawValue = `(${value}`
}
}
}
}
)
if (rawValue.length > 0) {
rawValue += ')'
}
} else if (
this.clauses.queryObj[groupInd].elements[clauseInd].value === ''
) {
if (
this.clauses.queryObj[groupInd].elements[clauseInd].type ===
'char'
) {
rawValue = `' '`
} else {
rawValue = '.'
}
} else {
if (
this.clauses.queryObj[groupInd].elements[clauseInd].type ===
'char'
) {
rawValue = `'${this.clauses.queryObj[groupInd].elements[clauseInd].value}'`
}
}
dynamicWhereClauseTable.push({
GROUP_LOGIC: this.clauses.groupLogic,
SUBGROUP_LOGIC:
this.clauses.queryObj[groupInd].clauseLogic || 'AND',
SUBGROUP_ID: groupInd,
VARIABLE_NM: variable,
OPERATOR_NM: operator,
RAW_VALUE:
rawValue ||
this.clauses.queryObj[groupInd].elements[clauseInd].value
})
}
}
}
return dynamicWhereClauseTable
}
public async getValuesLoadMore(
event: OnLoadingMoreEvent,
variable: any,
ind: any,
clauseIndex: any
) {
const libds = this.libds || ''
try {
if (this.cols !== undefined) {
for (let index = 0; index < this.cols.length; index++) {
let element = this.cols[index]
if (element.NAME === variable) {
this.selVar.index = index
}
}
const DDTYPE = this.cols[this.selVar.index].DDTYPE
const { startrow: currentStartrow, rows: currentRows } =
this.clauses.queryObj[clauseIndex].elements[ind]
const ROWS_INCREMENT: number = this.rows_increment
const STARTROW = currentStartrow + currentRows
let dynamicWhereClauseTable: any[] = []
if (this.dynamicWhereClause) {
dynamicWhereClauseTable = this.dynamicWhereClauseCreator(
clauseIndex,
ind
)
}
const isDateOrTime = ['DATETIME', 'TIME', 'DATE'].includes(DDTYPE)
this.sasStoreService
.getQueryValues(
variable,
libds,
dynamicWhereClauseTable,
STARTROW,
ROWS_INCREMENT
)
.then((res: PublicGetcolvalsSASResponse) => {
const values = res.vals
const { STARTROW, ROWS, NOBS } = res.meta[0]
this.clauses.queryObj[clauseIndex].elements[ind].startrow = STARTROW
this.clauses.queryObj[clauseIndex].elements[ind].rows = ROWS
this.clauses.queryObj[clauseIndex].elements[ind].nobs = NOBS
if (
!(
values.length === 1 &&
values[0].FORMATTED === '' &&
values[0].UNFORMATTED === ''
)
) {
this.clauses.queryObj[clauseIndex].elements[ind].values.push(
...values.map((item: any) => {
const numeric = res.$vals.vars.UNFORMATTED.type === 'num'
const specialMissing =
numeric && isSpecialMissing(item.UNFORMATTED)
let unformatted = specialMissing
? '.' + item.UNFORMATTED
: item.UNFORMATTED
// If it's not special missing and is numeric and null then it is normal missing `.`
if (numeric && unformatted === null) unformatted = '.'
return {
formatted: isDateOrTime
? item.FORMATTED.split('.')[0]
: item.FORMATTED, //WORKAROUND SHOULD BE FIXED PROPERLY (#413): We will remove the milliseconds inside the formatted value, if decimal exists and it is date, time or datetime ddtype
unformatted: unformatted
}
})
)
const currentValues =
this.clauses.queryObj[clauseIndex].elements[ind].values.length
const moreExists = NOBS - currentValues > 0
event.loadMoreFinished(moreExists)
} else {
event.loadMoreFinished(false)
}
this.whereClauseFn()
this.setToGlobals()
this.whereClauseLoading = false
/**
* If getValues request did not finish when operator was changed to IN, we need to set values after the request is finished.
* Othervise values are not beign populated
*/
if (this.pendingINValuesSet !== null) {
const { clauseIndex, queryIndex } = this.pendingINValuesSet
this.setINValues(clauseIndex, queryIndex)
this.pendingINValuesSet = null
}
this.cdf.detectChanges()
})
.catch((err: any) => {
this.whereClauseLoading = false
})
}
} catch (error) {
this.eventService.catchResponseError('public/getcolvals', error)
}
}
public async getValues(variable: any, ind: any, clauseIndex: any) {
this.whereClauseLoading = true
let libds: string = ''
if (this.libds !== undefined) {
libds = this.libds
}
this.clearValues(ind, clauseIndex)
this.clauses.queryObj[clauseIndex].elements[ind].values = []
this.clauses.queryObj[clauseIndex].elements[ind].value = ''
this.clauses.queryObj[clauseIndex].elements[ind].operator = '='
this.clauses.queryObj[clauseIndex].elements[ind].variable = variable
try {
if (this.cols !== undefined) {
for (let index = 0; index < this.cols.length; index++) {
let element = this.cols[index]
if (element.NAME === variable) {
this.selVar.index = index
}
}
const DDTYPE = this.cols[this.selVar.index].DDTYPE
this.clauses.queryObj[clauseIndex].elements[ind].ddtype = DDTYPE
this.clauses.queryObj[clauseIndex].elements[ind].type =
this.cols[this.selVar.index].TYPE
if (this.clauses.queryObj[clauseIndex].elements[ind].type === 'num') {
this.clauses.queryObj[clauseIndex].elements[ind].operators =
this.numOperators
} else {
this.clauses.queryObj[clauseIndex].elements[ind].operators =
this.charOperators
}
let dynamicWhereClauseTable: any[] = []
if (this.dynamicWhereClause) {
dynamicWhereClauseTable = this.dynamicWhereClauseCreator(
clauseIndex,
ind
)
}
const isDateOrTime = ['DATETIME', 'TIME', 'DATE'].includes(DDTYPE)
this.sasStoreService
.getQueryValues(
variable,
libds,
dynamicWhereClauseTable,
1,
this.initial_rows
)
.then((res: PublicGetcolvalsSASResponse) => {
const values = res.vals
const { STARTROW, ROWS, NOBS } = res.meta[0]
this.clauses.queryObj[clauseIndex].elements[ind].startrow = STARTROW
this.clauses.queryObj[clauseIndex].elements[ind].rows = ROWS
this.clauses.queryObj[clauseIndex].elements[ind].nobs = NOBS
this.clauses.queryObj[clauseIndex].elements[ind].values = values
.map((item: any) => {
const numeric = res.$vals.vars.UNFORMATTED.type === 'num'
const specialMissing =
numeric && isSpecialMissing(item.UNFORMATTED)
let unformatted = specialMissing
? '.' + item.UNFORMATTED
: item.UNFORMATTED
// If it's not special missing and is numeric and null then it is normal missing `.`
if (numeric && unformatted === null) unformatted = '.'
return {
formatted: isDateOrTime
? item.FORMATTED.split('.')[0]
: item.FORMATTED, //WORKAROUND SHOULD BE FIXED PROPERLY (#413): We will remove the milliseconds inside the formatted value, if decimal exists and it is date, time or datetime ddtype
unformatted: unformatted
}
})
.slice(0, 2000)
this.whereClauseFn()
this.setToGlobals()
this.whereClauseLoading = false
/**
* If getValues request did not finish when operator was changed to IN, we need to set values after the request is finished.
* Othervise values are not beign populated
*/
if (this.pendingINValuesSet !== null) {
const { clauseIndex, queryIndex } = this.pendingINValuesSet
this.setINValues(clauseIndex, queryIndex)
this.pendingINValuesSet = null
}
this.cdf.detectChanges()
})
.catch((err: any) => {
this.whereClauseLoading = false
})
}
} catch (error) {
this.eventService.catchResponseError('public/getcolvals', error)
}
}
public getlogic(logic: any) {
this.logic = logic
this.whereClauseFn()
}
public setLogic() {
this.whereClauseFn()
this.setToGlobals()
}
public isArr(val: any) {
return (
val instanceof Array &&
val.length > 0 &&
typeof val[0].checked !== 'undefined'
)
}
public variableInputChange(
queryVariable: any,
index: number,
clauseIndex: number,
event: any
) {
this.getValues(queryVariable, index, clauseIndex)
}
public setVariableValues(valueObj: any, ind: any, clauseIndex: any) {
// clauseIndex is current clause in group clauses, ind is current query in clause
let operator = this.clauses.queryObj[clauseIndex].elements[ind].operator
if (operator !== 'BETWEEN' && operator !== 'IN' && operator !== 'NOT IN') {
this.clauses.queryObj[clauseIndex].elements[ind].value =
valueObj.toString()
}
this.whereClauseFn()
this.setToGlobals()
}
public setVariableOperator(ind: any, operator: any, clauseIndex: any) {
let currentValue = this.clauses.queryObj[clauseIndex].elements[ind].value
if (
currentValue instanceof Array &&
operator !== 'IN' &&
operator !== 'NOT IN'
) {
if (
currentValue instanceof Array &&
currentValue.length === 2 &&
typeof currentValue[0] === 'string'
) {
currentValue = currentValue[0]
} else {
currentValue = ''
}
}
this.clearValuesOperator(ind, clauseIndex)
this.clauses.queryObj[clauseIndex].elements[ind].operator = operator
// tslint:disable-next-line:max-line-length
if (
operator === '=' ||
operator === '>' ||
operator === '<' ||
operator === '<=' ||
operator === '>=' ||
operator === 'NE'
) {
this.clauses.queryObj[clauseIndex].elements[ind].value = currentValue
}
if (operator === 'BETWEEN') {
this.clauses.queryObj[clauseIndex].elements[ind].value = []
this.clauses.queryObj[clauseIndex].elements[ind].value.push(currentValue)
this.clauses.queryObj[clauseIndex].elements[ind].value.push('')
}
if (operator === 'IN' || operator === 'NOT IN') {
this.setINValues(clauseIndex, ind)
}
this.whereClauseFn()
this.setToGlobals()
}
public setINValues(clauseIndex: number, queryIndex: number) {
const vals = []
const inValues =
this.clauses.queryObj[clauseIndex].elements[queryIndex].values
if (inValues.length < 1) {
this.pendingINValuesSet = {
clauseIndex,
queryIndex
}
}
for (let index = 0; index < inValues.length; index++) {
vals.push({ checked: false, val: inValues[index].formatted })
}
this.clauses.queryObj[clauseIndex].elements[queryIndex].value = vals
}
public clearValues(ind: any, clauseIndex: any) {
this.clauses.queryObj[clauseIndex].elements[ind].value = ''
}
public clearValuesOperator(ind: any, clauseIndex: any) {
let operator = this.clauses.queryObj[clauseIndex].elements[ind].operator
if (
operator === 'BETWEEN' ||
operator === 'IN' ||
operator === 'NOT IN' ||
operator === 'CONTAINS'
) {
this.clearValues(ind, clauseIndex)
}
}
/**
* Checks if clause is invalid and sets bool property accordingly
* It is being used in html to mark invalid clauses red
*/
public hasInvalidCluase(clauses: any): boolean {
for (let clause of clauses) {
if (
clause.variable === null ||
clause.operator === null ||
clause.value === null ||
clause.value === ''
) {
clause['invalidClause'] = true
return true
} else {
clause['invalidClause'] = false
}
}
clauses.invalidClause = false
return false
}
/**
* Checks if group clause is invalid and sets bool property accordingly
* It is being used in html to mark invalid group clauses red
*/
public hasInvalidGroupCluase(): boolean {
for (let i = 0; i < this.clauses.queryObj.length; i++) {
if (this.hasInvalidCluase(this.clauses.queryObj[i].elements)) {
this.clauses.queryObj[i].invalidClause = true
return true
} else {
this.clauses.queryObj[i].invalidClause = false
}
}
return false
}
public addClause(clauseIndex: number) {
if (this.hasInvalidCluase(this.clauses.queryObj[clauseIndex].elements)) {
this.eventService.showInfoModal(
'Error',
'Cannot add new clause, when one or more clauses are invalid or empty.'
)
return
}
this.clauseAmt.push('')
this.clauses.queryObj[clauseIndex].elements.push({
logic: null,
type: null,
variable: null,
operator: null,
value: null,
values: [],
operators: []
})
let clauseLogic = this.clauses.queryObj[clauseIndex].clauseLogic
if (typeof clauseLogic === 'undefined') {
this.clauses.queryObj[clauseIndex].clauseLogic = 'AND'
} else if (clauseLogic === 'OR') {
this.clauses.queryObj[clauseIndex].clauseLogic = 'OR'
} else {
this.clauses.queryObj[clauseIndex].clauseLogic = 'AND'
}
this.whereClauseFn()
this.setToGlobals()
}
public addGroupClause() {
if (this.hasInvalidGroupCluase()) {
this.eventService.showInfoModal(
'Error',
'Cannot add new clause, when one or more clauses are invalid or empty.'
)
return
}
this.clauses.queryObj.push({
elements: [
{
logic: null,
type: null,
variable: null,
operator: null,
value: null,
values: [],
operators: []
}
]
})
this.setToGlobals()
}
public isInHtmlCollection(
value: string,
collection: HTMLCollectionOf<HTMLOptionElement>
): boolean {
for (let i = 0; i < collection.length; i++) {
if (collection[i].value === value) return true
}
return false
}
public removeGroupClause(clauseIndex: number) {
this.clauses.queryObj.splice(clauseIndex, 1)
this.whereClauseFn()
}
public removeClause(ind: number, clauseIndex: any) {
this.clauses.queryObj[clauseIndex].elements.splice(ind, 1)
this.whereClauseFn()
this.setToGlobals()
}
public whereClauseFn(reset: boolean = false) {
const clauses = this.helperService.deepClone(this.clauses)
if (reset) clauses.queryObj[0].elements = []
if (this.libds !== undefined) {
let result = this.sasStoreService.whereClauseCreator(
clauses,
this.groupLogic,
this.libds
)
if (!reset) {
this.whereClause = result.whereClause
this.whereString = result.string
}
}
}
async ngAfterViewInit() {
this._removeQry = this.sasStoreService.removeQuery.subscribe((remove) => {
let res = remove
if (this.clauses.queryObj.length >= 1) {
this.clauses.queryObj.length = 1
if (this.clauses.queryObj[0].elements.length >= 1) {
this.clauses.queryObj[0].elements.length = 1
this.clauses.queryObj[0].elements = []
this.clauses.queryObj[0].elements.push({
logic: null,
type: null,
variable: null,
operator: null,
value: null,
values: [],
operators: []
})
this.whereClauseFn()
}
}
})
this.columnsSub = this.sasStoreService.columns.subscribe(
(response: any) => {
let cols = response.data.cols
if (globals.rootParam === 'home' || globals.rootParam === 'editor') {
this.cols = cols
let some = cols[0].NAME
this.libds = response.libds
globals.editor.filter.cols = JSON.parse(JSON.stringify(cols))
}
if (globals.rootParam === 'view') {
if (globals.viewer.filter.cols.length < 1) {
this.cols = cols
let some = cols[0].NAME
this.libds = response.libds
globals.viewer.filter.cols = JSON.parse(JSON.stringify(cols))
}
}
if (!this.libds) {
this.libds = response.libds
}
}
)
this.valuesSub = this.sasStoreService.values.subscribe((res: any) => {
if (globals.rootParam === 'home' || globals.rootParam === 'editor') {
if (globals.editor.filter.vals.length < 1) {
this.vals = res.vals
globals.editor.filter.vals = JSON.parse(JSON.stringify(res.vals))
}
}
if (globals.rootParam === 'view') {
if (globals.viewer.filter.vals.length < 1) {
this.vals = res.vals
globals.viewer.filter.vals = JSON.parse(JSON.stringify(res.vals))
}
}
})
}
onAutocompleteLoadingMore(
event: OnLoadingMoreEvent,
variable: any,
ind: any,
clauseIndex: any
) {
this.getValuesLoadMore(event, variable, ind, clauseIndex)
}
ngAfterContentInit(): void {
this.getFromGlobals()
setTimeout(() => {
let varInput: HTMLElement | null =
document.querySelector('#vals_var_id0_0')
if (varInput) varInput.focus()
}, 500)
}
ngOnDestroy(): void {
if (this.columnsSub) {
this.columnsSub.unsubscribe()
}
if (this.valuesSub) {
this.valuesSub.unsubscribe()
}
}
}