diff --git a/src/app/[locale]/initSettingsModal/page.jsx b/src/app/[locale]/initSettingsModal/page.jsx new file mode 100644 index 00000000..a081ef47 --- /dev/null +++ b/src/app/[locale]/initSettingsModal/page.jsx @@ -0,0 +1,16 @@ +import Hero from '@/components/Hero' +import InitSettingsModal from '@/components/InitSettingsModal' +import { initCheck } from '@/util/session-util' + +export default async function InitSettingsModalPage() { + await initCheck() + + return ( + <> + +
+ +
+ + ) +} diff --git a/src/components/Headers.jsx b/src/components/Headers.jsx index 331e899c..02859c96 100644 --- a/src/components/Headers.jsx +++ b/src/components/Headers.jsx @@ -10,6 +10,7 @@ export default function Headers() {
Intro Playground + Basic Settings Canvas Settings Roof Roof2 diff --git a/src/components/InitSettingsModal.jsx b/src/components/InitSettingsModal.jsx index a79c7a9e..1deb81a7 100644 --- a/src/components/InitSettingsModal.jsx +++ b/src/components/InitSettingsModal.jsx @@ -1,22 +1,31 @@ +'use client' + import { useEffect, useState, memo, useCallback } from 'react' import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input, Select, SelectItem } from '@nextui-org/react' import { useRecoilState, useRecoilValue } from 'recoil' import { modalContent, modalState } from '@/store/modalAtom' import { canvasSettingState } from '@/store/canvasAtom' import { useAxios } from '@/hooks/useAxios' +import { get, post } from '@/lib/Axios' export default function InitSettingsModal(props) { + const [objectNo, setObjectNo] = useState('test123240909001') // 후에 삭제 필요 const [open, setOpen] = useRecoilState(modalState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [roofMaterials, setRoofMaterials] = useState([]) const [basicSetting, setBasicSettings] = useState({ - type: '1', - inputType: '1', - angleType: 'slope', + roofDrawingSet: '1', + roofSizeSet: '1', + roofAngleSet: 'slope', roofs: [], }) - const { get, post } = useAxios() + const modelProps = { + open, + setOpen, + } + + //const { get, post } = useAxios() useEffect(() => { get({ url: '/api/roof-material/roof-material-infos' }).then((res) => { @@ -26,6 +35,41 @@ export default function InitSettingsModal(props) { setRoofMaterials(res) }) + get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${objectNo}` }).then((res) => { + if (!res) return + + // 'roofs' 배열을 생성하여 각 항목을 추가 + const roofsRow = res.map((item) => { + return { + roofDrawingSet: String(item.roofDrawingSet), + roofSizeSet: String(item.roofSizeSet), + roofAngleSet: item.roofAngleSet, + } + }) + + const roofsArray = res.map((item) => { + return { + roofSeq: String(item.roofSeq), + roofType: String(item.roofType), + roofWidth: String(item.roofWidth), + roofHeight: String(item.roofHeight), + roofGap: String(item.roofGap), + roofLayout: item.roofLayout, + } + }) + + // 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음 + const patternData = { + roofDrawingSet: roofsRow[0].roofDrawingSet, // 첫 번째 항목의 값을 사용 + roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용 + roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용 + roofs: roofsArray, // 만들어진 roofs 배열 + } + + // 데이터 설정 + setBasicSettings({ ...patternData }) + }) + if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) { setBasicSettings({ ...canvasSetting }) } @@ -46,12 +90,12 @@ export default function InitSettingsModal(props) { //기본값 const newRoofSettings = { - id: basicSetting.roofs.length + 1, - roofId: '3', - width: '200', - height: '200', - gap: '0', - layout: 'parallel', + roofSeq: basicSetting.roofs.length + 1, + roofType: '3', + roofWidth: '200', + roofHeight: '200', + roofGap: '0', + roofLayout: 'parallel', } setBasicSettings((prevState) => ({ @@ -62,19 +106,45 @@ export default function InitSettingsModal(props) { //배열 값 변경 함수 const handleRoofSettings = (id, event) => { - const roof = basicSetting.roofs.map((roof, i) => (id === roof.id ? { ...roof, [event.target.name]: event.target.value } : roof)) + const roof = basicSetting.roofs.map((roof, i) => (id === roof.roofSeq ? { ...roof, [event.target.name]: event.target.value } : roof)) setBasicSettings((prevState) => ({ ...prevState, roofs: [...roof], })) } - const submitCanvasConfig = () => { - post({ url: '/api/canvas-config', data: basicSetting }).then((res) => { - if (!res) { - setCanvasSetting({ ...basicSetting }) - } - }) + //저장 + const submitCanvasConfig = async () => { + if (!objectNo) { + alert('object_no를 입력하세요.') + return + } + + const patternData = { + objectNo, + roofDrawingSet: basicSetting.roofDrawingSet, + roofSizeSet: basicSetting.roofSizeSet, + roofAngleSet: basicSetting.roofAngleSet, + roofMaterialsAddList: basicSetting.roofs, + } + await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }) + + //Recoil 설정 + setCanvasSetting({ ...basicSetting }) + + // 저장 후 재조회 + //await handleSelect() + } + + // 삭제버튼 클릭시 해당 요소 id를 targetId로 전달받음 + const onRemove = async (targetId) => { + console.log(targetId) + + setBasicSettings((prevState) => ({ + ...prevState, + roofs: prevState.roofs.filter((roof) => roof.roofSeq !== targetId), + })) + // setBasicSettings({ ...newRoofSettings }) // 삭제한 데이터 배열을 setData()에 상태를 변화시킴 } return ( @@ -84,7 +154,13 @@ export default function InitSettingsModal(props) {
- + 치수 입력에 의한 물건작성
@@ -92,7 +168,13 @@ export default function InitSettingsModal(props) {
- + 복사도 입력 실측값 입력 육지붕 @@ -102,13 +184,20 @@ export default function InitSettingsModal(props) {
- + 경사 각도
+
지붕재 추가(단위 : mm)
+ setObjectNo(e.target.value)} />
@@ -137,15 +227,16 @@ export default function InitSettingsModal(props) { const RoofSelectBox = (props) => { return (
+ 타입 : + 너비 : props.onChange(props.roof.id, e)} - /> - props.onChange(props.roof.id, e)} + onChange={(e) => props.onChange(props.roof.roofSeq, e)} /> mm - props.onChange(props.roof.id, e)} /> + 높이 : + props.onChange(props.roof.roofSeq, e)} + /> + mm + 서까래 간격 : + props.onChange(props.roof.roofSeq, e)} + /> mm
props.onChange(props.roof.id, e)} + onChange={(e) => props.onChange(props.roof.roofSeq, e)} > 병렬식 계단식
+
+ +
) } diff --git a/src/components/Settings.jsx b/src/components/Settings.jsx index 2d6e5142..43288dbe 100644 --- a/src/components/Settings.jsx +++ b/src/components/Settings.jsx @@ -6,12 +6,57 @@ import { Button } from '@nextui-org/react' import { get, post } from '@/lib/Axios' import { useRecoilState } from 'recoil' import { customSettingsState } from '@/store/canvasAtom' +import { modalContent, modalState } from '@/store/modalAtom' + +import ColorPicker from './common/color-picker/ColorPicker' export default function Settings() { const [objectNo, setObjectNo] = useState('test123240829010') const [error, setError] = useState(null) const [customSettings, setCustomSettings] = useRecoilState(customSettingsState) + const [color, setColor] = useState('#ff0000') + + const [open, setOpen] = useRecoilState(modalState) + const [contents, setContent] = useRecoilState(modalContent) + + const handleSavePopup = () => { + console.log('color ', color) + } + + const handleClosePopup = () => { + setContent('') + setOpen(false) + console.log('colorSetting ', color) + } + + const colorSetting = ( + <> +
+

React ColorPicker

+ +
{color}
+
+

+ +

+ + ) + + const customStyles = { + overlay: { + backgroundColor: 'rgba(0,0,0,0.5)', + }, + content: { + width: '300px', + height: '400px', + margin: 'auto', + borderRadius: '4px', + boxShadow: '0 2px 4px rgba(0,0,0,0.2)', + padding: '20px', + }, + } + // 상태를 하나의 객체로 관리 const [settings, setSettings] = useState({ display1: Array(11).fill(false), // 화면 표시1 @@ -48,6 +93,21 @@ export default function Settings() { // 클릭 시 상태 변경 함수 const handleToggle = (type, index) => { + // '실선 그리드' 클릭 시 팝업 열기 + if (type === 'gridSettings' && gridItems.gridSettings[index] === '실선 그리드') { + //openGridPopup() + } + + // '그리드 색 설정' 클릭 시 팝업 열기 + if (type === 'gridSettings' && gridItems.gridSettings[index] === '그리드 색 설정') { + //setSelectedGridSetting(gridItems.gridSettings[index]) + //setIsPopupOpen(true) + //return prevSettings // 설정은 변경하지 않음 + + setOpen(true) + setContent({ ...colorSetting }) + } + setSettings((prevSettings) => { // prevSettings[type]이 배열인지 확인하고, 그렇지 않은 경우 빈 배열로 초기화 let updated = Array.isArray(prevSettings[type]) ? [...prevSettings[type]] : [] @@ -61,6 +121,24 @@ export default function Settings() { }) } + // '실선 그리드' 클릭 시 팝업을 열기 위한 함수 + const openGridPopup = () => { + const popupWidth = 500 + const popupHeight = 300 + + // 팝업 창 위치를 화면 중앙으로 조정하기 위해 계산 + const left = window.innerWidth / 2 - popupWidth / 2 + const top = window.innerHeight / 2 - popupHeight / 2 + + // 새 창 열기 + window + .open + //'./components/intro', // 팝업으로 띄울 페이지의 URL + //'_blank', // 새 창으로 열기 + //`width=${popupWidth},height=${popupHeight},top=${top},left=${left}`, // 크기와 위치 지정 + () + } + // Canvas Setting 조회 및 초기화 const handleSelect = async () => { try { @@ -221,6 +299,10 @@ export default function Settings() {
흡착점 ON

[그리드 설정]

+
+ +
{color}
+
{gridItems.gridSettings.map((item, index) => (
{ this.addLengthText() + if (this.arrow) { + drawDirectionArrow(this) + } }) this.on('selected', () => { @@ -144,6 +147,17 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { this.canvas.remove(text) }) this.texts = null + + if (this.arrow) { + this.canvas.remove(this.arrow) + this.canvas + .getObjects() + .filter((obj) => obj.name === 'directionText' && obj.parent === this.arrow) + .forEach((text) => { + this.canvas.remove(text) + }) + this.arrow = null + } }) // polygon.fillCell({ width: 50, height: 30, padding: 10 }) diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js index df0dc0d2..a19d2944 100644 --- a/src/hooks/useMode.js +++ b/src/hooks/useMode.js @@ -32,7 +32,7 @@ import { import { QLine } from '@/components/fabric/QLine' import { fabric } from 'fabric' import { QPolygon } from '@/components/fabric/QPolygon' -import offsetPolygon from '@/util/qpolygon-utils' +import offsetPolygon, { inPolygon } from '@/util/qpolygon-utils' import { isObjectNotEmpty } from '@/util/common-utils' import * as turf from '@turf/turf' import { Mode } from '@/common/common' @@ -1061,8 +1061,25 @@ export function useMode() { origY: 0, down: (o) => { if (mode !== Mode.OPENING) return - mouseEvent.openingMode.isDown = true + const roofs = canvas?._objects.filter((obj) => obj.name === 'roof') + if (roofs.length === 0) { + alert('지붕을 먼저 그려주세요') + setMode(Mode.DEFAULT) + return + } const pointer = canvas.getPointer(o.e) + let selectRoof = null + roofs.forEach((roof) => { + if (roof.inPolygon({ x: pointer.x, y: pointer.y })) { + selectRoof = roof + } + }) + if (!selectRoof) { + alert('지붕 내부에만 생성 가능합니다.') + return + } + mouseEvent.openingMode.isDown = true + mouseEvent.openingMode.origX = pointer.x mouseEvent.openingMode.origY = pointer.y mouseEvent.openingMode.rect = new fabric.Rect({ @@ -1123,17 +1140,21 @@ export function useMode() { return false } + const rectPoints = [ + { x: rect.left, y: rect.top }, + { x: rect.left, y: rect.top + rect.height }, + { x: rect.left + rect.width, y: rect.top + rect.height }, + { x: rect.left + rect.width, y: rect.top }, + ] + for (let i = 0; i < openings.length; i++) { const rect2 = openings[i] - // Check if one rectangle is to the left of the other - if (rect.x + rect.width <= rect2.x || rect2.x + rect2.width <= rect.x) { - return true - } - - // Check if one rectangle is above the other - if (rect.y + rect.height <= rect2.y || rect2.y + rect2.height <= rect.y) { - return true - } + const rect2Points = [ + { x: rect2.left, y: rect2.top }, + { x: rect2.left, y: rect2.top + rect2.height }, + { x: rect2.left + rect2.width, y: rect2.top + rect2.height }, + { x: rect2.left + rect2.width, y: rect2.top }, + ] } return false @@ -1147,6 +1168,7 @@ export function useMode() { canvas?.remove(rect) return false } + return result } diff --git a/src/locales/ja.json b/src/locales/ja.json index a1725dfd..146bb78a 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1,3 +1,90 @@ { - "hi": "こんにちは" + "hi": "こんにちは", + "common.message.no.data": "No data", + "common.message.no.dataDown": "ダウンロードするデータがありません", + "common.message.noData": "表示するデータがありません", + "common.message.search": "search success", + "common.message.insert": "insert success", + "common.message.update": "update success", + "common.message.delete": "削除", + "common.message.restoration": "復元", + "common.message.cancel": "キャンセル", + "common.message.send": "メールを送信しました.", + "common.message.no.delete": "削除するデータがありません", + "common.message.save": "保存", + "common.message.transfer": "転送", + "common.message.batch.exec": "batch success", + "common.message.not.mov": "移動できません.", + "common.message.required.data": "{0} は入力必須項目となります。", + "common.message.save.error": "データの保存中にエラーが発生しました。 サイト管理者にお問い合わせください。", + "common.message.transfer.error": "データの転送中にエラーが発生しました。 サイト管理者にお問い合わせください。", + "common.message.delete.error": "データの削除中にエラーが発生しました。 サイト管理者にお問い合わせください。", + "common.message.batch.error": "バッチの実行中にエラーが発生しました。 サイト管理者に連絡してください。", + "common.message.send.error": "データの送信中にエラーが発生しました。サイト管理者にお問い合わせください", + "common.message.communication.error": "ネットワークエラーが発生しました。サイト管理者に連絡してください。", + "common.message.data.error": "{0} はデータ形式が無効です。", + "common.message.data.setting.error": "{0} は削除されたか、すでに構成されているデータです。", + "common.message.parameter.error": "パラメータエラー", + "common.message.product.parameter.error": "存在しない製品があります。", + "common.message.customer.parameter.error": "存在しない顧客があります。", + "common.message.file.exists.error": "ファイルが正常にアップロードされないためにエラーが発生しました", + "common.message.file.download.exists": "ファイルが存在しません。", + "common.message.file.download.error": "ァイルのダウンロードエラー", + "common.message.file.template.validation01": "フォルダをアップロードできません", + "common.message.file.template.validation02": "アップロードできるのはExcelファイルのみです。", + "common.message.file.template.validation03": "登録できない拡張子です", + "common.message.file.template.validation04": "容量を超えています アップロード可能な容量:{0} MB", + "common.message.file.template.validation05": "アップロードファイルを選択して下さい", + "common.message.multi.insert": "合計 {0} 件数 ({1}成功、 {2} 失敗 {3})", + "common.message.error": "エラーが発生しました。サイト管理者に連絡してください。", + "common.message.data.save": "保存しますか?", + "common.message.data.delete": " 削除しますか?", + "common.message.data.exists": "{0} はすでに存在するデータです。", + "common.message.data.no.exists": "{0} は存在しないデータです。", + "common.message.all": "All", + "common.message.tab.close.all": "すべてのタブを閉じますか?", + "common.message.transfer.save": "{0}件転送しますか?", + "common.message.confirm.save": "保存しますか?", + "common.message.confirm.confirm": "承認しますか?", + "common.message.confirm.request": "承認リクエストしますか?", + "common.message.confirm.delete": "削除しますか?", + "common.message.confirm.close": "閉じますか?", + "common.message.confirm.unclose": "クローズ中止しますか?", + "common.message.confirm.cancel": "キャンセルしますか?", + "common.message.confirm.uncancel": "キャンセル中止しますか?", + "common.message.confirm.copy": "コピーしますか?", + "common.message.confirm.createSo": "S/O作成しますか?", + "common.message.confirm.mark": "保存完了", + "common.message.confirm.mail": "メールを送信しますか?", + "common.message.confirm.printPriceItem": "価格を印刷しますか?", + "common.message.confirm.allAppr ": "Do you want to Batch approve the selected data?", + "common.message.confirm.deliveryFee": "送料を登録しますか?", + "common.message.success.delete": "削除完了", + "common.message.success.close": "閉じる", + "common.message.success.unclose": "キャンセルしました", + "common.message.validation.date": "終了日を開始日より前にすることはできません。 もう一度入力してください。", + "common.message.no.editfield": "フィールドを編集できません", + "common.message.success.rmmail": "リスク管理チームにメールを送信しました。", + "common.message.password.validation01": "パスワードの変更が一致しません。", + "common.message.password.validation02": "英語、数字、特殊文字を組み合わせた8桁以上を入力してください。", + "common.message.password.validation03": "パスワードをIDと同じにすることはできません。", + "common.message.menu.validation01": "注文を保存するメニューはありません.", + "common.message.menu.validation02": "The same sort order exists.", + "common.message.menuCode.check01": "登録可能", + "common.message.menuCode.check02": "登録できません", + "common.message.pleaseSelect": "{0}を選択してください", + "common.message.pleaseInput": "{0}を入力してください。", + "common.message.pleaseInputOr": "{0}または{1}を入力してください。", + "common.message.approved ": "承認済み", + "common.message.errorFieldExist": "エラー項目が存在します", + "common.message.storeIdExist ": "既に利用されている販売店IDです", + "common.message.userIdExist ": "すでに使用しているユーザーID。", + "common.message.noExists ": "削除された掲示物です", + "common.message.emailReqTo": "メール宛先が必要です", + "common.message.downloadPeriod": "ダウンロード検索期間を{0}日以内に選択してください。", + "common.message.backToSubmit": "販売店ブロック解除実行しますか?", + "common.message.backToG3": "Back to G3処理実行しますか?", + "common.message.writeToConfirm": "作成解除を実行しますか?", + "common.message.password.init.success": "パスワード [{0}] に初期化されました。", + "common.message.no.edit.save": "この文書は変更できません。" } diff --git a/src/locales/ko.json b/src/locales/ko.json index 282d9722..04b14c9f 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1,3 +1,90 @@ { - "hi": "안녕하세요" + "hi": "안녕하세요", + "common.message.no.data": "No data", + "common.message.no.dataDown": "No data to download", + "common.message.noData": "No data to display", + "common.message.search": "search success", + "common.message.insert": "insert success", + "common.message.update": "update success", + "common.message.delete": "Deleted", + "common.message.restoration": "Restored", + "common.message.cancel": "Canceled", + "common.message.send": "The mail has been sent.", + "common.message.no.delete": "There is no data to delete.", + "common.message.save": "Saved.", + "common.message.transfer": "Transfered", + "common.message.batch.exec": "batch success", + "common.message.not.mov": "Its impossible to move.", + "common.message.required.data": "{0} is required input value.", + "common.message.save.error": "An error occurred while saving the data. Please contact site administrator.", + "common.message.transfer.error": "An error occurred while transfer the data. Please contact site administrator.", + "common.message.delete.error": "An error occurred while deleting data. Please contact site administrator.", + "common.message.batch.error": "An error occurred while executing the batch. Please contact site administrator.", + "common.message.send.error": "Error sending data, please contact your administrator.", + "common.message.communication.error": "Network error occurred. \n Please contact site administrator.", + "common.message.data.error": "{0} The data format is not valid.", + "common.message.data.setting.error": "{0} is data that has been deleted or already configured.", + "common.message.parameter.error": "Parameter Error", + "common.message.product.parameter.error": "존재하지 않는 제품이 있습니다.", + "common.message.customer.parameter.error": "존재하지 않는 고객이 있습니다.", + "common.message.file.exists.error": "Error due to file not uploading normally", + "common.message.file.download.exists": "File does not exist.", + "common.message.file.download.error": "File download error", + "common.message.file.template.validation01": "Unable to upload folder", + "common.message.file.template.validation02": "Only Excel files can be uploaded.", + "common.message.file.template.validation03": "Non-registerable extension", + "common.message.file.template.validation04": "Exceed capacity \n Uploadable capacity : {0} MB", + "common.message.file.template.validation05": "업로드 파일을 선택해주세요.", + "common.message.multi.insert": "Total {0} cases ({1} successes, {2} failures {3})", + "common.message.error": "Error occurred, please contact site administrator.", + "common.message.data.save": "Do you want to save it?", + "common.message.data.delete": "Do you want to delete it?", + "common.message.data.exists": "{0} is data that already exists.", + "common.message.data.no.exists": "{0} is data that does not exist.", + "common.message.all": "All", + "common.message.tab.close.all": "Close all tabs?", + "common.message.transfer.save": "Want to {0} transfer it?", + "common.message.confirm.save": "Want to save it?", + "common.message.confirm.confirm": "Want to approve?", + "common.message.confirm.request": "Would you like to request a Approval?", + "common.message.confirm.delete": "Do you want to delete it?", + "common.message.confirm.close": "Want to close?", + "common.message.confirm.unclose": "Do you want to cancel the close?", + "common.message.confirm.cancel": "Want to cancellation?", + "common.message.confirm.uncancel": "Do you want to cancel the cancellation?", + "common.message.confirm.copy": "Do you want to copy?", + "common.message.confirm.createSo": "Create Sales Order?", + "common.message.confirm.mark": "Saved.", + "common.message.confirm.mail": "Do you want to send mail?", + "common.message.confirm.printPriceItem": "Would you like to print item price?", + "common.message.confirm.allAppr ": "Do you want to Batch approve the selected data?", + "common.message.confirm.deliveryFee": "Do you want to register shipping fee?", + "common.message.success.delete": "Deleted.", + "common.message.success.close": "Closed.", + "common.message.success.unclose": "Cancel Closed.", + "common.message.validation.date": "The end date cannot be earlier than the start date. Please enter it again.", + "common.message.no.editfield": "Can not edit field", + "common.message.success.rmmail": "You have successfully sent mail to the Risk Management team.", + "common.message.password.validation01": "Change passwords do not match.", + "common.message.password.validation02": "Please enter at least 8 digits combining English, numbers, and special characters.", + "common.message.password.validation03": "Password cannot be the same as ID.", + "common.message.menu.validation01": "There is no menu to save the order.", + "common.message.menu.validation02": "The same sort order exists.", + "common.message.menuCode.check01": "Registerable", + "common.message.menuCode.check02": "Unable to register", + "common.message.pleaseSelect": "Please Select {0}", + "common.message.pleaseInput": "Please Input a {0}.", + "common.message.pleaseInputOr": "Please Input a {0} or {1}.", + "common.message.approved ": "Approved.", + "common.message.errorFieldExist": "Error Field Exist", + "common.message.storeIdExist ": "이미 사용하고 있는 판매점 ID 입니다.", + "common.message.userIdExist ": "이미 사용하고 있는 사용자 ID 입니다.", + "common.message.noExists ": "삭제된 게시물 입니다.", + "common.message.emailReqTo": "Email To is required", + "common.message.downloadPeriod": "Please select the download search period within {0} days.", + "common.message.backToSubmit": "판매점 블록 해제를 실행하시겠습니까?", + "common.message.backToG3": "Back to G3 처리를 실행하시겠습니까?", + "common.message.writeToConfirm": "작성 해제를 실행하시겠습니까?", + "common.message.password.init.success": "비밀번호 [{0}]로 초기화 되었습니다.", + "common.message.no.edit.save": "This document cannot be changed." } diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 24697a02..ae020901 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -171,5 +171,5 @@ export const surfacePlacementModeState = atom({ // 오브젝트 배치 모드 export const objectPlacementModeState = atom({ key: 'objectPlacementMode', - default: { width: 0, height: 0, areaBoundary: true, inputType: 'free', batchType: 'opening' }, + default: { width: 0, height: 0, areaBoundary: false, inputType: 'free', batchType: 'opening' }, }) diff --git a/src/util/qpolygon-utils.js b/src/util/qpolygon-utils.js index 5e00b197..8d8a28ec 100644 --- a/src/util/qpolygon-utils.js +++ b/src/util/qpolygon-utils.js @@ -2714,6 +2714,12 @@ export const drawDirectionArrow = (polygon) => { if (!direction) { return } + + polygon.canvas + .getObjects() + .filter((obj) => obj.name === 'directionText' && obj.parent === polygon.arrow) + .forEach((obj) => polygon.canvas.remove(obj)) + let arrow = null let points = [] @@ -2721,13 +2727,13 @@ export const drawDirectionArrow = (polygon) => { polygon.canvas.remove(polygon.arrow) } - let centerPoint = polygon.getCenterPoint() + let centerPoint = { x: polygon.width / 2 + polygon.left, y: polygon.height / 2 + polygon.top } let stickeyPoint - const polygonMaxX = Math.max(...polygon.points.map((point) => point.x)) - const polygonMinX = Math.min(...polygon.points.map((point) => point.x)) - const polygonMaxY = Math.max(...polygon.points.map((point) => point.y)) - const polygonMinY = Math.min(...polygon.points.map((point) => point.y)) + const polygonMaxX = Math.max(...polygon.getCurrentPoints().map((point) => point.x)) + const polygonMinX = Math.min(...polygon.getCurrentPoints().map((point) => point.x)) + const polygonMaxY = Math.max(...polygon.getCurrentPoints().map((point) => point.y)) + const polygonMinY = Math.min(...polygon.getCurrentPoints().map((point) => point.y)) switch (direction) { case 'north': @@ -2800,6 +2806,7 @@ export const drawDirectionArrow = (polygon) => { polygon.arrow = arrow polygon.canvas.add(arrow) polygon.canvas.renderAll() + drawDirectionStringToArrow(polygon.canvas, 0) } /** @@ -2807,7 +2814,7 @@ export const drawDirectionArrow = (polygon) => { * @param canvas * @param compass */ -export const drawDirectionStringToArrow = (canvas, compass, fontSize) => { +export const drawDirectionStringToArrow = (canvas, compass = 0) => { const arrows = canvas?.getObjects().filter((obj) => obj.name === 'arrow') if (arrows.length === 0) { @@ -3000,8 +3007,10 @@ const addTextByArrows = (arrows, txt, canvas) => { originX: 'center', originY: 'center', name: 'directionText', + selectable: false, left: arrow.stickeyPoint.x, top: arrow.stickeyPoint.y, + parent: arrow, }) canvas.add(text) })