Compare commits

...
Author SHA1 Message Date
dependabot[bot] aba16584fe Chore(deps-dev): Bump @playwright/test from 1.62.1 to 1.64.1 in /src-ui
Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.62.1 to 1.64.1.
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](https://github.com/microsoft/playwright/compare/v1.62.1...v1.64.1)

---
updated-dependencies:
- dependency-name: "@playwright/test"
  dependency-version: 1.64.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-11-01 20:25:55 +00:00
shamoon 5b63c9a0ff Fixhancement: add tag names to document history list (#14625) 2026-11-01 05:39:52 -08:00
shamoon 217c5e681d Fix: add button type to zoom buttons to prevent form submission (#14624) 2026-11-01 05:35:38 -08:00
6 changed files with 79 additions and 27 deletions

No files matched your search

+1 -1
View File
@@ -56,7 +56,7 @@
"@angular/build": "22.2.2",
"@angular/cli": "22.2.2",
"@angular/compiler-cli": "~22.2.2",
"@playwright/test": "^1.62.1",
"@playwright/test": "^1.64.1",
"@types/jest": "^30.0.0",
"@types/node": "^26.6.2",
"@typescript-eslint/eslint-plugin": "^8.70.1",
+13 -23
View File
@@ -131,8 +131,8 @@ importers:
specifier: ~22.2.2
version: 22.2.2(@angular/compiler@22.2.2)(typescript@6.0.3)
'@playwright/test':
specifier: ^1.62.1
version: 1.62.1
specifier: ^1.64.1
version: 1.64.1
'@types/jest':
specifier: ^30.0.0
version: 30.0.0
@@ -1747,8 +1747,8 @@ packages:
resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==}
engines: {node: ^14.18.0 || >=16.0.0}
'@playwright/test@1.62.1':
resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==}
'@playwright/test@1.64.1':
resolution: {integrity: sha512-IaYGml/nSOiZWROfPtuIL7neuu9qDOZ3TNvNljUIrhDMxiGTgPjzj/g9p9RxpS2tSepPDRY+UwAaEeiKtUvIAg==}
engines: {node: '>=20'}
hasBin: true
@@ -2746,11 +2746,6 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -3595,13 +3590,13 @@ packages:
resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
engines: {node: '>=8'}
playwright-core@1.62.1:
resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==}
playwright-core@1.64.1:
resolution: {integrity: sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==}
engines: {node: '>=20'}
hasBin: true
playwright@1.62.1:
resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==}
playwright@1.64.1:
resolution: {integrity: sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==}
engines: {node: '>=20'}
hasBin: true
@@ -5832,9 +5827,9 @@ snapshots:
'@pkgr/core@0.3.6': {}
'@playwright/test@1.62.1':
'@playwright/test@1.64.1':
dependencies:
playwright: 1.62.1
playwright: 1.64.1
'@popperjs/core@2.11.8': {}
@@ -6752,9 +6747,6 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
fsevents@2.3.2:
optional: true
fsevents@2.3.3:
optional: true
@@ -7822,13 +7814,11 @@ snapshots:
dependencies:
find-up: 4.1.0
playwright-core@1.62.1: {}
playwright-core@1.64.1: {}
playwright@1.62.1:
playwright@1.64.1:
dependencies:
playwright-core: 1.62.1
optionalDependencies:
fsevents: 2.3.2
playwright-core: 1.64.1
postcss-media-query-parser@0.2.3: {}
@@ -485,7 +485,7 @@
</div>
}
<div class="input-group input-group-sm w-auto flex-nowrap">
<button class="btn btn-outline-secondary" (click)="decreaseZoom()" aria-label="Zoom out" i18n-aria-label>
<button class="btn btn-outline-secondary" type="button" (click)="decreaseZoom()" aria-label="Zoom out" i18n-aria-label>
<i-bs width="1em" height="1em" name="dash"></i-bs>
</button>
<select class="form-select" (change)="setZoom($event.target.value)" [ngModelOptions]="{standalone: true}" [ngModel]="currentZoom" aria-label="Zoom" i18n-aria-label>
@@ -495,7 +495,7 @@
</option>
}
</select>
<button class="btn btn-outline-secondary" (click)="increaseZoom()" aria-label="Zoom in" i18n-aria-label>
<button class="btn btn-outline-secondary" type="button" (click)="increaseZoom()" aria-label="Zoom in" i18n-aria-label>
<i-bs width="1em" height="1em" name="plus"></i-bs>
</button>
</div>
@@ -47,6 +47,8 @@
<span>{{ change.key | titlecase }}</span>:&nbsp;
@if (change.key === 'content') {
<code class="text-primary">{{ change.value[1]?.substring(0,100) }}...</code>
} @else if (change.key === 'tags') {
<code class="text-primary">{{ getTagNames($any(change.value[1])) | async }}</code>
} @else {
<code class="text-primary">{{ getPrettyName(change.key, change.value[1]) | async }}</code>
}
@@ -12,6 +12,7 @@ import { CorrespondentService } from 'src/app/services/rest/correspondent.servic
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { TagService } from 'src/app/services/rest/tag.service'
import { UserService } from 'src/app/services/rest/user.service'
import { DocumentHistoryComponent } from './document-history.component'
@@ -174,6 +175,39 @@ describe('DocumentHistoryComponent', () => {
})
})
it('should render bulk tag history with names and preserve missing tag IDs', () => {
const getCachedSpy = jest
.spyOn(TestBed.inject(TagService), 'getCached')
.mockImplementation((id) =>
of(id === 1 ? { id: 1, name: 'Invoice' } : null)
)
component.entries.set([
{
id: 1,
action: AuditLogAction.Update,
timestamp: '2021-01-01T00:00:00Z',
remote_addr: null,
changes: JSON.parse('{"tags":[[],[1,2345]]}'),
},
])
component.loading.set(false)
fixture.detectChanges()
expect(fixture.nativeElement.querySelector('code').textContent).toBe(
'Invoice, 2345'
)
fixture.detectChanges()
expect(getCachedSpy).toHaveBeenCalledTimes(2)
})
it('should handle removal of all tags without a lookup', () => {
const getCachedSpy = jest.spyOn(TestBed.inject(TagService), 'getCached')
component.getTagNames([]).subscribe((result) => {
expect(result).toBe('')
})
expect(getCachedSpy).not.toHaveBeenCalled()
})
it('getPrettyName should return the value as is for other types', () => {
const id = '123'
component.getPrettyName('other', id).subscribe((result) => {
@@ -2,7 +2,7 @@ import { AsyncPipe, KeyValuePipe, TitleCasePipe } from '@angular/common'
import { Component, Input, OnInit, inject, signal } from '@angular/core'
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Observable, first, map, of, shareReplay } from 'rxjs'
import { Observable, first, forkJoin, map, of, shareReplay } from 'rxjs'
import { AuditLogAction, AuditLogEntry } from 'src/app/data/auditlog-entry'
import { DataType } from 'src/app/data/datatype'
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
@@ -10,6 +10,7 @@ import { CorrespondentService } from 'src/app/services/rest/correspondent.servic
import { DocumentTypeService } from 'src/app/services/rest/document-type.service'
import { DocumentService } from 'src/app/services/rest/document.service'
import { StoragePathService } from 'src/app/services/rest/storage-path.service'
import { TagService } from 'src/app/services/rest/tag.service'
import { UserService } from 'src/app/services/rest/user.service'
@Component({
@@ -30,6 +31,7 @@ export class DocumentHistoryComponent implements OnInit {
private readonly correspondentService = inject(CorrespondentService)
private readonly storagePathService = inject(StoragePathService)
private readonly documentTypeService = inject(DocumentTypeService)
private readonly tagService = inject(TagService)
private readonly userService = inject(UserService)
public AuditLogAction = AuditLogAction
@@ -63,6 +65,30 @@ export class DocumentHistoryComponent implements OnInit {
}
}
getTagNames(tagIds: number[]): Observable<string> {
const cacheKey = `tags:${JSON.stringify(tagIds)}`
const cachedNames = this.prettyNameCache.get(cacheKey)
if (cachedNames) {
return cachedNames
}
const tagNames$ = tagIds.length
? forkJoin(
tagIds.map((tagId) =>
this.tagService.getCached(tagId).pipe(
first(),
map((tag) => tag?.name ?? String(tagId))
)
)
).pipe(map((names) => names.join(', ')))
: of('')
const names$ = tagNames$.pipe(
shareReplay({ bufferSize: 1, refCount: true })
)
this.prettyNameCache.set(cacheKey, names$)
return names$
}
getPrettyName(type: DataType | string, id: string): Observable<string> {
const cacheKey = `${type}:${id}`
const cached = this.prettyNameCache.get(cacheKey)