พอร์ต taskpane ของ Word add-in "e-Court Documents Versioning" จาก D:\word-addin-poc มาเป็น sibling app ที่ route /docedit/wordaddin: - wordaddin/ (client-only zone): services พอร์ตดิบทั้งชุด (authService/versioningService เป็น mock รอ backend จริง) + models + config - components/wordaddin/: WordAddinGate ฉีด office.js self-host (singleton กัน StrictMode double-inject + fallback timer ครอบเคส onReady เงียบ) และ TaskpaneApp state machine แปลง JSX เป็น Genesis design system - scripts/fetch-office-js.mjs (postinstall ตัวที่สาม): ดาวน์โหลด Office.js runtime ล่าสุดจาก CDN Microsoft ไป public/wordaddin/office-js/ (gitignore สร้างใหม่ได้ — npm @microsoft/office-js ตกรุ่นไม่มี Document.close) - middleware/basePath/root page: เปิด /wordaddin เป็น public (auth แยกจาก แอป note), root /docedit redirect ไป taskpane ยกเว้นลิงก์ e-Court N8 (?fileUrl=&fileId=&typeId=) ที่ยังส่งต่อ /note ตามเดิม - docker/web.Dockerfile รัน fetch-office-js ตอน build + npm scripts dev:https สำหรับ sideload ตาม docs/WORDADDIN-DEV.md Co-Authored-By: Claude Code <noreply@anthropic.com>
8 KiB
Word Add-in (wordaddin) — คู่มือ dev และการทดสอบ
Taskpane ของ Word add-in "e-Court Documents Versioning" พอร์ตมาเป็น route ของ Next.js ที่ /docedit/wordaddin (ต้นฉบับ webpack + Fluent UI: D:\word-addin-poc\addin) — spec พฤติกรรม UI ทั้งหมดอยู่ที่ docs/addin-ui-flow.md
ทางเข้า: เปิด /docedit เปล่า ๆ จะ redirect มาที่ taskpane ทันที (ไม่ผ่าน login — คำขอผู้ใช้ 2026-10-14) ยกเว้นลิงก์ e-Court /docedit/?fileUrl=&fileId=&typeId= ที่ยังส่งต่อให้ /note ตามสัญญา N8 · manifest ชี้ /docedit/wordaddin ตรง ๆ (ไม่ว่าผ่าน root เพื่อลด hop ใน webview)
สถานะช่วงนี้: auth และ API เป็น mock (login ทันที + version store เก็บ metadata ค้างข้าม session ใน localStorage ของ taskpane เพื่อทดสอบวงปิดเอกสาร→เปิดใหม่ — สลับกลับของจริงด้วยการลบ wordaddin-mock-versions หรือเคลียร์ storage ของ origin) รอ backend/auth จริง — ดูหัว "การสลับกลับของจริง" ด้านล่าง
ไฟล์หลัก
| ที่ | คือ |
|---|---|
app/wordaddin/page.tsx + components/wordaddin/WordAddinGate.tsx |
gate โหลด Office.js (self-host) → Office.onReady → mount TaskpaneApp |
components/wordaddin/TaskpaneApp.tsx |
state machine checking/signed-out/untracked/tracking + ทุก handler |
wordaddin/services/* |
ชั้น Office.js พอร์ตดิบจากต้นฉบับ + authService/versioningService เป็น mock |
public/wordaddin/manifest.xml |
manifest sideload (URL เป็น absolute https ต่อ environment) |
public/wordaddin/office-js/ |
Office.js runtime — สร้างโดย postinstall scripts/fetch-office-js.mjs ดาวน์โหลดฉบับล่าสุดจาก CDN ของ Microsoft (gitignore — รัน npm install ทุกครั้งหลัง clone เครื่องต้องออกอินเทอร์เน็ตตอนติดตั้ง ส่วนตัวระบบ deploy ใช้ intranet ล้วน) |
wordaddin/config.ts |
env NEXT_PUBLIC_ADDIN_* (ตารางด้านล่าง) |
Env
| ตัวแปร | default | ใช้เมื่อไหร่ |
|---|---|---|
NEXT_PUBLIC_ADDIN_API_BASE_URL |
"" (ว่าง) |
ปลด mock ต่อ backend จริง (ต้องเป็น HTTPS) |
NEXT_PUBLIC_ADDIN_MOCK_USERNAME |
"tester01" |
ชื่อผู้ใช้ของ mock — แสดง header + เป็น createdByUserId |
รัน dev ด้วย HTTPS (จำเป็นสำหรับ sideload ใน Word)
manifest ต้องชี้ https — 2 ทางเลือก:
- self-signed ของ Next (ง่ายสุด):
npm run dev:https→ https://localhost:3000 — Word อาจเตือน certificate ครั้งแรก (เปิด URL ใน browser กดผ่านก่อน 1 ครั้ง) - ใบรับรอง trusted (แนะนำ ไม่มี warning): รัน
npx office-addin-dev-certs installครั้งเดียว แล้ว copy%USERPROFILE%\.office-addin-dev-certs\localhost.crt+localhost.keyมาที่certs/(gitignore แล้ว) แล้วใช้npm run dev:https:cert
Sideload ใน Word Desktop (Windows)
- รัน dev server (https) แล้วดาวน์โหลด manifest:
https://localhost:3000/docedit/wordaddin/manifest.xml - เอาไฟล์ manifest ไว้โฟลเดอร์ใดโฟลเดอร์หนึ่ง เช่น
%USERPROFILE%\Documents\wordaddin-manifest\ - Word: File > Options > Trust Center > Trust Center Settings > Trusted Add-in Catalogs เพิ่มโฟลเดอร์นั้น > restart Word
- Insert > My Add-ins > SHARED FOLDER > เปิด "e-Court Documents Versioning"
Deploy จริง (intranet): rewrite URL ทุกตัวใน manifest จาก https://localhost:3000/docedit/wordaddin เป็น https://<โฮสต์>/docedit/wordaddin (และ AppDomain + icons ด้วย)
ทดสอบใน browser ธรรมดา (ไม่ต้องเปิด Word)
/docedit/wordaddin— เส้นทางจริง: Office.js โหลดได้แม่นนอก host (host เป็น null) → เห็นsigned-out→ กด Sign in (mock ผ่านทันที) → detect พังที่Word.run→bootError+ ปุ่มลองใหม่ (ตรวจ state machine/handler ได้ครบ)/docedit/wordaddin?addindemo=untracked/?addindemo=tracking— dev-only: ข้าม Office.js + sign in mock ทันที + ตั้ง phase ตามค่า (tracking มี history ตัวอย่าง 3 รายการ) — ทุกปุ่มกดได้ แต่ flow ที่แตะ Word จริง (Start Versioning / Save & Version / บันทึก) จะจบที่ error ตาม expected- หมายเหตุ: ใน browser ปกติ (ไม่ใช่ demo) banner "บันทึกอัตโนมัติไม่สำเร็จ" จะโผล่หลัง ~30 วิ เพราะ auto-save (FR-17) พยายาม save ทุก 30 วิแต่ไม่มี Word — ถือว่าถูกต้อง
การสลับกลับของจริง (วันหน้า)
- Auth:
wordaddin/services/authService.tsเป็น mock คง surface เดิมครบ (login/getAccessToken/refreshAccessToken/getUsername/signOut/startAutoRefresh/...) — เขียน implementation จริงทับ (ต้นฉบับ Keycloak PKCE + Office Dialog API อยู่ที่D:\word-addin-poc\addin\src\services\authService.ts; ถ้าใช้ ต้องเพิม DialogAPI กลับเข้า manifest + หน้า auth-start/auth-callback) - API:
wordaddin/services/versioningService.tsเก็บชื่อ/ลายเซ็นเหมือนต้นฉบับเป๊ะ — ก้อบ body เดิม (multipart POST ผ่านapiClientซึ่งพอร์ตไว้แล้ว) กลับมา + ตั้งNEXT_PUBLIC_ADDIN_API_BASE_URL - ชุด unit test ของ services (jest → vitest) ยังไม่พอร์ต — ต้นฉบับอยู่ที่
D:\word-addin-poc\addin\src\services\*.test.ts+ mock ที่src/test/
Docker
ไม่ต้องทำอะไรเพิ่ม — docker/web.Dockerfile รัน scripts/fetch-office-js.mjs ใน build อยู่แล้ว (build stage ต้องออกอินเทอร์เน็ตถึง appsforoffice.microsoft.com ได้) และ Next รวม public/ ไว้ใน standalone อัตโนมัติ
ทำไมต้องเป็นฉบับ CDN ล่าสุด: แพ็กเกจ npm
@microsoft/office-jsเลิกอัปเดตที่ 1.1.110 (~2018) ก่อน WordApi 1.4/1.5 — runtime ตัวนั้นไม่มีDocument.close(ปุ่ม "บันทึกเวอร์ชันและปิดเอกสาร" พัง:context.document.close is not a function) และไม่มี enumWord.CloseBehavior/SaveBehaviorทับ ๆ กับ@types/office-jsฉบับใหม่ที่ใช้ compile