พอร์ต 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>
59 lines
8 KiB
Markdown
59 lines
8 KiB
Markdown
# 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`](./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 ทางเลือก:
|
|
|
|
1. **self-signed ของ Next (ง่ายสุด):** `npm run dev:https` → https://localhost:3000 — Word อาจเตือน certificate ครั้งแรก (เปิด URL ใน browser กดผ่านก่อน 1 ครั้ง)
|
|
2. **ใบรับรอง 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)
|
|
|
|
1. รัน dev server (https) แล้วดาวน์โหลด manifest: `https://localhost:3000/docedit/wordaddin/manifest.xml`
|
|
2. เอาไฟล์ manifest ไว้โฟลเดอร์ใดโฟลเดอร์หนึ่ง เช่น `%USERPROFILE%\Documents\wordaddin-manifest\`
|
|
3. Word: **File > Options > Trust Center > Trust Center Settings > Trusted Add-in Catalogs** เพิ่มโฟลเดอร์นั้น > restart Word
|
|
4. **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`) และไม่มี enum `Word.CloseBehavior`/`SaveBehavior` ทับ ๆ กับ `@types/office-js` ฉบับใหม่ที่ใช้ compile
|