Source

components/shared/MapPopup/MapPopup.vue

<template lang="pug">
    .map_popup
        div
          .modal_header.text-white.justify-content-center
            slot(name="header")
                .header_title {{title}}
        slot
        .modal_sections
            .row.m-0.py-2.font-weight-bold(v-for="section in visibleSections")
                slot(:name="getSectionSlotName(section)")
                .col-12.section_header(
                        v-if="isSectionHeaderVisible(section)"
                        :class="{section_collapsable:isCollapsableSection(section)}"
                        @click="()=>section.collapsed=!section.collapsed")
                    div {{ getSectionTitle(section.title) }}
                    em.collapsible_icon(
                        v-if="isCollapsableSection(section)"
                        :class="section.collapsed? 'fas fa-chevron-up ' : 'fas fa-chevron-down  collapsed'"
                        :aria-expanded="section.collapsed ? 'true' : 'false'"
                        :aria-controls="section.id"
                    )
                b-collapse.col-12(
                    v-if="isCollapsableSection(section)"
                    :id="section.id" v-model="section.collapsed")
                    .col-12
                        .row(v-for="row in section.rows.filter(r=>r.visible!==false)")
                            .col-12.my-1(v-if="row.singleColumn")
                                .row(v-if="row.singleColumn.inline!==undefined||row.singleColumn.inline===true") 
                                    .col-6.p-0.section_label
                                        slot(:name="getColumnSlotName(row.singleColumn)+'_label'")
                                            span {{(row.singleColumn.label&&$t(row.singleColumn.label))||'{label}'}}
                                    .col-6.p-0.section_value
                                        slot(:name="getColumnSlotName(row.singleColumn)" v-bind:value="row.singleColumn.value")
                                            span {{row.singleColumn.value}}
                                .row.section_label(v-if="row.singleColumn.inline===undefined||row.singleColumn.inline===false") 
                                    slot(:name="getColumnSlotName(row.singleColumn)+'_label'")
                                        span {{(row.singleColumn.label&&$t(row.singleColumn.label))||''}}
                                .row.section_value(v-if="row.singleColumn.inline===undefined||row.singleColumn.inline===false")
                                    slot(:name="getColumnSlotName(row.singleColumn)")
                                        span {{row.singleColumn.value}}
                            .col-6.my-1(v-for="col in (row.twoColumns||[])")
                                .row.section_label 
                                    slot(:name="getColumnSlotName(col)+'_label'")
                                        span {{(col.label&&$t(col.label))||'{label}'}}
                                .row.section_value 
                                    slot(:name="getColumnSlotName(col)")
                                        span {{col.value}}




</template>
<script>
import i18n from '@/i18n'
export function createMapPopupMixin(settings = {}) {
  return {
    methods: {
      /**
       * Set values programatically by name
       */
      setPopupSectionValueByName(name, value) {
        let match = null
        ;(
          this[settings.popupSectionsVariableName || 'popupSections'] || []
        ).forEach((section) =>
          (section.rows || []).forEach((row) => {
            match =
              row.singleColumn && row.singleColumn.name === name
                ? row.singleColumn
                : null
            match =
              (row.twoColumns &&
                row.twoColumns.find((col) => col.name === name)) ||
              match
          })
        )
        if (match) {
          match.value = value
        }
      },
    },
  }
}

/**
 * Wrapper to render dynamic sections.
 * For an updated version, check: src/components/shared/DynamicSections.vue
 */
export default {
  props: {
    title: {
      type: String,
      default: 'Title',
    },
    sections: {
      type: Array,
      default: () => [],
    },
  },
  computed: {
    visibleSections() {
      return this.sections.filter(
        (s) => s.visible === undefined || s.visible === true
      )
    },
  },
  mounted() {
    //Hack: Remove undesired href (Leaflet computed close button)
    setTimeout(() => {
      try {
        let el = document.querySelector("a[role=button][href='#close']")
        if (el) {
          el.removeAttribute('href')
        }
      } catch (err) {
        console.error(err)
      }
    }, 1000)
  },
  methods: {
    getSectionTitle(sectionTitle) {
      //Deprecated i18n key code path
      if (i18n.te(`popup.form_builder.sections.${sectionTitle}`)) {
        return this.$t(`popup.form_builder.sections.${sectionTitle}`)
      }

      //New: Give the full i18n code path
      if (i18n.te(sectionTitle)) {
        return this.$t(sectionTitle)
      }

      return sectionTitle
    },
    isSectionHeaderVisible(section) {
      return section.header === undefined || section.header === true
    },
    getColumnSlotName(column) {
      return (
        column.name ||
        (column.label || btoa(JSON.stringify(column))).toLowerCase()
      )
    },
    isCollapsableSection(section) {
      return section.collapsable === undefined || section.collapsable === true
    },
    getSectionSlotName(section) {
      return (
        section.name ||
        (section.title || '').toLowerCase().split(' ').join('_').trim()
      )
    },
  },
}
</script>
<style lang="scss" scoped>
.map_popup {
  position: relative;
}
.modal_header {
  background-color: var(--color-denim);
  display: flex;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  font: normal normal 600 14px/18px Open Sans;
}
.header_title {
  margin: 5px;
  color: white;
  font-weight: bold;
}
.section_label {
  font: normal normal bold 11px/18px Open Sans;
  letter-spacing: 0;
  color: var(--color-tundora);
}
.section_value {
  font: normal normal normal 12px/18px Open Sans;
  color: var(--color-tundora);
}
.section_header {
  position: relative;
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--color-denim);
  font: normal normal bold 14px/18px Open Sans;
}
.section_collapsable {
  cursor: pointer;
}

.modal_sections > div {
  margin-top: 10px;
  border-top: 1px solid rgb(0 0 0 / 10%);
  background-color: white;
}
.modal_sections > div:first-child {
  border-top: 1px solid transparent;
}
</style>