@iankibetsh/shframework 5.8.3 → 5.8.4
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/README.md +3 -0
- package/dist/dist/library.mjs.css +50 -47
- package/dist/library.js +177 -27
- package/dist/library.mjs +178 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,6 +22,9 @@ A robust table component that handles server-side pagination, searching, and cus
|
|
|
22
22
|
- **Auto-Label Generation**: Automatically generates human-readable labels from keys if not explicitly provided (e.g., `user.first_name` becomes "First Name").
|
|
23
23
|
- **Named Slots for Custom Formatting**: Use named slots for columns to provide custom formatting (e.g., `<template #age="{ row }">`).
|
|
24
24
|
- **Multi-Action Support**: Enable row selection and collective operations with a floating action bar.
|
|
25
|
+
- **Caching & Background Loading**: Uses IndexedDB to cache data. Shows cached data immediately while fetching fresh data in the background (enabled via `enableTableCache` config or `:cache="true"` prop).
|
|
26
|
+
- **Row Links**: Easily define clickable rows with dynamic placeholders (e.g., `:row-link="'/users/{id}'"`).
|
|
27
|
+
- **Search Optimization**: Automatically clears stale data and shows a spinner when searching to ensure fresh results.
|
|
25
28
|
- **Links & Actions**: Easily define column links and action buttons.
|
|
26
29
|
|
|
27
30
|
```html
|
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
|
|
2
|
+
.sh-phone{
|
|
3
|
+
display: flex;
|
|
4
|
+
width: 100%;
|
|
5
|
+
align-items: center;
|
|
6
|
+
padding: 0 0.25rem;
|
|
7
|
+
}
|
|
8
|
+
.phone-country{
|
|
9
|
+
width: 2rem;
|
|
10
|
+
border: none;
|
|
11
|
+
align-self: center;
|
|
12
|
+
outline: none !important;
|
|
13
|
+
padding: 0.4rem;
|
|
14
|
+
border-right: 1px solid #0003;
|
|
15
|
+
}
|
|
16
|
+
.phone-number{
|
|
17
|
+
width: calc(100% - 2.2rem);
|
|
18
|
+
border: none;
|
|
19
|
+
align-self: center;
|
|
20
|
+
outline: none;
|
|
21
|
+
margin-bottom: 0;
|
|
22
|
+
padding: 0.4rem;
|
|
23
|
+
}
|
|
24
|
+
.sh-phone img{
|
|
25
|
+
padding: 0.125rem;
|
|
26
|
+
width: 2rem;
|
|
27
|
+
height: 2rem;
|
|
28
|
+
}
|
|
29
|
+
.phone-number::placeholder{
|
|
30
|
+
font-weight: 300;
|
|
31
|
+
opacity: 0.5;
|
|
32
|
+
}
|
|
33
|
+
|
|
2
34
|
/* Step Container */
|
|
3
35
|
.sh-form-steps-container {
|
|
4
36
|
margin-bottom: 2.5rem;
|
|
@@ -300,53 +332,8 @@
|
|
|
300
332
|
z-index: 1050;
|
|
301
333
|
min-width: 300px;
|
|
302
334
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
display: flex;
|
|
306
|
-
width: 100%;
|
|
307
|
-
align-items: center;
|
|
308
|
-
padding: 0 0.25rem;
|
|
309
|
-
}
|
|
310
|
-
.phone-country{
|
|
311
|
-
width: 2rem;
|
|
312
|
-
border: none;
|
|
313
|
-
align-self: center;
|
|
314
|
-
outline: none !important;
|
|
315
|
-
padding: 0.4rem;
|
|
316
|
-
border-right: 1px solid #0003;
|
|
317
|
-
}
|
|
318
|
-
.phone-number{
|
|
319
|
-
width: calc(100% - 2.2rem);
|
|
320
|
-
border: none;
|
|
321
|
-
align-self: center;
|
|
322
|
-
outline: none;
|
|
323
|
-
margin-bottom: 0;
|
|
324
|
-
padding: 0.4rem;
|
|
325
|
-
}
|
|
326
|
-
.sh-phone img{
|
|
327
|
-
padding: 0.125rem;
|
|
328
|
-
width: 2rem;
|
|
329
|
-
height: 2rem;
|
|
330
|
-
}
|
|
331
|
-
.phone-number::placeholder{
|
|
332
|
-
font-weight: 300;
|
|
333
|
-
opacity: 0.5;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
.sh-selected-item{
|
|
337
|
-
line-height: unset!important;
|
|
338
|
-
}
|
|
339
|
-
.sh-suggestion-input{
|
|
340
|
-
padding: 0.375rem 0.75rem;
|
|
341
|
-
}
|
|
342
|
-
.sh-suggest{
|
|
343
|
-
margin-bottom: 1rem;
|
|
344
|
-
padding: 0rem 0rem;
|
|
345
|
-
}
|
|
346
|
-
.sh-suggest-control::after{
|
|
347
|
-
margin-top: auto;
|
|
348
|
-
margin-bottom: auto;
|
|
349
|
-
margin-right: 0.255em;
|
|
335
|
+
.cursor-pointer {
|
|
336
|
+
cursor: pointer;
|
|
350
337
|
}
|
|
351
338
|
|
|
352
339
|
.permissions-main {
|
|
@@ -381,6 +368,22 @@
|
|
|
381
368
|
flex-grow: 1;
|
|
382
369
|
}
|
|
383
370
|
|
|
371
|
+
.sh-selected-item{
|
|
372
|
+
line-height: unset!important;
|
|
373
|
+
}
|
|
374
|
+
.sh-suggestion-input{
|
|
375
|
+
padding: 0.375rem 0.75rem;
|
|
376
|
+
}
|
|
377
|
+
.sh-suggest{
|
|
378
|
+
margin-bottom: 1rem;
|
|
379
|
+
padding: 0rem 0rem;
|
|
380
|
+
}
|
|
381
|
+
.sh-suggest-control::after{
|
|
382
|
+
margin-top: auto;
|
|
383
|
+
margin-bottom: auto;
|
|
384
|
+
margin-right: 0.255em;
|
|
385
|
+
}
|
|
386
|
+
|
|
384
387
|
.callout{
|
|
385
388
|
--bs-link-color-rgb: 110,168,254;
|
|
386
389
|
--bs-code-color: #e685b5;
|
package/dist/library.js
CHANGED
|
@@ -19,7 +19,7 @@ var Swal__default = /*#__PURE__*/_interopDefaultLegacy(Swal);
|
|
|
19
19
|
var NProgress__default = /*#__PURE__*/_interopDefaultLegacy(NProgress);
|
|
20
20
|
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
21
21
|
|
|
22
|
-
function setItem (key, value) {
|
|
22
|
+
function setItem$1 (key, value) {
|
|
23
23
|
let toStore = value;
|
|
24
24
|
if (typeof value === 'object') {
|
|
25
25
|
toStore = JSON.stringify(value);
|
|
@@ -27,20 +27,20 @@ function setItem (key, value) {
|
|
|
27
27
|
return localStorage.setItem(key, toStore)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function getItem (key) {
|
|
30
|
+
function getItem$1 (key) {
|
|
31
31
|
try {
|
|
32
32
|
return JSON.parse(localStorage.getItem(key))
|
|
33
33
|
} catch (err) {
|
|
34
34
|
return localStorage.getItem(key)
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
function removeItem (key) {
|
|
37
|
+
function removeItem$1 (key) {
|
|
38
38
|
return localStorage.removeItem(key)
|
|
39
39
|
}
|
|
40
40
|
var shStorage = {
|
|
41
|
-
setItem,
|
|
42
|
-
getItem,
|
|
43
|
-
removeItem
|
|
41
|
+
setItem: setItem$1,
|
|
42
|
+
getItem: getItem$1,
|
|
43
|
+
removeItem: removeItem$1
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
function swalSuccess(message){
|
|
@@ -5464,6 +5464,112 @@ function render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
5464
5464
|
script$e.render = render$1;
|
|
5465
5465
|
script$e.__file = "src/lib/components/list_templates/Pagination.vue";
|
|
5466
5466
|
|
|
5467
|
+
const DB_NAME = 'ShTableCacheDB';
|
|
5468
|
+
const STORE_NAME = 'table_cache';
|
|
5469
|
+
const DB_VERSION = 1;
|
|
5470
|
+
|
|
5471
|
+
let dbPromise = null;
|
|
5472
|
+
|
|
5473
|
+
function getDB() {
|
|
5474
|
+
if (dbPromise) return dbPromise;
|
|
5475
|
+
|
|
5476
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
5477
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
5478
|
+
|
|
5479
|
+
request.onupgradeneeded = (event) => {
|
|
5480
|
+
const db = event.target.result;
|
|
5481
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
5482
|
+
db.createObjectStore(STORE_NAME);
|
|
5483
|
+
}
|
|
5484
|
+
};
|
|
5485
|
+
|
|
5486
|
+
request.onsuccess = (event) => {
|
|
5487
|
+
resolve(event.target.result);
|
|
5488
|
+
};
|
|
5489
|
+
|
|
5490
|
+
request.onerror = (event) => {
|
|
5491
|
+
console.error('IndexedDB error:', event.target.error);
|
|
5492
|
+
reject(event.target.error);
|
|
5493
|
+
};
|
|
5494
|
+
});
|
|
5495
|
+
|
|
5496
|
+
return dbPromise;
|
|
5497
|
+
}
|
|
5498
|
+
|
|
5499
|
+
async function setItem(key, value) {
|
|
5500
|
+
try {
|
|
5501
|
+
const db = await getDB();
|
|
5502
|
+
return new Promise((resolve, reject) => {
|
|
5503
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5504
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5505
|
+
const request = store.put(value, key);
|
|
5506
|
+
|
|
5507
|
+
request.onsuccess = () => resolve();
|
|
5508
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5509
|
+
});
|
|
5510
|
+
} catch (error) {
|
|
5511
|
+
console.error('ShIndexedDB setItem error:', error);
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
5514
|
+
|
|
5515
|
+
async function getItem(key, defaultValue = null) {
|
|
5516
|
+
try {
|
|
5517
|
+
const db = await getDB();
|
|
5518
|
+
return new Promise((resolve, reject) => {
|
|
5519
|
+
const transaction = db.transaction([STORE_NAME], 'readonly');
|
|
5520
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5521
|
+
const request = store.get(key);
|
|
5522
|
+
|
|
5523
|
+
request.onsuccess = (event) => {
|
|
5524
|
+
resolve(event.target.result !== undefined ? event.target.result : defaultValue);
|
|
5525
|
+
};
|
|
5526
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5527
|
+
});
|
|
5528
|
+
} catch (error) {
|
|
5529
|
+
console.error('ShIndexedDB getItem error:', error);
|
|
5530
|
+
return defaultValue;
|
|
5531
|
+
}
|
|
5532
|
+
}
|
|
5533
|
+
|
|
5534
|
+
async function removeItem(key) {
|
|
5535
|
+
try {
|
|
5536
|
+
const db = await getDB();
|
|
5537
|
+
return new Promise((resolve, reject) => {
|
|
5538
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5539
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5540
|
+
const request = store.delete(key);
|
|
5541
|
+
|
|
5542
|
+
request.onsuccess = () => resolve();
|
|
5543
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5544
|
+
});
|
|
5545
|
+
} catch (error) {
|
|
5546
|
+
console.error('ShIndexedDB removeItem error:', error);
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
|
|
5550
|
+
async function clear() {
|
|
5551
|
+
try {
|
|
5552
|
+
const db = await getDB();
|
|
5553
|
+
return new Promise((resolve, reject) => {
|
|
5554
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5555
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5556
|
+
const request = store.clear();
|
|
5557
|
+
|
|
5558
|
+
request.onsuccess = () => resolve();
|
|
5559
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5560
|
+
});
|
|
5561
|
+
} catch (error) {
|
|
5562
|
+
console.error('ShIndexedDB clear error:', error);
|
|
5563
|
+
}
|
|
5564
|
+
}
|
|
5565
|
+
|
|
5566
|
+
var shIndexedDB = {
|
|
5567
|
+
setItem,
|
|
5568
|
+
getItem,
|
|
5569
|
+
removeItem,
|
|
5570
|
+
clear
|
|
5571
|
+
};
|
|
5572
|
+
|
|
5467
5573
|
const _hoisted_1$b = { class: "auto-table mt-2" };
|
|
5468
5574
|
const _hoisted_2$8 = {
|
|
5469
5575
|
key: 0,
|
|
@@ -5648,6 +5754,10 @@ var script$d = {
|
|
|
5648
5754
|
selectedRange: [Object, null],
|
|
5649
5755
|
noRecordsMessage: [String, null],
|
|
5650
5756
|
multiActions: { type: Array, default: () => [] },
|
|
5757
|
+
// Caching configuration: true to enable, false to disable. If null, respects global configure 'enableTableCache'
|
|
5758
|
+
cache: { type: Boolean, default: null },
|
|
5759
|
+
// Dynamic link for the entire row. Supports placeholders like '/user/{id}'
|
|
5760
|
+
rowLink: [String, null],
|
|
5651
5761
|
},
|
|
5652
5762
|
emits: ["rowSelected", "dataReloaded", "dataLoaded"],
|
|
5653
5763
|
setup(__props, { emit: __emit }) {
|
|
@@ -5706,7 +5816,7 @@ const hasRecordsSlot = vue.computed(() => !!slots.records);
|
|
|
5706
5816
|
const hasEmptySlot = vue.computed(() => !!slots.empty);
|
|
5707
5817
|
|
|
5708
5818
|
// --- Lifecycle
|
|
5709
|
-
vue.onMounted(() => {
|
|
5819
|
+
vue.onMounted(async () => {
|
|
5710
5820
|
if (props.headers) tableHeaders.value = props.headers;
|
|
5711
5821
|
|
|
5712
5822
|
if (props.actions?.actions) {
|
|
@@ -5715,7 +5825,7 @@ vue.onMounted(() => {
|
|
|
5715
5825
|
});
|
|
5716
5826
|
}
|
|
5717
5827
|
|
|
5718
|
-
if (
|
|
5828
|
+
if (shouldCache.value) await setCachedData();
|
|
5719
5829
|
|
|
5720
5830
|
reloadData();
|
|
5721
5831
|
|
|
@@ -5793,14 +5903,28 @@ const canvasClosed = () => {
|
|
|
5793
5903
|
selectedRecord.value = null;
|
|
5794
5904
|
};
|
|
5795
5905
|
|
|
5906
|
+
const router = vueRouter.useRouter();
|
|
5796
5907
|
const rowSelected = (row) => {
|
|
5797
5908
|
selectedRecord.value = null;
|
|
5798
5909
|
setTimeout(() => {
|
|
5799
5910
|
selectedRecord.value = row;
|
|
5800
5911
|
emit("rowSelected", row);
|
|
5912
|
+
if (props.rowLink) {
|
|
5913
|
+
router.push(replaceRowLink(props.rowLink, row));
|
|
5914
|
+
}
|
|
5801
5915
|
}, 100);
|
|
5802
5916
|
};
|
|
5803
5917
|
|
|
5918
|
+
const replaceRowLink = (p, obj) => {
|
|
5919
|
+
let path = p;
|
|
5920
|
+
const matches = path.match(/\{(.*?)\}/g);
|
|
5921
|
+
matches?.forEach((k) => {
|
|
5922
|
+
const key = k.replace("{", "").replace("}", "");
|
|
5923
|
+
path = path.replace(`{${key}}`, obj[key]);
|
|
5924
|
+
});
|
|
5925
|
+
return path;
|
|
5926
|
+
};
|
|
5927
|
+
|
|
5804
5928
|
const changeKey = (key, value) => {
|
|
5805
5929
|
if (key === "order_by") {
|
|
5806
5930
|
order_by.value = value;
|
|
@@ -5941,20 +6065,46 @@ const exportData = () => {
|
|
|
5941
6065
|
});
|
|
5942
6066
|
};
|
|
5943
6067
|
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
6068
|
+
// Attempts to load data from IndexedDB before API call
|
|
6069
|
+
const setCachedData = async () => {
|
|
6070
|
+
if (shouldCache.value) {
|
|
6071
|
+
const cached = await shIndexedDB.getItem(computedCacheKey.value, null);
|
|
6072
|
+
if (cached) {
|
|
6073
|
+
records.value = cached;
|
|
6074
|
+
// Set to 'done' immediately to show cached data without initial spinner
|
|
6075
|
+
loading.value = "done";
|
|
6076
|
+
}
|
|
5947
6077
|
}
|
|
5948
6078
|
};
|
|
5949
6079
|
|
|
6080
|
+
// Determines if caching should be active based on component props or global configuration
|
|
6081
|
+
const shouldCache = vue.computed(() => {
|
|
6082
|
+
if (props.cache !== null) return props.cache;
|
|
6083
|
+
return shRepo.getShConfig("enableTableCache", false);
|
|
6084
|
+
});
|
|
6085
|
+
|
|
6086
|
+
// Generates a unique, slug-safe key for IndexedDB storage
|
|
6087
|
+
const computedCacheKey = vue.computed(() => {
|
|
6088
|
+
if (props.cacheKey) return "sh_table_cache_" + props.cacheKey;
|
|
6089
|
+
const keyBase = props.endPoint || props.query || "default";
|
|
6090
|
+
const safeBase = keyBase.replace(/[^a-z0-9]/gi, "_").toLowerCase();
|
|
6091
|
+
return "sh_table_cache_" + safeBase;
|
|
6092
|
+
});
|
|
6093
|
+
|
|
5950
6094
|
// Main loader
|
|
6095
|
+
// Main data fetcher. Handles background updates when cache is present
|
|
5951
6096
|
const reloadData = (newPage, append) => {
|
|
5952
6097
|
if (typeof newPage !== "undefined") page.value = newPage;
|
|
5953
6098
|
|
|
5954
|
-
|
|
6099
|
+
// If we have cached data and not searching, we don't show the initial loading spinner
|
|
6100
|
+
if (shouldCache.value && records.value && records.value.length > 0 && !filter_value.value) {
|
|
5955
6101
|
loading.value = "done";
|
|
5956
6102
|
} else if (!append) {
|
|
5957
6103
|
loading.value = "loading";
|
|
6104
|
+
// Clear records when searching to ensure we show fresh results
|
|
6105
|
+
if (filter_value.value) {
|
|
6106
|
+
records.value = [];
|
|
6107
|
+
}
|
|
5958
6108
|
}
|
|
5959
6109
|
|
|
5960
6110
|
let data = {
|
|
@@ -5993,8 +6143,8 @@ const reloadData = (newPage, append) => {
|
|
|
5993
6143
|
const response = req.data.data;
|
|
5994
6144
|
emit("dataLoaded", response);
|
|
5995
6145
|
|
|
5996
|
-
if (page.value < 2 &&
|
|
5997
|
-
|
|
6146
|
+
if (page.value < 2 && shouldCache.value) {
|
|
6147
|
+
shIndexedDB.setItem(computedCacheKey.value, response.data);
|
|
5998
6148
|
}
|
|
5999
6149
|
|
|
6000
6150
|
pagination_data.value = {
|
|
@@ -6179,7 +6329,7 @@ return (_ctx, _cache) => {
|
|
|
6179
6329
|
: vue.createCommentVNode("v-if", true),
|
|
6180
6330
|
(hasDefaultSlot.value)
|
|
6181
6331
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
|
|
6182
|
-
(loading.value === 'loading')
|
|
6332
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6183
6333
|
? (vue.openBlock(), vue.createElementBlock("div", _hoisted_9$2, [...(_cache[13] || (_cache[13] = [
|
|
6184
6334
|
vue.createElementVNode("div", {
|
|
6185
6335
|
class: "spinner-border",
|
|
@@ -6188,12 +6338,12 @@ return (_ctx, _cache) => {
|
|
|
6188
6338
|
vue.createElementVNode("span", { class: "visually-hidden" }, "Loading...")
|
|
6189
6339
|
], -1 /* CACHED */)
|
|
6190
6340
|
]))]))
|
|
6191
|
-
: (loading.value === 'error')
|
|
6341
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6192
6342
|
? (vue.openBlock(), vue.createElementBlock("div", _hoisted_10$2, [
|
|
6193
6343
|
vue.createElementVNode("span", null, vue.toDisplayString(loading_error.value), 1 /* TEXT */)
|
|
6194
6344
|
]))
|
|
6195
6345
|
: vue.createCommentVNode("v-if", true),
|
|
6196
|
-
(loading.value === 'done')
|
|
6346
|
+
(loading.value === 'done' || records.value.length > 0)
|
|
6197
6347
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
|
|
6198
6348
|
(records.value.length === 0)
|
|
6199
6349
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
|
|
@@ -6217,7 +6367,7 @@ return (_ctx, _cache) => {
|
|
|
6217
6367
|
], 64 /* STABLE_FRAGMENT */))
|
|
6218
6368
|
: (hasRecordsSlot.value)
|
|
6219
6369
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 3 }, [
|
|
6220
|
-
(loading.value === 'loading' &&
|
|
6370
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6221
6371
|
? (vue.openBlock(), vue.createElementBlock("div", _hoisted_12$1, [...(_cache[15] || (_cache[15] = [
|
|
6222
6372
|
vue.createElementVNode("div", {
|
|
6223
6373
|
class: "spinner-border",
|
|
@@ -6226,12 +6376,12 @@ return (_ctx, _cache) => {
|
|
|
6226
6376
|
vue.createElementVNode("span", { class: "visually-hidden" }, "Loading...")
|
|
6227
6377
|
], -1 /* CACHED */)
|
|
6228
6378
|
]))]))
|
|
6229
|
-
: (loading.value === 'error' &&
|
|
6379
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6230
6380
|
? (vue.openBlock(), vue.createElementBlock("div", _hoisted_13$1, [
|
|
6231
6381
|
vue.createElementVNode("span", null, vue.toDisplayString(loading_error.value), 1 /* TEXT */)
|
|
6232
6382
|
]))
|
|
6233
6383
|
: vue.createCommentVNode("v-if", true),
|
|
6234
|
-
(loading.value === 'done' ||
|
|
6384
|
+
(loading.value === 'done' || records.value.length > 0)
|
|
6235
6385
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
|
|
6236
6386
|
(!records.value || records.value.length === 0)
|
|
6237
6387
|
? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
|
|
@@ -6308,7 +6458,7 @@ return (_ctx, _cache) => {
|
|
|
6308
6458
|
])
|
|
6309
6459
|
]),
|
|
6310
6460
|
vue.createElementVNode("tbody", _hoisted_22, [
|
|
6311
|
-
(loading.value === 'loading')
|
|
6461
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6312
6462
|
? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_23, [
|
|
6313
6463
|
vue.createElementVNode("td", {
|
|
6314
6464
|
colspan:
|
|
@@ -6327,7 +6477,7 @@ return (_ctx, _cache) => {
|
|
|
6327
6477
|
], -1 /* CACHED */)
|
|
6328
6478
|
]))], 8 /* PROPS */, _hoisted_24)
|
|
6329
6479
|
]))
|
|
6330
|
-
: (loading.value === 'error')
|
|
6480
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6331
6481
|
? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_25, [
|
|
6332
6482
|
vue.createElementVNode("td", {
|
|
6333
6483
|
colspan:
|
|
@@ -6358,7 +6508,7 @@ return (_ctx, _cache) => {
|
|
|
6358
6508
|
? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 3 }, vue.renderList(records.value, (record, index) => {
|
|
6359
6509
|
return (vue.openBlock(), vue.createElementBlock("tr", {
|
|
6360
6510
|
key: record.id,
|
|
6361
|
-
class: vue.normalizeClass(record.class),
|
|
6511
|
+
class: vue.normalizeClass([record.class, props.rowLink ? 'cursor-pointer' : '']),
|
|
6362
6512
|
onClick: $event => (rowSelected(record))
|
|
6363
6513
|
}, [
|
|
6364
6514
|
(activeMultiActions.value.length > 0)
|
|
@@ -6455,7 +6605,7 @@ return (_ctx, _cache) => {
|
|
|
6455
6605
|
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(records.value, (record, index) => {
|
|
6456
6606
|
return (vue.openBlock(), vue.createElementBlock("div", {
|
|
6457
6607
|
key: record.id,
|
|
6458
|
-
class: "single-mobile-req bg-light p-3",
|
|
6608
|
+
class: vue.normalizeClass(["single-mobile-req bg-light p-3", props.rowLink ? 'cursor-pointer' : '']),
|
|
6459
6609
|
onClick: $event => (rowSelected(record))
|
|
6460
6610
|
}, [
|
|
6461
6611
|
(activeMultiActions.value.length > 0)
|
|
@@ -6560,7 +6710,7 @@ return (_ctx, _cache) => {
|
|
|
6560
6710
|
}, null, 8 /* PROPS */, ["actions", "record"])
|
|
6561
6711
|
]))
|
|
6562
6712
|
: vue.createCommentVNode("v-if", true)
|
|
6563
|
-
],
|
|
6713
|
+
], 10 /* CLASS, PROPS */, _hoisted_44))
|
|
6564
6714
|
}), 128 /* KEYED_FRAGMENT */))
|
|
6565
6715
|
]))
|
|
6566
6716
|
: (vue.openBlock(), vue.createElementBlock("div", _hoisted_62, [
|
|
@@ -8397,8 +8547,8 @@ const ShFrontend = {
|
|
|
8397
8547
|
}
|
|
8398
8548
|
//filter unwanted config items from options to be put in local storage
|
|
8399
8549
|
const removeKeys = ['formTextInput','router','shFormElementClasses'];
|
|
8400
|
-
const allowKeys = [];
|
|
8401
|
-
Object.keys(options).map(key=> ((!['string','integer','number'].includes(typeof options[key]) && !allowKeys.includes(key)) || removeKeys.includes(key)) && delete options[key]);
|
|
8550
|
+
const allowKeys = ['enableTableCache'];
|
|
8551
|
+
Object.keys(options).map(key=> ((!['string','integer','number','boolean'].includes(typeof options[key]) && !allowKeys.includes(key)) || removeKeys.includes(key)) && delete options[key]);
|
|
8402
8552
|
|
|
8403
8553
|
shStorage.setItem('ShConfig',options);
|
|
8404
8554
|
}
|
package/dist/library.mjs
CHANGED
|
@@ -5,10 +5,10 @@ import { Modal, Offcanvas } from 'bootstrap';
|
|
|
5
5
|
import NProgress from 'nprogress';
|
|
6
6
|
import { ref, computed, watch, onMounted, openBlock, createElementBlock, createElementVNode, createTextVNode, toDisplayString, createCommentVNode, withDirectives, Fragment, renderList, unref, vModelSelect, vModelText, normalizeClass, createBlock, resolveDynamicComponent, resolveComponent, inject, useTemplateRef, mergeProps, vShow, renderSlot, normalizeStyle, Teleport, createVNode, withCtx, useSlots, onBeforeUnmount, reactive, vModelCheckbox, withModifiers, resolveDirective, shallowRef, markRaw, isRef } from 'vue';
|
|
7
7
|
import _ from 'lodash';
|
|
8
|
-
import {
|
|
8
|
+
import { useRouter, useRoute } from 'vue-router';
|
|
9
9
|
import { defineStore, storeToRefs } from 'pinia';
|
|
10
10
|
|
|
11
|
-
function setItem (key, value) {
|
|
11
|
+
function setItem$1 (key, value) {
|
|
12
12
|
let toStore = value;
|
|
13
13
|
if (typeof value === 'object') {
|
|
14
14
|
toStore = JSON.stringify(value);
|
|
@@ -16,20 +16,20 @@ function setItem (key, value) {
|
|
|
16
16
|
return localStorage.setItem(key, toStore)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function getItem (key) {
|
|
19
|
+
function getItem$1 (key) {
|
|
20
20
|
try {
|
|
21
21
|
return JSON.parse(localStorage.getItem(key))
|
|
22
22
|
} catch (err) {
|
|
23
23
|
return localStorage.getItem(key)
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
function removeItem (key) {
|
|
26
|
+
function removeItem$1 (key) {
|
|
27
27
|
return localStorage.removeItem(key)
|
|
28
28
|
}
|
|
29
29
|
var shStorage = {
|
|
30
|
-
setItem,
|
|
31
|
-
getItem,
|
|
32
|
-
removeItem
|
|
30
|
+
setItem: setItem$1,
|
|
31
|
+
getItem: getItem$1,
|
|
32
|
+
removeItem: removeItem$1
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
function swalSuccess(message){
|
|
@@ -5453,6 +5453,112 @@ function render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
5453
5453
|
script$e.render = render$1;
|
|
5454
5454
|
script$e.__file = "src/lib/components/list_templates/Pagination.vue";
|
|
5455
5455
|
|
|
5456
|
+
const DB_NAME = 'ShTableCacheDB';
|
|
5457
|
+
const STORE_NAME = 'table_cache';
|
|
5458
|
+
const DB_VERSION = 1;
|
|
5459
|
+
|
|
5460
|
+
let dbPromise = null;
|
|
5461
|
+
|
|
5462
|
+
function getDB() {
|
|
5463
|
+
if (dbPromise) return dbPromise;
|
|
5464
|
+
|
|
5465
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
5466
|
+
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
5467
|
+
|
|
5468
|
+
request.onupgradeneeded = (event) => {
|
|
5469
|
+
const db = event.target.result;
|
|
5470
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
5471
|
+
db.createObjectStore(STORE_NAME);
|
|
5472
|
+
}
|
|
5473
|
+
};
|
|
5474
|
+
|
|
5475
|
+
request.onsuccess = (event) => {
|
|
5476
|
+
resolve(event.target.result);
|
|
5477
|
+
};
|
|
5478
|
+
|
|
5479
|
+
request.onerror = (event) => {
|
|
5480
|
+
console.error('IndexedDB error:', event.target.error);
|
|
5481
|
+
reject(event.target.error);
|
|
5482
|
+
};
|
|
5483
|
+
});
|
|
5484
|
+
|
|
5485
|
+
return dbPromise;
|
|
5486
|
+
}
|
|
5487
|
+
|
|
5488
|
+
async function setItem(key, value) {
|
|
5489
|
+
try {
|
|
5490
|
+
const db = await getDB();
|
|
5491
|
+
return new Promise((resolve, reject) => {
|
|
5492
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5493
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5494
|
+
const request = store.put(value, key);
|
|
5495
|
+
|
|
5496
|
+
request.onsuccess = () => resolve();
|
|
5497
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5498
|
+
});
|
|
5499
|
+
} catch (error) {
|
|
5500
|
+
console.error('ShIndexedDB setItem error:', error);
|
|
5501
|
+
}
|
|
5502
|
+
}
|
|
5503
|
+
|
|
5504
|
+
async function getItem(key, defaultValue = null) {
|
|
5505
|
+
try {
|
|
5506
|
+
const db = await getDB();
|
|
5507
|
+
return new Promise((resolve, reject) => {
|
|
5508
|
+
const transaction = db.transaction([STORE_NAME], 'readonly');
|
|
5509
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5510
|
+
const request = store.get(key);
|
|
5511
|
+
|
|
5512
|
+
request.onsuccess = (event) => {
|
|
5513
|
+
resolve(event.target.result !== undefined ? event.target.result : defaultValue);
|
|
5514
|
+
};
|
|
5515
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5516
|
+
});
|
|
5517
|
+
} catch (error) {
|
|
5518
|
+
console.error('ShIndexedDB getItem error:', error);
|
|
5519
|
+
return defaultValue;
|
|
5520
|
+
}
|
|
5521
|
+
}
|
|
5522
|
+
|
|
5523
|
+
async function removeItem(key) {
|
|
5524
|
+
try {
|
|
5525
|
+
const db = await getDB();
|
|
5526
|
+
return new Promise((resolve, reject) => {
|
|
5527
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5528
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5529
|
+
const request = store.delete(key);
|
|
5530
|
+
|
|
5531
|
+
request.onsuccess = () => resolve();
|
|
5532
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5533
|
+
});
|
|
5534
|
+
} catch (error) {
|
|
5535
|
+
console.error('ShIndexedDB removeItem error:', error);
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
|
|
5539
|
+
async function clear() {
|
|
5540
|
+
try {
|
|
5541
|
+
const db = await getDB();
|
|
5542
|
+
return new Promise((resolve, reject) => {
|
|
5543
|
+
const transaction = db.transaction([STORE_NAME], 'readwrite');
|
|
5544
|
+
const store = transaction.objectStore(STORE_NAME);
|
|
5545
|
+
const request = store.clear();
|
|
5546
|
+
|
|
5547
|
+
request.onsuccess = () => resolve();
|
|
5548
|
+
request.onerror = (event) => reject(event.target.error);
|
|
5549
|
+
});
|
|
5550
|
+
} catch (error) {
|
|
5551
|
+
console.error('ShIndexedDB clear error:', error);
|
|
5552
|
+
}
|
|
5553
|
+
}
|
|
5554
|
+
|
|
5555
|
+
var shIndexedDB = {
|
|
5556
|
+
setItem,
|
|
5557
|
+
getItem,
|
|
5558
|
+
removeItem,
|
|
5559
|
+
clear
|
|
5560
|
+
};
|
|
5561
|
+
|
|
5456
5562
|
const _hoisted_1$b = { class: "auto-table mt-2" };
|
|
5457
5563
|
const _hoisted_2$8 = {
|
|
5458
5564
|
key: 0,
|
|
@@ -5637,6 +5743,10 @@ var script$d = {
|
|
|
5637
5743
|
selectedRange: [Object, null],
|
|
5638
5744
|
noRecordsMessage: [String, null],
|
|
5639
5745
|
multiActions: { type: Array, default: () => [] },
|
|
5746
|
+
// Caching configuration: true to enable, false to disable. If null, respects global configure 'enableTableCache'
|
|
5747
|
+
cache: { type: Boolean, default: null },
|
|
5748
|
+
// Dynamic link for the entire row. Supports placeholders like '/user/{id}'
|
|
5749
|
+
rowLink: [String, null],
|
|
5640
5750
|
},
|
|
5641
5751
|
emits: ["rowSelected", "dataReloaded", "dataLoaded"],
|
|
5642
5752
|
setup(__props, { emit: __emit }) {
|
|
@@ -5695,7 +5805,7 @@ const hasRecordsSlot = computed(() => !!slots.records);
|
|
|
5695
5805
|
const hasEmptySlot = computed(() => !!slots.empty);
|
|
5696
5806
|
|
|
5697
5807
|
// --- Lifecycle
|
|
5698
|
-
onMounted(() => {
|
|
5808
|
+
onMounted(async () => {
|
|
5699
5809
|
if (props.headers) tableHeaders.value = props.headers;
|
|
5700
5810
|
|
|
5701
5811
|
if (props.actions?.actions) {
|
|
@@ -5704,7 +5814,7 @@ onMounted(() => {
|
|
|
5704
5814
|
});
|
|
5705
5815
|
}
|
|
5706
5816
|
|
|
5707
|
-
if (
|
|
5817
|
+
if (shouldCache.value) await setCachedData();
|
|
5708
5818
|
|
|
5709
5819
|
reloadData();
|
|
5710
5820
|
|
|
@@ -5782,14 +5892,28 @@ const canvasClosed = () => {
|
|
|
5782
5892
|
selectedRecord.value = null;
|
|
5783
5893
|
};
|
|
5784
5894
|
|
|
5895
|
+
const router = useRouter();
|
|
5785
5896
|
const rowSelected = (row) => {
|
|
5786
5897
|
selectedRecord.value = null;
|
|
5787
5898
|
setTimeout(() => {
|
|
5788
5899
|
selectedRecord.value = row;
|
|
5789
5900
|
emit("rowSelected", row);
|
|
5901
|
+
if (props.rowLink) {
|
|
5902
|
+
router.push(replaceRowLink(props.rowLink, row));
|
|
5903
|
+
}
|
|
5790
5904
|
}, 100);
|
|
5791
5905
|
};
|
|
5792
5906
|
|
|
5907
|
+
const replaceRowLink = (p, obj) => {
|
|
5908
|
+
let path = p;
|
|
5909
|
+
const matches = path.match(/\{(.*?)\}/g);
|
|
5910
|
+
matches?.forEach((k) => {
|
|
5911
|
+
const key = k.replace("{", "").replace("}", "");
|
|
5912
|
+
path = path.replace(`{${key}}`, obj[key]);
|
|
5913
|
+
});
|
|
5914
|
+
return path;
|
|
5915
|
+
};
|
|
5916
|
+
|
|
5793
5917
|
const changeKey = (key, value) => {
|
|
5794
5918
|
if (key === "order_by") {
|
|
5795
5919
|
order_by.value = value;
|
|
@@ -5930,20 +6054,46 @@ const exportData = () => {
|
|
|
5930
6054
|
});
|
|
5931
6055
|
};
|
|
5932
6056
|
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
6057
|
+
// Attempts to load data from IndexedDB before API call
|
|
6058
|
+
const setCachedData = async () => {
|
|
6059
|
+
if (shouldCache.value) {
|
|
6060
|
+
const cached = await shIndexedDB.getItem(computedCacheKey.value, null);
|
|
6061
|
+
if (cached) {
|
|
6062
|
+
records.value = cached;
|
|
6063
|
+
// Set to 'done' immediately to show cached data without initial spinner
|
|
6064
|
+
loading.value = "done";
|
|
6065
|
+
}
|
|
5936
6066
|
}
|
|
5937
6067
|
};
|
|
5938
6068
|
|
|
6069
|
+
// Determines if caching should be active based on component props or global configuration
|
|
6070
|
+
const shouldCache = computed(() => {
|
|
6071
|
+
if (props.cache !== null) return props.cache;
|
|
6072
|
+
return shRepo.getShConfig("enableTableCache", false);
|
|
6073
|
+
});
|
|
6074
|
+
|
|
6075
|
+
// Generates a unique, slug-safe key for IndexedDB storage
|
|
6076
|
+
const computedCacheKey = computed(() => {
|
|
6077
|
+
if (props.cacheKey) return "sh_table_cache_" + props.cacheKey;
|
|
6078
|
+
const keyBase = props.endPoint || props.query || "default";
|
|
6079
|
+
const safeBase = keyBase.replace(/[^a-z0-9]/gi, "_").toLowerCase();
|
|
6080
|
+
return "sh_table_cache_" + safeBase;
|
|
6081
|
+
});
|
|
6082
|
+
|
|
5939
6083
|
// Main loader
|
|
6084
|
+
// Main data fetcher. Handles background updates when cache is present
|
|
5940
6085
|
const reloadData = (newPage, append) => {
|
|
5941
6086
|
if (typeof newPage !== "undefined") page.value = newPage;
|
|
5942
6087
|
|
|
5943
|
-
|
|
6088
|
+
// If we have cached data and not searching, we don't show the initial loading spinner
|
|
6089
|
+
if (shouldCache.value && records.value && records.value.length > 0 && !filter_value.value) {
|
|
5944
6090
|
loading.value = "done";
|
|
5945
6091
|
} else if (!append) {
|
|
5946
6092
|
loading.value = "loading";
|
|
6093
|
+
// Clear records when searching to ensure we show fresh results
|
|
6094
|
+
if (filter_value.value) {
|
|
6095
|
+
records.value = [];
|
|
6096
|
+
}
|
|
5947
6097
|
}
|
|
5948
6098
|
|
|
5949
6099
|
let data = {
|
|
@@ -5982,8 +6132,8 @@ const reloadData = (newPage, append) => {
|
|
|
5982
6132
|
const response = req.data.data;
|
|
5983
6133
|
emit("dataLoaded", response);
|
|
5984
6134
|
|
|
5985
|
-
if (page.value < 2 &&
|
|
5986
|
-
|
|
6135
|
+
if (page.value < 2 && shouldCache.value) {
|
|
6136
|
+
shIndexedDB.setItem(computedCacheKey.value, response.data);
|
|
5987
6137
|
}
|
|
5988
6138
|
|
|
5989
6139
|
pagination_data.value = {
|
|
@@ -6168,7 +6318,7 @@ return (_ctx, _cache) => {
|
|
|
6168
6318
|
: createCommentVNode("v-if", true),
|
|
6169
6319
|
(hasDefaultSlot.value)
|
|
6170
6320
|
? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
6171
|
-
(loading.value === 'loading')
|
|
6321
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6172
6322
|
? (openBlock(), createElementBlock("div", _hoisted_9$2, [...(_cache[13] || (_cache[13] = [
|
|
6173
6323
|
createElementVNode("div", {
|
|
6174
6324
|
class: "spinner-border",
|
|
@@ -6177,12 +6327,12 @@ return (_ctx, _cache) => {
|
|
|
6177
6327
|
createElementVNode("span", { class: "visually-hidden" }, "Loading...")
|
|
6178
6328
|
], -1 /* CACHED */)
|
|
6179
6329
|
]))]))
|
|
6180
|
-
: (loading.value === 'error')
|
|
6330
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6181
6331
|
? (openBlock(), createElementBlock("div", _hoisted_10$2, [
|
|
6182
6332
|
createElementVNode("span", null, toDisplayString(loading_error.value), 1 /* TEXT */)
|
|
6183
6333
|
]))
|
|
6184
6334
|
: createCommentVNode("v-if", true),
|
|
6185
|
-
(loading.value === 'done')
|
|
6335
|
+
(loading.value === 'done' || records.value.length > 0)
|
|
6186
6336
|
? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
6187
6337
|
(records.value.length === 0)
|
|
6188
6338
|
? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
@@ -6206,7 +6356,7 @@ return (_ctx, _cache) => {
|
|
|
6206
6356
|
], 64 /* STABLE_FRAGMENT */))
|
|
6207
6357
|
: (hasRecordsSlot.value)
|
|
6208
6358
|
? (openBlock(), createElementBlock(Fragment, { key: 3 }, [
|
|
6209
|
-
(loading.value === 'loading' &&
|
|
6359
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6210
6360
|
? (openBlock(), createElementBlock("div", _hoisted_12$1, [...(_cache[15] || (_cache[15] = [
|
|
6211
6361
|
createElementVNode("div", {
|
|
6212
6362
|
class: "spinner-border",
|
|
@@ -6215,12 +6365,12 @@ return (_ctx, _cache) => {
|
|
|
6215
6365
|
createElementVNode("span", { class: "visually-hidden" }, "Loading...")
|
|
6216
6366
|
], -1 /* CACHED */)
|
|
6217
6367
|
]))]))
|
|
6218
|
-
: (loading.value === 'error' &&
|
|
6368
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6219
6369
|
? (openBlock(), createElementBlock("div", _hoisted_13$1, [
|
|
6220
6370
|
createElementVNode("span", null, toDisplayString(loading_error.value), 1 /* TEXT */)
|
|
6221
6371
|
]))
|
|
6222
6372
|
: createCommentVNode("v-if", true),
|
|
6223
|
-
(loading.value === 'done' ||
|
|
6373
|
+
(loading.value === 'done' || records.value.length > 0)
|
|
6224
6374
|
? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
|
|
6225
6375
|
(!records.value || records.value.length === 0)
|
|
6226
6376
|
? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
@@ -6297,7 +6447,7 @@ return (_ctx, _cache) => {
|
|
|
6297
6447
|
])
|
|
6298
6448
|
]),
|
|
6299
6449
|
createElementVNode("tbody", _hoisted_22, [
|
|
6300
|
-
(loading.value === 'loading')
|
|
6450
|
+
(loading.value === 'loading' && records.value.length === 0)
|
|
6301
6451
|
? (openBlock(), createElementBlock("tr", _hoisted_23, [
|
|
6302
6452
|
createElementVNode("td", {
|
|
6303
6453
|
colspan:
|
|
@@ -6316,7 +6466,7 @@ return (_ctx, _cache) => {
|
|
|
6316
6466
|
], -1 /* CACHED */)
|
|
6317
6467
|
]))], 8 /* PROPS */, _hoisted_24)
|
|
6318
6468
|
]))
|
|
6319
|
-
: (loading.value === 'error')
|
|
6469
|
+
: (loading.value === 'error' && records.value.length === 0)
|
|
6320
6470
|
? (openBlock(), createElementBlock("tr", _hoisted_25, [
|
|
6321
6471
|
createElementVNode("td", {
|
|
6322
6472
|
colspan:
|
|
@@ -6347,7 +6497,7 @@ return (_ctx, _cache) => {
|
|
|
6347
6497
|
? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(records.value, (record, index) => {
|
|
6348
6498
|
return (openBlock(), createElementBlock("tr", {
|
|
6349
6499
|
key: record.id,
|
|
6350
|
-
class: normalizeClass(record.class),
|
|
6500
|
+
class: normalizeClass([record.class, props.rowLink ? 'cursor-pointer' : '']),
|
|
6351
6501
|
onClick: $event => (rowSelected(record))
|
|
6352
6502
|
}, [
|
|
6353
6503
|
(activeMultiActions.value.length > 0)
|
|
@@ -6444,7 +6594,7 @@ return (_ctx, _cache) => {
|
|
|
6444
6594
|
(openBlock(true), createElementBlock(Fragment, null, renderList(records.value, (record, index) => {
|
|
6445
6595
|
return (openBlock(), createElementBlock("div", {
|
|
6446
6596
|
key: record.id,
|
|
6447
|
-
class: "single-mobile-req bg-light p-3",
|
|
6597
|
+
class: normalizeClass(["single-mobile-req bg-light p-3", props.rowLink ? 'cursor-pointer' : '']),
|
|
6448
6598
|
onClick: $event => (rowSelected(record))
|
|
6449
6599
|
}, [
|
|
6450
6600
|
(activeMultiActions.value.length > 0)
|
|
@@ -6549,7 +6699,7 @@ return (_ctx, _cache) => {
|
|
|
6549
6699
|
}, null, 8 /* PROPS */, ["actions", "record"])
|
|
6550
6700
|
]))
|
|
6551
6701
|
: createCommentVNode("v-if", true)
|
|
6552
|
-
],
|
|
6702
|
+
], 10 /* CLASS, PROPS */, _hoisted_44))
|
|
6553
6703
|
}), 128 /* KEYED_FRAGMENT */))
|
|
6554
6704
|
]))
|
|
6555
6705
|
: (openBlock(), createElementBlock("div", _hoisted_62, [
|
|
@@ -8386,8 +8536,8 @@ const ShFrontend = {
|
|
|
8386
8536
|
}
|
|
8387
8537
|
//filter unwanted config items from options to be put in local storage
|
|
8388
8538
|
const removeKeys = ['formTextInput','router','shFormElementClasses'];
|
|
8389
|
-
const allowKeys = [];
|
|
8390
|
-
Object.keys(options).map(key=> ((!['string','integer','number'].includes(typeof options[key]) && !allowKeys.includes(key)) || removeKeys.includes(key)) && delete options[key]);
|
|
8539
|
+
const allowKeys = ['enableTableCache'];
|
|
8540
|
+
Object.keys(options).map(key=> ((!['string','integer','number','boolean'].includes(typeof options[key]) && !allowKeys.includes(key)) || removeKeys.includes(key)) && delete options[key]);
|
|
8391
8541
|
|
|
8392
8542
|
shStorage.setItem('ShConfig',options);
|
|
8393
8543
|
}
|