diff --git a/src/app/core/database/pouch-database.ts b/src/app/core/database/pouch-database.ts
index 325a799c08..f7cf401540 100644
--- a/src/app/core/database/pouch-database.ts
+++ b/src/app/core/database/pouch-database.ts
@@ -387,7 +387,9 @@ export class PouchDatabase extends Database {
newObject._rev = existingObject._rev;
return this.put(newObject);
} else {
- existingError.message = existingError.message + " (unable to resolve)";
+ existingError.message = `${
+ existingError.message
+ } (unable to resolve) ID: ${JSON.stringify(newObject)}`;
throw new DatabaseException(existingError);
}
}
diff --git a/src/app/core/support/support/support.component.html b/src/app/core/support/support/support.component.html
index 00ed333a2e..6d2e14d6cb 100644
--- a/src/app/core/support/support/support.component.html
+++ b/src/app/core/support/support/support.component.html
@@ -41,6 +41,10 @@
Technical User Support Details
Storage usage |
{{ storageInfo || 'No information' }} |
+
+ Database documents |
+ {{ dbInfo }} |
+
Service Worker |
{{ swStatus }} |
diff --git a/src/app/core/support/support/support.component.spec.ts b/src/app/core/support/support/support.component.spec.ts
index e0d159c081..191c4c732f 100644
--- a/src/app/core/support/support/support.component.spec.ts
+++ b/src/app/core/support/support/support.component.spec.ts
@@ -3,6 +3,7 @@ import {
fakeAsync,
TestBed,
tick,
+ waitForAsync,
} from "@angular/core/testing";
import { SupportComponent } from "./support.component";
@@ -10,7 +11,6 @@ import { SessionService } from "../../session/session-service/session.service";
import { BehaviorSubject, of } from "rxjs";
import { SyncState } from "../../session/session-states/sync-state.enum";
import { SwUpdate } from "@angular/service-worker";
-import { Database } from "../../database/database";
import { LOCATION_TOKEN, WINDOW_TOKEN } from "../../../utils/di-tokens";
import { TEST_USER } from "../../../utils/mocked-testing.module";
import { RemoteSession } from "../../session/session-service/remote-session";
@@ -20,6 +20,7 @@ import { SyncedSessionService } from "../../session/session-service/synced-sessi
import { MatDialogModule } from "@angular/material/dialog";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
+import { PouchDatabase } from "../../database/pouch-database";
describe("SupportComponent", () => {
let component: SupportComponent;
@@ -27,7 +28,7 @@ describe("SupportComponent", () => {
const testUser = { name: TEST_USER, roles: [] };
let mockSessionService: jasmine.SpyObj;
const mockSW = { isEnabled: false };
- let mockDB: jasmine.SpyObj;
+ let mockDB: jasmine.SpyObj;
const mockWindow = {
navigator: {
userAgent: "mock user agent",
@@ -42,7 +43,10 @@ describe("SupportComponent", () => {
syncState: new BehaviorSubject(SyncState.UNSYNCED),
});
mockSessionService.getCurrentUser.and.returnValue(testUser);
- mockDB = jasmine.createSpyObj(["destroy"]);
+ mockDB = jasmine.createSpyObj(["destroy", "getPouchDB"]);
+ mockDB.getPouchDB.and.returnValue({
+ info: () => Promise.resolve({ doc_count: 1, update_seq: 2 }),
+ } as any);
mockLocation = jasmine.createSpyObj(["reload"]);
await TestBed.configureTestingModule({
imports: [
@@ -54,18 +58,18 @@ describe("SupportComponent", () => {
providers: [
{ provide: SessionService, useValue: mockSessionService },
{ provide: SwUpdate, useValue: mockSW },
- { provide: Database, useValue: mockDB },
+ { provide: PouchDatabase, useValue: mockDB },
{ provide: WINDOW_TOKEN, useValue: mockWindow },
{ provide: LOCATION_TOKEN, useValue: mockLocation },
],
}).compileComponents();
});
- beforeEach(() => {
+ beforeEach(waitForAsync(() => {
fixture = TestBed.createComponent(SupportComponent);
component = fixture.componentInstance;
fixture.detectChanges();
- });
+ }));
it("should create", () => {
expect(component).toBeTruthy();
@@ -78,15 +82,16 @@ describe("SupportComponent", () => {
expect(component.lastRemoteLogin).toBe("never");
expect(component.swStatus).toBe("not enabled");
expect(component.userAgent).toBe("mock user agent");
+ expect(component.dbInfo).toBe("1 (update sequence 2)");
});
- it("should correctly read sync and remote login status from local storage", () => {
+ it("should correctly read sync and remote login status from local storage", async () => {
const lastSync = new Date("2022-01-01").toISOString();
localStorage.setItem(SyncedSessionService.LAST_SYNC_KEY, lastSync);
const lastRemoteLogin = new Date("2022-01-02").toISOString();
localStorage.setItem(RemoteSession.LAST_LOGIN_KEY, lastRemoteLogin);
- component.ngOnInit();
+ await component.ngOnInit();
expect(component.lastSync).toBe(lastSync);
expect(component.lastRemoteLogin).toBe(lastRemoteLogin);
diff --git a/src/app/core/support/support/support.component.ts b/src/app/core/support/support/support.component.ts
index 2e6765e541..0682b9045c 100644
--- a/src/app/core/support/support/support.component.ts
+++ b/src/app/core/support/support/support.component.ts
@@ -3,7 +3,6 @@ import { SessionService } from "../../session/session-service/session.service";
import { LOCATION_TOKEN, WINDOW_TOKEN } from "../../../utils/di-tokens";
import { SyncState } from "../../session/session-states/sync-state.enum";
import { SwUpdate } from "@angular/service-worker";
-import { Database } from "../../database/database";
import * as Sentry from "@sentry/browser";
import { RemoteSession } from "../../session/session-service/remote-session";
import { ConfirmationDialogService } from "../../confirmation-dialog/confirmation-dialog.service";
@@ -14,16 +13,14 @@ import { AuthUser } from "../../session/session-service/auth-user";
import { firstValueFrom } from "rxjs";
import { MatExpansionModule } from "@angular/material/expansion";
import { MatButtonModule } from "@angular/material/button";
+import { PouchDatabase } from "../../database/pouch-database";
@Component({
selector: "app-support",
templateUrl: "./support.component.html",
styleUrls: ["./support.component.scss"],
- imports: [
- MatExpansionModule,
- MatButtonModule
- ],
- standalone: true
+ imports: [MatExpansionModule, MatButtonModule],
+ standalone: true,
})
export class SupportComponent implements OnInit {
currentUser: AuthUser;
@@ -35,18 +32,19 @@ export class SupportComponent implements OnInit {
swLog = "not available";
userAgent = this.window.navigator.userAgent;
appVersion: string;
+ dbInfo: string;
constructor(
private sessionService: SessionService,
private sw: SwUpdate,
- private database: Database,
+ private database: PouchDatabase,
private confirmationDialog: ConfirmationDialogService,
private http: HttpClient,
@Inject(WINDOW_TOKEN) private window: Window,
@Inject(LOCATION_TOKEN) private location: Location
) {}
- ngOnInit(): void {
+ ngOnInit() {
this.currentUser = this.sessionService.getCurrentUser();
this.appVersion = environment.appVersion;
this.initCurrentSyncState();
@@ -54,6 +52,7 @@ export class SupportComponent implements OnInit {
this.initLastRemoteLogin();
this.initStorageInfo();
this.initSwStatus();
+ return this.initDbInfo();
}
private initCurrentSyncState() {
@@ -103,6 +102,16 @@ export class SupportComponent implements OnInit {
.then((res) => (this.swLog = res));
}
+ private initDbInfo() {
+ return this.database
+ .getPouchDB()
+ .info()
+ .then(
+ (res) =>
+ (this.dbInfo = `${res.doc_count} (update sequence ${res.update_seq})`)
+ );
+ }
+
sendReport() {
// This is sent even without submitting the crash report.
Sentry.captureMessage("report information", {
@@ -116,6 +125,7 @@ export class SupportComponent implements OnInit {
userAgent: this.userAgent,
swLog: this.swLog,
storageInfo: this.storageInfo,
+ dbInfo: this.dbInfo,
},
});
Sentry.showReportDialog({