-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathItemLabel.vue
More file actions
112 lines (96 loc) · 3.09 KB
/
Copy pathItemLabel.vue
File metadata and controls
112 lines (96 loc) · 3.09 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
<script setup>
import { middleTruncate } from "@ogw_front/utils/string";
const { item, isLeaf } = defineProps({
item: { type: Object, required: true },
isLeaf: { type: Boolean, required: false, default: undefined },
});
const emit = defineEmits(["contextmenu", "mouseenter", "mouseleave"]);
const labelContainer = useTemplateRef("label-container");
const { width: containerWidth } = useElementSize(labelContainer);
const actualItem = computed(() => item.raw || item);
const UUID_END_CHARS = 12;
const ELLIPSIS_LENGTH = 3;
const MIN_START_CHARS = 4;
const displayTitle = computed(() => {
const { title } = actualItem.value;
if (!title) {
return "";
}
// Estimate max characters based on width (approx 9px per char for typical font)
// We subtract some padding/icon space
const estimatedCharWidth = 8.5;
const maxChars = Math.floor(containerWidth.value / estimatedCharWidth);
// Only truncate if the text is longer than what fits
if (title.length <= maxChars) {
return title;
}
// Calculate dynamic start/end based on available space
// For UUIDs, showing the last 12 characters is often useful
const endChars = Math.min(UUID_END_CHARS, Math.floor(maxChars / ELLIPSIS_LENGTH));
const startChars = Math.max(MIN_START_CHARS, maxChars - endChars - ELLIPSIS_LENGTH);
return middleTruncate(title, maxChars, startChars, endChars);
});
const tooltipDisabled = computed(() => {
if (isLeaf !== undefined) {
return !isLeaf;
}
return actualItem.value.children && actualItem.value.children.length > 0;
});
</script>
<template>
<div
ref="label-container"
:data-testid="'treeRow-' + actualItem.id"
class="tree-item-label-container w-100"
>
<v-tooltip :disabled="tooltipDisabled" location="right" open-delay="400">
<template #activator="{ props: tooltipProps }">
<span
v-bind="tooltipProps"
class="tree-item-label"
:class="{ 'inactive-item': actualItem.is_active === false }"
@contextmenu.prevent.stop="emit('contextmenu', $event)"
@mouseenter="emit('mouseenter')"
@mouseleave="emit('mouseleave')"
>
{{ displayTitle }}
</span>
</template>
<div class="d-flex flex-column ga-1">
<span class="text-caption">
<strong class="text-white">ID:</strong> {{ actualItem.id }}
</span>
<span v-if="actualItem.title" class="text-caption">
<strong class="text-white">Name:</strong> {{ actualItem.title }}
</span>
<span class="text-caption">
<strong class="text-white">Status:</strong>
<i class="ml-1">{{ actualItem.is_active ? "Active" : "Inactive" }}</i>
</span>
</div>
</v-tooltip>
</div>
</template>
<style scoped>
.tree-item-label-container {
display: flex;
align-items: center;
min-width: 0;
height: 100%;
width: 100%;
}
.tree-item-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
display: inline-flex;
align-items: center;
cursor: pointer;
font-size: 0.8rem;
}
.inactive-item {
opacity: 0.4;
font-style: italic;
}
</style>