Chorehancement: update to Angular v22, 'zoneless' / 'reactive' (#13114)

This commit is contained in:
shamoon
2026-07-10 00:42:16 -07:00
committed by GitHub
parent f244442c65
commit 106b41a15c
213 changed files with 5363 additions and 5842 deletions
@@ -8,18 +8,18 @@
<div>
<p class="mb-1">
<ng-container i18n>Selected documents:</ng-container>
{{ selectionCount }}
{{ selectionCount() }}
</p>
@if (documentPreview.length > 0) {
@if (documentPreview().length > 0) {
<ul class="list-unstyled small mb-0">
@for (doc of documentPreview; track doc.id) {
@for (doc of documentPreview(); track doc.id) {
<li>
<strong>{{ doc.title | documentTitle }}</strong>
</li>
}
@if (selectionCount > documentPreview.length) {
@if (selectionCount() > documentPreview().length) {
<li>
<ng-container i18n>+ {{ selectionCount - documentPreview.length }} more…</ng-container>
<ng-container i18n>+ {{ selectionCount() - documentPreview().length }} more…</ng-container>
</li>
}
</ul>
@@ -72,10 +72,10 @@
type="button"
(click)="copy(createdBundle)"
>
@if (copied) {
@if (copied()) {
<i-bs name="clipboard-check"></i-bs>
}
@if (!copied) {
@if (!copied()) {
<i-bs name="clipboard"></i-bs>
}
<span class="visually-hidden" i18n>Copy link</span>
@@ -118,8 +118,8 @@
type="button"
class="btn btn-primary btn-sm d-inline-flex align-items-center gap-2 text-nowrap"
(click)="submit()"
[disabled]="loading || !buttonsEnabled">
@if (loading) {
[disabled]="loading() || !buttonsEnabled">
@if (loading()) {
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
}
{{ btnCaption }}
@@ -1,10 +1,5 @@
import { Clipboard } from '@angular/cdk/clipboard'
import {
ComponentFixture,
TestBed,
fakeAsync,
tick,
} from '@angular/core/testing'
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule, allIcons } from 'ngx-bootstrap-icons'
import { FileVersion } from 'src/app/data/share-link'
@@ -58,10 +53,10 @@ describe('ShareLinkBundleDialogComponent', () => {
it('builds payload and emits confirm on submit', () => {
const confirmSpy = jest.spyOn(component.confirmClicked, 'emit')
component.documents = [
component.setDocuments([
{ id: 1, title: 'Doc 1' } as any,
{ id: 2, title: 'Doc 2' } as any,
]
])
component.form.setValue({
shareArchiveVersion: false,
expirationDays: 3,
@@ -101,14 +96,15 @@ describe('ShareLinkBundleDialogComponent', () => {
const docs = Array.from({ length: 12 }).map((_, index) => ({
id: index + 1,
}))
component.documents = docs as any
component.setDocuments(docs as any)
expect(component.selectionCount).toBe(12)
expect(component.documentPreview).toHaveLength(10)
expect(component.documentPreview[0].id).toBe(1)
expect(component.selectionCount()).toBe(12)
expect(component.documentPreview()).toHaveLength(10)
expect(component.documentPreview()[0].id).toBe(1)
})
it('copies share link and resets state after timeout', fakeAsync(() => {
it('copies share link and resets state after timeout', () => {
jest.useFakeTimers()
const copySpy = jest.spyOn(clipboard, 'copy').mockReturnValue(true)
const bundle = {
slug: 'bundle-slug',
@@ -118,12 +114,13 @@ describe('ShareLinkBundleDialogComponent', () => {
component.copy(bundle)
expect(copySpy).toHaveBeenCalledWith(component.getShareUrl(bundle))
expect(component.copied).toBe(true)
expect(component.copied()).toBe(true)
expect(toastService.showInfo).toHaveBeenCalled()
tick(3000)
expect(component.copied).toBe(false)
}))
jest.advanceTimersByTime(3000)
expect(component.copied()).toBe(false)
jest.useRealTimers()
})
it('generates share URLs based on API base URL', () => {
environment.apiBaseUrl = 'https://example.com/api/'
@@ -1,6 +1,6 @@
import { Clipboard } from '@angular/cdk/clipboard'
import { CommonModule } from '@angular/common'
import { Component, Input, inject } from '@angular/core'
import { Component, inject, signal } from '@angular/core'
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Document } from 'src/app/data/document'
@@ -38,10 +38,11 @@ export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
private readonly clipboard = inject(Clipboard)
private readonly toastService = inject(ToastService)
private _documents: Document[] = []
readonly documents = signal<Document[]>([])
readonly selectionCount = signal(0)
readonly documentPreview = signal<Document[]>([])
readonly copied = signal(false)
selectionCount = 0
documentPreview: Document[] = []
form: FormGroup = this.formBuilder.group({
shareArchiveVersion: true,
expirationDays: [7],
@@ -51,28 +52,27 @@ export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
readonly expirationOptions = SHARE_LINK_EXPIRATION_OPTIONS
createdBundle: ShareLinkBundleSummary | null = null
copied = false
onOpenManage?: () => void
readonly statuses = ShareLinkBundleStatus
constructor() {
super()
this.loading = false
this.loading.set(false)
this.title = $localize`Create share link bundle`
this.btnCaption = $localize`Create link`
}
@Input()
set documents(docs: Document[]) {
this._documents = docs.concat()
this.selectionCount = this._documents.length
this.documentPreview = this._documents.slice(0, 10)
setDocuments(docs: Document[]) {
const documents = docs.concat()
this.documents.set(documents)
this.selectionCount.set(documents.length)
this.documentPreview.set(documents.slice(0, 10))
}
submit() {
if (this.createdBundle) return
this.payload = {
document_ids: this._documents.map((doc) => doc.id),
document_ids: this.documents().map((doc) => doc.id),
file_version: this.form.value.shareArchiveVersion
? FileVersion.Archive
: FileVersion.Original,
@@ -92,10 +92,10 @@ export class ShareLinkBundleDialogComponent extends ConfirmDialogComponent {
copy(bundle: ShareLinkBundleSummary): void {
const success = this.clipboard.copy(this.getShareUrl(bundle))
if (success) {
this.copied = true
this.copied.set(true)
this.toastService.showInfo($localize`Share link copied to clipboard.`)
setTimeout(() => {
this.copied = false
this.copied.set(false)
}, 3000)
}
}