# Repeater Bone

# Introducción

Componente lógico.

# Código fuente

<script>
import { separateValidPositions } from '../../../mixins/comportamientoPositionCheck'
const validPositions = ['append', 'prepend']
const props = {
  hint: {type: String},
  item: {type: Array, required: true},
  label: {
    type: String,
    default: ''
  },
  readonly: {type: Boolean, default: false},
  items: {type: Array, default: () => ([])},
  required: {type: Boolean, default: false},
  max: {type: Number, default: -1},
  min: {type: Number, default: 1},
  duplicate: {type: Boolean, default: false},
  // logic_delete: {type: Boolean, default: false }, //funcionalidad parcialmente desarrollada (Borrado lógico de filas)
  items_fcn: {type: String},
  comportamientos:{type: Array, required: false},
  args_items_fcn: {
    type: Array,
    default: () => ([])
  },
  id_resolver:{
      type: String
  },
  props: {
    type: Object,
    required: true
  }
}
import { normalizeProps, assignCamelToSnake } from '../../../helpers/propsGenerator';
const mergedProps = normalizeProps(props)
import { endpointIcl, repeaterComponentName } from '../../../constants'
export default {
  name: repeaterComponentName + 'Bone',
  props: mergedProps,
  data() {
    return {
      itemsBoneModified: [],
      loading: false,
      itemsBoneModifiedAux: [],
      usedPosition:[],
      structureError: false
    }
  },
  computed: {
    columnasControl(){
      let mayor = 1
      for (let i in this.item){
        if(this.item[i].props.width > mayor)
          mayor = this.item[i].props.width
      }
      return mayor
    },
  },
  watch: {
    itemsBoneModified: {
      deep: true,
      handler(isItems) {
        this.props.items = isItems
      }
    },
    readonly(isReadonly) {
      if (this.itemsBoneModifiedAux.length === 0 && this.itemsBoneModified.length !== 0)
        this.itemsBoneModifiedAux = JSON.parse(JSON.stringify(this.itemsBoneModified))
      if (isReadonly) {
        this.itemsBoneModified.forEach(campo => {
          campo.forEach(c => {
            c.props.readonly = true
          })
        })
      } else {
        if (this.itemsBoneModifiedAux.length !== 0)
          this.itemsBoneModified = JSON.parse(JSON.stringify(this.itemsBoneModifiedAux))
      }
    }
  },
  methods: {
    moveItem(index, item, moveUp = true) {
      let move = moveUp ? -1 : 1
      this.itemsBoneModified.splice(index, 1)
      this.itemsBoneModified.splice(index + move, 0, item)
    },
    addItem() {
      if(this.readonly)
        return
      if (this.max !== -1 && this.itemsBoneModified.length < this.max || this.max === -1)
        this.add()
    },
    add() {
      let obj = JSON.parse(JSON.stringify(this.item))
      // if(this.logic_delete){ //funcionalidad parcialmente desarrollada (Borrado lógico de filas)
      //   let campoIndex = this.itemsBoneModified.findIndex(item => item.label === 'Index')
      //   if(campoIndex != -1){
      //     let indmax = 0
      //     this.itemsBoneModified.forEach(item => {
      //       item[campoIndex].value > indmax ? indmax = item[campoIndex].value : ''
      //     });
      //     obj[campoIndex].value = indmax + 1
      //   }
      // }
      obj[0].key = (Math.floor(Math.random() * 999) + this.itemsBoneModified.length)
      this.itemsBoneModified.push(obj)
    },
    duplicateItem(item) {
      let itemAux = Object.assign(item)
      this.itemsBoneModified.push(itemAux)
    },
    deleteItem(i) {
      if (this.readonly)
        return
      // if(!this.logic_delete){
      if (this.itemsBoneModified.length > this.min) {
        this.itemsBoneModified.splice(i, 1)
      }
      // }
      // else{ //funcionalidad parcialmente desarrollada (Borrado lógico de filas)
      //   let statusField = this.itemsBoneModified[i].find(campo=> { //TODO To do: revisar funcionalidad
      //     return campo.label === 'Status'
      //   });
      //   statusField.value = false
      // }
    },
    addMinItems() {
      while (this.itemsBoneModified.length < this.min && !this.readonly)
        this.addItem()
    },
    getItems() {
      return this.$iclAxios.post(endpointIcl + this.items_fcn, [
        JSON.stringify({args: this.args_items_fcn, id_usuario: this.$iclstore.state.id_usuario})
      ]).then((res) => {
        res.forEach((item)=>{
          this.$detectResponseStructErrors(item, this.items_fcn, ['props', 'type'], repeaterComponentName, '{props: Object, type: String}', 'https://icl.iridiumrobotics.com.ar/components/ir-repeater.html#uso')
        })
        return res
      }
      ).catch((err) =>{
          console.log(err)
          this.$iclstore.commit('updateSnack', {active: true, text: 'Error al consultar los datos' + (!!this.label ? ' de ' + this.label : ''), color: 'error'})
        }
      ).finally(() =>
        this.loading = false
      )
    },
    async manageItems() {
      this.itemsBoneModified = [...this.items]
      if (typeof this.items_fcn === 'undefined')
        this.addMinItems()
      else {
        this.loading = true
        let res = await this.getItems()
        if (!!res && Array.isArray(res)) {
          res.forEach((itemRes) => {
            itemRes.forEach((rowField, i) => {
              let itemObj = Object.assign(this.item[i])
              if (!itemObj || Object.keys(rowField).toString() !== Object.keys(itemObj).toString()) { // se chequea que los items recibidos en la consulta tengan la misma estructura que this.item
                this.$logErrorComponent(repeaterComponentName, 'Error en la estructura "items_fcn" en IrRepeater, la respuesta no coincide con los campos predefinidos del IrRepeater (propiedad "item") - ' + this.label)
                this.$iclstore.commit('updateSnack', {active: true, text: 'Error al consultar los datos' + (!!this.label ? ' de ' + this.label : ''), color: 'error'})
                return
              }
            })
          })
          this.itemsBoneModified = res
        }
      }
    },
    manageReadonly() {
      if (this.readonly) {
        this.itemsBoneModified.forEach((fila) => {
          fila.forEach((campoFila) => {
            campoFila.props.readonly = true
          })
        })
      }
    },
    async createdFunctions() {
      await this.manageItems()
      this.manageReadonly()
    }
  },
  mounted(){
    this.structureError = this.$propError(props, this.$props, repeaterComponentName)
    if(this.structureError){
      this.$iclstore.commit('updateSnack', {text: 'Ha ocurrido un error al cargar algunos campos del formulario', active: true, color:'warning'})
    }
    this.usedPosition = separateValidPositions(this.comportamientos, validPositions, repeaterComponentName,
    this.$iclRouter.currentRoute.path, this.$logError) // Valida las posiciones válidas para comportamientos
  },
  created() {
    assignCamelToSnake(mergedProps, this)
    this.createdFunctions()
  },
  render() {
    if(this.structureError){
      return
    }
    return this.$scopedSlots.default({
      hint: this.hint,
      item: this.item,
      items: this.itemsBoneModified,
      readonly: this.readonly,
      loading: this.loading,
      addButtonEvent: this.addItem,
      deleteItem: this.deleteItem,
      columnNumber: this.columnasControl,
      moveItem: this.moveItem,
      duplicateItem: this.duplicateItem,
      duplicate: this.duplicate,
      required: this.required,
      label: this.label,
      comportamientos: this.comportamientos,
      comportamientosPositions: this.usedPosition,
      valueType: props.items.type.name.toLowerCase(),
      id_resolver: this.id_resolver,
      comportamientoEvents:{
        changeFieldValue:(e) => {
          this.itemsBoneModified = [...e]
        },
        'close-dialog': (e) => {
          this.$emit('close-dialog', e)
        },
        refresh: () => {
          this.$emit('refresh')
        }
      }
    })
  }
}
</script>
Last Updated: 4/5/2024, 4:52:19 PM