@fy-/fws-vue 2.2.67 → 2.2.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/fws/DataTable.vue +27 -70
- package/components/ui/DefaultPaging.vue +21 -21
- package/package.json +1 -1
|
@@ -4,8 +4,6 @@ import {
|
|
|
4
4
|
ArrowDownTrayIcon,
|
|
5
5
|
ArrowsUpDownIcon,
|
|
6
6
|
ArrowUpIcon,
|
|
7
|
-
MagnifyingGlassIcon,
|
|
8
|
-
XCircleIcon,
|
|
9
7
|
} from '@heroicons/vue/24/solid'
|
|
10
8
|
import { useStorage } from '@vueuse/core'
|
|
11
9
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
@@ -33,7 +31,6 @@ const currentPage = ref<number>(1)
|
|
|
33
31
|
const route = useRoute()
|
|
34
32
|
const data = ref<any[]>([])
|
|
35
33
|
const paging = ref<any>(undefined)
|
|
36
|
-
const searchTerm = ref<string>('')
|
|
37
34
|
const isLoading = ref<boolean>(false)
|
|
38
35
|
const perPageOptions = [
|
|
39
36
|
['10', '10'],
|
|
@@ -90,7 +87,6 @@ async function getData(page: number = 1) {
|
|
|
90
87
|
sort,
|
|
91
88
|
results_per_page: perPage.value,
|
|
92
89
|
page_no: page,
|
|
93
|
-
search: searchTerm.value || undefined, // Only include if not empty
|
|
94
90
|
}
|
|
95
91
|
try {
|
|
96
92
|
const r = await restFunction(props.apiPath, 'GET', requestParams, {
|
|
@@ -175,26 +171,6 @@ function exportToCsv() {
|
|
|
175
171
|
document.body.removeChild(link)
|
|
176
172
|
}
|
|
177
173
|
|
|
178
|
-
function handleSearch() {
|
|
179
|
-
getData(1) // Reset to page 1 when searching
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function clearSearch() {
|
|
183
|
-
searchTerm.value = ''
|
|
184
|
-
getData(1)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Debounced search
|
|
188
|
-
let searchTimeout: number | null = null
|
|
189
|
-
function debouncedSearch() {
|
|
190
|
-
if (searchTimeout) {
|
|
191
|
-
clearTimeout(searchTimeout)
|
|
192
|
-
}
|
|
193
|
-
searchTimeout = window.setTimeout(() => {
|
|
194
|
-
handleSearch()
|
|
195
|
-
}, 400)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
174
|
watch(perPage, () => {
|
|
199
175
|
getData()
|
|
200
176
|
})
|
|
@@ -230,63 +206,32 @@ onUnmounted(() => {
|
|
|
230
206
|
<div class="data-table-container bg-white dark:bg-fv-neutral-900 rounded-lg shadow-sm hover:shadow-md transition-all duration-300 overflow-hidden">
|
|
231
207
|
<!-- Table header with controls -->
|
|
232
208
|
<div class="table-controls p-4 border-b border-fv-neutral-200 dark:border-fv-neutral-800">
|
|
233
|
-
<div class="flex flex-wrap items-center justify-
|
|
234
|
-
<!--
|
|
235
|
-
<div class="
|
|
236
|
-
<div class="relative">
|
|
237
|
-
<input
|
|
238
|
-
v-model="searchTerm"
|
|
239
|
-
type="search"
|
|
240
|
-
class="w-full pl-10 pr-4 py-2 text-sm rounded-lg border border-fv-neutral-300 dark:border-fv-neutral-700 bg-white dark:bg-fv-neutral-800 text-fv-neutral-900 dark:text-white focus:ring-2 focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600 focus:border-fv-primary-500 dark:focus:border-fv-primary-600 transition-colors duration-200"
|
|
241
|
-
:placeholder="$t('search_placeholder')"
|
|
242
|
-
@input="debouncedSearch"
|
|
243
|
-
@keyup.enter="handleSearch"
|
|
244
|
-
>
|
|
245
|
-
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
|
246
|
-
<MagnifyingGlassIcon class="w-4 h-4 text-fv-neutral-500 dark:text-fv-neutral-400" aria-hidden="true" />
|
|
247
|
-
</div>
|
|
248
|
-
<button
|
|
249
|
-
v-if="searchTerm"
|
|
250
|
-
type="button"
|
|
251
|
-
class="absolute inset-y-0 right-0 flex items-center pr-3 text-fv-neutral-500 hover:text-fv-neutral-700 dark:text-fv-neutral-400 dark:hover:text-fv-neutral-200"
|
|
252
|
-
aria-label="Clear search"
|
|
253
|
-
@click="clearSearch"
|
|
254
|
-
>
|
|
255
|
-
<XCircleIcon class="w-5 h-5" aria-hidden="true" />
|
|
256
|
-
</button>
|
|
257
|
-
</div>
|
|
258
|
-
</div>
|
|
259
|
-
|
|
260
|
-
<!-- Export and per page settings -->
|
|
261
|
-
<div class="flex items-center gap-2">
|
|
209
|
+
<div v-if="hasExportableColumns && hasData" class="flex flex-wrap items-center justify-end gap-3">
|
|
210
|
+
<!-- Export button -->
|
|
211
|
+
<div class="flex items-center">
|
|
262
212
|
<button
|
|
263
|
-
v-if="hasExportableColumns && hasData"
|
|
264
213
|
class="export-btn flex items-center justify-center gap-2 px-3 py-2 bg-fv-neutral-100 hover:bg-fv-neutral-200 text-fv-neutral-800 rounded-lg text-sm transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-fv-neutral-400 dark:bg-fv-neutral-800 dark:hover:bg-fv-neutral-700 dark:text-fv-neutral-200"
|
|
265
214
|
@click="exportToCsv"
|
|
266
215
|
>
|
|
267
216
|
<ArrowDownTrayIcon class="w-4 h-4" aria-hidden="true" />
|
|
268
217
|
<span class="hidden sm:inline">{{ $t("global_table_export") }}</span>
|
|
269
218
|
</button>
|
|
270
|
-
|
|
271
|
-
<div class="flex items-center gap-2">
|
|
272
|
-
<label for="perPageSelect" class="text-sm font-medium text-fv-neutral-600 dark:text-fv-neutral-400 whitespace-nowrap hidden sm:block">
|
|
273
|
-
{{ $t("per_page") }}:
|
|
274
|
-
</label>
|
|
275
|
-
<DefaultInput
|
|
276
|
-
id="perPageSelect"
|
|
277
|
-
v-model="perPage"
|
|
278
|
-
:options="perPageOptions"
|
|
279
|
-
:show-label="false"
|
|
280
|
-
type="select"
|
|
281
|
-
class="w-20"
|
|
282
|
-
/>
|
|
283
|
-
</div>
|
|
284
219
|
</div>
|
|
285
220
|
</div>
|
|
286
221
|
|
|
287
222
|
<!-- Pagination - top -->
|
|
288
|
-
<div v-if="hasPaging" class="mt-3">
|
|
223
|
+
<div v-if="hasPaging" class="mt-3 flex flex-wrap justify-between items-center gap-3">
|
|
289
224
|
<DefaultPaging :id="`${props.id}Pages`" :items="paging" />
|
|
225
|
+
<div class="flex items-center">
|
|
226
|
+
<DefaultInput
|
|
227
|
+
id="perPageSelectTop"
|
|
228
|
+
v-model="perPage"
|
|
229
|
+
:options="perPageOptions"
|
|
230
|
+
:show-label="false"
|
|
231
|
+
type="select"
|
|
232
|
+
class="w-20"
|
|
233
|
+
/>
|
|
234
|
+
</div>
|
|
290
235
|
</div>
|
|
291
236
|
</div>
|
|
292
237
|
|
|
@@ -385,7 +330,19 @@ onUnmounted(() => {
|
|
|
385
330
|
|
|
386
331
|
<!-- Pagination - bottom -->
|
|
387
332
|
<div v-if="hasPaging" class="px-4 py-3 border-t border-fv-neutral-200 dark:border-fv-neutral-800">
|
|
388
|
-
<
|
|
333
|
+
<div class="flex flex-wrap justify-between items-center gap-3">
|
|
334
|
+
<DefaultPaging :id="`${props.id}Pages`" :items="paging" />
|
|
335
|
+
<div class="flex items-center">
|
|
336
|
+
<DefaultInput
|
|
337
|
+
id="perPageSelectBottom"
|
|
338
|
+
v-model="perPage"
|
|
339
|
+
:options="perPageOptions"
|
|
340
|
+
:show-label="false"
|
|
341
|
+
type="select"
|
|
342
|
+
class="w-20"
|
|
343
|
+
/>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
389
346
|
</div>
|
|
390
347
|
</div>
|
|
391
348
|
</template>
|
|
@@ -18,7 +18,7 @@ const props = withDefaults(
|
|
|
18
18
|
showLegend?: boolean
|
|
19
19
|
}>(),
|
|
20
20
|
{
|
|
21
|
-
showLegend:
|
|
21
|
+
showLegend: false,
|
|
22
22
|
hash: '',
|
|
23
23
|
},
|
|
24
24
|
)
|
|
@@ -156,7 +156,7 @@ onMounted(() => {
|
|
|
156
156
|
class="flex flex-col items-center justify-center"
|
|
157
157
|
>
|
|
158
158
|
<div class="paging-container w-full">
|
|
159
|
-
<nav aria-label="Pagination" class="mb-
|
|
159
|
+
<nav aria-label="Pagination" class="mb-1 flex justify-center">
|
|
160
160
|
<ul class="pagination-list">
|
|
161
161
|
<!-- Previous Button -->
|
|
162
162
|
<li v-if="items.page_no >= 2" class="pagination-item md:block">
|
|
@@ -167,13 +167,13 @@ onMounted(() => {
|
|
|
167
167
|
title="Previous page"
|
|
168
168
|
@click="prev()"
|
|
169
169
|
>
|
|
170
|
-
<ChevronLeftIcon class="w-
|
|
170
|
+
<ChevronLeftIcon class="w-4 h-4" aria-hidden="true" />
|
|
171
171
|
<span class="sr-only">{{ $t("previous_paging") }}</span>
|
|
172
172
|
</button>
|
|
173
173
|
</li>
|
|
174
174
|
<li v-else class="pagination-item invisible md:hidden">
|
|
175
175
|
<div class="pagination-placeholder">
|
|
176
|
-
<ChevronLeftIcon class="w-
|
|
176
|
+
<ChevronLeftIcon class="w-4 h-4 invisible" aria-hidden="true" />
|
|
177
177
|
</div>
|
|
178
178
|
</li>
|
|
179
179
|
|
|
@@ -267,26 +267,26 @@ onMounted(() => {
|
|
|
267
267
|
title="Next page"
|
|
268
268
|
@click="next()"
|
|
269
269
|
>
|
|
270
|
-
<ChevronRightIcon class="w-
|
|
270
|
+
<ChevronRightIcon class="w-4 h-4" aria-hidden="true" />
|
|
271
271
|
<span class="sr-only">{{ $t("next_paging") }}</span>
|
|
272
272
|
</button>
|
|
273
273
|
</li>
|
|
274
274
|
<li v-else class="pagination-item invisible md:hidden">
|
|
275
275
|
<div class="pagination-placeholder">
|
|
276
|
-
<ChevronRightIcon class="w-
|
|
276
|
+
<ChevronRightIcon class="w-4 h-4 invisible" aria-hidden="true" />
|
|
277
277
|
</div>
|
|
278
278
|
</li>
|
|
279
279
|
</ul>
|
|
280
280
|
</nav>
|
|
281
281
|
|
|
282
282
|
<!-- Mobile page indication (x of y) -->
|
|
283
|
-
<div class="sm:hidden text-center mb-
|
|
284
|
-
<span class="text-
|
|
283
|
+
<div class="sm:hidden text-center mb-1">
|
|
284
|
+
<span class="text-xs font-medium text-fv-neutral-700 dark:text-fv-neutral-200">
|
|
285
285
|
Page {{ items.page_no }} of {{ items.page_max }}
|
|
286
286
|
</span>
|
|
287
287
|
</div>
|
|
288
288
|
|
|
289
|
-
<!-- Results summary -->
|
|
289
|
+
<!-- Results summary - Now defaults to not showing -->
|
|
290
290
|
<p
|
|
291
291
|
v-if="showLegend"
|
|
292
292
|
class="text-xs text-center text-fv-neutral-700 dark:text-fv-neutral-400"
|
|
@@ -306,7 +306,7 @@ onMounted(() => {
|
|
|
306
306
|
|
|
307
307
|
<style scoped>
|
|
308
308
|
.pagination-list {
|
|
309
|
-
@apply inline-flex items-center justify-center gap-
|
|
309
|
+
@apply inline-flex items-center justify-center gap-0.5 shadow-sm rounded-lg;
|
|
310
310
|
}
|
|
311
311
|
|
|
312
312
|
.pagination-item {
|
|
@@ -319,14 +319,14 @@ onMounted(() => {
|
|
|
319
319
|
.pagination-ellipsis,
|
|
320
320
|
.pagination-placeholder {
|
|
321
321
|
@apply flex items-center justify-center;
|
|
322
|
-
min-width:
|
|
323
|
-
height:
|
|
322
|
+
min-width: 1.85rem;
|
|
323
|
+
height: 1.85rem;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
.pagination-link {
|
|
327
|
-
@apply px-
|
|
327
|
+
@apply px-2 py-1 rounded-md text-xs font-medium bg-white border border-fv-neutral-200
|
|
328
328
|
text-fv-neutral-700 hover:bg-fv-neutral-50 hover:text-fv-primary-600
|
|
329
|
-
focus:z-10 focus:outline-none focus:ring-
|
|
329
|
+
focus:z-10 focus:outline-none focus:ring-1 focus:ring-fv-primary-500 focus:ring-offset-1
|
|
330
330
|
transition-colors duration-200
|
|
331
331
|
dark:bg-fv-neutral-800 dark:border-fv-neutral-700 dark:text-fv-neutral-200
|
|
332
332
|
dark:hover:bg-fv-neutral-700 dark:hover:text-white
|
|
@@ -334,34 +334,34 @@ onMounted(() => {
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
.pagination-current {
|
|
337
|
-
@apply px-
|
|
337
|
+
@apply px-2 py-1 rounded-md text-xs font-bold
|
|
338
338
|
bg-fv-primary-100 text-fv-primary-700 border border-fv-primary-300
|
|
339
339
|
dark:bg-fv-primary-900 dark:text-fv-primary-100 dark:border-fv-primary-700;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
.pagination-nav-button {
|
|
343
|
-
@apply p-
|
|
343
|
+
@apply p-1.5 rounded-md text-fv-neutral-600 bg-white border border-fv-neutral-200
|
|
344
344
|
hover:bg-fv-neutral-50 hover:text-fv-primary-600
|
|
345
|
-
focus:z-10 focus:outline-none focus:ring-
|
|
345
|
+
focus:z-10 focus:outline-none focus:ring-1 focus:ring-fv-primary-500 focus:ring-offset-1
|
|
346
346
|
transition-colors duration-200
|
|
347
347
|
dark:bg-fv-neutral-800 dark:border-fv-neutral-700 dark:text-fv-neutral-300
|
|
348
348
|
dark:hover:bg-fv-neutral-700 dark:hover:text-white;
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
.pagination-ellipsis {
|
|
352
|
-
@apply px-
|
|
352
|
+
@apply px-1 py-0.5 text-fv-neutral-500 dark:text-fv-neutral-400;
|
|
353
353
|
}
|
|
354
354
|
|
|
355
355
|
@media (max-width: 640px) {
|
|
356
356
|
.pagination-list {
|
|
357
|
-
@apply gap-
|
|
357
|
+
@apply gap-1;
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
.pagination-link,
|
|
361
361
|
.pagination-button,
|
|
362
362
|
.pagination-current {
|
|
363
|
-
min-width:
|
|
364
|
-
height:
|
|
363
|
+
min-width: 1.65rem;
|
|
364
|
+
height: 1.65rem;
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
</style>
|