vue2-excel-grid 2.2.2 → 2.3.0
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/package.json
CHANGED
|
@@ -1460,10 +1460,34 @@ const ExcelGridComponent = {
|
|
|
1460
1460
|
localSyncKey: { type: String, default: null },
|
|
1461
1461
|
|
|
1462
1462
|
/**
|
|
1463
|
-
*
|
|
1464
|
-
*
|
|
1465
|
-
*
|
|
1466
|
-
* `
|
|
1463
|
+
* Optional tenant/organization identifier for multi-tenant hosts (SaaS
|
|
1464
|
+
* apps where the same browser/device is used across different
|
|
1465
|
+
* organizations). When set, it's combined with `localSyncKey`
|
|
1466
|
+
* internally (`${tenant}::${localSyncKey}`) so each tenant gets a fully
|
|
1467
|
+
* isolated IndexedDB version history — switching tenants on the same
|
|
1468
|
+
* device never shows another tenant's saved drafts. Omit it (default)
|
|
1469
|
+
* for single-tenant hosts; behavior is then identical to before this
|
|
1470
|
+
* prop existed.
|
|
1471
|
+
*
|
|
1472
|
+
* Has no effect without `localSyncKey` — it only changes how that key
|
|
1473
|
+
* is namespaced internally, it doesn't opt into the feature by itself.
|
|
1474
|
+
* Reactive: changing `tenant` (e.g. after an async "current
|
|
1475
|
+
* organization" load) reloads that tenant's own version list/buffer,
|
|
1476
|
+
* the same way a `localSyncKey` that starts empty and becomes truthy
|
|
1477
|
+
* later does. Avoid `::` inside `tenant`/`localSyncKey` values
|
|
1478
|
+
* themselves — it's the internal separator between the two.
|
|
1479
|
+
* @type {String}
|
|
1480
|
+
* @default null
|
|
1481
|
+
* @example
|
|
1482
|
+
* <excel-grid :columns="columns" v-model="data" local-sync-key="invoice-42" :tenant="currentOrgId" toolbar />
|
|
1483
|
+
*/
|
|
1484
|
+
tenant: { type: String, default: null },
|
|
1485
|
+
|
|
1486
|
+
/**
|
|
1487
|
+
* Maximum number of local versions kept per `localSyncKey` (per
|
|
1488
|
+
* `tenant`, when set). Once a new version pushes the count past this,
|
|
1489
|
+
* the oldest version(s) (by `createdAt`) are deleted automatically
|
|
1490
|
+
* (FIFO). Has no effect without `localSyncKey`.
|
|
1467
1491
|
* @type {Number}
|
|
1468
1492
|
* @default 10
|
|
1469
1493
|
* @example
|
|
@@ -1666,6 +1690,17 @@ const ExcelGridComponent = {
|
|
|
1666
1690
|
computed: {
|
|
1667
1691
|
t() { return getMessages(this.locale) },
|
|
1668
1692
|
|
|
1693
|
+
// localSyncKey feature — the actual IndexedDB storage key. idbStore.js
|
|
1694
|
+
// itself knows nothing about "tenants"; this is the one place that
|
|
1695
|
+
// namespaces localSyncKey by tenant when one is given, so every
|
|
1696
|
+
// storage-layer call site below just uses this instead of
|
|
1697
|
+
// this.localSyncKey directly. null whenever localSyncKey itself is
|
|
1698
|
+
// unset — tenant alone doesn't opt into the feature.
|
|
1699
|
+
effectiveSyncKey() {
|
|
1700
|
+
if (!this.localSyncKey) return null
|
|
1701
|
+
return this.tenant ? `${this.tenant}::${this.localSyncKey}` : this.localSyncKey
|
|
1702
|
+
},
|
|
1703
|
+
|
|
1669
1704
|
pinnedLeftSet() {
|
|
1670
1705
|
const s = new Set()
|
|
1671
1706
|
this.leafCols.forEach(col => { if (this.internalPinnedColumns[col.key] === 'left') s.add(col._flatIndex) })
|
|
@@ -2419,17 +2454,23 @@ const ExcelGridComponent = {
|
|
|
2419
2454
|
},
|
|
2420
2455
|
widthMode() { this.$nextTick(this.syncHeaderViewportWidth) },
|
|
2421
2456
|
|
|
2422
|
-
// localSyncKey feature — mounted() only calls
|
|
2423
|
-
// once, at mount time. Without
|
|
2424
|
-
//
|
|
2425
|
-
//
|
|
2426
|
-
//
|
|
2427
|
-
//
|
|
2428
|
-
//
|
|
2457
|
+
// localSyncKey/tenant feature — mounted() only calls
|
|
2458
|
+
// _loadLocalVersionsOnMount() once, at mount time. Without these
|
|
2459
|
+
// watchers, a key/tenant that starts empty (a host conditionally
|
|
2460
|
+
// passing `:local-sync-key="ready ? id : null"`, or a `tenant` only
|
|
2461
|
+
// known after an async "current organization" load) and later becomes
|
|
2462
|
+
// truthy would never load its version list, never promote a leftover
|
|
2463
|
+
// buffer, and never show the toolbar badge — the feature would look
|
|
2464
|
+
// "broken" for the rest of that page's lifetime even though everything
|
|
2465
|
+
// else works. Both share _reloadLocalSyncForKeyChange() since either one
|
|
2466
|
+
// changing means the effective storage key changed.
|
|
2429
2467
|
localSyncKey(newKey, oldKey) {
|
|
2430
2468
|
if (newKey === oldKey) return
|
|
2431
|
-
this.
|
|
2432
|
-
|
|
2469
|
+
this._reloadLocalSyncForKeyChange()
|
|
2470
|
+
},
|
|
2471
|
+
tenant(newTenant, oldTenant) {
|
|
2472
|
+
if (newTenant === oldTenant) return
|
|
2473
|
+
this._reloadLocalSyncForKeyChange()
|
|
2433
2474
|
}
|
|
2434
2475
|
},
|
|
2435
2476
|
|
|
@@ -6423,9 +6464,19 @@ const ExcelGridComponent = {
|
|
|
6423
6464
|
|
|
6424
6465
|
// =========================================================
|
|
6425
6466
|
// LOCAL SYNC — save `data` as a local IndexedDB *version*, keyed by
|
|
6426
|
-
// localSyncKey, only when the page is
|
|
6467
|
+
// localSyncKey (optionally namespaced by tenant), only when the page is
|
|
6468
|
+
// being left (not per-edit).
|
|
6427
6469
|
// =========================================================
|
|
6428
6470
|
|
|
6471
|
+
// Shared by the localSyncKey and tenant watchers above — either one
|
|
6472
|
+
// changing means effectiveSyncKey now points at a (possibly) different
|
|
6473
|
+
// version history, so the badge/version-list state must be reloaded
|
|
6474
|
+
// from scratch rather than left stale.
|
|
6475
|
+
_reloadLocalSyncForKeyChange() {
|
|
6476
|
+
this.localSyncAvailable = false
|
|
6477
|
+
if (this.effectiveSyncKey) this._loadLocalVersionsOnMount()
|
|
6478
|
+
},
|
|
6479
|
+
|
|
6429
6480
|
// Internal, called once from mounted(): populates the toolbar "unseen
|
|
6430
6481
|
// local versions" dot and emits local-sync-available if any versions
|
|
6431
6482
|
// already exist for this key (e.g. saved in an earlier visit).
|
|
@@ -6433,7 +6484,7 @@ const ExcelGridComponent = {
|
|
|
6433
6484
|
if (!this.localSyncKey) return
|
|
6434
6485
|
await this._promoteBufferIfAny()
|
|
6435
6486
|
try {
|
|
6436
|
-
const versions = await listVersions(this.
|
|
6487
|
+
const versions = await listVersions(this.effectiveSyncKey)
|
|
6437
6488
|
if (!versions.length) return
|
|
6438
6489
|
this.localSyncAvailable = true
|
|
6439
6490
|
this.$emit('local-sync-available', {
|
|
@@ -6464,9 +6515,9 @@ const ExcelGridComponent = {
|
|
|
6464
6515
|
// turns it into a real version next time the grid mounts.
|
|
6465
6516
|
_scheduleBufferWrite(data) {
|
|
6466
6517
|
if (!this.localSyncKey) return
|
|
6467
|
-
const key = this.
|
|
6468
|
-
// a host that swaps localSyncKey mid-edit (rare, but now
|
|
6469
|
-
// the
|
|
6518
|
+
const key = this.effectiveSyncKey // captured now, not re-read 800ms later —
|
|
6519
|
+
// a host that swaps localSyncKey/tenant mid-edit (rare, but now
|
|
6520
|
+
// reactive, see the watchers below) must not have this land under the
|
|
6470
6521
|
// NEW key with the OLD key's data.
|
|
6471
6522
|
clearTimeout(this._bufferWriteTimer)
|
|
6472
6523
|
this._bufferWriteTimer = setTimeout(() => { this._writeBufferNow(key, data) }, 800)
|
|
@@ -6489,13 +6540,13 @@ const ExcelGridComponent = {
|
|
|
6489
6540
|
// like any other non-leave-signal path.
|
|
6490
6541
|
async _promoteBufferIfAny() {
|
|
6491
6542
|
try {
|
|
6492
|
-
const buffered = await getBuffer(this.
|
|
6543
|
+
const buffered = await getBuffer(this.effectiveSyncKey)
|
|
6493
6544
|
if (!buffered) return
|
|
6494
6545
|
const hash = await hashRowsAsync(buffered.data)
|
|
6495
6546
|
const { version, overwritten } = await saveOrTouchVersion(
|
|
6496
|
-
this.
|
|
6547
|
+
this.effectiveSyncKey, buffered.data, hash, this.localSyncMaxVersions
|
|
6497
6548
|
)
|
|
6498
|
-
await clearBuffer(this.
|
|
6549
|
+
await clearBuffer(this.effectiveSyncKey)
|
|
6499
6550
|
this.$emit('local-sync-save', {
|
|
6500
6551
|
key: this.localSyncKey,
|
|
6501
6552
|
id: version.id,
|
|
@@ -6565,12 +6616,12 @@ const ExcelGridComponent = {
|
|
|
6565
6616
|
// the version-store write below is best-effort on top of it, reliable
|
|
6566
6617
|
// for the common case (tab switch/background, page stays alive).
|
|
6567
6618
|
clearTimeout(this._bufferWriteTimer)
|
|
6568
|
-
this._writeBufferNow(this.
|
|
6619
|
+
this._writeBufferNow(this.effectiveSyncKey, data)
|
|
6569
6620
|
try {
|
|
6570
6621
|
const hash = sync ? hashRows(data) : await hashRowsAsync(data)
|
|
6571
6622
|
if (this.data !== data) return // data changed again mid-hash — a later flush will catch it
|
|
6572
6623
|
const { version, overwritten } = await saveOrTouchVersion(
|
|
6573
|
-
this.
|
|
6624
|
+
this.effectiveSyncKey, data, hash, this.localSyncMaxVersions
|
|
6574
6625
|
)
|
|
6575
6626
|
this._lastFlushedDataRef = data
|
|
6576
6627
|
// The version store now has this content durably — the buffer's job
|
|
@@ -6578,7 +6629,7 @@ const ExcelGridComponent = {
|
|
|
6578
6629
|
// doesn't complete before teardown, _promoteBufferIfAny() finds the
|
|
6579
6630
|
// (now-redundant but harmless, dedup makes it a no-op touch) buffer
|
|
6580
6631
|
// on next mount anyway.
|
|
6581
|
-
clearBuffer(this.
|
|
6632
|
+
clearBuffer(this.effectiveSyncKey).catch(() => {})
|
|
6582
6633
|
this.$emit('local-sync-save', {
|
|
6583
6634
|
key: this.localSyncKey,
|
|
6584
6635
|
id: version.id,
|
|
@@ -6608,7 +6659,7 @@ const ExcelGridComponent = {
|
|
|
6608
6659
|
async listLocalVersions() {
|
|
6609
6660
|
if (!this.localSyncKey) return []
|
|
6610
6661
|
try {
|
|
6611
|
-
const versions = await listVersions(this.
|
|
6662
|
+
const versions = await listVersions(this.effectiveSyncKey)
|
|
6612
6663
|
return versions.map(v => ({ id: v.id, createdAt: v.createdAt, updatedAt: v.updatedAt, rowCount: v.data.length }))
|
|
6613
6664
|
} catch (error) {
|
|
6614
6665
|
this.$emit('local-sync-error', { action: 'load', error })
|