Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2025-03-04 14:48:58 +09:00
commit 304d0840e3
8 changed files with 264 additions and 253 deletions

View File

@ -12,10 +12,12 @@ export default function QPagination(props) {
return ( return (
<ol className="pagination"> <ol className="pagination">
<li className="page-item first"> <li className="page-item first">
<button onClick={() => handlePage(1)}></button> <button type="button" disabled={currentPage === 1} onClick={() => handlePage(1)}></button>
</li> </li>
<li className="page-item prev"> <li className="page-item prev">
<button <button
type="button"
disabled={currentPage <= 1}
onClick={() => { onClick={() => {
if (currentPage === 1) return if (currentPage === 1) return
handlePage(Math.max(1, (pageGroup - 2) * pagePerBlock + 1)) handlePage(Math.max(1, (pageGroup - 2) * pagePerBlock + 1))
@ -24,11 +26,15 @@ export default function QPagination(props) {
</li> </li>
{pageRange.map((page) => ( {pageRange.map((page) => (
<li className={page === currentPage ? `page-item on` : `page-item`} key={page}> <li className={page === currentPage ? `page-item on` : `page-item`} key={page}>
<button onClick={() => handlePage(page)}>{page}</button> <button type="button" onClick={() => handlePage(page)}>
{page}
</button>
</li> </li>
))} ))}
<li className="page-item next"> <li className="page-item next">
<button <button
type="button"
disabled={currentPage >= totalPages}
onClick={() => { onClick={() => {
if (currentPage === totalPages) return if (currentPage === totalPages) return
if (pageGroup * pagePerBlock + 1 <= totalPages) handlePage(Math.max(1, pageGroup * pagePerBlock + 1)) if (pageGroup * pagePerBlock + 1 <= totalPages) handlePage(Math.max(1, pageGroup * pagePerBlock + 1))
@ -36,7 +42,7 @@ export default function QPagination(props) {
></button> ></button>
</li> </li>
<li className="page-item last"> <li className="page-item last">
<button onClick={() => handlePage(totalPages)}></button> <button type="button" disabled={currentPage === totalPages} onClick={() => handlePage(totalPages)}></button>
</li> </li>
</ol> </ol>
) )

View File

@ -73,7 +73,7 @@ const PentagonDormer = forwardRef((props, refs) => {
</div> </div>
</div> </div>
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('slope')}</div> <div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.slope')}</div>
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">
<div className="outline-form"> <div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}> <div className="input-grid mr5" style={{ width: '60px' }}>

View File

@ -48,7 +48,7 @@ const TriangleDormer = forwardRef((props, refs) => {
</div> </div>
</div> </div>
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('slope')}</div> <div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.slope')}</div>
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">
<div className="outline-form"> <div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}> <div className="input-grid mr5" style={{ width: '60px' }}>

View File

@ -536,7 +536,6 @@ export function useModule() {
const moduleRowRemove = (type) => { const moduleRowRemove = (type) => {
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0] const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
c
const rowModules = getRowModules(activeModule) const rowModules = getRowModules(activeModule)
const otherModules = getOtherModules(rowModules) const otherModules = getOtherModules(rowModules)
const objects = getObjects() const objects = getObjects()

View File

@ -239,7 +239,7 @@ export function useRoofAllocationSetting(id) {
*/ */
const onAddRoofMaterial = () => { const onAddRoofMaterial = () => {
if (currentRoofList.length >= 4) { if (currentRoofList.length >= 4) {
swalFire({ type: 'alert', icon: 'error', text: getMessage('지붕재는 4개까지 선택 가능합니다.') }) swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.exceed.count') })
return return
} }
setCurrentRoofList([ setCurrentRoofList([
@ -289,7 +289,7 @@ export function useRoofAllocationSetting(id) {
const handleSaveContext = () => { const handleSaveContext = () => {
basicSettingSave() basicSettingSave()
const newRoofList = currentRoofList.map((roof, idx) => { const newRoofList = currentRoofList.map((roof, idx) => {
return { ...roof, index: idx } return { ...roof, index: idx, raft: roof.raft ? roof.raft : roof.raftBaseCd }
}) })
setBasicSetting((prev) => { setBasicSetting((prev) => {
return { return {
@ -379,7 +379,7 @@ export function useRoofAllocationSetting(id) {
/** 데이터 설정 */ /** 데이터 설정 */
const newRoofList = currentRoofList.map((roof, idx) => { const newRoofList = currentRoofList.map((roof, idx) => {
return { ...roof, index: idx, ...basicInfo } return { ...roof, index: idx, ...basicInfo, raft: roof.raft ? roof.raft : roof.raftBaseCd }
}) })
setBasicSetting((prev) => { setBasicSetting((prev) => {

View File

@ -42,6 +42,7 @@ import { useAdsorptionPoint } from './useAdsorptionPoint'
import { useRoofFn } from '@/hooks/common/useRoofFn' import { useRoofFn } from '@/hooks/common/useRoofFn'
import { MODULE_ALIGN_TYPE, useModule } from './module/useModule' import { MODULE_ALIGN_TYPE, useModule } from './module/useModule'
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty' import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
import { selectedMenuState } from '@/store/menuAtom'
export function useContextMenu() { export function useContextMenu() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -71,10 +72,11 @@ export function useContextMenu() {
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { alignModule, modulesRemove, moduleRoofRemove } = useModule() const { alignModule, modulesRemove, moduleRoofRemove } = useModule()
const { removeRoofMaterial, removeAllRoofMaterial, moveRoofMaterial, removeOuterLines } = useRoofFn() const { removeRoofMaterial, removeAllRoofMaterial, moveRoofMaterial, removeOuterLines } = useRoofFn()
const selectedMenu = useRecoilValue(selectedMenuState)
const currentMenuSetting = () => { const currentMenuSetting = () => {
switch (currentMenu) { switch (selectedMenu) {
case MENU.PLAN_DRAWING: case 'placement':
setContextMenu([ setContextMenu([
[ [
{ {
@ -115,155 +117,9 @@ export function useContextMenu() {
], ],
]) ])
break break
case MENU.ROOF_COVERING.EXTERIOR_WALL_LINE: case 'outline':
case MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS: if (['roof', 'auxiliaryLine'].includes(currentObject?.name)) {
case MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS: }
case MENU.ROOF_COVERING.ROOF_SHAPE_EDITING:
case MENU.ROOF_COVERING.HELP_LINE_DRAWING:
case MENU.ROOF_COVERING.EAVES_KERAVA_EDIT:
case MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN:
case MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET:
case MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC:
case MENU.ROOF_COVERING.DEFAULT:
setContextMenu([
[
{
id: 'roofMaterialPlacement',
name: getMessage('contextmenu.roof.material.placement'),
component: <RoofAllocationSetting id={popupId} />,
},
{
id: 'roofMaterialRemoveAll',
name: getMessage('contextmenu.roof.material.remove.all'),
fn: () => removeAllRoofMaterial(),
},
{
id: 'selectMove',
name: getMessage('contextmenu.select.move'),
fn: (currentMousePos) => {
moveRoofMaterial(currentMousePos)
},
},
{
id: 'wallLineRemove',
name: getMessage('contextmenu.wallline.remove'),
fn: (currentMousePos) => {
removeOuterLines(currentMousePos)
},
},
],
[
{
id: 'sizeEdit',
name: getMessage('contextmenu.size.edit'),
component: <AuxiliarySize id={popupId} />,
},
{
id: 'auxiliaryMove',
name: `${getMessage('contextmenu.auxiliary.move')}(M)`,
shortcut: ['m', 'M'],
component: <AuxiliaryEdit id={popupId} type={'move'} />,
},
{
id: 'auxiliaryCopy',
name: `${getMessage('contextmenu.auxiliary.copy')}(C)`,
shortcut: ['c', 'C'],
component: <AuxiliaryEdit id={popupId} type={'copy'} />,
},
{
id: 'auxiliaryRemove',
shortcut: ['d', 'D'],
name: `${getMessage('contextmenu.auxiliary.remove')}(D)`,
fn: () => {
if (!currentObject) return
const roof = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0]
if (!roof) {
// 아직 innerLines로 세팅이 안되어있는 line인 경우 제거
canvas.remove(currentObject)
canvas.discardActiveObject()
return
}
const innerLines = roof.innerLines?.filter((line) => currentObject.id !== line.id)
roof.innerLines = [...innerLines]
canvas.remove(currentObject)
canvas.discardActiveObject()
},
},
{
id: 'auxiliaryVerticalBisector',
name: getMessage('contextmenu.auxiliary.vertical.bisector'),
fn: () => {
if (!currentObject) return
const slope = (currentObject.y2 - currentObject.y1) / (currentObject.x2 - currentObject.x1)
const length = currentObject.length
let startX, startY, endX, endY
if (slope === 0) {
startX = endX = (currentObject.x1 + currentObject.x2) / 2
startY = currentObject.y2 - length / 2
endY = currentObject.y2 + length / 2
} else if (slope === Infinity) {
startX = currentObject.x1 - length / 2
startY = endY = (currentObject.y1 + currentObject.y2) / 2
endX = currentObject.x1 + length / 2
} else {
const bisectorSlope = -1 / slope
const dx = length / 2 / Math.sqrt(1 + bisectorSlope * bisectorSlope)
const dy = bisectorSlope * dx
startX = (currentObject.x1 + currentObject.x2) / 2 + dx
startY = (currentObject.y1 + currentObject.y2) / 2 + dy
endX = (currentObject.x1 + currentObject.x2) / 2 - dx
endY = (currentObject.y1 + currentObject.y2) / 2 - dy
}
const line = addLine([startX, startY, endX, endY], {
stroke: 'red',
strokeWidth: 1,
selectable: true,
name: 'auxiliaryLine',
attributes: { ...currentObject.attributes },
})
if (!currentObject.attributes.roofId) {
return
}
canvas
.getObjects()
.filter((obj) => obj.id === currentObject.attributes.roofId)[0]
.innerLines.push(line)
},
},
{
id: 'auxiliaryRemoveAll',
name: getMessage('contextmenu.auxiliary.remove.all'),
fn: () => {
if (!currentObject) {
swalFire({ text: getMessage('roof.is.not.selected') })
return
}
const innerLines = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0]?.innerLines
if (innerLines) {
innerLines.forEach((line) => {
canvas.remove(line)
})
innerLines.length = 0
}
// 확정되지 않은 보조선
const notFixedAuxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isAuxiliaryFixed)
notFixedAuxiliaryLines.forEach((line) => {
canvas.remove(line)
})
canvas.renderAll()
},
},
],
])
break break
default: default:
setContextMenu([]) setContextMenu([])
@ -312,96 +168,244 @@ export function useContextMenu() {
switch (currentObject.name) { switch (currentObject.name) {
case 'triangleDormer': case 'triangleDormer':
case 'pentagonDormer': case 'pentagonDormer':
setContextMenu([ if (selectedMenu === 'surface') {
[ setContextMenu([
{ [
id: 'sizeEdit', {
name: getMessage('contextmenu.size.edit'), id: 'sizeEdit',
component: <SizeSetting id={popupId} target={currentObject} />, name: getMessage('contextmenu.size.edit'),
}, component: <SizeSetting id={popupId} target={currentObject} />,
{ },
id: 'dormerRemove', {
shortcut: ['d', 'D'], id: 'dormerRemove',
name: `${getMessage('contextmenu.remove')}(D)`, shortcut: ['d', 'D'],
fn: () => deleteObject(), name: `${getMessage('contextmenu.remove')}(D)`,
}, fn: () => deleteObject(),
{ },
id: 'dormerMove', {
shortcut: ['m', 'M'], id: 'dormerMove',
name: `${getMessage('contextmenu.move')}(M)`, shortcut: ['m', 'M'],
fn: () => moveObjectBatch(), name: `${getMessage('contextmenu.move')}(M)`,
}, fn: () => moveObjectBatch(),
{ },
id: 'dormerCopy', {
shortcut: ['c', 'C'], id: 'dormerCopy',
name: `${getMessage('contextmenu.copy')}(C)`, shortcut: ['c', 'C'],
fn: () => copyObject(), name: `${getMessage('contextmenu.copy')}(C)`,
}, fn: () => copyObject(),
{ },
id: 'roofMaterialEdit', {
name: getMessage('contextmenu.roof.material.edit'), id: 'roofMaterialEdit',
component: <RoofMaterialSetting id={popupId} />, name: getMessage('contextmenu.roof.material.edit'),
}, component: <RoofMaterialSetting id={popupId} />,
{ },
id: 'dormerOffset', {
name: getMessage('contextmenu.dormer.offset'), id: 'dormerOffset',
component: <DormerOffset id={popupId} title={getMessage('contextmenu.dormer.offset')} />, name: getMessage('contextmenu.dormer.offset'),
}, component: <DormerOffset id={popupId} title={getMessage('contextmenu.dormer.offset')} />,
], },
]) ],
])
}
break break
case 'roof': case 'roof':
setContextMenu([ case 'auxiliaryLine':
[ case 'hip':
{ case 'ridge':
id: 'sizeEdit', if (selectedMenu === 'surface') {
name: getMessage('contextmenu.size.edit'), setContextMenu([
component: <SizeSetting id={popupId} target={currentObject} />, [
}, {
{ id: 'sizeEdit',
id: 'roofMaterialRemove', name: getMessage('contextmenu.size.edit'),
shortcut: ['d', 'D'], component: <SizeSetting id={popupId} target={currentObject} />,
name: `${getMessage('contextmenu.remove')}(D)`,
fn: () => deleteObject(),
},
{
id: 'roofMaterialMove',
shortcut: ['m', 'M'],
name: `${getMessage('contextmenu.move')}(M)`,
fn: () => moveSurfaceShapeBatch(),
},
{
id: 'roofMaterialCopy',
shortcut: ['c', 'C'],
name: `${getMessage('contextmenu.copy')}(C)`,
fn: () => copyObject(),
},
],
[
{
id: 'roofMaterialEdit',
name: getMessage('contextmenu.roof.material.edit'),
component: <ContextRoofAllocationSetting id={popupId} />,
},
{
id: 'linePropertyEdit',
name: getMessage('contextmenu.line.property.edit'),
fn: () => {
if (+canvasSetting.roofSizeSet === 3) {
swalFire({ text: getMessage('contextmenu.line.property.edit.roof.size.3') })
} else {
addPopup(popupId, 1, <PlacementSurfaceLineProperty id={popupId} roof={currentObject} />)
}
}, },
// component: <LinePropertySetting id={popupId} target={currentObject} />, {
}, id: 'roofMaterialRemove',
{ shortcut: ['d', 'D'],
id: 'flowDirectionEdit', name: `${getMessage('contextmenu.remove')}(D)`,
name: getMessage('contextmenu.flow.direction.edit'), fn: () => deleteObject(),
component: <FlowDirectionSetting id={popupId} target={currentObject} />, },
}, {
], id: 'roofMaterialMove',
]) shortcut: ['m', 'M'],
name: `${getMessage('contextmenu.move')}(M)`,
fn: () => moveSurfaceShapeBatch(),
},
{
id: 'roofMaterialCopy',
shortcut: ['c', 'C'],
name: `${getMessage('contextmenu.copy')}(C)`,
fn: () => copyObject(),
},
],
[
{
id: 'roofMaterialEdit',
name: getMessage('contextmenu.roof.material.edit'),
component: <ContextRoofAllocationSetting id={popupId} />,
},
{
id: 'linePropertyEdit',
name: getMessage('contextmenu.line.property.edit'),
fn: () => {
if (+canvasSetting.roofSizeSet === 3) {
swalFire({ text: getMessage('contextmenu.line.property.edit.roof.size.3') })
} else {
addPopup(popupId, 1, <PlacementSurfaceLineProperty id={popupId} roof={currentObject} />)
}
},
// component: <LinePropertySetting id={popupId} target={currentObject} />,
},
{
id: 'flowDirectionEdit',
name: getMessage('contextmenu.flow.direction.edit'),
component: <FlowDirectionSetting id={popupId} target={currentObject} />,
},
],
])
} else if (selectedMenu === 'outline') {
setContextMenu([
[
{
id: 'roofMaterialPlacement',
name: getMessage('contextmenu.roof.material.placement'),
component: <RoofAllocationSetting id={popupId} />,
},
{
id: 'roofMaterialRemoveAll',
name: getMessage('contextmenu.roof.material.remove.all'),
fn: () => removeAllRoofMaterial(),
},
{
id: 'selectMove',
name: getMessage('contextmenu.select.move'),
fn: (currentMousePos) => {
moveRoofMaterial(currentMousePos)
},
},
{
id: 'wallLineRemove',
name: getMessage('contextmenu.wallline.remove'),
fn: (currentMousePos) => {
removeOuterLines(currentMousePos)
},
},
],
[
{
id: 'sizeEdit',
name: getMessage('contextmenu.size.edit'),
component: <AuxiliarySize id={popupId} />,
},
{
id: 'auxiliaryMove',
name: `${getMessage('contextmenu.auxiliary.move')}(M)`,
shortcut: ['m', 'M'],
component: <AuxiliaryEdit id={popupId} type={'move'} />,
},
{
id: 'auxiliaryCopy',
name: `${getMessage('contextmenu.auxiliary.copy')}(C)`,
shortcut: ['c', 'C'],
component: <AuxiliaryEdit id={popupId} type={'copy'} />,
},
{
id: 'auxiliaryRemove',
shortcut: ['d', 'D'],
name: `${getMessage('contextmenu.auxiliary.remove')}(D)`,
fn: () => {
if (!currentObject) return
const roof = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0]
if (!roof) {
// 아직 innerLines로 세팅이 안되어있는 line인 경우 제거
canvas.remove(currentObject)
canvas.discardActiveObject()
return
}
const innerLines = roof.innerLines?.filter((line) => currentObject.id !== line.id)
roof.innerLines = [...innerLines]
canvas.remove(currentObject)
canvas.discardActiveObject()
},
},
{
id: 'auxiliaryVerticalBisector',
name: getMessage('contextmenu.auxiliary.vertical.bisector'),
fn: () => {
if (!currentObject) return
const slope = (currentObject.y2 - currentObject.y1) / (currentObject.x2 - currentObject.x1)
const length = currentObject.length
let startX, startY, endX, endY
if (slope === 0) {
startX = endX = (currentObject.x1 + currentObject.x2) / 2
startY = currentObject.y2 - length / 2
endY = currentObject.y2 + length / 2
} else if (slope === Infinity) {
startX = currentObject.x1 - length / 2
startY = endY = (currentObject.y1 + currentObject.y2) / 2
endX = currentObject.x1 + length / 2
} else {
const bisectorSlope = -1 / slope
const dx = length / 2 / Math.sqrt(1 + bisectorSlope * bisectorSlope)
const dy = bisectorSlope * dx
startX = (currentObject.x1 + currentObject.x2) / 2 + dx
startY = (currentObject.y1 + currentObject.y2) / 2 + dy
endX = (currentObject.x1 + currentObject.x2) / 2 - dx
endY = (currentObject.y1 + currentObject.y2) / 2 - dy
}
const line = addLine([startX, startY, endX, endY], {
stroke: 'red',
strokeWidth: 1,
selectable: true,
name: 'auxiliaryLine',
attributes: { ...currentObject.attributes },
})
if (!currentObject.attributes.roofId) {
return
}
canvas
.getObjects()
.filter((obj) => obj.id === currentObject.attributes.roofId)[0]
.innerLines.push(line)
},
},
{
id: 'auxiliaryRemoveAll',
name: getMessage('contextmenu.auxiliary.remove.all'),
fn: () => {
if (!currentObject) {
swalFire({ text: getMessage('roof.is.not.selected') })
return
}
const innerLines = canvas.getObjects().filter((obj) => obj.id === currentObject.attributes.roofId)[0]?.innerLines
if (innerLines) {
innerLines.forEach((line) => {
canvas.remove(line)
})
innerLines.length = 0
}
// 확정되지 않은 보조선
const notFixedAuxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isAuxiliaryFixed)
notFixedAuxiliaryLines.forEach((line) => {
canvas.remove(line)
})
canvas.renderAll()
},
},
],
])
}
break break
case 'opening': case 'opening':
setContextMenu([ setContextMenu([

View File

@ -294,9 +294,9 @@
"modal.object.setting.size.setting": "サイズ設定", "modal.object.setting.size.setting": "サイズ設定",
"modal.object.setting.agreement.depth": "棟の長さ・深さ", "modal.object.setting.agreement.depth": "棟の長さ・深さ",
"modal.object.setting.offset.depth": "出幅(深さ)", "modal.object.setting.offset.depth": "出幅(深さ)",
"modal.object.setting.size.width": "", "modal.object.setting.size.width": "",
"modal.object.setting.offset.width": "出幅(幅)", "modal.object.setting.offset.width": "出幅(幅)",
"modal.object.setting.offset.slope": "", "modal.object.setting.offset.slope": "勾配",
"modal.object.setting.direction.select": "方向の選択", "modal.object.setting.direction.select": "方向の選択",
"modal.placement.surface.setting.info": "ⓘ①の長さ入力後、対角線長を入力すると②の長さを自動計算します。", "modal.placement.surface.setting.info": "ⓘ①の長さ入力後、対角線長を入力すると②の長さを自動計算します。",
"modal.placement.surface.setting.diagonal.length": "斜めの長さ", "modal.placement.surface.setting.diagonal.length": "斜めの長さ",
@ -1015,8 +1015,8 @@
"module.place.select.one.module": "モジュールは1つだけ選択してください。", "module.place.select.one.module": "モジュールは1つだけ選択してください。",
"batch.canvas.delete.all": "配置面の内容をすべて削除しますか?", "batch.canvas.delete.all": "配置面の内容をすべて削除しますか?",
"module.not.found": "インストールモジュールを選択してください。", "module.not.found": "インストールモジュールを選択してください。",
"module.circuit.minimun.error": "", "module.circuit.minimun.error": "회로번호는 1 이상입력해주세요.(JA)",
"module.already.exist.error": "", "module.already.exist.error": "회로번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로번호를 설정하십시오.(JA)",
"construction.length.difference": "屋根面工法をすべて選択してください。", "construction.length.difference": "屋根面工法をすべて選択してください。",
"menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。",
"batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。", "batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。",
@ -1028,5 +1028,6 @@
"not.allocation.exist.module": "回路を割り当てていないモジュールがあります。", "not.allocation.exist.module": "回路を割り当てていないモジュールがあります。",
"roof.is.not.selected": "屋根の選択をお願いします。", "roof.is.not.selected": "屋根の選択をお願いします。",
"length.direction.is.required": "長さと方向を入力します。", "length.direction.is.required": "長さと方向を入力します。",
"canvas.infomation.text": "数字は [半角] 入力のみ可能です。" "canvas.infomation.text": "数字は [半角] 入力のみ可能です。",
"roof.exceed.count": "屋根材は4つまで選択可能です。"
} }

View File

@ -1028,5 +1028,6 @@
"not.allocation.exist.module": "회로를 할당하지 않은 모듈이 있습니다.", "not.allocation.exist.module": "회로를 할당하지 않은 모듈이 있습니다.",
"roof.is.not.selected": "지붕을 선택해주세요.", "roof.is.not.selected": "지붕을 선택해주세요.",
"length.direction.is.required": "길이와 방향을 입력하세요.", "length.direction.is.required": "길이와 방향을 입력하세요.",
"canvas.infomation.text": "숫자는 [반각] 입력만 가능합니다." "canvas.infomation.text": "숫자는 [반각] 입력만 가능합니다.",
"roof.exceed.count": "지붕재는 4개까지 선택 가능합니다."
} }