# Iterator Bone

# Introducción

Éste componente no está encargado de renderizar, es de uso interno del componente IrChartIterator. Guía de uso parte lógica

# Código fuente

<script>
  const props = {
    title: {
      type: String,
      default: ''
    },
    titleStyle: {
      type: Object,
      default: () => ({
        fontSize: '40px'
      })
    },
    legendsStyle: {
      type: Object,
      default: () => ({
        fontSize: '16px'
      })
    },
    hasLegends: {
      type: Boolean,
      default: true
    },
    type: {
      type: String,
      default: 'donut'
    },
    iteratorStyle: {
      type: Object,
      required: false
    },
    colors: {
      type: Array,
      required: false
    },
    groups: {
      type: Array,
      default: () => ([])
    },
    items_fcn: {
      type: String,
      required: false
    },
    filtros_fcn: {
      type: String,
      required: false
    },
    args_filtros_fcn: {
      type: String,
      required: false
    },
    filtros: {
      type: Array,
      default: () => ([])
    },
    args_items_fcn: {
      type: Array,
      default: () => ([])
    },
    cache_items: {
      type: Boolean,
      default: true
    },
    id_resolver: {
      type: String,
      required: false
    }
  }
  import { normalizeProps, assignCamelToSnake } from '../../helpers/propsGenerator';
  const mergedProps = normalizeProps(props)
  import { chartIteratorComponentName, defaultColors, externalDBEndpoint, getCamposEndpoint } from '../../constants'
  import fcnResponseHandler from '../../mixins/fcnResponseHandler'
  import { generateLegendsColors } from '../../helpers/mapLegendsColors'
  export default {
    name: chartIteratorComponentName + 'Bone',
    props: mergedProps,
    mixins: [
      fcnResponseHandler
    ],
    data() {
      return {
        loading: false,
        filtrosLocal: [],
        groupsLocal: [],
        onlyLegends: [],
        coloredLegends: [],
        localGroups: [],
        localLegends: [],
        legendGeneratorsByTypes: [
          {
            type: 'donut',
            generator: this.donutLegendGenerator
          },
          {
            type: 'bar',
            generator: this.barLegendGenerator
          },
        ]
      }
    },
    methods: {
      generateLegend() { // determina el generador de leyenda que se va a usar dependiendo del tipo de gráfico que se quiera mostrar
        let type = this.legendGeneratorsByTypes.find( type => type.type === this.type )
        if (!!type)
          return type.generator()
        return []
      },
      // En la siguiente función se generan las leyendas de la forma [legend: '', color: '']
      // Es necesario que se generen independientemente de si se deben mostrar las leyendas o no
      // porque tienen la misma estructura que el arreglo que se utiliza para mapear los colores con cada dato en cada chart
      donutLegendGenerator() { // genera las leyendas para el tipo de gráfico donut
        this.setLegends() // consigue todas las leyendas según los datos de cada gráfico
        this.coloredLegends = generateLegendsColors(this.onlyLegends, this.colors, defaultColors) // mapea los colores con las leyendas
        if (this.hasLegends) // si deben mostrarse las leyendas las devuelve, sino devuelve array vacío
          return this.coloredLegends // devuelve arreglo de leyendas con colores asignados
        else return []
      },
      setLegends() { // consigue todas las leyendas según los datos de cada gráfico
        this.groupsLocal.forEach(( { charts } ) => {
          charts.forEach(( { data } ) => {
            data.forEach(( { key } ) => {
              if (!this.onlyLegends.some(legend => legend === key))
                this.onlyLegends.push(key)
            })
          })
        })
      },
      barLegendGenerator() { // futuro generador de leyendas para gráficos de barra
        return []
      },
      setGroupsData() { // agrega el tipo de gráfico, los colores y las leyendas (en caso de tener) en cada grupo
        let groupsLocal = this.groupsLocal.map(group => {
          if (!!this.hasLegends)
            group = { ...group, groupOptions: { ...group.groupOptions, legends: this.coloredLegends } }
          return { ...group, groupOptions: { ...group.groupOptions, type: this.type, colors: this.coloredLegends } }
        })
        return [ ...groupsLocal ]
      },
      async getFiltros(fcn, args) { // obtiene los filtros
        let argsAux = {
          id_usuario: this.$iclstore.state.id_usuario,
          id_resolver: this.id_resolver ? this.id_resolver : this.$iclRouter.currentRoute.path,
          ...args
        }
        return this.$iclAxios.post(getCamposEndpoint + fcn, [JSON.stringify(argsAux)]
        ).then(rsp => {
          return rsp
        }).catch((error) => {
          console.log(error)
          this.$logErrorComponent(chartIteratorComponentName, 'Ocurrió un error en la consulta de los campos.')
          return this.filtros
        })
      },
      getItems(fcn, filters, args) { // obtiene los items
        this.loading = true
        let params = {
          filtros: filters,
          args,
          id_usuario: this.$iclstore.state.id_usuario,
          id_resolver: this.id_resolver ? this.id_resolver : this.$iclRouter.currentRoute.path
        }
        this.$iclAxios.post(externalDBEndpoint + fcn, [JSON.stringify(params)]
        ).then(rsp => {
          this.handleSuccess(rsp, () => {}, {
            iclRouter: this.$iclRouter,
            iclstore: this.$iclstore,
            ctx: this, //En caso de options api pasar ctx
            handleSuccessResponse: this.handleSuccessResponse
          })
          this.$detectResponseStructErrors(rsp, fcn, [], 'IrDataCardBone', '{ <propName>: Any }', 'https://icl.iridiumrobotics.com.ar/components/ir-data-table.html#uso') //En caso de detección de errores en la respuesta NO interrumpe la ejecución del componente, solo loguea.
          if (rsp === null || rsp.length === 0 || ((typeof rsp[0][fcn]) !== 'undefined' && rsp[0][fcn] === null))
            rsp = Object.assign([])
          this.groupsLocal = rsp
          this.assignlocalValues()
        }).catch((error) => {
          this.handleError(error, this.$iclstore)
          console.log(error)
        }).finally(() => {
          this.loading = false
        })
      },
      assignlocalValues() {
        this.localLegends = this.generateLegend()
        this.localGroups = this.setGroupsData()
      },
      async createdFunctions() { // controla que se haya recibido una función para obtener los items
        if(!!this.items_fcn && this.$iclAxios) {
          if ((typeof this.filtros_fcn) !== 'undefined') {
            let datosFiltros = this.$iclstore.getters.getDatosSitios({sitio: this.$iclRouter.app._route.path, query: this.filtros_fcn, method: 'post', params: this.args_filtros_fcn})
            if (datosFiltros !== null) { // los busca en el store, si los encuentra los guarda en filtrosLocal hasta que se termine de hacer la consulta por los filtros
              datosFiltros = Object.assign({}, JSON.parse(datosFiltros.response))
              this.filtrosLocal = datosFiltros[0].props.campos
            }
            this.filtrosLocal = await this.getFiltros(this.filtros_fcn, this.args_filtros_fcn)
          } else
            this.filtrosLocal = this.filtros
          let params = {filtros: this.filtrosLocal, args: this.args_items_fcn}
          let datosSitio = this.$iclstore.getters.getDatosSitios({sitio: this.$iclRouter.app._route.path, query: this.items_fcn, method: 'get', params: [JSON.stringify(params)]})
          if (datosSitio !== null && this.cache_items && datosSitio.response !== null) // los busca en el store, si los encuentra los guarda en groupsLocal hasta que se termine de hacer la consulta por los items
            this.groupsLocal = [...datosSitio.response]
          await this.getItems(this.items_fcn, this.filtrosLocal, this.args_items_fcn)
        } else { // si no se envía items_fcn se asigna a groupsLocal la propiedad items
          let isFiltrosValid = (typeof this.filtros_fcn) !== 'undefined' || this.filtros.length > 0
          let isItemsFcnValid = (typeof this.items_fcn) !== 'undefined' || this.items_fcn !== null || this.items_fcn !== ''
          if (isFiltrosValid && !isItemsFcnValid)
            this.$logErrorComponent(chartIteratorComponentName, 'Se quiso renderizar un formulario de filtros pero no se detalló alguna función en la propiedad "items_fcn".')
          this.groupsLocal = this.groups
          this.assignlocalValues()
        }
      },
    },
    created() {
      assignCamelToSnake(mergedProps, this)
      this.createdFunctions()
    },
    render() {
      return this.$scopedSlots.default({
        title: this.title,
        legends: this.localLegends,
        groups: this.localGroups,
        filtros: this.filtrosLocal,
        titleStyle: this.titleStyle,
        legendsStyle: this.legendsStyle,
        iteratorStyle: this.iteratorStyle,
        submitForm: {
          click: () => {
            this.getItems(this.items_fcn, this.filtrosLocal, this.args_items_fcn)
          }
        }
      })
    },
  }
</script>
Last Updated: 4/5/2024, 4:52:19 PM