# All files / features/areas/components AreaTreeNode.vue

90.32% Statements 28/31
100% Branches 39/39
83.33% Functions 15/18
88.88% Lines 24/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    26x
    2x

    1x

    2x

    23x

    2x

    1x

    18x

    1x

    18x

    1x

    18x

    1x

    19x

    1x

    2x

    19x

    19x

    19x
    19x
    23x
    24x
    24x
    19x

     <template>
      <li v-if="!isCycle" class="area-tree-node" :class="{ 'is-open': isOpen, 'is-leaf': isLeaf }">
        <article class="area-tree-card">
          <button
            class="tree-toggle"
            type="button"
            :disabled="isLeaf"
            :aria-expanded="isOpen"
            @click="isOpen = !isOpen"
          >
            {{ isLeaf ? "·" : isOpen ? "−" : "+" }}
          </button>

          <div class="area-tree-info">
            <h2>{{ area.display_name }}</h2>
            <p>
              <GnBadge variant="secondary">{{ area.type }}</GnBadge>
              <code>{{ area.alias }}</code>
            </p>
          </div>

          <div class="area-tree-actions">
            <GnButton
              variant="secondary"
              icon="ph-pencil"
              @click="emit('rename', area)"
            >
              Rename
            </GnButton>
            <GnButton
              variant="secondary"
              icon="ph-arrow-up"
              :disabled="area.parent_id == null || area.parent_id === 0"
              @click="emit('unassign', area)"
            >
              Unassign
            </GnButton>
            <GnButton
              variant="danger"
              icon="ph-trash"
              @click="emit('remove', area)"
            >
              Remove
            </GnButton>
            <GnButton
              :variant="isFavorite ? 'warning' : 'secondary'"
              :icon="isFavorite ? 'ph-star' : 'ph-star'"
              @click="favoritesStore.toggle(area.id)"
            >
              {{ isFavorite ? "Unstar" : "Star" }}
            </GnButton>
          </div>
        </article>

        <ul v-if="area.children?.length && isOpen" class="area-tree-children">
          <AreaTreeNode
            v-for="child in area.children"
            :key="child.id"
            :area="child"
            :ancestors="nextAncestors"
            @rename="(a) => emit('rename', a)"
            @remove="(a) => emit('remove', a)"
            @unassign="(a) => emit('unassign', a)"
          />
        </ul>
      </li>
      <li v-else class="area-tree-node">
        <article class="area-tree-card area-tree-cycle">
          Cycle skipped for area ID {{ area.id }}
        </article>
      </li>
    </template>

    <script setup>
    import { computed, ref } from "vue";
    import { useFavoritesStore } from "../../../stores/favorites";
    import { GnBadge, GnButton } from "gnexus-ui-kit/vue";

    const props = defineProps({
      area: {
        type: Object,
        required: true,
      },
      ancestors: {
        type: Array,
        default: () => [],
      },
    });

    const emit = defineEmits(["rename", "remove", "unassign"]);

    const favoritesStore = useFavoritesStore();
    const isOpen = ref(false);
    const isLeaf = computed(() => !props.area.children?.length);
    const isFavorite = computed(() => favoritesStore.has(props.area.id));
    const isCycle = computed(() => props.ancestors.includes(String(props.area.id)));
    const nextAncestors = computed(() => [...props.ancestors, String(props.area.id)]);
    </script>