File upload
parent
2bdae49425
commit
aabae53e5d
|
@ -1,4 +1,6 @@
|
||||||
import {
|
import {
|
||||||
|
basicAuth,
|
||||||
|
encodeBase64,
|
||||||
fetchLinesIterator,
|
fetchLinesIterator,
|
||||||
maybeWithBasicAuth,
|
maybeWithBasicAuth,
|
||||||
topicShortUrl,
|
topicShortUrl,
|
||||||
|
@ -42,6 +44,43 @@ class Api {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishXHR(baseUrl, topic, body, headers, onProgress) {
|
||||||
|
const url = topicUrl(baseUrl, topic);
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
console.log(`[Api] Publishing message to ${url}`);
|
||||||
|
const send = new Promise(function (resolve, reject) {
|
||||||
|
xhr.open("PUT", url);
|
||||||
|
xhr.addEventListener('readystatechange', (ev) => {
|
||||||
|
if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 299) {
|
||||||
|
console.log(`[Api] Publish successful`, ev);
|
||||||
|
resolve(xhr.response);
|
||||||
|
} else if (xhr.readyState === 4) {
|
||||||
|
console.log(`[Api] Publish failed (1)`, ev);
|
||||||
|
xhr.abort();
|
||||||
|
reject(ev);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
xhr.onerror = (ev) => {
|
||||||
|
console.log(`[Api] Publish failed (2)`, ev);
|
||||||
|
reject(ev);
|
||||||
|
};
|
||||||
|
xhr.upload.addEventListener("progress", onProgress);
|
||||||
|
if (body.type) {
|
||||||
|
xhr.overrideMimeType(body.type);
|
||||||
|
}
|
||||||
|
for (const [key, value] of Object.entries(headers)) {
|
||||||
|
xhr.setRequestHeader(key, value);
|
||||||
|
}
|
||||||
|
xhr.send(body);
|
||||||
|
});
|
||||||
|
send.abort = () => {
|
||||||
|
console.log(`[Api] Publish aborted by user`);
|
||||||
|
xhr.abort();
|
||||||
|
}
|
||||||
|
return send;
|
||||||
|
}
|
||||||
|
|
||||||
async auth(baseUrl, topic, user) {
|
async auth(baseUrl, topic, user) {
|
||||||
const url = topicUrlAuth(baseUrl, topic);
|
const url = topicUrlAuth(baseUrl, topic);
|
||||||
console.log(`[Api] Checking auth for ${url}`);
|
console.log(`[Api] Checking auth for ${url}`);
|
||||||
|
|
|
@ -18,7 +18,7 @@ import IconButton from "@mui/material/IconButton";
|
||||||
import InsertEmoticonIcon from '@mui/icons-material/InsertEmoticon';
|
import InsertEmoticonIcon from '@mui/icons-material/InsertEmoticon';
|
||||||
import {Close} from "@mui/icons-material";
|
import {Close} from "@mui/icons-material";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import {formatBytes, shortUrl, splitNoEmpty, splitTopicUrl, validTopicUrl} from "../app/utils";
|
import {basicAuth, formatBytes, shortUrl, splitNoEmpty, splitTopicUrl, validTopicUrl} from "../app/utils";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import DialogFooter from "./DialogFooter";
|
import DialogFooter from "./DialogFooter";
|
||||||
|
@ -26,6 +26,7 @@ import api from "../app/Api";
|
||||||
import Divider from "@mui/material/Divider";
|
import Divider from "@mui/material/Divider";
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import CheckIcon from '@mui/icons-material/Check';
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
|
import userManager from "../app/UserManager";
|
||||||
|
|
||||||
const SendDialog = (props) => {
|
const SendDialog = (props) => {
|
||||||
const [topicUrl, setTopicUrl] = useState(props.topicUrl);
|
const [topicUrl, setTopicUrl] = useState(props.topicUrl);
|
||||||
|
@ -50,7 +51,9 @@ const SendDialog = (props) => {
|
||||||
const showAttachFile = !!attachFile && !showAttachUrl;
|
const showAttachFile = !!attachFile && !showAttachUrl;
|
||||||
const attachFileInput = useRef();
|
const attachFileInput = useRef();
|
||||||
|
|
||||||
const [errorText, setErrorText] = useState("");
|
const [sendRequest, setSendRequest] = useState(null);
|
||||||
|
const [statusText, setStatusText] = useState("");
|
||||||
|
const disabled = !!sendRequest;
|
||||||
|
|
||||||
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
const sendButtonEnabled = (() => {
|
const sendButtonEnabled = (() => {
|
||||||
|
@ -61,38 +64,59 @@ const SendDialog = (props) => {
|
||||||
})();
|
})();
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
const { baseUrl, topic } = splitTopicUrl(topicUrl);
|
const { baseUrl, topic } = splitTopicUrl(topicUrl);
|
||||||
const options = {};
|
const headers = {};
|
||||||
if (title.trim()) {
|
if (title.trim()) {
|
||||||
options["title"] = title.trim();
|
headers["X-Title"] = title.trim();
|
||||||
}
|
}
|
||||||
if (tags.trim()) {
|
if (tags.trim()) {
|
||||||
options["tags"] = splitNoEmpty(tags, ",");
|
headers["X-Tags"] = tags.trim();
|
||||||
}
|
}
|
||||||
if (priority && priority !== 3) {
|
if (priority && priority !== 3) {
|
||||||
options["priority"] = priority;
|
headers["X-Priority"] = priority.toString();
|
||||||
}
|
}
|
||||||
if (clickUrl.trim()) {
|
if (clickUrl.trim()) {
|
||||||
options["click"] = clickUrl.trim();
|
headers["X-Click"] = clickUrl.trim();
|
||||||
}
|
}
|
||||||
if (attachUrl.trim()) {
|
if (attachUrl.trim()) {
|
||||||
options["attach"] = attachUrl.trim();
|
headers["X-Attach"] = attachUrl.trim();
|
||||||
}
|
}
|
||||||
if (filename.trim()) {
|
if (filename.trim()) {
|
||||||
options["filename"] = filename.trim();
|
headers["X-Filename"] = filename.trim();
|
||||||
}
|
}
|
||||||
if (email.trim()) {
|
if (email.trim()) {
|
||||||
options["email"] = email.trim();
|
headers["X-Email"] = email.trim();
|
||||||
}
|
}
|
||||||
if (delay.trim()) {
|
if (delay.trim()) {
|
||||||
options["delay"] = delay.trim();
|
headers["X-Delay"] = delay.trim();
|
||||||
}
|
}
|
||||||
|
if (attachFile && message.trim()) {
|
||||||
|
headers["X-Message"] = message.replaceAll("\n", "\\n").trim();
|
||||||
|
}
|
||||||
|
const body = (attachFile) ? attachFile : message;
|
||||||
try {
|
try {
|
||||||
const response = await api.publish(baseUrl, topic, message, options);
|
const user = await userManager.get(baseUrl);
|
||||||
console.log(response);
|
if (user) {
|
||||||
props.onClose();
|
headers["Authorization"] = basicAuth(user.username, user.password);
|
||||||
} catch (e) {
|
|
||||||
setErrorText(e);
|
|
||||||
}
|
}
|
||||||
|
const progressFn = (ev) => {
|
||||||
|
console.log(ev);
|
||||||
|
if (ev.loaded > 0 && ev.total > 0) {
|
||||||
|
const percent = Math.round(ev.loaded * 100.0 / ev.total);
|
||||||
|
setStatusText(`Uploading ${formatBytes(ev.loaded)}/${formatBytes(ev.total)} (${percent}%) ...`);
|
||||||
|
} else {
|
||||||
|
setStatusText(`Uploading ...`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const request = api.publishXHR(baseUrl, topic, body, headers, progressFn);
|
||||||
|
setSendRequest(request);
|
||||||
|
await request;
|
||||||
|
setStatusText("Message published");
|
||||||
|
//props.onClose();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("error", e);
|
||||||
|
setStatusText("An error occurred");
|
||||||
|
}
|
||||||
|
setSendRequest(null);
|
||||||
};
|
};
|
||||||
const handleAttachFileClick = () => {
|
const handleAttachFileClick = () => {
|
||||||
attachFileInput.current.click();
|
attachFileInput.current.click();
|
||||||
|
@ -109,7 +133,7 @@ const SendDialog = (props) => {
|
||||||
<DialogTitle>Publish to {shortUrl(topicUrl)}</DialogTitle>
|
<DialogTitle>Publish to {shortUrl(topicUrl)}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
{showTopicUrl &&
|
{showTopicUrl &&
|
||||||
<ClosableRow onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setTopicUrl(props.topicUrl);
|
setTopicUrl(props.topicUrl);
|
||||||
setShowTopicUrl(false);
|
setShowTopicUrl(false);
|
||||||
}}>
|
}}>
|
||||||
|
@ -118,6 +142,7 @@ const SendDialog = (props) => {
|
||||||
label="Topic URL"
|
label="Topic URL"
|
||||||
value={topicUrl}
|
value={topicUrl}
|
||||||
onChange={ev => setTopicUrl(ev.target.value)}
|
onChange={ev => setTopicUrl(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
@ -130,6 +155,7 @@ const SendDialog = (props) => {
|
||||||
label="Title"
|
label="Title"
|
||||||
value={title}
|
value={title}
|
||||||
onChange={ev => setTitle(ev.target.value)}
|
onChange={ev => setTitle(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="standard"
|
variant="standard"
|
||||||
|
@ -141,6 +167,7 @@ const SendDialog = (props) => {
|
||||||
placeholder="Type the main message body here."
|
placeholder="Type the main message body here."
|
||||||
value={message}
|
value={message}
|
||||||
onChange={ev => setMessage(ev.target.value)}
|
onChange={ev => setMessage(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
rows={5}
|
rows={5}
|
||||||
|
@ -149,13 +176,14 @@ const SendDialog = (props) => {
|
||||||
multiline
|
multiline
|
||||||
/>
|
/>
|
||||||
<div style={{display: 'flex'}}>
|
<div style={{display: 'flex'}}>
|
||||||
<DialogIconButton onClick={() => null}><InsertEmoticonIcon/></DialogIconButton>
|
<DialogIconButton disabled={disabled} onClick={() => null}><InsertEmoticonIcon/></DialogIconButton>
|
||||||
<TextField
|
<TextField
|
||||||
margin="dense"
|
margin="dense"
|
||||||
label="Tags"
|
label="Tags"
|
||||||
placeholder="Comma-separated list of tags, e.g. warning, srv1-backup"
|
placeholder="Comma-separated list of tags, e.g. warning, srv1-backup"
|
||||||
value={tags}
|
value={tags}
|
||||||
onChange={ev => setTags(ev.target.value)}
|
onChange={ev => setTags(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
sx={{flexGrow: 1, marginRight: 1}}
|
sx={{flexGrow: 1, marginRight: 1}}
|
||||||
|
@ -171,6 +199,7 @@ const SendDialog = (props) => {
|
||||||
margin="dense"
|
margin="dense"
|
||||||
value={priority}
|
value={priority}
|
||||||
onChange={(ev) => setPriority(ev.target.value)}
|
onChange={(ev) => setPriority(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{[5,4,3,2,1].map(priority =>
|
{[5,4,3,2,1].map(priority =>
|
||||||
<MenuItem value={priority}>
|
<MenuItem value={priority}>
|
||||||
|
@ -184,7 +213,7 @@ const SendDialog = (props) => {
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
{showClickUrl &&
|
{showClickUrl &&
|
||||||
<ClosableRow onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setClickUrl("");
|
setClickUrl("");
|
||||||
setShowClickUrl(false);
|
setShowClickUrl(false);
|
||||||
}}>
|
}}>
|
||||||
|
@ -194,6 +223,7 @@ const SendDialog = (props) => {
|
||||||
placeholder="URL that is opened when notification is clicked"
|
placeholder="URL that is opened when notification is clicked"
|
||||||
value={clickUrl}
|
value={clickUrl}
|
||||||
onChange={ev => setClickUrl(ev.target.value)}
|
onChange={ev => setClickUrl(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="url"
|
type="url"
|
||||||
fullWidth
|
fullWidth
|
||||||
variant="standard"
|
variant="standard"
|
||||||
|
@ -201,7 +231,7 @@ const SendDialog = (props) => {
|
||||||
</ClosableRow>
|
</ClosableRow>
|
||||||
}
|
}
|
||||||
{showEmail &&
|
{showEmail &&
|
||||||
<ClosableRow onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setEmail("");
|
setEmail("");
|
||||||
setShowEmail(false);
|
setShowEmail(false);
|
||||||
}}>
|
}}>
|
||||||
|
@ -211,6 +241,7 @@ const SendDialog = (props) => {
|
||||||
placeholder="Address to forward the message to, e.g. phil@example.com"
|
placeholder="Address to forward the message to, e.g. phil@example.com"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={ev => setEmail(ev.target.value)}
|
onChange={ev => setEmail(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="email"
|
type="email"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
@ -218,7 +249,7 @@ const SendDialog = (props) => {
|
||||||
</ClosableRow>
|
</ClosableRow>
|
||||||
}
|
}
|
||||||
{showAttachUrl &&
|
{showAttachUrl &&
|
||||||
<ClosableRow onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setAttachUrl("");
|
setAttachUrl("");
|
||||||
setFilename("");
|
setFilename("");
|
||||||
setFilenameEdited(false);
|
setFilenameEdited(false);
|
||||||
|
@ -244,6 +275,7 @@ const SendDialog = (props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
disabled={disabled}
|
||||||
type="url"
|
type="url"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
sx={{flexGrow: 5, marginRight: 1}}
|
sx={{flexGrow: 5, marginRight: 1}}
|
||||||
|
@ -257,6 +289,7 @@ const SendDialog = (props) => {
|
||||||
setFilename(ev.target.value);
|
setFilename(ev.target.value);
|
||||||
setFilenameEdited(true);
|
setFilenameEdited(true);
|
||||||
}}
|
}}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
sx={{flexGrow: 1}}
|
sx={{flexGrow: 1}}
|
||||||
|
@ -272,6 +305,7 @@ const SendDialog = (props) => {
|
||||||
{showAttachFile && <AttachmentBox
|
{showAttachFile && <AttachmentBox
|
||||||
file={attachFile}
|
file={attachFile}
|
||||||
filename={filename}
|
filename={filename}
|
||||||
|
disabled={disabled}
|
||||||
onChangeFilename={(f) => setFilename(f)}
|
onChangeFilename={(f) => setFilename(f)}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setAttachFile(null);
|
setAttachFile(null);
|
||||||
|
@ -279,7 +313,7 @@ const SendDialog = (props) => {
|
||||||
}}
|
}}
|
||||||
/>}
|
/>}
|
||||||
{showDelay &&
|
{showDelay &&
|
||||||
<ClosableRow onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setDelay("");
|
setDelay("");
|
||||||
setShowDelay(false);
|
setShowDelay(false);
|
||||||
}}>
|
}}>
|
||||||
|
@ -289,6 +323,7 @@ const SendDialog = (props) => {
|
||||||
placeholder="Unix timestamp, duration or English natural language"
|
placeholder="Unix timestamp, duration or English natural language"
|
||||||
value={delay}
|
value={delay}
|
||||||
onChange={ev => setDelay(ev.target.value)}
|
onChange={ev => setDelay(ev.target.value)}
|
||||||
|
disabled={disabled}
|
||||||
type="text"
|
type="text"
|
||||||
variant="standard"
|
variant="standard"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
@ -299,21 +334,26 @@ const SendDialog = (props) => {
|
||||||
Other features:
|
Other features:
|
||||||
</Typography>
|
</Typography>
|
||||||
<div>
|
<div>
|
||||||
{!showClickUrl && <Chip clickable label="Click URL" onClick={() => setShowClickUrl(true)} sx={{marginRight: 1}}/>}
|
{!showClickUrl && <Chip clickable disabled={disabled} label="Click URL" onClick={() => setShowClickUrl(true)} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
{!showEmail && <Chip clickable label="Forward to email" onClick={() => setShowEmail(true)} sx={{marginRight: 1}}/>}
|
{!showEmail && <Chip clickable disabled={disabled} label="Forward to email" onClick={() => setShowEmail(true)} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
{!showAttachUrl && !showAttachFile && <Chip clickable label="Attach file by URL" onClick={() => setShowAttachUrl(true)} sx={{marginRight: 1}}/>}
|
{!showAttachUrl && !showAttachFile && <Chip clickable disabled={disabled} label="Attach file by URL" onClick={() => setShowAttachUrl(true)} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
{!showAttachFile && !showAttachUrl && <Chip clickable label="Attach local file" onClick={() => handleAttachFileClick()} sx={{marginRight: 1}}/>}
|
{!showAttachFile && !showAttachUrl && <Chip clickable disabled={disabled} label="Attach local file" onClick={() => handleAttachFileClick()} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
{!showDelay && <Chip clickable label="Delay delivery" onClick={() => setShowDelay(true)} sx={{marginRight: 1}}/>}
|
{!showDelay && <Chip clickable disabled={disabled} label="Delay delivery" onClick={() => setShowDelay(true)} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
{!showTopicUrl && <Chip clickable label="Change topic" onClick={() => setShowTopicUrl(true)} sx={{marginRight: 1}}/>}
|
{!showTopicUrl && <Chip clickable disabled={disabled} label="Change topic" onClick={() => setShowTopicUrl(true)} sx={{marginRight: 1, marginBottom: 1}}/>}
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="body1" sx={{marginTop: 2, marginBottom: 1}}>
|
<Typography variant="body1" sx={{marginTop: 1, marginBottom: 1}}>
|
||||||
For examples and a detailed description of all send features, please
|
For examples and a detailed description of all send features, please
|
||||||
refer to the <Link href="/docs">documentation</Link>.
|
refer to the <Link href="/docs">documentation</Link>.
|
||||||
</Typography>
|
</Typography>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogFooter status={errorText}>
|
<DialogFooter status={statusText}>
|
||||||
|
{sendRequest && <Button onClick={() => sendRequest.abort()}>Cancel sending</Button>}
|
||||||
|
{!sendRequest &&
|
||||||
|
<>
|
||||||
<Button onClick={props.onClose}>Cancel</Button>
|
<Button onClick={props.onClose}>Cancel</Button>
|
||||||
<Button onClick={handleSubmit} disabled={!sendButtonEnabled}>Send</Button>
|
<Button onClick={handleSubmit} disabled={!sendButtonEnabled}>Send</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
@ -331,7 +371,7 @@ const ClosableRow = (props) => {
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
{props.children}
|
{props.children}
|
||||||
<DialogIconButton onClick={props.onClose} sx={{marginLeft: "6px"}}><Close/></DialogIconButton>
|
<DialogIconButton disabled={props.disabled} onClick={props.onClose} sx={{marginLeft: "6px"}}><Close/></DialogIconButton>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -345,6 +385,7 @@ const DialogIconButton = (props) => {
|
||||||
edge="start"
|
edge="start"
|
||||||
sx={{height: "45px", marginTop: "17px", ...sx}}
|
sx={{height: "45px", marginTop: "17px", ...sx}}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
|
disabled={props.disabled}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -371,11 +412,12 @@ const AttachmentBox = (props) => {
|
||||||
variant="body2"
|
variant="body2"
|
||||||
value={props.filename}
|
value={props.filename}
|
||||||
onChange={(ev) => props.onChangeFilename(ev.target.value)}
|
onChange={(ev) => props.onChangeFilename(ev.target.value)}
|
||||||
|
disabled={props.disabled}
|
||||||
/>
|
/>
|
||||||
<br/>
|
<br/>
|
||||||
{formatBytes(file.size)}
|
{formatBytes(file.size)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<DialogIconButton onClick={props.onClose} sx={{marginLeft: "6px"}}><Close/></DialogIconButton>
|
<DialogIconButton disabled={props.disabled} onClick={props.onClose} sx={{marginLeft: "6px"}}><Close/></DialogIconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -414,6 +456,7 @@ const ExpandingTextField = (props) => {
|
||||||
sx={{ width: `${textWidth}px`, borderBottom: "none" }}
|
sx={{ width: `${textWidth}px`, borderBottom: "none" }}
|
||||||
InputProps={{ style: { fontSize: theme.typography[props.variant].fontSize } }}
|
InputProps={{ style: { fontSize: theme.typography[props.variant].fontSize } }}
|
||||||
inputProps={{ style: { paddingBottom: 0, paddingTop: 0 } }}
|
inputProps={{ style: { paddingBottom: 0, paddingTop: 0 } }}
|
||||||
|
disabled={props.disabled}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue