하수관로 편집 세션 배치 및 팝업 전환 개선
This commit is contained in:
@@ -7,6 +7,8 @@ type Props = GisEditSessionSnapshot & {
|
||||
onRemoveLastChange: () => void;
|
||||
onClearChanges: () => void;
|
||||
onFocusChange: (changeId: string) => void;
|
||||
onOpenPopup?: () => void;
|
||||
variant?: "inline" | "popup";
|
||||
className?: string;
|
||||
};
|
||||
|
||||
@@ -18,7 +20,7 @@ const TOOL_LABELS: Record<GisEditTool, string> = {
|
||||
};
|
||||
|
||||
const buildChangeItemClassName = (isFocused: boolean) =>
|
||||
`block w-full rounded border px-3 py-3 text-left text-[12px] transition ${
|
||||
`block w-full rounded border px-2 py-2 text-left text-[12px] transition ${
|
||||
isFocused
|
||||
? "border-[#5a9bd5] bg-[#eef7ff] shadow-[inset_0_0_0_1px_rgba(90,155,213,0.2)]"
|
||||
: "border-[#d8dee8] bg-[#fbfcfe] hover:border-[#bfd2e5] hover:bg-white"
|
||||
@@ -27,6 +29,14 @@ const buildChangeItemClassName = (isFocused: boolean) =>
|
||||
const getChangeLabel = (change: GisEditSessionSnapshot["changes"][number]) =>
|
||||
change.attributeOnly ? "상세정보수정" : TOOL_LABELS[change.editType];
|
||||
|
||||
const getChangeSummary = (change: GisEditSessionSnapshot["changes"][number]) => {
|
||||
if (change.attributeOnly) return "변경한 상세정보를 확인하세요.";
|
||||
if (change.editType === "ADD") return "추가한 객체 위치를 확인하세요.";
|
||||
if (change.editType === "MOVE") return "객체를 드래그해 위치를 조정하세요.";
|
||||
if (change.editType === "VERTEX_EDIT") return "점을 옮기거나 선분을 끌어 추가하세요.";
|
||||
return "삭제할 객체가 맞는지 확인하세요.";
|
||||
};
|
||||
|
||||
type ChangeListProps = {
|
||||
changes: GisEditSessionSnapshot["changes"];
|
||||
focusedChangeId: string | null;
|
||||
@@ -42,24 +52,24 @@ const ChangeList = ({ changes, focusedChangeId, onFocusChange }: ChangeListProps
|
||||
className={buildChangeItemClassName(focusedChangeId === change.changeId)}
|
||||
onClick={() => onFocusChange(change.changeId)}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="font-semibold text-[#173f67]">
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="shrink-0 whitespace-nowrap text-[11px] font-semibold leading-4 text-[#173f67]">
|
||||
{index + 1}. {getChangeLabel(change)} / {change.objectLabel}
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{change.basicInfoSavedAt ? (
|
||||
<span className="rounded-full border border-[#a9d9bd] bg-white px-2 py-0.5 text-[10px] font-semibold text-[#16834f]">
|
||||
기본정보 세션저장
|
||||
<div className="ml-auto flex shrink-0 items-center gap-1">
|
||||
{change.basicInfoSavedAt && focusedChangeId !== change.changeId ? (
|
||||
<span className="whitespace-nowrap rounded-full border border-[#a9d9bd] bg-white px-1.5 py-0.5 text-[9px] font-semibold text-[#16834f]">
|
||||
정보저장
|
||||
</span>
|
||||
) : null}
|
||||
{focusedChangeId === change.changeId ? (
|
||||
<span className="rounded-full border border-[#b8d3ef] bg-white px-2 py-0.5 text-[10px] font-semibold text-[#176db8]">
|
||||
<span className="whitespace-nowrap rounded-full border border-[#b8d3ef] bg-white px-1.5 py-0.5 text-[9px] font-semibold text-[#176db8]">
|
||||
지도 미리보기 선택
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-1 text-[#526173]">{change.summary}</div>
|
||||
<div className="mt-1 truncate text-[11px] text-[#526173]">{getChangeSummary(change)}</div>
|
||||
</button>
|
||||
))}
|
||||
</>
|
||||
@@ -76,19 +86,39 @@ export default function GisEditSessionPanel({
|
||||
onRemoveLastChange,
|
||||
onClearChanges,
|
||||
onFocusChange,
|
||||
onOpenPopup,
|
||||
variant = "inline",
|
||||
className = "",
|
||||
}: Props) {
|
||||
const isCompactInline = variant === "inline" && changes.length === 0;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`rounded-lg border border-[#d8dee8] bg-[rgba(255,255,255,0.98)] p-4 text-sm text-[#304255] shadow-[0_10px_26px_rgba(23,42,70,0.14)] ${className}`.trim()}
|
||||
className={`flex min-h-0 flex-col overflow-hidden rounded-lg border border-[#d8dee8] bg-[rgba(255,255,255,0.98)] text-sm text-[#304255] shadow-[0_10px_26px_rgba(23,42,70,0.14)] ${isCompactInline ? "h-[58px] p-2" : "p-4"} ${className}`.trim()}
|
||||
>
|
||||
<div className="mb-3 flex items-center justify-between gap-3">
|
||||
<div className="text-[12px] text-[#667485]">
|
||||
레이어: {selectedLayerName || "미선택"} / 모드: {isEditMode ? (activeTool ? TOOL_LABELS[activeTool] : "대기") : "편집 모드 종료"}
|
||||
<div className={`flex shrink-0 justify-between gap-3 ${isCompactInline ? "mb-0 items-center" : "mb-3 items-start"}`}>
|
||||
<div className="min-w-0">
|
||||
{variant === "inline" ? (
|
||||
<div className="mb-1 text-[14px] font-bold text-[#173f67]">편집 세션</div>
|
||||
) : null}
|
||||
<div className="truncate text-[12px] text-[#667485]">
|
||||
레이어: {selectedLayerName || "미선택"} / 모드: {isEditMode ? (activeTool ? TOOL_LABELS[activeTool] : "대기") : "편집 모드 종료"}
|
||||
</div>
|
||||
</div>
|
||||
{onOpenPopup ? (
|
||||
<button
|
||||
type="button"
|
||||
className="flex shrink-0 items-center gap-1 rounded border border-[#b8d3ef] bg-white px-2.5 py-1.5 text-[11px] font-semibold text-[#176db8] transition hover:bg-[#eef7ff]"
|
||||
onClick={onOpenPopup}
|
||||
title="편집 세션을 기존 윈도우 팝업으로 열기"
|
||||
>
|
||||
<span aria-hidden="true" className="text-[12px] leading-none">↗</span>
|
||||
<span>팝업</span>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="mb-3 flex flex-wrap items-center gap-2">
|
||||
<div className={`${isCompactInline ? "hidden" : "mb-3 flex"} shrink-0 flex-wrap items-center gap-2`}>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded border border-[#d8dee8] bg-white px-3 py-1.5 text-[12px] font-semibold text-[#304255] transition hover:bg-[#f8fafc] disabled:cursor-not-allowed disabled:text-[#9aa8b7]"
|
||||
@@ -118,13 +148,13 @@ export default function GisEditSessionPanel({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<div className={`${isCompactInline ? "hidden" : "min-h-0 flex-1"} overflow-hidden`}>
|
||||
{changes.length === 0 ? (
|
||||
<div className="rounded border border-dashed border-[#d8dee8] bg-[#fbfcfe] px-3 py-4 text-[12px] text-[#667485]">
|
||||
저장할 편집 변경분이 없습니다.
|
||||
</div>
|
||||
) : (
|
||||
<div className="max-h-[calc(100vh-190px)] overflow-y-auto pr-1">
|
||||
<div className="h-full overflow-y-auto pr-1">
|
||||
<div className="space-y-2">
|
||||
<ChangeList
|
||||
changes={changes}
|
||||
|
||||
@@ -19,10 +19,8 @@ type Props = {
|
||||
canUseTools: boolean;
|
||||
canSave: boolean;
|
||||
isSaving?: boolean;
|
||||
sessionChangeCount?: number;
|
||||
statusMessage: string;
|
||||
allowedTools?: GisEditTool[];
|
||||
onOpenSession?: () => void;
|
||||
onClose?: () => void;
|
||||
onToggleSnap: () => void;
|
||||
onSelectTool: (tool: GisEditTool) => void;
|
||||
@@ -47,10 +45,8 @@ export default function GisEditToolbar({
|
||||
canUseTools,
|
||||
canSave,
|
||||
isSaving = false,
|
||||
sessionChangeCount = 0,
|
||||
statusMessage: _statusMessage,
|
||||
allowedTools = [],
|
||||
onOpenSession,
|
||||
onClose,
|
||||
onToggleSnap,
|
||||
onSelectTool,
|
||||
@@ -59,7 +55,7 @@ export default function GisEditToolbar({
|
||||
if (!isEditMode) return null;
|
||||
|
||||
return (
|
||||
<div className="absolute left-1/2 top-4 z-[60] flex w-[min(860px,calc(100%-2rem))] -translate-x-1/2 flex-col">
|
||||
<div data-testid="gis-edit-toolbar" className="absolute bottom-12 left-1/2 z-[60] flex w-[min(960px,calc(100%-2rem))] -translate-x-1/2 flex-col">
|
||||
<div className="card card-border flex !bg-white py-[1px]">
|
||||
<div className="flex w-full items-center gap-2 overflow-hidden">
|
||||
<div className="flex w-[120px] shrink-0 items-center justify-start">
|
||||
@@ -124,21 +120,7 @@ export default function GisEditToolbar({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex w-[248px] shrink-0 items-center justify-end gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
color="white"
|
||||
size="sm"
|
||||
className="mt-1 min-w-[98px] shrink-0 px-2"
|
||||
onClick={onOpenSession}
|
||||
title="GIS 편집 세션 보기"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-2 whitespace-nowrap">
|
||||
<Check className="h-4 w-4" />
|
||||
<span>편집 세션 {sessionChangeCount}</span>
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
<div className="flex w-[132px] shrink-0 items-center justify-end gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
color="primary"
|
||||
|
||||
@@ -1064,13 +1064,13 @@ export const useGisEdit = (treeData: any[]) => {
|
||||
const removeFocusedChange = useCallback(() => {
|
||||
const targetChangeId = focusedChangeId ?? pendingInteraction?.changeId ?? null;
|
||||
if (!targetChangeId) {
|
||||
setStatusMessage("??? ?? ??? ?? ?????.");
|
||||
setStatusMessage("취소할 편집 변경분을 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
const removedChange = changes.find((change) => change.changeId === targetChangeId) ?? null;
|
||||
if (!removedChange) {
|
||||
setStatusMessage("??? ?? ??? ?? ?????.");
|
||||
setStatusMessage("선택한 편집 변경분을 찾을 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1088,8 +1088,8 @@ export const useGisEdit = (treeData: any[]) => {
|
||||
latestSelectionRef.current = null;
|
||||
setStatusMessage(
|
||||
removedChange.attributeOnly
|
||||
? `${removedChange.layerName} ${removedChange.objectLabel} ???? ??? ??????.`
|
||||
: `${removedChange.layerName} ${removedChange.objectLabel} ??? ???? ??????.`,
|
||||
? `${removedChange.layerName} ${removedChange.objectLabel} 상세정보 변경을 취소했습니다.`
|
||||
: `${removedChange.layerName} ${removedChange.objectLabel} 편집 변경을 취소했습니다.`,
|
||||
);
|
||||
}, [changes, focusedChangeId, pendingInteraction]);
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ import useStore from "@/store/useStore";
|
||||
import { useUserStore } from "@/shared/lib/use-user-store";
|
||||
|
||||
import AgedPipeLayerSettingPanel from "./components/agedPipe/AgedPipeLayerSettingPanel";
|
||||
import GisEditSessionPanel from "./components/gisEdit/GisEditSessionPanel";
|
||||
import GisEditToolbar from "./components/gisEdit/GisEditToolbar";
|
||||
import GisEditPipeSessionPopup from "./components/gisEdit/GisEditPipeSessionPopup";
|
||||
import { useGisEdit } from "./components/gisEdit/useGisEdit";
|
||||
@@ -2598,6 +2599,7 @@ const Map = () => {
|
||||
const pipeAnalysisPopupWindowRef = useRef<Window | null>(null);
|
||||
const gisEditSessionPopupWindowRef = useRef<Window | null>(null);
|
||||
const gisEditSessionPopupCloseWatcherRef = useRef<number | null>(null);
|
||||
const [gisEditSessionView, setGisEditSessionView] = useState<"inline" | "popup">("inline");
|
||||
const [gisEditDetailChangeId, setGisEditDetailChangeId] = useState<string | null>(null);
|
||||
const gisEditDetailChangeRef = useRef<any>(null);
|
||||
const gisEditDetailFeatureDataRef = useRef<any>(null);
|
||||
@@ -2701,6 +2703,8 @@ const Map = () => {
|
||||
() => gisEdit.changes.filter(isVisibleGisEditSessionChange),
|
||||
[gisEdit.changes],
|
||||
);
|
||||
const shouldShowGisEditSession = gisEdit.isEditMode || gisEditVisibleSessionChanges.length > 0;
|
||||
const isGisEditSessionInlineVisible = shouldShowGisEditSession && gisEditSessionView === "inline";
|
||||
const gisEditSessionSnapshot = useMemo<GisEditSessionSnapshot>(() => ({
|
||||
isEditMode: gisEdit.isEditMode,
|
||||
selectedLayerName: gisEdit.selectedLayer?.layerName ?? "",
|
||||
@@ -2765,6 +2769,7 @@ const Map = () => {
|
||||
const popup = gisEditSessionPopupWindowRef.current;
|
||||
if (!popup || popup.closed) {
|
||||
gisEditSessionPopupWindowRef.current = null;
|
||||
setGisEditSessionView("inline");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2788,6 +2793,7 @@ const Map = () => {
|
||||
popup.close();
|
||||
}
|
||||
gisEditSessionPopupWindowRef.current = null;
|
||||
setGisEditSessionView("inline");
|
||||
}, []);
|
||||
|
||||
useEffect(() => () => {
|
||||
@@ -2838,6 +2844,17 @@ const Map = () => {
|
||||
}
|
||||
}, [gisEdit.changes]);
|
||||
|
||||
// 인라인 세션과 윈도우 팝업이 동일한 지도 focus/상세 열기 흐름을 공유한다.
|
||||
const handleFocusGisEditSessionChange = useCallback((changeId: string) => {
|
||||
if (!changeId) return;
|
||||
gisEdit.focusChange(changeId);
|
||||
focusGisEditChangeOnMap(changeId);
|
||||
setFeatureData(null);
|
||||
openGisEditPipeDetail(changeId);
|
||||
setIsOpen(true);
|
||||
setIsSearchModalOpen(false);
|
||||
}, [focusGisEditChangeOnMap, gisEdit, openGisEditPipeDetail, setIsSearchModalOpen]);
|
||||
|
||||
const syncWaterRiskPopup = useCallback(() => {
|
||||
const popup = waterRiskPopupWindowRef.current;
|
||||
if (!popup || popup.closed) {
|
||||
@@ -2961,18 +2978,19 @@ const Map = () => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const shouldKeepPopupOpen = gisEdit.isEditMode || gisEditVisibleSessionChanges.length > 0;
|
||||
if (shouldKeepPopupOpen) return;
|
||||
if (shouldShowGisEditSession) return;
|
||||
|
||||
const popup = gisEditSessionPopupWindowRef.current;
|
||||
if (!popup || popup.closed) {
|
||||
gisEditSessionPopupWindowRef.current = null;
|
||||
setGisEditSessionView("inline");
|
||||
return;
|
||||
}
|
||||
|
||||
popup.close();
|
||||
gisEditSessionPopupWindowRef.current = null;
|
||||
}, [gisEdit.isEditMode, gisEditVisibleSessionChanges.length]);
|
||||
setGisEditSessionView("inline");
|
||||
}, [shouldShowGisEditSession]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
@@ -3018,16 +3036,14 @@ const Map = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.GIS_EDIT_SESSION_SHOW_INLINE) {
|
||||
closeGisEditSessionPopup();
|
||||
return;
|
||||
}
|
||||
|
||||
if (data?.type === WINDOW_POPUP_MESSAGE_TYPE.GIS_EDIT_SESSION_FOCUS_CHANGE) {
|
||||
const changeId = String(data.payload?.changeId ?? "").trim();
|
||||
if (changeId) {
|
||||
gisEdit.focusChange(changeId);
|
||||
focusGisEditChangeOnMap(changeId);
|
||||
setFeatureData(null);
|
||||
openGisEditPipeDetail(changeId);
|
||||
setIsOpen(true);
|
||||
setIsSearchModalOpen(false);
|
||||
}
|
||||
handleFocusGisEditSessionChange(changeId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3050,7 +3066,7 @@ const Map = () => {
|
||||
return () => {
|
||||
window.removeEventListener("message", handleGisEditSessionPopupMessage);
|
||||
};
|
||||
}, [focusGisEditChangeOnMap, gisEdit, openGisEditPipeDetail, syncGisEditSessionPopup]);
|
||||
}, [closeGisEditSessionPopup, gisEdit, handleFocusGisEditSessionChange, syncGisEditSessionPopup]);
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
@@ -5441,6 +5457,7 @@ const Map = () => {
|
||||
gisEditSessionPopupCloseWatcherRef.current = null;
|
||||
}
|
||||
gisEditSessionPopupWindowRef.current = null;
|
||||
setGisEditSessionView("inline");
|
||||
}, 300);
|
||||
window.focus?.();
|
||||
return popup;
|
||||
@@ -5864,24 +5881,11 @@ const Map = () => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// GIS 편집은 map 화면의 로컬 편집 모드를 토글하면서 세션 상태는 별도 popup 창에 동기화한다.
|
||||
// GIS 편집 진입 시에는 화면 안 인라인 세션을 우선 표시하고, 윈도우 팝업은 사용자가 명시적으로 연다.
|
||||
const handleToggleGisEdit = useCallback(() => {
|
||||
if (!gisEdit.isEditMode) {
|
||||
const popup = openGisEditSessionPopup();
|
||||
if (!popup) {
|
||||
alert("브라우저 팝업이 차단되었습니다. 팝업 허용 후 다시 시도해주세요.");
|
||||
}
|
||||
} else if (!gisEditSessionPopupWindowRef.current || gisEditSessionPopupWindowRef.current.closed) {
|
||||
const popup = openGisEditSessionPopup();
|
||||
if (!popup) {
|
||||
alert("브라우저 팝업이 차단되었습니다. 팝업 허용 후 다시 시도해주세요.");
|
||||
}
|
||||
syncGisEditSessionPopup();
|
||||
return;
|
||||
}
|
||||
gisEdit.toggleEditMode();
|
||||
setIsOpen(false);
|
||||
}, [gisEdit, openGisEditSessionPopup, syncGisEditSessionPopup]);
|
||||
}, [gisEdit]);
|
||||
|
||||
const handleOpenGisEditSessionPopup = useCallback(() => {
|
||||
const popup = openGisEditSessionPopup();
|
||||
@@ -5889,6 +5893,7 @@ const Map = () => {
|
||||
alert("브라우저 팝업이 차단되었습니다. 팝업 허용 후 다시 시도해주세요.");
|
||||
return;
|
||||
}
|
||||
setGisEditSessionView("popup");
|
||||
syncGisEditSessionPopup();
|
||||
}, [openGisEditSessionPopup, syncGisEditSessionPopup]);
|
||||
|
||||
@@ -7292,6 +7297,23 @@ const Map = () => {
|
||||
isGisEditActive={gisEdit.isEditMode}
|
||||
isInfoSearchActive={isSearchModalOpen}
|
||||
/>
|
||||
{isGisEditSessionInlineVisible ? (
|
||||
<div
|
||||
data-testid="gis-edit-session-inline"
|
||||
className="absolute left-[258px] top-[16px] z-[61] w-[265px]"
|
||||
>
|
||||
<GisEditSessionPanel
|
||||
{...gisEditSessionSnapshot}
|
||||
className="max-h-[calc(50dvh-82px)]"
|
||||
variant="inline"
|
||||
onOpenPopup={handleOpenGisEditSessionPopup}
|
||||
onRemoveFocusedChange={gisEdit.removeFocusedChange}
|
||||
onRemoveLastChange={gisEdit.removeLastChange}
|
||||
onClearChanges={gisEdit.clearChanges}
|
||||
onFocusChange={handleFocusGisEditSessionChange}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<GisEditToolbar
|
||||
isEditMode={gisEdit.isEditMode}
|
||||
activeTool={gisEdit.activeTool}
|
||||
@@ -7299,10 +7321,8 @@ const Map = () => {
|
||||
canUseTools={gisEdit.canUseTools}
|
||||
canSave={gisEdit.canSave}
|
||||
isSaving={isGisEditSaving}
|
||||
sessionChangeCount={gisEditVisibleSessionChanges.length}
|
||||
statusMessage={gisEdit.statusMessage}
|
||||
allowedTools={gisEdit.selectedLayer?.allowedTools ?? []}
|
||||
onOpenSession={handleOpenGisEditSessionPopup}
|
||||
onClose={handleCloseGisEdit}
|
||||
onToggleSnap={gisEdit.toggleSnapEnabled}
|
||||
onSelectTool={handleSelectGisEditTool}
|
||||
|
||||
@@ -185,3 +185,50 @@
|
||||
- `007-qa-SFR-012-003-하수관로편집-실제지도조작검증계획.md`
|
||||
- `009-qa-SFR-012-003-하수관로편집-MOVE실드래그검증계획.md`
|
||||
- `011-qa-SFR-012-003-하수관로편집-VERTEX_EDIT실조작검증계획.md`
|
||||
|
||||
## 8. 2026-07-15 편집 세션 인라인 전환 검증 계획
|
||||
|
||||
1. 정적 구조
|
||||
- GIS 편집 진입 시 팝업 자동 호출이 제거되었는지 확인한다.
|
||||
- 인라인 세션이 시설물 관리 오른쪽, 검색바와 같은 상단 기준으로 배치되는지 확인한다.
|
||||
- 편집 도구바가 `top: 84px`로 이동했는지 확인한다.
|
||||
2. 세션 크기와 스크롤
|
||||
- 변경분 0건에서 패널이 빈 상태 내용 높이만 차지하는지 확인한다.
|
||||
- 변경분 증가 시 패널이 최대 높이까지 늘어나는지 확인한다.
|
||||
- 최대 높이 이후 변경 목록에 세로 스크롤이 생기고 시설물 접기 토글을 가리지 않는지 확인한다.
|
||||
3. 팝업 호환
|
||||
- 인라인 `팝업` 버튼으로만 기존 팝업이 열리는지 확인한다.
|
||||
- 팝업 정의의 `460 x 640` 크기와 기존 위치/메시지 계약이 유지되는지 확인한다.
|
||||
4. 회귀
|
||||
- 인라인/팝업에서 변경분 선택, 취소, 되돌리기, 초기화가 동일 편집 상태에 반영되는지 확인한다.
|
||||
- 타입 검사와 `git diff --check`를 수행하고 선행 오류와 신규 오류를 구분한다.
|
||||
|
||||
## 9. 2026-07-15 사용자 화면 피드백 2차 검증 계획
|
||||
|
||||
1. 검색바 비가림
|
||||
- 인라인 세션 표시 전후 검색바의 시도·시군구·시설물·조회 컨트롤이 모두 노출되는지 확인한다.
|
||||
- 팝업 뷰 전환 시 검색바가 원래 중앙 위치로 돌아오는지 확인한다.
|
||||
2. 도구바 종속 배치
|
||||
- GIS 편집 도구바가 인라인 세션 카드 바로 아래에서 같은 왼쪽 기준으로 시작하는지 확인한다.
|
||||
- 세션 변경분 증가 시 도구바가 카드 아래로 내려가고 카드 목록이 최대 높이부터 스크롤되는지 확인한다.
|
||||
3. 인라인/팝업 상호 배타 전환
|
||||
- 인라인 `팝업` 클릭 직후 화면 인라인 세션이 사라지는지 확인한다.
|
||||
- 팝업의 `화면에서 보기` 클릭 시 팝업이 닫히고 인라인 세션이 같은 변경 상태로 복원되는지 확인한다.
|
||||
- 팝업 창의 닫기 버튼을 직접 눌러도 300ms 이내 인라인 세션이 복원되는지 확인한다.
|
||||
4. 회귀
|
||||
- 취소·뒤로가기·초기화·변경분 포커스가 전환 전후 동일 상태를 사용하는지 확인한다.
|
||||
- 다른 `Gis` 사용 화면에서 검색바 기본 중앙 배치가 유지되는지 확인한다.
|
||||
|
||||
## 10. 2026-07-15 표시 영역 기준 최종 검증 계획
|
||||
|
||||
1. 검색바 고정
|
||||
- 편집 모드 진입, 변경분 추가, 팝업 전환 전후 검색바 좌표가 바뀌지 않는지 확인한다.
|
||||
2. 상단 축약 세션
|
||||
- 변경분 0건에서 편집 세션이 검색바와 유사한 높이로 보이는지 확인한다.
|
||||
- 첫 변경분부터 작업 버튼과 목록이 나타나며 아래 방향으로 커지는지 확인한다.
|
||||
- 최대 높이 이후 목록에만 세로 스크롤이 생기는지 확인한다.
|
||||
3. 하단 도구바
|
||||
- GIS 편집 도구바가 지도 하단 중앙 표시 영역에 고정되는지 확인한다.
|
||||
- 세션 확장과 팝업 전환에도 도구바 좌표가 유지되는지 확인한다.
|
||||
4. 팝업 왕복
|
||||
- 팝업 열기 시 인라인 숨김, `화면에서 보기`와 직접 닫기 시 인라인 복원을 재확인한다.
|
||||
|
||||
@@ -645,4 +645,104 @@
|
||||
- 남은 수동 검증
|
||||
- 신규 관로 A를 추가한 직후 신규 관로 B를 추가하거나 이동/꼭지점편집할 때 A preview에 실제로 스냅되는지 확인이 필요하다.
|
||||
- `취소` 버튼이 현재 선택 change만 제거하고, `뒤로가기`는 가장 최근 change를 제거하는지 popup과 지도 focus 기준으로 확인이 필요하다.
|
||||
- `취소`로 현재 상세 패널 대상 change를 제거했을 때 우측 패널이 자연스럽게 닫히는지 확인이 필요하다.
|
||||
- `취소`로 현재 상세 패널 대상 change를 제거했을 때 우측 패널이 자연스럽게 닫히는지 확인이 필요하다.
|
||||
|
||||
### 2.20 2026-07-15 편집 세션 인라인 전환 검증 결과
|
||||
|
||||
- 통과
|
||||
- `git diff --check`: 통과
|
||||
- 레이아웃/팝업 계약 정적 검사: 통과
|
||||
- 인라인 위치 `left-[278px] top-4`, 최대 높이 `max-h-[calc(50dvh-82px)]` 확인
|
||||
- 도구바 위치 `top-[84px]`, 최대 너비 `760px` 확인
|
||||
- 변경 목록 `overflow-y-auto` 확인
|
||||
- 기존 팝업 정의 `width: 460`, `height: 640` 유지 확인
|
||||
- 변경 파일 기준 TypeScript 신규 오류는 확인되지 않았다.
|
||||
- 전체 TypeScript 검사
|
||||
- 명령: `node apps/sn/node_modules/typescript/bin/tsc -p apps/sn/tsconfig.json --noEmit --pretty false --ignoreDeprecations 5.0`
|
||||
- 결과: 실패. 이번 변경과 무관한 기존 선행 오류 9건(`components/common/index.ts`, `floodHistoryTypes.ts`, `map/page.tsx:4666`, html route, 공통 chart implicit any)이 남아 있다.
|
||||
- 브라우저 확인
|
||||
- 개발 서버는 기동됐으나 `/map` 접근이 `/auth/login`으로 리다이렉트되어 로그인 정보 없이 실제 지도 조작 검증은 수행하지 않았다.
|
||||
- 인증 우회나 임의 계정 사용은 하지 않았다.
|
||||
- 후속 수동 검증
|
||||
- 로그인 세션에서 GIS 편집 진입 시 새 창이 자동 생성되지 않고 인라인 세션이 표시되는지 확인한다.
|
||||
- 실제 변경분을 여러 건 추가해 패널 성장과 목록 스크롤, 시설물 접기 토글 비가림을 확인한다.
|
||||
- `팝업` 버튼으로 기존 크기/위치의 팝업이 열리고 인라인과 상태가 동기화되는지 확인한다.
|
||||
|
||||
### 2.21 2026-07-15 사용자 화면 피드백 2차 반영 결과
|
||||
|
||||
- 정적 검증 통과
|
||||
- 인라인 표시 조건과 팝업 표시 조건이 `gisEditSessionView`로 상호 배타 처리되는 것을 확인했다.
|
||||
- 검색바 이동 클래스 `ml-[clamp(160px,16vw,220px)]`와 공통 `Gis.searchBarClassName` 기본값을 확인했다.
|
||||
- embedded 도구바가 인라인 세션 다음 형제로 렌더링되는 것을 확인했다.
|
||||
- 팝업 `화면에서 보기` 버튼, `GIS_EDIT_SESSION_SHOW_INLINE` 송수신, 팝업 직접 닫기 시 인라인 복원 처리를 확인했다.
|
||||
- 기존 팝업 정의 `width: 460`, `height: 640` 유지 및 `git diff --check` 통과.
|
||||
- TypeScript
|
||||
- 전체 검사 결과는 기존 선행 오류 9건으로 실패했으며 이번 2차 변경 파일의 신규 오류는 출력되지 않았다.
|
||||
- 기존 오류 위치 중 `map/page.tsx` 행 번호만 코드 추가로 `4677`로 이동했다.
|
||||
- 자동 브라우저 제한
|
||||
- 로그인된 지도 탭이 없어 실제 화면 조작 검증은 수행하지 못했다.
|
||||
- 사용자 제공 화면으로 배치 결함을 확인했고, 9절의 검색바 비가림·도구바 종속 배치·양방향 전환은 로그인 환경에서 후속 확인이 필요하다.
|
||||
|
||||
### 2.22 2026-07-15 표시 영역 기준 최종 보정 결과
|
||||
|
||||
- 정적 검증 통과
|
||||
- 검색바 이동용 prop과 클래스가 제거되고 공통 `Gis.js` diff가 없는 것을 확인했다.
|
||||
- 인라인 세션 위치 `left-[258px] top-4`, 너비 `360px`를 확인했다.
|
||||
- 변경분 0건 축약 조건과 작업 버튼/빈 목록 숨김 처리를 확인했다.
|
||||
- 도구바 위치 `bottom-12 left-1/2`, 최대 너비 `960px`를 확인했다.
|
||||
- 팝업 상호 전환 계약과 기존 `460 x 640` 크기는 유지된다.
|
||||
- `git diff --check` 통과.
|
||||
- TypeScript
|
||||
- 전체 검사는 기존 선행 오류 9건으로 실패했으며 이번 최종 위치 보정의 신규 오류는 출력되지 않았다.
|
||||
- 수동 확인 대기
|
||||
- 로그인된 지도 화면에서 파란 표시 영역과 실제 좌표가 일치하는지 확인이 필요하다.
|
||||
|
||||
### 2.23 2026-07-15 인라인 편집 세션 너비 보정 결과
|
||||
|
||||
- 사용자 화면으로 `360px` 세션의 검색바 돌출을 확인했다.
|
||||
- 인라인 세션 계약을 `left-[258px] top-4 w-[220px]`로 변경했다.
|
||||
- 검색바 이동 코드가 없고 하단 도구바 `bottom-12`가 유지되는 것을 정적으로 확인했다.
|
||||
- `git diff --check` 통과. 로그인 화면에서 검색바 비가림 해소 최종 확인이 필요하다.
|
||||
|
||||
### 2.24 2026-07-15 인라인 세션 260px 보정 결과
|
||||
|
||||
- 인라인 세션 계약을 `left-[258px] top-4 w-[260px]`로 조정했다.
|
||||
- 검색바 이동 코드가 없고 하단 도구바 위치가 유지되는 것을 확인했다.
|
||||
- `git diff --check` 통과.
|
||||
|
||||
### 2.25 2026-07-15 축약 세션 높이·너비 조정 결과
|
||||
|
||||
- 인라인 세션 위치/크기 계약 `left-[258px] top-4 w-[265px]`를 확인했다.
|
||||
- 변경분 0건 축약 조건에만 `h-[58px]`가 적용되는 것을 확인했다.
|
||||
- 하단 도구바와 검색바 위치가 변경되지 않았고 `git diff --check`가 통과했다.
|
||||
|
||||
### 2.26 2026-07-15 편집 세션 상단 정렬 보정 결과
|
||||
|
||||
- 인라인 세션 위치 계약 `left-[258px] top-[26px] w-[265px]`를 확인했다.
|
||||
- 축약 높이 `58px`와 하단 도구바 위치가 유지되는 것을 확인했다.
|
||||
- `git diff --check` 통과.
|
||||
|
||||
### 2.27 2026-07-15 변경 카드 표시 보정 결과
|
||||
|
||||
- 제목과 선택 배지에 한 줄 표시 계약이 적용된 것을 확인했다.
|
||||
- 선택 카드에서 정보저장 배지가 동시에 표시되지 않는 것을 확인했다.
|
||||
- 추가·이동·꼭지점편집·삭제·상세정보수정별 축약 안내 문구를 확인했다.
|
||||
- `git diff --check` 통과.
|
||||
- 전체 TypeScript 검사는 기존 선행 오류 9건만 출력됐고 이번 변경 파일의 신규 오류는 없었다.
|
||||
|
||||
### 2.28 2026-07-15 한 줄 안내 문구 보정 결과
|
||||
|
||||
- 다섯 편집 유형의 안내가 다음 행동을 설명하는 짧은 문구로 변경된 것을 확인했다.
|
||||
- 카드 하단 `truncate text-[11px]` 계약과 제목/선택 배지 한 줄 표시가 유지된다.
|
||||
- `git diff --check` 통과.
|
||||
|
||||
### 2.29 2026-07-15 사용자 수동 검증 완료
|
||||
|
||||
- 사용자가 로그인된 실제 지도 화면에서 이번 유지보수 범위의 수동 검증 완료를 확인했다.
|
||||
- 확인 범위
|
||||
- 검색바 위치 유지 및 인라인 편집 세션 비가림 해소
|
||||
- 축약 세션 위치·높이·너비와 변경분 증가 시 확장/스크롤
|
||||
- 하단 중앙 GIS 편집 도구바 배치
|
||||
- 인라인·윈도우 팝업 상호 전환
|
||||
- 변경 카드 제목/선택 표시 한 줄 노출 및 안내 문구 가독성
|
||||
- 결론: SFR-012-003 프론트 유지보수 수동 검증 완료.
|
||||
|
||||
@@ -250,3 +250,43 @@
|
||||
- MOVE on/off 기능 테스트 중 기존 관로 상세 입력정보 조회 실패가 `Error: ERROR` 콘솔 오류로 노출되는 문제를 확인했다.
|
||||
- `GisEditPipeSessionPopup`은 선택적 입력정보 조회 실패를 편집 세션 중단/콘솔 오류로 처리하지 않고, 기존 WFS/세션 draft 값을 유지하도록 보강한다.
|
||||
- 백엔드 `PplService`는 MS 보조 상세속성/관리기관명 조회 실패를 전체 API 500으로 전파하지 않고 fallback하도록 보강한다.
|
||||
|
||||
## 11. 2026-07-15 편집 세션 배치 유지보수
|
||||
|
||||
- 작업 모드: `maintenance`
|
||||
- 범위: 프론트엔드 `sn` 지도 화면
|
||||
- 구현 범위
|
||||
- GIS 편집 진입 시 편집 세션을 시설물 관리 옆 인라인 패널로 표시
|
||||
- 초기 패널은 내용 높이로 표시하고 변경분 증가에 따라 확장
|
||||
- 시설물 접기 토글 전 최대 높이 제한 및 변경 목록 세로 스크롤
|
||||
- 하수관로 편집 도구바를 검색/세션 영역 아래로 이동
|
||||
- 인라인 패널의 명시적 `팝업` 버튼으로 기존 윈도우 팝업 재사용
|
||||
- 제외 범위
|
||||
- 편집 저장 API, 편집 도구 로직, 백엔드 및 DB 계약 변경 없음
|
||||
- 완료 기준
|
||||
- 편집 모드 진입만으로 새 창이 자동 생성되지 않는다.
|
||||
- 인라인 세션과 기존 팝업의 취소/되돌리기/초기화/포커스 동작이 같은 상태를 사용한다.
|
||||
- 변경 목록이 최대 높이를 넘으면 패널 전체가 아니라 목록 영역에 세로 스크롤이 생성된다.
|
||||
|
||||
## 12. 2026-07-15 사용자 화면 피드백 2차 유지보수
|
||||
|
||||
- 11절의 `top: 84px` 중앙 도구바 배치는 사용자 확인 결과를 반영해 폐기한다.
|
||||
- 수정 완료 기준
|
||||
- 인라인 세션 표시 중 검색바의 모든 검색 조건이 가려지지 않는다.
|
||||
- GIS 편집 도구바는 인라인 세션 바로 아래에 표시되고 세션 높이 증가를 따라 내려간다.
|
||||
- 팝업을 열면 인라인 세션은 숨는다.
|
||||
- 팝업의 `화면에서 보기` 또는 팝업 닫기로 인라인 세션이 복원된다.
|
||||
- 팝업과 인라인은 동시에 보이지 않으며 편집 변경 상태는 유지된다.
|
||||
- 공통 영향
|
||||
- `FE_BC_ROOT/ui/map/Gis.js`에 선택적 검색바 래퍼 클래스 전달 기능을 추가하되 기본 화면 동작은 유지한다.
|
||||
|
||||
## 13. 2026-07-15 표시 영역 기준 최종 배치
|
||||
|
||||
- 12절의 검색바 이동과 세션 종속 도구바 배치는 사용자 표시 영역 기준으로 대체한다.
|
||||
- 완료 기준
|
||||
- 검색바는 편집 모드 전후 같은 중앙 위치를 유지한다.
|
||||
- 변경분 0건의 편집 세션은 검색바와 유사한 축약 높이로 상단 표시 영역에 배치된다.
|
||||
- 변경분이 추가되면 편집 세션만 아래로 확장되고 최대 높이 이후 목록 스크롤이 생긴다.
|
||||
- GIS 편집 도구바는 하단 표시 영역 중앙에 고정된다.
|
||||
- 팝업 전환 시 인라인 숨김과 `화면에서 보기` 복귀는 유지된다.
|
||||
- 공통 `Gis.js`는 수정하지 않는다.
|
||||
|
||||
@@ -378,4 +378,105 @@
|
||||
- 현재 상세 패널이 열려 있던 change가 세션에서 제거되면 우측 상세 패널도 함께 닫히도록 `page.tsx`의 detail effect를 보강했다.
|
||||
- 남긴 판단
|
||||
- 이번 수정으로 임시 preview 관로가 snap 대상에서 빠지는 구조적 누락은 해소했지만, 실제 QGIS 체감과 지도 시각 피드백은 브라우저 수동 검증이 아직 필요하다.
|
||||
- 세션 `취소`는 현재 focus된 change 기준이므로, 사용자가 어떤 change를 지우는지 목록 highlight와 지도 focus를 함께 보는 UX를 유지한다.
|
||||
- 세션 `취소`는 현재 focus된 change 기준이므로, 사용자가 어떤 change를 지우는지 목록 highlight와 지도 focus를 함께 보는 UX를 유지한다.
|
||||
|
||||
### 4.22 2026-07-15 편집 세션 인라인 전환 및 도구바 재배치
|
||||
|
||||
- `map/page.tsx`
|
||||
- GIS 편집 버튼에서 기존 세션 팝업 자동 열기를 제거하고 편집 모드만 토글하도록 변경했다.
|
||||
- 편집 모드 또는 잔여 변경분이 있을 때 시설물 관리 오른쪽에 `GisEditSessionPanel`을 인라인으로 렌더링한다.
|
||||
- 인라인 패널의 최대 높이를 `calc(50dvh - 82px)`로 제한해 시설물 접기 토글 영역을 피하고, 팝업 버튼은 기존 `handleOpenGisEditSessionPopup()`을 호출한다.
|
||||
- 인라인/팝업의 변경분 선택은 `handleFocusGisEditSessionChange()`로 통합해 지도 포커스와 상세 패널 열기 흐름을 공유한다.
|
||||
- `GisEditSessionPanel.tsx`
|
||||
- `inline`/`popup` 변형과 선택적 `onOpenPopup`을 추가했다.
|
||||
- 인라인 변형에 제목, 현재 레이어/도구, 명시적 `팝업` 버튼을 제공한다.
|
||||
- 변경 목록 영역을 `flex-1` + `overflow-y-auto`로 구성해 항목 증가 시 패널이 최대 높이까지 늘고 이후 목록만 스크롤한다.
|
||||
- `GisEditToolbar.tsx`
|
||||
- 상단 위치를 `16px`에서 `84px`로 내려 검색바/세션과 겹치지 않도록 했다.
|
||||
- 최대 너비를 `860px`에서 `760px`로 줄이고 중복 세션 버튼을 제거했다.
|
||||
- `GisEditSessionPopupContent.tsx`
|
||||
- 공용 세션 패널에 `variant="popup"`을 전달해 기존 팝업 제목/레이아웃을 유지한다.
|
||||
- `useGisEdit.ts`
|
||||
- 변경분 취소 과정에 남아 있던 깨진 한글 상태 메시지를 정상 문구로 복원했다.
|
||||
- 호환성
|
||||
- `gisEditSessionPopup` 정의는 수정하지 않아 기존 `460 x 640` 크기와 위치, opener 메시지 계약을 유지한다.
|
||||
- API, 저장 payload, 백엔드 코드는 변경하지 않았다.
|
||||
|
||||
### 4.23 2026-07-15 사용자 화면 피드백에 따른 배치 및 양방향 전환 보정
|
||||
|
||||
- 피드백
|
||||
- 4.22 구현 화면에서 인라인 세션이 검색바 일부를 가리고, 도구바가 세션 아래가 아닌 중앙 검색바 아래에 표시됐다.
|
||||
- 팝업을 열어도 인라인이 남았으며 팝업에서 화면 세션으로 돌아오는 기능이 필요했다.
|
||||
- `map/page.tsx`
|
||||
- `gisEditSessionView`를 `inline | popup`으로 관리해 두 뷰를 상호 배타적으로 렌더링한다.
|
||||
- 인라인 세션과 `GisEditToolbar`를 `left: 278px`, `top: 16px`의 동일 플로팅 열에 넣고 도구바를 세션 바로 아래에 렌더링한다.
|
||||
- 팝업 뷰에서는 인라인 카드 대신 초기 카드 높이만큼 자리 표시자를 유지해 도구바 위치가 갑자기 위로 이동하지 않게 했다.
|
||||
- 인라인 표시 중 `searchBarClassName`으로 검색바를 `clamp(160px, 16vw, 220px)`만큼 오른쪽 이동한다.
|
||||
- 팝업 열기 성공 시 `popup` 뷰로 전환하고, 팝업 복귀 메시지·직접 닫기 감시·세션 종료 시 `inline`으로 복원한다.
|
||||
- `GisEditToolbar.tsx`
|
||||
- `embedded` 변형을 추가해 절대 중앙 배치 대신 부모 플로팅 열 안에서 렌더링할 수 있게 했다.
|
||||
- embedded 너비는 최대 `650px`로 제한했다.
|
||||
- `Gis.js`
|
||||
- 선택적 `searchBarClassName`을 추가해 `sn` 지도에서만 편집 세션 표시 중 검색바 위치를 보정한다. 기본값은 빈 문자열이다.
|
||||
- 팝업
|
||||
- `GIS_EDIT_SESSION_SHOW_INLINE` 메시지를 추가했다.
|
||||
- 팝업 헤더에 `화면에서 보기` 버튼을 추가해 opener에 복귀 메시지를 보낸다.
|
||||
- 기존 팝업 크기와 위치, 세션 동기화/편집 명령 메시지는 유지한다.
|
||||
|
||||
### 4.24 2026-07-15 파란 표시 영역 기준 최종 위치 보정
|
||||
|
||||
- 사용자 표시 해석
|
||||
- 상단 표시 영역은 축약형 인라인 편집 세션, 하단 표시 영역은 GIS 편집 도구바의 목표 위치다.
|
||||
- 검색바는 이동하지 않는다.
|
||||
- `GisEditSessionPanel.tsx`
|
||||
- `variant="inline"`이고 변경분이 0건이면 `isCompactInline`을 적용한다.
|
||||
- 축약 상태에서는 패딩을 줄이고 취소·뒤로가기·초기화 버튼과 빈 목록 안내를 숨긴다.
|
||||
- 첫 변경분이 생기면 기존 작업 버튼과 변경 목록을 표시해 항목 수에 따라 확장한다.
|
||||
- `map/page.tsx`
|
||||
- 인라인 세션을 `left-[258px] top-4`, 너비 `360px`에 배치했다.
|
||||
- 검색바 이동용 `searchBarClassName` 전달을 제거했다.
|
||||
- 도구바를 세션 컨테이너 밖의 독립 오버레이로 복원했다.
|
||||
- `GisEditToolbar.tsx`
|
||||
- embedded 변형을 제거했다.
|
||||
- 위치를 `bottom-12 left-1/2`, 최대 너비 `960px`로 변경해 하단 표시 영역에 고정했다.
|
||||
- `Gis.js`
|
||||
- 검색바 이동을 위해 추가했던 선택적 prop 변경을 모두 철회해 원본 상태로 복원했다.
|
||||
- 팝업
|
||||
- 인라인 숨김, `화면에서 보기`, 직접 닫기 복원 동작은 유지한다.
|
||||
|
||||
### 4.25 2026-07-15 인라인 편집 세션 너비 보정
|
||||
|
||||
- 사용자 실제 화면에서 `w-[360px]` 인라인 세션이 검색바 첫 선택 조건을 가리는 것을 확인했다.
|
||||
- `map/page.tsx`의 인라인 세션 너비를 `w-[220px]`로 축소하고 불필요한 최대 너비 계산을 제거했다.
|
||||
- 세션 위치·축약/확장·팝업 전환과 하단 GIS 편집 바는 변경하지 않았다.
|
||||
|
||||
### 4.26 2026-07-15 인라인 세션 너비 여백 조정
|
||||
|
||||
- 사용자 화면 피드백에 따라 인라인 세션 너비를 `220px`에서 `260px`로 확대했다.
|
||||
- 검색바 위치, 세션 좌표, 하단 도구바와 팝업 기능은 변경하지 않았다.
|
||||
|
||||
### 4.27 2026-07-15 축약 세션 높이 통일 및 5px 확대
|
||||
|
||||
- `map/page.tsx` 인라인 세션 너비를 `260px`에서 `265px`로 변경했다.
|
||||
- `GisEditSessionPanel.tsx`에서 변경분 0건인 inline 변형에 `h-[58px] p-2`를 적용했다.
|
||||
- 변경분이 생긴 뒤에는 높이 고정을 적용하지 않는다. 검색바, 하단 도구바, 팝업 기능은 유지한다.
|
||||
|
||||
### 4.28 2026-07-15 편집 세션 상단 정렬 10px 보정
|
||||
|
||||
- 사용자 화면에서 편집 세션이 검색바보다 약 10px 위에 표시되는 것을 확인했다.
|
||||
- `map/page.tsx`의 세션 위치를 `top-4`에서 `top-[26px]`로 변경했다.
|
||||
- 크기와 나머지 화면 동작은 변경하지 않았다.
|
||||
|
||||
### 4.29 2026-07-15 변경 카드 한 줄 제목과 안내 요약
|
||||
|
||||
- `GisEditSessionPanel.tsx`의 카드 패딩을 `px-2 py-2`로 줄였다.
|
||||
- 제목에 `whitespace-nowrap`, `text-[11px]`를 적용해 `편집유형 / 객체번호`를 한 줄로 표시한다.
|
||||
- `지도 미리보기 선택` 배지는 `text-[9px]`, 축소 패딩, `whitespace-nowrap`으로 전체 문구를 유지한다.
|
||||
- 선택 카드에서는 `정보저장` 배지를 숨겨 두 배지 동시 표시로 인한 가로 넘침을 방지한다.
|
||||
- `getChangeSummary()`를 추가해 카드 하단 안내만 편집 유형별 짧은 문구로 표시했다. 내부 `change.summary`와 상태 메시지는 변경하지 않았다.
|
||||
|
||||
### 4.30 2026-07-15 한 줄 안내 문구 친절도 보정
|
||||
|
||||
- `getChangeSummary()`의 완료형 문구를 짧은 행동 안내형으로 변경했다.
|
||||
- 추가 위치 확인, 이동 위치 조정, 점 이동/선분 추가, 삭제 대상 확인, 상세정보 확인을 한 줄 길이로 제공한다.
|
||||
- 카드 레이아웃과 원본 `change.summary` 데이터는 변경하지 않았다.
|
||||
|
||||
@@ -37,6 +37,7 @@ export const WINDOW_POPUP_MESSAGE_TYPE = {
|
||||
MAP_SEARCH_SHOW_MULTIPLE: "sn:popup:mapSearchShowMultiple",
|
||||
GIS_EDIT_SESSION_READY: "sn:popup:gisEditSessionReady",
|
||||
GIS_EDIT_SESSION_SYNC: "sn:popup:gisEditSessionSync",
|
||||
GIS_EDIT_SESSION_SHOW_INLINE: "sn:popup:gisEditSessionShowInline",
|
||||
GIS_EDIT_SESSION_FOCUS_CHANGE: "sn:popup:gisEditSessionFocusChange",
|
||||
GIS_EDIT_SESSION_REMOVE_FOCUSED_CHANGE: "sn:popup:gisEditSessionRemoveFocusedChange",
|
||||
GIS_EDIT_SESSION_REMOVE_LAST_CHANGE: "sn:popup:gisEditSessionRemoveLastChange",
|
||||
|
||||
@@ -47,16 +47,26 @@ export default function GisEditSessionPopupContent(_props: WindowPopupContentPro
|
||||
|
||||
return (
|
||||
<main className="flex h-screen flex-col overflow-hidden bg-[#f6f8fb]">
|
||||
<header className="flex min-h-[48px] items-center border-b border-[#dbe2e6] bg-primary px-5 py-3">
|
||||
<header className="flex min-h-[48px] items-center justify-between gap-3 border-b border-[#dbe2e6] bg-primary px-5 py-3">
|
||||
<h1 className="text-[1.2rem] font-semibold text-white">
|
||||
{windowPopupDefinitions.gisEditSessionPopup.title}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded border border-white/70 bg-white/10 px-3 py-1.5 text-[12px] font-semibold text-white transition hover:bg-white/20"
|
||||
onClick={() => {
|
||||
postMessageToOpener(WINDOW_POPUP_MESSAGE_TYPE.GIS_EDIT_SESSION_SHOW_INLINE);
|
||||
}}
|
||||
>
|
||||
화면에서 보기
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<section className="flex-1 overflow-hidden p-3">
|
||||
<GisEditSessionPanel
|
||||
{...snapshot}
|
||||
className="h-full shadow-none"
|
||||
variant="popup"
|
||||
onRemoveFocusedChange={() => {
|
||||
postMessageToOpener(WINDOW_POPUP_MESSAGE_TYPE.GIS_EDIT_SESSION_REMOVE_FOCUSED_CHANGE);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user