feat(copy): 복사 항목 기본 체크를 기준 교각에서 바뀐 항목으로 설정
- 기준 교각의 되돌리기가 보이는 값에 해당하는 복사 항목을 자동으로 체크 - 기준 교각이나 부재가 바뀔 때만 다시 계산, 그 사이 사용자의 체크는 유지 - "변경 항목으로 선택" 버튼으로 언제든 같은 상태로 되돌림 - 바뀐 값이 없으면 아무 항목도 체크하지 않음 (적용 버튼 비활성) - copyItemsWithOverrides 추가, 테스트 4건 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
70fa0be86f
commit
7314da639b
4 files changed
+54
-6
No files matched your search
@@ -168,6 +168,9 @@
|
|||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h3>2 · 복사할 항목</h3>
|
<h3>2 · 복사할 항목</h3>
|
||||||
|
<div class="cp-tools">
|
||||||
|
<button id="cp-items-reset" class="btn-o small" type="button">변경 항목으로 선택</button>
|
||||||
|
</div>
|
||||||
<div id="cp-items" class="cp-chips"></div>
|
<div id="cp-items" class="cp-chips"></div>
|
||||||
<p id="cp-none" class="muted small" hidden>이 부재는 복사 항목이 없습니다. 기둥·받침은 예정입니다.</p>
|
<p id="cp-none" class="muted small" hidden>이 부재는 복사 항목이 없습니다. 기둥·받침은 예정입니다.</p>
|
||||||
<p class="muted small">복사하지 않는 값: 좌표 · IP · 받침 EL · 코핑 상면 EL · 기초 하단 EL · 지반고 · 기둥 높이 · 말뚝 선단 EL · 계단 구간</p>
|
<p class="muted small">복사하지 않는 값: 좌표 · IP · 받침 EL · 코핑 상면 EL · 기초 하단 EL · 지반고 · 기둥 높이 · 말뚝 선단 EL · 계단 구간</p>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { CopyItem } from './copy';
|
import { COPY_ITEMS, type CopyItem } from './copy';
|
||||||
|
import { overrideKeys, type PierValues } from './changes';
|
||||||
import type { MemberId } from './shape-options';
|
import type { MemberId } from './shape-options';
|
||||||
|
|
||||||
/** One pier as a target of 속성 복사. */
|
/** One pier as a target of 속성 복사. */
|
||||||
@@ -43,3 +44,12 @@ export const MEMBER_COPY_ITEMS: Record<MemberId, CopyItem[]> = {
|
|||||||
export function copyItemsFor(member: MemberId): CopyItem[] {
|
export function copyItemsFor(member: MemberId): CopyItem[] {
|
||||||
return MEMBER_COPY_ITEMS[member];
|
return MEMBER_COPY_ITEMS[member];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The copy items whose values the 기준 pier has changed from the imported default (되돌리기가 보이는 항목).
|
||||||
|
* They are ticked by default; the user can change the ticks afterwards.
|
||||||
|
*/
|
||||||
|
export function copyItemsWithOverrides(source: PierValues): CopyItem[] {
|
||||||
|
const changed = new Set<string>(overrideKeys(source));
|
||||||
|
return (Object.keys(COPY_ITEMS) as CopyItem[]).filter((item) => COPY_ITEMS[item].keys.some((k) => changed.has(k)));
|
||||||
|
}
|
||||||
+17
-4
@@ -8,8 +8,8 @@ import { NOT_IMPLEMENTED_RULES, validateInput, validatePier } from './core/valid
|
|||||||
import { buildTemplateWorkbook } from './core/template';
|
import { buildTemplateWorkbook } from './core/template';
|
||||||
import { EDITABLE_FIELDS, FIELD_LABELS, overrideKeys, pendingKeys, revertDraft, type EditableKey, type PierValues } from './core/changes';
|
import { EDITABLE_FIELDS, FIELD_LABELS, overrideKeys, pendingKeys, revertDraft, type EditableKey, type PierValues } from './core/changes';
|
||||||
import { adjustRow, layoutText, resolveRowCounts, rowLayout, totalPiles } from './core/piles';
|
import { adjustRow, layoutText, resolveRowCounts, rowLayout, totalPiles } from './core/piles';
|
||||||
import { applyCopy, COPY_ITEMS, DEFAULT_COPY_ITEMS, planCopy, type CopyItem } from './core/copy';
|
import { applyCopy, COPY_ITEMS, planCopy, type CopyItem } from './core/copy';
|
||||||
import { copyCandidates, copyItemsFor, selectedTargets, type CopyCandidate } from './core/copy-targets';
|
import { copyCandidates, copyItemsFor, copyItemsWithOverrides, selectedTargets, type CopyCandidate } from './core/copy-targets';
|
||||||
import { pileGeometry } from './core/geometry';
|
import { pileGeometry } from './core/geometry';
|
||||||
import { rebarSummary, type RebarRow } from './core/rebar/summary';
|
import { rebarSummary, type RebarRow } from './core/rebar/summary';
|
||||||
import { shearSegments } from './core/rebar/coping';
|
import { shearSegments } from './core/rebar/coping';
|
||||||
@@ -649,11 +649,18 @@ function chosenCopyItems(): CopyItem[] {
|
|||||||
return copyItemsFor(state.member).filter((item) => copyItemChoice.has(item));
|
return copyItemsFor(state.member).filter((item) => copyItemChoice.has(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The items ticked by the user; kept across 부재 changes. */
|
/** The items ticked by the user. Reset to the 기준 pier's changed items when the 기준 pier or 부재 changes. */
|
||||||
let copyItemChoice = new Set<CopyItem>(DEFAULT_COPY_ITEMS);
|
let copyItemChoice = new Set<CopyItem>();
|
||||||
|
let copyItemKey = '';
|
||||||
|
|
||||||
/** Shows the copy items of the selected 부재 only. A 부재 without items shows a note instead. */
|
/** Shows the copy items of the selected 부재 only. A 부재 without items shows a note instead. */
|
||||||
function renderCopyItems(): void {
|
function renderCopyItems(): void {
|
||||||
|
const src = activePier();
|
||||||
|
const key = `${src?.input.name ?? ''}|${state.member}`;
|
||||||
|
if (key !== copyItemKey) {
|
||||||
|
copyItemKey = key;
|
||||||
|
copyItemChoice = new Set(src ? copyItemsWithOverrides(src) : []);
|
||||||
|
}
|
||||||
const box = $('cp-items');
|
const box = $('cp-items');
|
||||||
box.replaceChildren();
|
box.replaceChildren();
|
||||||
const items = copyItemsFor(state.member);
|
const items = copyItemsFor(state.member);
|
||||||
@@ -3080,6 +3087,12 @@ $<HTMLButtonElement>('cp-select-same').addEventListener('click', () => {
|
|||||||
renderCopyTargets();
|
renderCopyTargets();
|
||||||
renderCopyPreview();
|
renderCopyPreview();
|
||||||
});
|
});
|
||||||
|
$<HTMLButtonElement>('cp-items-reset').addEventListener('click', () => {
|
||||||
|
const src = activePier();
|
||||||
|
copyItemChoice = new Set(src ? copyItemsWithOverrides(src) : []);
|
||||||
|
renderCopyItems();
|
||||||
|
renderCopyPreview();
|
||||||
|
});
|
||||||
$<HTMLButtonElement>('cp-clear').addEventListener('click', () => {
|
$<HTMLButtonElement>('cp-clear').addEventListener('click', () => {
|
||||||
copySelection = new Set();
|
copySelection = new Set();
|
||||||
renderCopyTargets();
|
renderCopyTargets();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { copyCandidates, copyItemsFor, selectedTargets, type CopyCandidate } from '../src/core/copy-targets';
|
import { copyCandidates, copyItemsFor, copyItemsWithOverrides, selectedTargets, type CopyCandidate } from '../src/core/copy-targets';
|
||||||
|
import { loadP1 } from './helpers';
|
||||||
|
|
||||||
const piers: CopyCandidate[] = [
|
const piers: CopyCandidate[] = [
|
||||||
{ name: 'P1', type: 'T형', hasModel: true },
|
{ name: 'P1', type: 'T형', hasModel: true },
|
||||||
@@ -63,3 +64,24 @@ describe('copyItemsFor (부재 선택에 해당하는 복사 항목)', () => {
|
|||||||
expect([...all].sort()).toEqual(['coping-length', 'coping-width', 'ground-position', 'pile-length', 'pile-rows']);
|
expect([...all].sort()).toEqual(['coping-length', 'coping-width', 'ground-position', 'pile-length', 'pile-rows']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('copyItemsWithOverrides (기준 교각에서 되돌리기가 표시된 항목)', () => {
|
||||||
|
const base = loadP1();
|
||||||
|
const source = (draft: Partial<typeof base>) => ({ defaults: base, input: base, draft: { ...base, ...draft } });
|
||||||
|
|
||||||
|
it('is empty when the 기준 pier has no changed values', () => {
|
||||||
|
expect(copyItemsWithOverrides(source({}))).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selects the item of a changed coping length', () => {
|
||||||
|
expect(copyItemsWithOverrides(source({ copingLengthMm: base.copingLengthMm + 500 }))).toEqual(['coping-length']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('selects the pile item when the pile length changed', () => {
|
||||||
|
expect(copyItemsWithOverrides(source({ pileLengthMm: base.pileLengthMm + 100 }))).toEqual(['pile-length']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores a changed value that no copy item carries (groundEl)', () => {
|
||||||
|
expect(copyItemsWithOverrides(source({ groundEl: base.groundEl + 0.5 }))).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user