176 lines
5.4 KiB
JavaScript
176 lines
5.4 KiB
JavaScript
import React, { useState, useEffect } from 'react'
|
||
|
||
function ModalData({ modalData, onClose, onSave }) {
|
||
const [inputValue, setInputValue] = useState('')
|
||
const [fromType, setFromType] = useState('INT')
|
||
const [toType, setToType] = useState('REAL')
|
||
|
||
useEffect(() => {
|
||
setInputValue('')
|
||
setFromType('INT')
|
||
setToType('REAL')
|
||
}, [modalData])
|
||
|
||
if (!modalData)
|
||
return null
|
||
|
||
function getTypeValue() {
|
||
const value = inputValue.toLowerCase().trim()
|
||
const timeRegex = /^(t|time)#(-)?\d+(d|h|m|s|ms)(\d+(d|h|m|s|ms))*/
|
||
const realRegex = /^-?\d+\.\d+$/
|
||
const intRegex = /^-?\d+$/
|
||
|
||
if (value === 'true' || value === 'false')
|
||
return 'BOOL'
|
||
if (timeRegex.test(value))
|
||
return 'TIME'
|
||
if (value.startsWith("'") && value.endsWith("'"))
|
||
return 'STRING'
|
||
if (realRegex.test(value))
|
||
return 'REAL'
|
||
if (intRegex.test(value)) {
|
||
const num = Number(value)
|
||
if (num >= -32768 && num <= 32767)
|
||
return 'INT'
|
||
if (num >= -2147483648 && num <= 2147483647)
|
||
return 'DINT'
|
||
}
|
||
return null
|
||
}
|
||
|
||
function handleConfirm() {
|
||
const trimmed = inputValue.trim()
|
||
|
||
if (modalData.type === 'const') {
|
||
if (trimmed === '') {
|
||
alert('Переменная пуста')
|
||
return
|
||
}
|
||
}
|
||
else if (trimmed === '' && (modalData.type === 'input' || modalData.type === 'output')) {
|
||
alert('Не заданно имя переменной')
|
||
return
|
||
}
|
||
|
||
if (modalData.type === 'const') {
|
||
const getedType = getTypeValue()
|
||
if (!getedType) {
|
||
alert('Не удалось получить тип переменной (не корректный ввод)')
|
||
return
|
||
}
|
||
onSave({
|
||
value: trimmed,
|
||
fromType: getedType,
|
||
toType: getedType
|
||
})
|
||
return
|
||
}
|
||
|
||
onSave({
|
||
value: trimmed,
|
||
fromType,
|
||
toType
|
||
})
|
||
}
|
||
|
||
function getWindowWithType() {
|
||
const types = ["BOOL", "INT", "DINT", "REAL", "STRING", "TIME"]
|
||
switch(modalData.type) {
|
||
case 'switch_type':
|
||
return(
|
||
<div style = {{ marginBottom: '15px' }}>
|
||
<label style = {{ fontSize: '12px', display: 'block', marginBottom: '5px' }}>Входной тип данных:</label>
|
||
<select
|
||
value = {fromType}
|
||
onChange={(e) => setFromType(e.target.value)}
|
||
style={{ width: '100%', padding: '6px', marginBottom: '10px' }}
|
||
>
|
||
{types.map((type) => (
|
||
<option key = {`from-${type}`} value = {type}>{type}</option>
|
||
))}
|
||
</select>
|
||
|
||
<label style = {{ fontSize: '12px', display: 'block', marginBottom: '5px' }}>Выходной тип данных:</label>
|
||
<select
|
||
value = {toType}
|
||
onChange={(e) => setToType(e.target.value)}
|
||
style={{ width: '100%', padding: '6px' }}
|
||
>
|
||
{types.map((type) => (
|
||
<option key = {`from-${type}`} value = {type}>{type}</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
)
|
||
case 'const':
|
||
return(
|
||
<div style = {{ marginBottom: '15px' }}>
|
||
<label style = {{ fontSize: '12px', display: 'block', marginBottom: '5px' }}>Значение константы:</label>
|
||
<input
|
||
type = "text"
|
||
value = {inputValue}
|
||
onChange = {(e) => setInputValue(e.target.value)}
|
||
style = {{ width: '100%', padding: '6px', boxSizing: 'border-box', marginBottom: '12px' }}
|
||
placeholder = {12.5}
|
||
autoFocus
|
||
/>
|
||
</div>
|
||
)
|
||
case 'input':
|
||
case 'output':
|
||
return(
|
||
<div style = {{ marginBottom: '15px' }}>
|
||
<label style = {{ fontSize: '12px', display: 'block', marginBottom: '5px' }}>Имя переменной/тега:</label>
|
||
<input
|
||
type = "text"
|
||
value = {inputValue}
|
||
onChange = {(e) => setInputValue(e.target.value)}
|
||
style = {{ width: '100%', padding: '6px', boxSizing: 'border-box', marginBottom: '12px' }}
|
||
placeholder = {'Name'}
|
||
autoFocus
|
||
/>
|
||
<label style = {{ fontSize: '12px', display: 'block', marginBottom: '5px' }}>Тип данных:</label>
|
||
<select
|
||
value = {fromType}
|
||
onChange = {(e) => setFromType(e.target.value)}
|
||
style = {{ width: '100%', padding: '6px' }}
|
||
>
|
||
{types.map((type) => (
|
||
<option key={`from-${type}`} value = {type}>{type}</option>
|
||
))}
|
||
</select>
|
||
</div>
|
||
)
|
||
default:
|
||
return;
|
||
}
|
||
}
|
||
|
||
return(
|
||
<div className = "modalDataBack">
|
||
<div className = "modalDataMain">
|
||
<h4 style = {{ marginTop: 0, marginBottom: '15px'}}>Настройка: {modalData.label}</h4>
|
||
{getWindowWithType()}
|
||
<div style = {{ display: 'flex', justifyContent: 'flex-end', gap: '10px', marginTop: '20px' }}>
|
||
<button
|
||
onClick = {onClose}
|
||
style = {{ padding: '6px 12px', cursor: 'pointer'}}
|
||
>Отмена</button>
|
||
<button
|
||
onClick = {handleConfirm}
|
||
style = {{
|
||
padding: '6px 12px',
|
||
background: '#1717D8',
|
||
color: 'white',
|
||
border: 'none',
|
||
borderRadius: '4px',
|
||
cursor: 'pointer'
|
||
}}
|
||
>ОК</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default ModalData |