bookmark: ดักความยาวชื่อ/โน้ตที่ช่องกรอก + F19 สรุปสิ่งที่เปลี่ยนใน dialog ประวัติ + formatThaiDate — (1) bookmark limits: utils/bookmark-limits.ts ใหม่เป็น source of truth เดียว (ชื่อ 120/โน้ต 200 ตัวอักษร) server action import ร่วมแทน const ท้องถิ่น + ใส่ maxLength ที่ popup บันทึก bookmark (PDFViewer) และฟอร์มแก้ไข ✏ ใน sidebar ดักทั้งพิมพ์/paste ตั้งแต่ในช่อง ไม่รอ error ตอนกดบันทึก + แก้ off-by-one ของ normalizeBookmarkTitle (เดิม slice 120 แล้วต่อ … = 121 ตัว ทำให้คลุมข้อความยาวแล้วกด B บันทึกเลยโดน limit ของ server ตีกลับทั้งที่ไม่ได้พิมพ์เอง — ตอนนี้ slice 119 + … = 120 พอดีตามสเปก §7 N2 ที่เขียนไว้ ≤ 120 อยู่แล้ว) + PLAN-FEAT.md §7 N2 บันทึกเพิ่ม — (2) งานคู่ขนาดจากอีก session (แชร์ไฟล์ PDFViewer/sidebar เลยรวม commit): dialog ประวัติ F19 แสดงสรุปสิ่งที่เปลี่ยนต่อรอบผ่าน describeAnnotationChange ใหม่ใน utils/annotation-display.ts (เทียบ snapshot ก่อนแก้ v.data กับ state ถัดไป — snapshot รอบใหม่กว่า หรือค่าปัจจุบันจาก realtime lookup สด historyCurrent — สรุปเป็นหน่วยเดียวกับตัวปรับ UI: ความหนา ×10 ความทึบ % fontSize px ชื่อสี preset ย้าย/ปรับขนาดจาก bbox ผลต่างเกิน GEOM_EPS_PCT 0.5% ข้อความ/โน้ต/label) + dialog ขยาย w-96 max-h-[60vh] แถวเปลี่ยน items-start + utils/date-format.ts ใหม่ formatThaiDate วันที่ไทยเต็ม "18 กันยายน พ.ศ. 2569" (+เวลา) แทน toLocaleString("th-TH") ทุกจุดแสดงวันที่ใน UI (หน้ารายการไฟล์ sidebar ประวัติ/รายการ timestamps ใน PDFViewer) กัน server/client locale ไม่ตรงกัน + tests ใหม่/ขยาย (date-format + describeAnnotationChange) — CLAUDE.md sync โครงสร้าง utils — verify: tsc strict ผ่าน + vitest 139/139 ผ่าน
All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 3s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 43s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 3s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s
All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 3s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 43s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 3s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
parent
8ba911a119
commit
e0c78d68fe
11 changed files with 469 additions and 38 deletions
|
|
@ -114,8 +114,13 @@ import {
|
|||
type Size,
|
||||
} from "@/utils/coordinates";
|
||||
import type { OacUser } from "@/utils/user";
|
||||
import {
|
||||
MAX_BOOKMARK_NOTE_CHARS,
|
||||
MAX_BOOKMARK_TITLE_CHARS,
|
||||
} from "@/utils/bookmark-limits";
|
||||
import { fileKindFromUrl, imageFormatFromUrl } from "@/utils/file-kind";
|
||||
import { withBasePath } from "@/utils/base-path";
|
||||
import { formatThaiDate } from "@/utils/date-format";
|
||||
import { decodeTiffPages } from "@/utils/tiff-client";
|
||||
import {
|
||||
TEXTBOX_DEFAULT_WIDTH_PCT,
|
||||
|
|
@ -196,10 +201,13 @@ const HIGHLIGHT_COLORS = ["#fde047", "#86efac", "#93c5fd", "#f9a8d4", "#fdba74"]
|
|||
|
||||
/** ชื่อ bookmark ที่มาจากข้อความ (คลุม/ข้อความรายการ) — ล้างขยะของ textLayer ไทย
|
||||
* (sanitizePdfText ครอบด้วยข้อความจาก DB เก่าที่ยังไม่ผ่านการล้าง) ยุบ whitespace
|
||||
* และตัดยาวไม่เกิน 120 ตัวอักษร */
|
||||
* และตัดยาวไม่เกิน MAX_BOOKMARK_TITLE_CHARS ตัวอักษร (รวม … ที่ต่อท้าย —
|
||||
* เดิม slice 120 แล้วต่อ … กลายเป็น 121 ตัว โดน limit ของ server ตีกลับตอนบันทึก) */
|
||||
function normalizeBookmarkTitle(s: string): string {
|
||||
const t = sanitizePdfText(s).replace(/\s+/g, " ").trim();
|
||||
return t.length > 120 ? `${t.slice(0, 120)}…` : t;
|
||||
return t.length > MAX_BOOKMARK_TITLE_CHARS
|
||||
? `${t.slice(0, MAX_BOOKMARK_TITLE_CHARS - 1)}…`
|
||||
: t;
|
||||
}
|
||||
|
||||
/** ความสูง sticky header ของ viewer — ใช้เว้นระยะเวลาเลื่อนหน้าไม่ให้เป้าหมายถูก header บัง */
|
||||
|
|
@ -492,12 +500,7 @@ function ReplyBox({
|
|||
<p className="text-[11px] font-medium text-slate-600">
|
||||
{r.userName}
|
||||
<span className="ml-1 font-normal text-slate-400" suppressHydrationWarning>
|
||||
{new Date(r.createdAt).toLocaleString("th-TH", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
})}
|
||||
{formatThaiDate(r.createdAt, true)}
|
||||
</span>
|
||||
</p>
|
||||
<p className="whitespace-pre-wrap break-words text-[11px]">{r.message}</p>
|
||||
|
|
@ -1075,7 +1078,7 @@ function PdfPage({
|
|||
</p>
|
||||
)}
|
||||
<p className="mt-1 text-[11px] text-slate-400" suppressHydrationWarning>
|
||||
{new Date(a.createdAt).toLocaleString("th-TH")}
|
||||
{formatThaiDate(a.createdAt, true)}
|
||||
</p>
|
||||
{/* F10/A5: toggle จัดการแล้ว — ใครก็ได้ (D6) */}
|
||||
<button
|
||||
|
|
@ -3550,6 +3553,7 @@ export default function PDFViewer({
|
|||
<input
|
||||
autoFocus
|
||||
onFocus={(e) => e.target.select()} // เลือกข้อความ default ทั้งหมด — พิมพ์ทับ/Enter ยอมรับได้ทันที
|
||||
maxLength={MAX_BOOKMARK_TITLE_CHARS}
|
||||
value={bookmarkComposer.title}
|
||||
onChange={(e) =>
|
||||
setBookmarkComposer({ ...bookmarkComposer, title: e.target.value })
|
||||
|
|
@ -3564,6 +3568,7 @@ export default function PDFViewer({
|
|||
/>
|
||||
<textarea
|
||||
rows={2}
|
||||
maxLength={MAX_BOOKMARK_NOTE_CHARS}
|
||||
value={bookmarkComposer.note}
|
||||
onChange={(e) =>
|
||||
setBookmarkComposer({ ...bookmarkComposer, note: e.target.value })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue