fix(documents): refine unread badges and mark all read
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
color: #64748b;
|
color: #64748b;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 750;
|
font-weight: 750;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-tabs button.active {
|
.status-tabs button.active {
|
||||||
@@ -33,20 +34,33 @@
|
|||||||
background: var(--theme-primary);
|
background: var(--theme-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scope-tab-label {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
.scope-tab-badge {
|
.scope-tab-badge {
|
||||||
min-width: 18px;
|
position: absolute;
|
||||||
height: 18px;
|
top: -8px;
|
||||||
|
right: -15px;
|
||||||
|
min-width: 15px;
|
||||||
|
height: 15px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 5px;
|
padding: 0 4px;
|
||||||
|
border: 1px solid #fff;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ef4444;
|
background: #ef4444;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
font-weight: 850;
|
font-weight: 850;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
box-shadow: 0 6px 14px rgba(239, 68, 68, 0.22);
|
box-shadow:
|
||||||
|
0 0 0 2px rgba(239, 68, 68, 0.1),
|
||||||
|
0 6px 14px rgba(239, 68, 68, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
.document-toolbar {
|
.document-toolbar {
|
||||||
@@ -167,6 +181,38 @@
|
|||||||
filter: none;
|
filter: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mark-read-btn {
|
||||||
|
min-height: 34px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border: 1px solid #fecaca;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fff;
|
||||||
|
color: #dc2626;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 800;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition:
|
||||||
|
border-color 160ms ease,
|
||||||
|
background 160ms ease,
|
||||||
|
color 160ms ease,
|
||||||
|
box-shadow 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark-read-btn .mdi {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mark-read-btn:hover {
|
||||||
|
border-color: #fca5a5;
|
||||||
|
background: #fff5f5;
|
||||||
|
color: #b91c1c;
|
||||||
|
box-shadow: 0 8px 18px rgba(239, 68, 68, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
.table-wrap {
|
.table-wrap {
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@@ -495,6 +541,7 @@ td small {
|
|||||||
.document-actions,
|
.document-actions,
|
||||||
.list-search,
|
.list-search,
|
||||||
.filter-btn,
|
.filter-btn,
|
||||||
|
.mark-read-btn,
|
||||||
.page-size-select {
|
.page-size-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,11 +216,14 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
max-width: 128px;
|
max-width: 128px;
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition:
|
transition:
|
||||||
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
max-width var(--rail-motion-duration) var(--rail-motion-ease),
|
||||||
@@ -229,6 +232,16 @@
|
|||||||
will-change: max-width, opacity, transform;
|
will-change: max-width, opacity, transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-label-text {
|
||||||
|
position: relative;
|
||||||
|
min-width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: visible;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-badge {
|
.nav-badge {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-width: 34px;
|
min-width: 34px;
|
||||||
@@ -251,13 +264,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-unread-dot {
|
.nav-unread-dot {
|
||||||
flex: 0 0 auto;
|
width: 9px;
|
||||||
width: 8px;
|
height: 9px;
|
||||||
height: 8px;
|
|
||||||
border: 2px solid #fff;
|
border: 2px solid #fff;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #ef4444;
|
background: #ef4444;
|
||||||
box-shadow: 0 6px 14px rgba(239, 68, 68, 0.26);
|
box-shadow:
|
||||||
|
0 0 0 3px rgba(239, 68, 68, 0.12),
|
||||||
|
0 6px 14px rgba(239, 68, 68, 0.32);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-unread-dot-label {
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-unread-dot-collapsed {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rail-user {
|
.rail-user {
|
||||||
@@ -469,8 +493,13 @@
|
|||||||
transition-delay: 0ms;
|
transition-delay: 0ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rail-collapsed .nav-unread-dot {
|
.rail-collapsed .nav-unread-dot-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rail-collapsed .nav-unread-dot-collapsed {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
display: block;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 11px;
|
right: 11px;
|
||||||
width: 9px;
|
width: 9px;
|
||||||
|
|||||||
@@ -50,8 +50,13 @@
|
|||||||
@click="emit('navigate', item.id)"
|
@click="emit('navigate', item.id)"
|
||||||
>
|
>
|
||||||
<span class="nav-icon" v-html="item.icon"></span>
|
<span class="nav-icon" v-html="item.icon"></span>
|
||||||
<span class="nav-label">{{ item.displayLabel }}</span>
|
<span class="nav-label">
|
||||||
<span v-if="item.hasNewMessage" class="nav-unread-dot" aria-hidden="true"></span>
|
<span class="nav-label-text">
|
||||||
|
{{ item.displayLabel }}
|
||||||
|
<span v-if="item.hasNewMessage" class="nav-unread-dot nav-unread-dot-label" aria-hidden="true"></span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="item.hasNewMessage" class="nav-unread-dot nav-unread-dot-collapsed" aria-hidden="true"></span>
|
||||||
<span v-if="item.badge" class="nav-badge">{{ item.badge }}</span>
|
<span v-if="item.badge" class="nav-badge">{{ item.badge }}</span>
|
||||||
</button>
|
</button>
|
||||||
</ElTooltip>
|
</ElTooltip>
|
||||||
|
|||||||
@@ -77,3 +77,26 @@ export function markDocumentViewed(row, viewedKeys, storage = getStorage()) {
|
|||||||
writeViewedDocumentKeys(nextKeys, storage)
|
writeViewedDocumentKeys(nextKeys, storage)
|
||||||
return nextKeys
|
return nextKeys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function markDocumentsViewed(rows, viewedKeys, storage = getStorage()) {
|
||||||
|
const nextKeys = new Set(viewedKeys)
|
||||||
|
let changed = false
|
||||||
|
|
||||||
|
;(Array.isArray(rows) ? rows : []).forEach((row) => {
|
||||||
|
if (!isNewDocument(row, nextKeys)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = resolveDocumentNewKey(row)
|
||||||
|
if (key) {
|
||||||
|
nextKeys.add(key)
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
writeViewedDocumentKeys(nextKeys, storage)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextKeys
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
:class="{ active: activeScopeTab === tab.value }"
|
:class="{ active: activeScopeTab === tab.value }"
|
||||||
@click="activeScopeTab = tab.value"
|
@click="activeScopeTab = tab.value"
|
||||||
>
|
>
|
||||||
<span>{{ tab.label }}</span>
|
<span class="scope-tab-label">
|
||||||
<span v-if="tab.badgeCount > 0" class="scope-tab-badge" aria-label="新增单据数">
|
{{ tab.label }}
|
||||||
{{ tab.badgeCount > 99 ? '99+' : tab.badgeCount }}
|
<span v-if="tab.badgeCount > 0" class="scope-tab-badge" aria-label="新增单据数">
|
||||||
|
{{ tab.badgeCount > 99 ? '99+' : tab.badgeCount }}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -122,7 +124,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="[DOCUMENT_SCOPE_APPLICATION, DOCUMENT_SCOPE_REIMBURSEMENT].includes(activeScopeTab)" class="document-actions">
|
<div v-if="showToolbarActions" class="document-actions">
|
||||||
|
<button
|
||||||
|
v-if="totalNewDocumentCount > 0"
|
||||||
|
class="mark-read-btn"
|
||||||
|
type="button"
|
||||||
|
@click="markAllDocumentsRead"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-check-all"></i>
|
||||||
|
<span>一键已读</span>
|
||||||
|
</button>
|
||||||
<button v-if="activeScopeTab === DOCUMENT_SCOPE_APPLICATION" class="create-request-btn" type="button" @click="emit('create-application')">
|
<button v-if="activeScopeTab === DOCUMENT_SCOPE_APPLICATION" class="create-request-btn" type="button" @click="emit('create-application')">
|
||||||
<i class="mdi mdi-file-plus-outline"></i>
|
<i class="mdi mdi-file-plus-outline"></i>
|
||||||
<span>发起申请</span>
|
<span>发起申请</span>
|
||||||
@@ -238,7 +249,7 @@ import TableLoadingState from '../components/shared/TableLoadingState.vue'
|
|||||||
import { useMinimumVisibleState } from '../composables/useMinimumVisibleState.js'
|
import { useMinimumVisibleState } from '../composables/useMinimumVisibleState.js'
|
||||||
import { mapExpenseClaimToRequest } from '../composables/useRequests.js'
|
import { mapExpenseClaimToRequest } from '../composables/useRequests.js'
|
||||||
import { fetchApprovalExpenseClaims, fetchArchivedExpenseClaims } from '../services/reimbursements.js'
|
import { fetchApprovalExpenseClaims, fetchArchivedExpenseClaims } from '../services/reimbursements.js'
|
||||||
import { countNewDocuments, isNewDocument, markDocumentViewed, readDocumentScope, readViewedDocumentKeys, writeDocumentScope } from '../utils/documentCenterNewState.js'
|
import { countNewDocuments, isNewDocument, markDocumentViewed, markDocumentsViewed, readDocumentScope, readViewedDocumentKeys, writeDocumentScope } from '../utils/documentCenterNewState.js'
|
||||||
import { extractDateText, formatDocumentListTime, resolveDocumentSortTime, resolveDocumentStayTimeDisplay } from '../utils/documentCenterTime.js'
|
import { extractDateText, formatDocumentListTime, resolveDocumentSortTime, resolveDocumentStayTimeDisplay } from '../utils/documentCenterTime.js'
|
||||||
import { excludeArchivedDocumentRows, filterApplicationScopeNewRows, isArchivedDocumentRow, prepareApplicationScopeRows } from '../utils/documentCenterRows.js'
|
import { excludeArchivedDocumentRows, filterApplicationScopeNewRows, isArchivedDocumentRow, prepareApplicationScopeRows } from '../utils/documentCenterRows.js'
|
||||||
import { normalizeRequestForUi } from '../utils/requestViewModel.js'
|
import { normalizeRequestForUi } from '../utils/requestViewModel.js'
|
||||||
@@ -468,6 +479,17 @@ const scopeTabItems = computed(() =>
|
|||||||
badgeCount: scopeNewCountMap.value[tab] || 0
|
badgeCount: scopeNewCountMap.value[tab] || 0
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
|
const allReadableDocumentRows = computed(() => [
|
||||||
|
...nonArchivedRows.value,
|
||||||
|
...filterApplicationScopeNewRows(applicationScopeRows.value),
|
||||||
|
...ownedRows.value.filter((row) => row.documentTypeCode === DOCUMENT_TYPE_REIMBURSEMENT),
|
||||||
|
...approvalRows.value
|
||||||
|
])
|
||||||
|
const totalNewDocumentCount = computed(() => countNewDocuments(allReadableDocumentRows.value, viewedDocumentKeys.value))
|
||||||
|
const showCreateDocumentActions = computed(() =>
|
||||||
|
[DOCUMENT_SCOPE_APPLICATION, DOCUMENT_SCOPE_REIMBURSEMENT].includes(activeScopeTab.value)
|
||||||
|
)
|
||||||
|
const showToolbarActions = computed(() => showCreateDocumentActions.value || totalNewDocumentCount.value > 0)
|
||||||
|
|
||||||
const activeScopeRows = computed(() => {
|
const activeScopeRows = computed(() => {
|
||||||
if (activeScopeTab.value === DOCUMENT_SCOPE_ALL) return nonArchivedRows.value
|
if (activeScopeTab.value === DOCUMENT_SCOPE_ALL) return nonArchivedRows.value
|
||||||
@@ -831,6 +853,14 @@ function openDocument(row) {
|
|||||||
emit('open-document', row.rawRequest || row)
|
emit('open-document', row.rawRequest || row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function markAllDocumentsRead() {
|
||||||
|
if (!totalNewDocumentCount.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
viewedDocumentKeys.value = markDocumentsViewed(allReadableDocumentRows.value, viewedDocumentKeys.value)
|
||||||
|
}
|
||||||
|
|
||||||
async function loadSupportingRows() {
|
async function loadSupportingRows() {
|
||||||
supportingLoading.value = true
|
supportingLoading.value = true
|
||||||
supportingError.value = ''
|
supportingError.value = ''
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
countNewDocuments,
|
countNewDocuments,
|
||||||
isNewDocument,
|
isNewDocument,
|
||||||
markDocumentViewed,
|
markDocumentViewed,
|
||||||
|
markDocumentsViewed,
|
||||||
readDocumentScope,
|
readDocumentScope,
|
||||||
readViewedDocumentKeys,
|
readViewedDocumentKeys,
|
||||||
resolveDocumentNewKey,
|
resolveDocumentNewKey,
|
||||||
@@ -47,6 +48,19 @@ test('document center new state counts unseen documents and persists viewed rows
|
|||||||
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1'])
|
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1'])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('document center new state can mark all unread rows as viewed at once', () => {
|
||||||
|
const storage = createMemoryStorage()
|
||||||
|
const rows = [
|
||||||
|
{ source: 'owned', claimId: 'claim-1' },
|
||||||
|
{ source: 'approval', claimId: 'claim-2' },
|
||||||
|
{ source: 'archive', claimId: 'claim-3' }
|
||||||
|
]
|
||||||
|
const viewedKeys = markDocumentsViewed(rows, readViewedDocumentKeys(storage), storage)
|
||||||
|
|
||||||
|
assert.equal(countNewDocuments(rows, viewedKeys), 0)
|
||||||
|
assert.deepEqual([...readViewedDocumentKeys(storage)], ['owned:claim-1', 'approval:claim-2'])
|
||||||
|
})
|
||||||
|
|
||||||
test('document center archive rows are never marked as new', () => {
|
test('document center archive rows are never marked as new', () => {
|
||||||
const viewedKeys = readViewedDocumentKeys(createMemoryStorage())
|
const viewedKeys = readViewedDocumentKeys(createMemoryStorage())
|
||||||
const rows = [
|
const rows = [
|
||||||
|
|||||||
@@ -137,9 +137,10 @@ test('documents center list shows created time and conditional stay time columns
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('documents center action buttons are scoped to application and reimbursement tabs', () => {
|
test('documents center action buttons are scoped to application and reimbursement tabs', () => {
|
||||||
|
assert.match(documentsCenterView, /v-if="showToolbarActions" class="document-actions"/)
|
||||||
assert.match(
|
assert.match(
|
||||||
documentsCenterView,
|
documentsCenterView,
|
||||||
/v-if="\[DOCUMENT_SCOPE_APPLICATION, DOCUMENT_SCOPE_REIMBURSEMENT\]\.includes\(activeScopeTab\)"[\s\S]*class="document-actions"/
|
/const showCreateDocumentActions = computed\(\(\) =>[\s\S]*DOCUMENT_SCOPE_APPLICATION[\s\S]*DOCUMENT_SCOPE_REIMBURSEMENT/
|
||||||
)
|
)
|
||||||
assert.match(
|
assert.match(
|
||||||
documentsCenterView,
|
documentsCenterView,
|
||||||
@@ -156,6 +157,7 @@ test('documents center category tabs render bubble counts for new documents', ()
|
|||||||
assert.match(documentsCenterView, /readViewedDocumentKeys/)
|
assert.match(documentsCenterView, /readViewedDocumentKeys/)
|
||||||
assert.match(documentsCenterView, /const viewedDocumentKeys = ref\(readViewedDocumentKeys\(\)\)/)
|
assert.match(documentsCenterView, /const viewedDocumentKeys = ref\(readViewedDocumentKeys\(\)\)/)
|
||||||
assert.match(documentsCenterView, /v-for="tab in scopeTabItems"/)
|
assert.match(documentsCenterView, /v-for="tab in scopeTabItems"/)
|
||||||
|
assert.match(documentsCenterView, /<span class="scope-tab-label">/)
|
||||||
assert.match(documentsCenterView, /<span v-if="tab\.badgeCount > 0" class="scope-tab-badge"/)
|
assert.match(documentsCenterView, /<span v-if="tab\.badgeCount > 0" class="scope-tab-badge"/)
|
||||||
assert.match(documentsCenterView, /tab\.badgeCount > 99 \? '99\+' : tab\.badgeCount/)
|
assert.match(documentsCenterView, /tab\.badgeCount > 99 \? '99\+' : tab\.badgeCount/)
|
||||||
assert.match(documentsCenterView, /const scopeNewCountMap = computed\(\(\) => \(\{/)
|
assert.match(documentsCenterView, /const scopeNewCountMap = computed\(\(\) => \(\{/)
|
||||||
@@ -178,6 +180,27 @@ test('documents center category tabs render bubble counts for new documents', ()
|
|||||||
documentsCenterView,
|
documentsCenterView,
|
||||||
/const scopeTabItems = computed\(\(\) =>[\s\S]*badgeCount: scopeNewCountMap\.value\[tab\] \|\| 0/
|
/const scopeTabItems = computed\(\(\) =>[\s\S]*badgeCount: scopeNewCountMap\.value\[tab\] \|\| 0/
|
||||||
)
|
)
|
||||||
|
assert.match(documentListSharedStyles, /\.scope-tab-label\s*\{[\s\S]*position:\s*relative;/)
|
||||||
|
assert.match(documentListSharedStyles, /\.scope-tab-badge\s*\{[\s\S]*position:\s*absolute;[\s\S]*top:\s*-8px;[\s\S]*height:\s*15px;/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('documents center can mark all unread documents as read from toolbar', () => {
|
||||||
|
assert.match(documentsCenterView, /markDocumentsViewed/)
|
||||||
|
assert.match(
|
||||||
|
documentsCenterView,
|
||||||
|
/const allReadableDocumentRows = computed\(\(\) => \[[\s\S]*nonArchivedRows\.value[\s\S]*filterApplicationScopeNewRows\(applicationScopeRows\.value\)[\s\S]*approvalRows\.value/
|
||||||
|
)
|
||||||
|
assert.match(documentsCenterView, /const totalNewDocumentCount = computed\(\(\) => countNewDocuments\(allReadableDocumentRows\.value, viewedDocumentKeys\.value\)\)/)
|
||||||
|
assert.match(documentsCenterView, /const showToolbarActions = computed\(\(\) => showCreateDocumentActions\.value \|\| totalNewDocumentCount\.value > 0\)/)
|
||||||
|
assert.match(
|
||||||
|
documentsCenterView,
|
||||||
|
/<button[\s\S]*v-if="totalNewDocumentCount > 0"[\s\S]*class="mark-read-btn"[\s\S]*@click="markAllDocumentsRead"[\s\S]*一键已读/
|
||||||
|
)
|
||||||
|
assert.match(
|
||||||
|
documentsCenterView,
|
||||||
|
/function markAllDocumentsRead\(\) \{[\s\S]*viewedDocumentKeys\.value = markDocumentsViewed\(allReadableDocumentRows\.value, viewedDocumentKeys\.value\)/
|
||||||
|
)
|
||||||
|
assert.match(documentListSharedStyles, /\.mark-read-btn\s*\{[\s\S]*border:\s*1px solid #fecaca;/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('documents center rows show NEW marker until the row is opened', () => {
|
test('documents center rows show NEW marker until the row is opened', () => {
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ const sidebar = readFileSync(
|
|||||||
'utf8'
|
'utf8'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const sidebarStyles = readFileSync(
|
||||||
|
fileURLToPath(new URL('../src/assets/styles/components/sidebar-rail.css', import.meta.url)),
|
||||||
|
'utf8'
|
||||||
|
)
|
||||||
|
|
||||||
const documentInbox = readFileSync(
|
const documentInbox = readFileSync(
|
||||||
fileURLToPath(new URL('../src/composables/useDocumentCenterInbox.js', import.meta.url)),
|
fileURLToPath(new URL('../src/composables/useDocumentCenterInbox.js', import.meta.url)),
|
||||||
'utf8'
|
'utf8'
|
||||||
@@ -21,13 +26,16 @@ const documentNewState = readFileSync(
|
|||||||
test('sidebar renders a red dot for unread document center rows', () => {
|
test('sidebar renders a red dot for unread document center rows', () => {
|
||||||
assert.match(sidebar, /useDocumentCenterInbox/)
|
assert.match(sidebar, /useDocumentCenterInbox/)
|
||||||
assert.match(sidebar, /hasUnread: documentInboxHasUnread/)
|
assert.match(sidebar, /hasUnread: documentInboxHasUnread/)
|
||||||
assert.match(sidebar, /<span v-if="item\.hasNewMessage" class="nav-unread-dot" aria-hidden="true"><\/span>/)
|
assert.match(sidebar, /class="nav-label-text"[\s\S]*class="nav-unread-dot nav-unread-dot-label"/)
|
||||||
|
assert.match(sidebar, /class="nav-unread-dot nav-unread-dot-collapsed"/)
|
||||||
assert.match(sidebar, /hasNewMessage: item\.id === 'documents' \? documentInboxHasUnread\.value : false/)
|
assert.match(sidebar, /hasNewMessage: item\.id === 'documents' \? documentInboxHasUnread\.value : false/)
|
||||||
assert.match(sidebar, /void refreshDocumentInbox\(\)/)
|
assert.match(sidebar, /void refreshDocumentInbox\(\)/)
|
||||||
assert.match(sidebar, /startDocumentInboxPolling\(\)/)
|
assert.match(sidebar, /startDocumentInboxPolling\(\)/)
|
||||||
assert.match(sidebar, /stopDocumentInboxPolling\(\)/)
|
assert.match(sidebar, /stopDocumentInboxPolling\(\)/)
|
||||||
assert.match(sidebar, /\.nav-unread-dot\s*\{[\s\S]*background:\s*#ef4444;/)
|
assert.match(sidebarStyles, /\.nav-label-text\s*\{[\s\S]*position:\s*relative;/)
|
||||||
assert.match(sidebar, /\.rail-collapsed \.nav-unread-dot\s*\{[\s\S]*position:\s*absolute;/)
|
assert.match(sidebarStyles, /\.nav-unread-dot\s*\{[\s\S]*background:\s*#ef4444;/)
|
||||||
|
assert.match(sidebarStyles, /\.nav-unread-dot-label\s*\{[\s\S]*position:\s*absolute;[\s\S]*top:\s*-8px;/)
|
||||||
|
assert.match(sidebarStyles, /\.rail-collapsed \.nav-unread-dot-collapsed\s*\{[\s\S]*position:\s*absolute;/)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('document inbox reuses document center viewed-key state', () => {
|
test('document inbox reuses document center viewed-key state', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user