Skip to content

Commit 76bd6e7

Browse files
authored
feat: adjust layout and add virtual scroll for plugin detail table (#83)
1 parent 04f4b69 commit 76bd6e7

1 file changed

Lines changed: 101 additions & 87 deletions

File tree

packages/devtools-vite/src/app/components/data/PluginDetailsTable.vue

Lines changed: 101 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -71,94 +71,108 @@ function toggleDurationSortType() {
7171
</script>
7272

7373
<template>
74-
<table w-full border-separate border-spacing-0>
75-
<thead border="b base">
76-
<tr px2 class="[&_th]:(sticky top-0 z10 border-b border-base)">
77-
<th v-if="selectedFields.includes('hookName')" bg-base w32 ws-nowrap p1 text-center font-600>
78-
Hook name
79-
</th>
80-
<th v-if="selectedFields.includes('module')" bg-base min-w100 ws-nowrap p1 text-left font-600>
81-
<button flex="~ row gap1 items-center" w-full>
82-
Module
83-
<VMenu>
84-
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
85-
<i text-xs class="i-carbon-filter" :class="filterModuleTypes.length !== searchFilterTypes.length ? 'text-primary op100' : 'op50'" />
86-
</span>
87-
<template #popper>
88-
<div class="p2" flex="~ col gap2">
89-
<label
90-
v-for="rule of searchFilterTypes"
91-
:key="rule.name"
92-
border="~ base rounded-md" px2 py1
93-
flex="~ items-center gap-1"
94-
select-none
95-
:title="rule.description"
96-
class="cursor-pointer module-type-filter"
97-
>
98-
<input
99-
type="checkbox"
100-
mr1
101-
:checked="filterModuleTypes?.includes(rule.name)"
102-
@change="toggleModuleType(rule)"
103-
>
104-
<div :class="rule.icon" icon-catppuccin />
105-
<div text-sm>{{ rule.description || rule.name }}</div>
106-
</label>
107-
</div>
108-
</template>
109-
</VMenu>
110-
</button>
111-
</th>
112-
<th v-if="selectedFields.includes('startTime')" rounded-tr-2 bg-base ws-nowrap p1 text-center font-600>
113-
Start Time
114-
</th>
115-
<th v-if="selectedFields.includes('endTime')" rounded-tr-2 bg-base ws-nowrap p1 text-center font-600>
116-
End Time
117-
</th>
118-
<th v-if="selectedFields.includes('duration')" rounded-tr-2 bg-base ws-nowrap p1 text-center font-600>
119-
<button flex="~ row gap1 items-center justify-center" w-full @click="toggleDurationSortType">
120-
Duration
74+
<div role="table" w-full>
75+
<div role="row" class="sticky top-0 z10 border-b border-base" flex="~ row">
76+
<div v-if="selectedFields.includes('hookName')" role="columnheader" bg-base flex-none w32 ws-nowrap p1 text-center font-600>
77+
Hook name
78+
</div>
79+
<div v-if="selectedFields.includes('module')" role="columnheader" bg-base flex-1 min-w100 ws-nowrap p1 text-left font-600>
80+
<button flex="~ row gap1 items-center" w-full>
81+
Module
82+
<VMenu>
12183
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
122-
<i text-xs :class="[durationSortType !== 'asc' ? 'i-carbon-arrow-down' : 'i-carbon-arrow-up', durationSortType ? 'op100 text-primary' : 'op50']" />
84+
<i text-xs class="i-carbon-filter" :class="filterModuleTypes.length !== searchFilterTypes.length ? 'text-primary op100' : 'op50'" />
12385
</span>
124-
</button>
125-
</th>
126-
</tr>
127-
</thead>
128-
<tbody v-if="filtered.length">
129-
<tr v-for="(item, index) in filtered" :key="item.id" class="[&_td]:(border-base border-b-1 border-dashed)" :class="[index === filtered.length - 1 ? '[&_td]:(border-b-0)' : '']">
130-
<td v-if="selectedFields.includes('hookName')" w32 ws-nowrap text-center text-sm op80>
131-
{{ HOOK_NAME_MAP[item.type] }}
132-
</td>
133-
<td v-if="selectedFields.includes('module')" min-w100 text-left text-ellipsis line-clamp-2>
134-
<DisplayModuleId
135-
:id="item.module"
136-
w-full border-none
137-
:session="session"
138-
:link="`/session/${session.id}/graph?module=${item.module}`"
139-
hover="bg-active"
140-
border="~ base rounded" block px2 py1
141-
/>
142-
</td>
143-
<td v-if="selectedFields.includes('startTime')" text-center font-mono text-sm min-w52 op80>
144-
<time v-if="item.timestamp_start" :datetime="new Date(item.timestamp_start).toISOString()">{{ normalizeTimestamp(item.timestamp_start) }}</time>
145-
</td>
146-
<td v-if="selectedFields.includes('endTime')" text-center font-mono text-sm min-w52 op80>
147-
<time v-if="item.timestamp_end" :datetime="new Date(item.timestamp_end).toISOString()">{{ normalizeTimestamp(item.timestamp_end) }}</time>
148-
</td>
149-
<td v-if="selectedFields.includes('duration')" text-center text-sm>
150-
<DisplayDuration :duration="item.duration" />
151-
</td>
152-
</tr>
153-
</tbody>
154-
<tbody v-else>
155-
<tr>
156-
<td :colspan="selectedFields.length" p4>
157-
<div w-full h-48 flex="~ items-center justify-center" op50 italic>
158-
No data
86+
<template #popper>
87+
<div class="p2" flex="~ col gap2">
88+
<label
89+
v-for="rule of searchFilterTypes"
90+
:key="rule.name"
91+
border="~ base rounded-md" px2 py1
92+
flex="~ items-center gap-1"
93+
select-none
94+
:title="rule.description"
95+
class="cursor-pointer module-type-filter"
96+
>
97+
<input
98+
type="checkbox"
99+
mr1
100+
:checked="filterModuleTypes?.includes(rule.name)"
101+
@change="toggleModuleType(rule)"
102+
>
103+
<div :class="rule.icon" icon-catppuccin />
104+
<div text-sm>{{ rule.description || rule.name }}</div>
105+
</label>
106+
</div>
107+
</template>
108+
</VMenu>
109+
</button>
110+
</div>
111+
<div v-if="selectedFields.includes('startTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
112+
Start Time
113+
</div>
114+
<div v-if="selectedFields.includes('endTime')" role="columnheader" rounded-tr-2 bg-base flex-none min-w52 ws-nowrap p1 text-center font-600>
115+
End Time
116+
</div>
117+
<div v-if="selectedFields.includes('duration')" role="columnheader" rounded-tr-2 bg-base flex-none ws-nowrap p1 text-center font-600 w-27>
118+
<button flex="~ row gap1 items-center justify-center" w-full @click="toggleDurationSortType">
119+
Duration
120+
<span w-6 h-6 rounded-full cursor-pointer hover="bg-active" flex="~ items-center justify-center">
121+
<i text-xs :class="[durationSortType !== 'asc' ? 'i-carbon-arrow-down' : 'i-carbon-arrow-up', durationSortType ? 'op100 text-primary' : 'op50']" />
122+
</span>
123+
</button>
124+
</div>
125+
</div>
126+
127+
<DataVirtualList
128+
v-if="filtered.length && selectedFields.length"
129+
role="rowgroup"
130+
:items="filtered"
131+
key-prop="id"
132+
>
133+
<template #default="{ item, index }">
134+
<div
135+
role="row"
136+
flex="~ row"
137+
class="border-base border-b-1 border-dashed"
138+
:class="[index === filtered.length - 1 ? 'border-b-0' : '']"
139+
>
140+
<div v-if="selectedFields.includes('hookName')" role="cell" flex="~ items-center justify-center" flex-none w32 ws-nowrap text-sm op80>
141+
{{ HOOK_NAME_MAP[item.type] }}
142+
</div>
143+
<div v-if="selectedFields.includes('module')" role="cell" flex-1 min-w100 text-left text-ellipsis line-clamp-2>
144+
<DisplayModuleId
145+
:id="item.module"
146+
w-full border-none
147+
:session="session"
148+
:link="`/session/${session.id}/graph?module=${item.module}`"
149+
hover="bg-active"
150+
border="~ base rounded" block px2 py1
151+
/>
159152
</div>
160-
</td>
161-
</tr>
162-
</tbody>
163-
</table>
153+
<div v-if="selectedFields.includes('startTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
154+
<time v-if="item.timestamp_start" :datetime="new Date(item.timestamp_start).toISOString()">{{ normalizeTimestamp(item.timestamp_start) }}</time>
155+
</div>
156+
<div v-if="selectedFields.includes('endTime')" role="cell" flex="~ items-center justify-center" flex-none text-center font-mono text-sm min-w52 op80>
157+
<time v-if="item.timestamp_end" :datetime="new Date(item.timestamp_end).toISOString()">{{ normalizeTimestamp(item.timestamp_end) }}</time>
158+
</div>
159+
<div v-if="selectedFields.includes('duration')" role="cell" flex="~ items-center justify-center" flex-none text-center text-sm w-27>
160+
<DisplayDuration :duration="item.duration" />
161+
</div>
162+
</div>
163+
</template>
164+
</DataVirtualList>
165+
<div v-else>
166+
<div p4>
167+
<div w-full h-48 flex="~ items-center justify-center" op50 italic>
168+
<p v-if="!selectedFields.length">
169+
No columns selected
170+
</p>
171+
<p v-else>
172+
No data
173+
</p>
174+
</div>
175+
</div>
176+
</div>
177+
</div>
164178
</template>

0 commit comments

Comments
 (0)