2026-10-16 12:07:25 +07:00
|
|
|
/**
|
|
|
|
|
* Type ตรงกับ response ของ backend (`Models/VersionDtos.cs` — ASP.NET Core serialize camelCase)
|
|
|
|
|
* พอร์ตดิบจาก D:\word-addin-poc\addin\src\models\versionRecord.ts
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** response ของ POST /api/documents/{documentId}/versions */
|
|
|
|
|
export interface UploadVersionResult {
|
|
|
|
|
hasPdf: boolean;
|
|
|
|
|
versionId: string;
|
|
|
|
|
versionNumber: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** field เดียวใน snapshot ของ version (เอกสารที่ผูก template) */
|
|
|
|
|
export interface FieldSnapshotEntry {
|
|
|
|
|
value: string;
|
|
|
|
|
missing: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* snapshot fields ต่อ version — backend เก็บ 2 รูปแบบ:
|
|
|
|
|
* - เอกสารผูก template: `{ [fieldKey]: { value, missing } }`
|
|
|
|
|
* - เอกสารไม่ผูก template (track เองจาก add-in): map ดิบ `{ [tag]: text }`
|
|
|
|
|
* UI ต้อง handle ได้ทั้งคู่ (ใช้ readSnapshotField ช่วยอ่าน)
|
|
|
|
|
*/
|
|
|
|
|
export type FieldsSnapshot = Record<string, FieldSnapshotEntry> | Record<string, string>;
|
|
|
|
|
|
|
|
|
|
/** item ของ GET /api/documents/{documentId}/versions */
|
|
|
|
|
export interface VersionRecord {
|
|
|
|
|
hasPdf?: boolean;
|
|
|
|
|
versionId: string;
|
|
|
|
|
versionNumber: number;
|
|
|
|
|
/** ISO-8601 */
|
|
|
|
|
createdAt: string;
|
|
|
|
|
createdByUserId: string;
|
feat(addin): unmock versioning — real upload/download against docver API
Replace the in-memory versioningService with real calls to the docver
group (/api/documents/*) via apiClient with the ticket-issued Bearer;
keep the mock only for ?addindemo (authService.isDemoMode).
- uploadVersion: multipart POST /api/documents/versions (file, optional
pdf when non-empty, clientVersionId, fields JSON, trimmed message,
fileName) — identity fields are never sent (userId/userName/templateId
in the form = 400 per the 2026-10-22 contract; docId comes from the
fid claim)
- getVersions: GET → DocumentVersionDTO mapped to VersionRecord (adds
optional createdByUserName; history panel shows it with userId
fallback)
- getDownloadLink: GET presigned URL (+ ?format=pdf)
- apiClient.toUrl: empty NEXT_PUBLIC_ADDIN_API_BASE_URL = same-origin
through withBasePath (/docedit/api/...); the env is now only for a
split deployment (must include basePath, HTTPS)
- documentId/templateId params stay in signatures but are not sent
- tests: versioningService.test.ts covers both modes (real sign-in via
signInWithTicket, FormData contract assertions, DTO mapping, format
query, 401 -> AuthRequiredError, demo mock without network)
- docs sync: WORDADDIN-DEV (new "การรันกับ backend จริง" section),
addin-ui-flow status note, PLAN-DOCVER §8, PLAN-ADDIN-AUTH §12, CLAUDE.md
Verified: tsc clean, 286/286 tests, full E2E against MinIO (ticket ->
token -> upload docx / docx+pdf -> history -> presigned download of both
formats).
Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-27 12:52:29 +07:00
|
|
|
/** ชื่อผู้สร้าง — ส่วนเสริมของ DTO กลุ่ม docver (mock/demo อาจไม่มี → UI fallback เป็น userId) */
|
|
|
|
|
createdByUserName?: string;
|
2026-10-16 12:07:25 +07:00
|
|
|
/** SHA256 hex */
|
|
|
|
|
contentHash: string;
|
|
|
|
|
fields: FieldsSnapshot | null;
|
|
|
|
|
/** คำอธิบาย version แบบ commit message ที่ผู้ใช้พิมพ์ตอนสร้าง (FR-13) — null ได้ */
|
|
|
|
|
message: string | null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** อ่านค่า + สถานะ missing ของ field หนึ่งจาก snapshot ไม่ว่าจะเก็บรูปแบบไหน — ไม่มี field นี้คืน null */
|
|
|
|
|
export function readSnapshotField(
|
|
|
|
|
snapshot: FieldsSnapshot | null,
|
|
|
|
|
key: string
|
|
|
|
|
): FieldSnapshotEntry | null {
|
|
|
|
|
if (!snapshot) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
const raw = snapshot[key];
|
|
|
|
|
if (raw === undefined) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
if (typeof raw === "string") {
|
|
|
|
|
return { value: raw, missing: false };
|
|
|
|
|
}
|
|
|
|
|
return { value: raw.value, missing: raw.missing };
|
|
|
|
|
}
|