Continued work on send dialog and drag and drop
This commit is contained in:
parent
2c8b258ae7
commit
f98743dd9b
5 changed files with 145 additions and 100 deletions
|
@ -34,7 +34,6 @@ var (
|
||||||
errHTTPBadRequestTopicInvalid = &errHTTP{40009, http.StatusBadRequest, "invalid topic: path invalid", ""}
|
errHTTPBadRequestTopicInvalid = &errHTTP{40009, http.StatusBadRequest, "invalid topic: path invalid", ""}
|
||||||
errHTTPBadRequestTopicDisallowed = &errHTTP{40010, http.StatusBadRequest, "invalid topic: topic name is disallowed", ""}
|
errHTTPBadRequestTopicDisallowed = &errHTTP{40010, http.StatusBadRequest, "invalid topic: topic name is disallowed", ""}
|
||||||
errHTTPBadRequestMessageNotUTF8 = &errHTTP{40011, http.StatusBadRequest, "invalid message: message must be UTF-8 encoded", ""}
|
errHTTPBadRequestMessageNotUTF8 = &errHTTP{40011, http.StatusBadRequest, "invalid message: message must be UTF-8 encoded", ""}
|
||||||
errHTTPBadRequestAttachmentTooLarge = &errHTTP{40012, http.StatusBadRequest, "invalid request: attachment too large, or bandwidth limit reached", ""}
|
|
||||||
errHTTPBadRequestAttachmentURLInvalid = &errHTTP{40013, http.StatusBadRequest, "invalid request: attachment URL is invalid", "https://ntfy.sh/docs/publish/#attachments"}
|
errHTTPBadRequestAttachmentURLInvalid = &errHTTP{40013, http.StatusBadRequest, "invalid request: attachment URL is invalid", "https://ntfy.sh/docs/publish/#attachments"}
|
||||||
errHTTPBadRequestAttachmentsDisallowed = &errHTTP{40014, http.StatusBadRequest, "invalid request: attachments not allowed", "https://ntfy.sh/docs/config/#attachments"}
|
errHTTPBadRequestAttachmentsDisallowed = &errHTTP{40014, http.StatusBadRequest, "invalid request: attachments not allowed", "https://ntfy.sh/docs/config/#attachments"}
|
||||||
errHTTPBadRequestAttachmentsExpiryBeforeDelivery = &errHTTP{40015, http.StatusBadRequest, "invalid request: attachment expiry before delayed delivery date", "https://ntfy.sh/docs/publish/#scheduled-delivery"}
|
errHTTPBadRequestAttachmentsExpiryBeforeDelivery = &errHTTP{40015, http.StatusBadRequest, "invalid request: attachment expiry before delayed delivery date", "https://ntfy.sh/docs/publish/#scheduled-delivery"}
|
||||||
|
@ -43,6 +42,7 @@ var (
|
||||||
errHTTPNotFound = &errHTTP{40401, http.StatusNotFound, "page not found", ""}
|
errHTTPNotFound = &errHTTP{40401, http.StatusNotFound, "page not found", ""}
|
||||||
errHTTPUnauthorized = &errHTTP{40101, http.StatusUnauthorized, "unauthorized", "https://ntfy.sh/docs/publish/#authentication"}
|
errHTTPUnauthorized = &errHTTP{40101, http.StatusUnauthorized, "unauthorized", "https://ntfy.sh/docs/publish/#authentication"}
|
||||||
errHTTPForbidden = &errHTTP{40301, http.StatusForbidden, "forbidden", "https://ntfy.sh/docs/publish/#authentication"}
|
errHTTPForbidden = &errHTTP{40301, http.StatusForbidden, "forbidden", "https://ntfy.sh/docs/publish/#authentication"}
|
||||||
|
errHTTPEntityTooLargeAttachmentTooLarge = &errHTTP{41301, http.StatusRequestEntityTooLarge, "attachment too large, or bandwidth limit reached", ""}
|
||||||
errHTTPTooManyRequestsLimitRequests = &errHTTP{42901, http.StatusTooManyRequests, "limit reached: too many requests, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
errHTTPTooManyRequestsLimitRequests = &errHTTP{42901, http.StatusTooManyRequests, "limit reached: too many requests, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
||||||
errHTTPTooManyRequestsLimitEmails = &errHTTP{42902, http.StatusTooManyRequests, "limit reached: too many emails, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
errHTTPTooManyRequestsLimitEmails = &errHTTP{42902, http.StatusTooManyRequests, "limit reached: too many emails, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
||||||
errHTTPTooManyRequestsLimitSubscriptions = &errHTTP{42903, http.StatusTooManyRequests, "limit reached: too many active subscriptions, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
errHTTPTooManyRequestsLimitSubscriptions = &errHTTP{42903, http.StatusTooManyRequests, "limit reached: too many active subscriptions, please be nice", "https://ntfy.sh/docs/publish/#limitations"}
|
||||||
|
|
|
@ -395,6 +395,7 @@ func (s *Server) handlePublish(w http.ResponseWriter, r *http.Request, v *visito
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
return errHTTPEntityTooLargeAttachmentTooLarge
|
||||||
body, err := util.Peak(r.Body, s.config.MessageLimit)
|
body, err := util.Peak(r.Body, s.config.MessageLimit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -590,7 +591,7 @@ func (s *Server) handleBodyAsAttachment(r *http.Request, v *visitor, m *message,
|
||||||
if contentLengthStr != "" { // Early "do-not-trust" check, hard limit see below
|
if contentLengthStr != "" { // Early "do-not-trust" check, hard limit see below
|
||||||
contentLength, err := strconv.ParseInt(contentLengthStr, 10, 64)
|
contentLength, err := strconv.ParseInt(contentLengthStr, 10, 64)
|
||||||
if err == nil && (contentLength > remainingVisitorAttachmentSize || contentLength > s.config.AttachmentFileSizeLimit) {
|
if err == nil && (contentLength > remainingVisitorAttachmentSize || contentLength > s.config.AttachmentFileSizeLimit) {
|
||||||
return errHTTPBadRequestAttachmentTooLarge
|
return errHTTPEntityTooLargeAttachmentTooLarge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m.Attachment == nil {
|
if m.Attachment == nil {
|
||||||
|
@ -609,7 +610,7 @@ func (s *Server) handleBodyAsAttachment(r *http.Request, v *visitor, m *message,
|
||||||
}
|
}
|
||||||
m.Attachment.Size, err = s.fileCache.Write(m.ID, body, v.BandwidthLimiter(), util.NewFixedLimiter(remainingVisitorAttachmentSize))
|
m.Attachment.Size, err = s.fileCache.Write(m.ID, body, v.BandwidthLimiter(), util.NewFixedLimiter(remainingVisitorAttachmentSize))
|
||||||
if err == util.ErrLimitReached {
|
if err == util.ErrLimitReached {
|
||||||
return errHTTPBadRequestAttachmentTooLarge
|
return errHTTPEntityTooLargeAttachmentTooLarge
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,19 +52,16 @@ class Api {
|
||||||
const send = new Promise(function (resolve, reject) {
|
const send = new Promise(function (resolve, reject) {
|
||||||
xhr.open("PUT", url);
|
xhr.open("PUT", url);
|
||||||
xhr.addEventListener('readystatechange', (ev) => {
|
xhr.addEventListener('readystatechange', (ev) => {
|
||||||
|
console.log("read change", xhr.readyState, xhr.status, xhr.responseText, xhr)
|
||||||
if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 299) {
|
if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status <= 299) {
|
||||||
console.log(`[Api] Publish successful`, ev);
|
console.log(`[Api] Publish successful (HTTP ${xhr.status})`, xhr.response);
|
||||||
resolve(xhr.response);
|
resolve(xhr.response);
|
||||||
} else if (xhr.readyState === 4) {
|
} else if (xhr.readyState === 4) {
|
||||||
console.log(`[Api] Publish failed (1)`, ev);
|
console.log(`[Api] Publish failed`, xhr.status, xhr.responseText, xhr);
|
||||||
xhr.abort();
|
xhr.abort();
|
||||||
reject(ev);
|
reject(ev);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
xhr.onerror = (ev) => {
|
|
||||||
console.log(`[Api] Publish failed (2)`, ev);
|
|
||||||
reject(ev);
|
|
||||||
};
|
|
||||||
xhr.upload.addEventListener("progress", onProgress);
|
xhr.upload.addEventListener("progress", onProgress);
|
||||||
if (body.type) {
|
if (body.type) {
|
||||||
xhr.overrideMimeType(body.type);
|
xhr.overrideMimeType(body.type);
|
||||||
|
|
|
@ -82,7 +82,6 @@ const Layout = () => {
|
||||||
return (
|
return (
|
||||||
<Box sx={{display: 'flex'}}>
|
<Box sx={{display: 'flex'}}>
|
||||||
<CssBaseline/>
|
<CssBaseline/>
|
||||||
<DropZone/>
|
|
||||||
<ActionBar
|
<ActionBar
|
||||||
selected={selected}
|
selected={selected}
|
||||||
onMobileDrawerToggle={() => setMobileDrawerOpen(!mobileDrawerOpen)}
|
onMobileDrawerToggle={() => setMobileDrawerOpen(!mobileDrawerOpen)}
|
||||||
|
@ -99,7 +98,7 @@ const Layout = () => {
|
||||||
<Toolbar/>
|
<Toolbar/>
|
||||||
<Outlet context={{ subscriptions, selected }}/>
|
<Outlet context={{ subscriptions, selected }}/>
|
||||||
</Main>
|
</Main>
|
||||||
<Sender selected={selected}/>
|
<Messaging selected={selected}/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -125,79 +124,28 @@ const Main = (props) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Sender = (props) => {
|
const Messaging = (props) => {
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [sendDialogKey, setSendDialogKey] = useState(0);
|
const [dialogKey, setDialogKey] = useState(0);
|
||||||
const [sendDialogOpen, setSendDialogOpen] = useState(false);
|
const [showDialog, setShowDialog] = useState(false);
|
||||||
const subscription = props.selected;
|
|
||||||
|
|
||||||
const handleSendClick = () => {
|
|
||||||
api.publish(subscription.baseUrl, subscription.topic, message); // FIXME
|
|
||||||
setMessage("");
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSendDialogClose = () => {
|
|
||||||
setSendDialogOpen(false);
|
|
||||||
setSendDialogKey(prev => prev+1);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!props.selected) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper
|
|
||||||
elevation={3}
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
position: 'fixed',
|
|
||||||
bottom: 0,
|
|
||||||
right: 0,
|
|
||||||
padding: 2,
|
|
||||||
width: `calc(100% - ${Navigation.width}px)`,
|
|
||||||
backgroundColor: (theme) => theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900]
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton color="inherit" size="large" edge="start" onClick={() => setSendDialogOpen(true)}>
|
|
||||||
<KeyboardArrowUpIcon/>
|
|
||||||
</IconButton>
|
|
||||||
<TextField
|
|
||||||
autoFocus
|
|
||||||
margin="dense"
|
|
||||||
placeholder="Message"
|
|
||||||
type="text"
|
|
||||||
fullWidth
|
|
||||||
variant="standard"
|
|
||||||
value={message}
|
|
||||||
onChange={ev => setMessage(ev.target.value)}
|
|
||||||
onKeyPress={(ev) => {
|
|
||||||
if (ev.key === 'Enter') {
|
|
||||||
ev.preventDefault();
|
|
||||||
handleSendClick();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<IconButton color="inherit" size="large" edge="end" onClick={handleSendClick}>
|
|
||||||
<SendIcon/>
|
|
||||||
</IconButton>
|
|
||||||
<SendDialog
|
|
||||||
key={`sendDialog${sendDialogKey}`} // Resets dialog when canceled/closed
|
|
||||||
open={sendDialogOpen}
|
|
||||||
onClose={handleSendDialogClose}
|
|
||||||
topicUrl={topicUrl(subscription.baseUrl, subscription.topic)}
|
|
||||||
message={message}
|
|
||||||
/>
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DropZone = (props) => {
|
|
||||||
const [showDropZone, setShowDropZone] = useState(false);
|
const [showDropZone, setShowDropZone] = useState(false);
|
||||||
|
|
||||||
|
const subscription = props.selected;
|
||||||
|
const selectedTopicUrl = (subscription) ? topicUrl(subscription.baseUrl, subscription.topic) : "";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('dragenter', () => setShowDropZone(true));
|
window.addEventListener('dragenter', () => {
|
||||||
|
setShowDialog(true);
|
||||||
|
setShowDropZone(true);
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const handleSendDialogClose = () => {
|
||||||
|
setShowDialog(false);
|
||||||
|
setShowDropZone(false);
|
||||||
|
setDialogKey(prev => prev+1);
|
||||||
|
};
|
||||||
|
|
||||||
const allowSubmit = () => true;
|
const allowSubmit = () => true;
|
||||||
|
|
||||||
const allowDrag = (e) => {
|
const allowDrag = (e) => {
|
||||||
|
@ -212,22 +160,68 @@ const DropZone = (props) => {
|
||||||
console.log(e.dataTransfer.files[0]);
|
console.log(e.dataTransfer.files[0]);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!showDropZone) {
|
return (
|
||||||
return null;
|
<>
|
||||||
|
{subscription && <MessageBar
|
||||||
|
subscription={subscription}
|
||||||
|
message={message}
|
||||||
|
onMessageChange={setMessage}
|
||||||
|
onOpenDialogClick={() => setShowDialog(true)}
|
||||||
|
/>}
|
||||||
|
<SendDialog
|
||||||
|
key={`sendDialog${dialogKey}`} // Resets dialog when canceled/closed
|
||||||
|
open={showDialog}
|
||||||
|
dropZone={showDropZone}
|
||||||
|
onClose={handleSendDialogClose}
|
||||||
|
topicUrl={selectedTopicUrl}
|
||||||
|
message={message}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MessageBar = (props) => {
|
||||||
|
const subscription = props.subscription;
|
||||||
|
const handleSendClick = () => {
|
||||||
|
api.publish(subscription.baseUrl, subscription.topic, props.message); // FIXME
|
||||||
|
props.onMessageChange("");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Backdrop
|
<Paper
|
||||||
sx={{ color: '#fff', zIndex: 3500 }}
|
elevation={3}
|
||||||
open={showDropZone}
|
sx={{
|
||||||
onClick={() => setShowDropZone(false)}
|
display: "flex",
|
||||||
onDragEnter={allowDrag}
|
position: 'fixed',
|
||||||
onDragOver={allowDrag}
|
bottom: 0,
|
||||||
onDragLeave={() => setShowDropZone(false)}
|
right: 0,
|
||||||
onDrop={handleDrop}
|
padding: 2,
|
||||||
|
width: `calc(100% - ${Navigation.width}px)`,
|
||||||
|
backgroundColor: (theme) => theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900]
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
|
<IconButton color="inherit" size="large" edge="start" onClick={props.onOpenDialogClick}>
|
||||||
</Backdrop>
|
<KeyboardArrowUpIcon/>
|
||||||
|
</IconButton>
|
||||||
|
<TextField
|
||||||
|
autoFocus
|
||||||
|
margin="dense"
|
||||||
|
placeholder="Message"
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
variant="standard"
|
||||||
|
value={props.message}
|
||||||
|
onChange={ev => props.onMessageChange(ev.target.value)}
|
||||||
|
onKeyPress={(ev) => {
|
||||||
|
if (ev.key === 'Enter') {
|
||||||
|
ev.preventDefault();
|
||||||
|
handleSendClick();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<IconButton color="inherit" size="large" edge="end" onClick={handleSendClick}>
|
||||||
|
<SendIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</Paper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ const SendDialog = (props) => {
|
||||||
const [delay, setDelay] = useState("");
|
const [delay, setDelay] = useState("");
|
||||||
const [publishAnother, setPublishAnother] = useState(false);
|
const [publishAnother, setPublishAnother] = useState(false);
|
||||||
|
|
||||||
const [showTopicUrl, setShowTopicUrl] = useState(props.topicUrl === "");
|
const [showTopicUrl, setShowTopicUrl] = useState(props.topicUrl === ""); // FIXME
|
||||||
const [showClickUrl, setShowClickUrl] = useState(false);
|
const [showClickUrl, setShowClickUrl] = useState(false);
|
||||||
const [showAttachUrl, setShowAttachUrl] = useState(false);
|
const [showAttachUrl, setShowAttachUrl] = useState(false);
|
||||||
const [showEmail, setShowEmail] = useState(false);
|
const [showEmail, setShowEmail] = useState(false);
|
||||||
|
@ -49,17 +49,21 @@ const SendDialog = (props) => {
|
||||||
const showAttachFile = !!attachFile && !showAttachUrl;
|
const showAttachFile = !!attachFile && !showAttachUrl;
|
||||||
const attachFileInput = useRef();
|
const attachFileInput = useRef();
|
||||||
|
|
||||||
const [sendRequest, setSendRequest] = useState(null);
|
const [activeRequest, setActiveRequest] = useState(null);
|
||||||
const [statusText, setStatusText] = useState("");
|
const [statusText, setStatusText] = useState("");
|
||||||
const disabled = !!sendRequest;
|
const disabled = !!activeRequest;
|
||||||
|
|
||||||
|
const dropZone = props.dropZone;
|
||||||
|
|
||||||
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
|
|
||||||
const sendButtonEnabled = (() => {
|
const sendButtonEnabled = (() => {
|
||||||
if (!validTopicUrl(topicUrl)) {
|
if (!validTopicUrl(topicUrl)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
const { baseUrl, topic } = splitTopicUrl(topicUrl);
|
const { baseUrl, topic } = splitTopicUrl(topicUrl);
|
||||||
const headers = {};
|
const headers = {};
|
||||||
|
@ -106,7 +110,7 @@ const SendDialog = (props) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const request = api.publishXHR(baseUrl, topic, body, headers, progressFn);
|
const request = api.publishXHR(baseUrl, topic, body, headers, progressFn);
|
||||||
setSendRequest(request);
|
setActiveRequest(request);
|
||||||
await request;
|
await request;
|
||||||
if (!publishAnother) {
|
if (!publishAnother) {
|
||||||
props.onClose();
|
props.onClose();
|
||||||
|
@ -117,11 +121,13 @@ const SendDialog = (props) => {
|
||||||
console.log("error", e);
|
console.log("error", e);
|
||||||
setStatusText("An error occurred");
|
setStatusText("An error occurred");
|
||||||
}
|
}
|
||||||
setSendRequest(null);
|
setActiveRequest(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAttachFileClick = () => {
|
const handleAttachFileClick = () => {
|
||||||
attachFileInput.current.click();
|
attachFileInput.current.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAttachFileChanged = (ev) => {
|
const handleAttachFileChanged = (ev) => {
|
||||||
const file = ev.target.files[0];
|
const file = ev.target.files[0];
|
||||||
setAttachFile(file);
|
setAttachFile(file);
|
||||||
|
@ -129,10 +135,57 @@ const SendDialog = (props) => {
|
||||||
console.log(ev.target.files[0]);
|
console.log(ev.target.files[0]);
|
||||||
console.log(URL.createObjectURL(ev.target.files[0]));
|
console.log(URL.createObjectURL(ev.target.files[0]));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDrop = (ev) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
const file = ev.dataTransfer.files[0];
|
||||||
|
setAttachFile(file);
|
||||||
|
setFilename(file.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
const allowDrag = (ev) => {
|
||||||
|
if (true /* allowSubmit */) {
|
||||||
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
|
ev.preventDefault();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog maxWidth="md" open={props.open} onClose={props.onCancel} fullScreen={fullScreen}>
|
<Dialog maxWidth="md" open={props.open} onClose={props.onCancel} fullScreen={fullScreen}>
|
||||||
<DialogTitle>Publish to {shortUrl(topicUrl)}</DialogTitle>
|
<DialogTitle>Publish to {shortUrl(topicUrl)}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
|
{dropZone &&
|
||||||
|
<Box sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
zIndex: 10000,
|
||||||
|
backgroundColor: "#ffffffbb"
|
||||||
|
}}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
border: '3px dashed #ccc',
|
||||||
|
borderRadius: '5px',
|
||||||
|
left: "40px",
|
||||||
|
top: "40px",
|
||||||
|
right: "40px",
|
||||||
|
bottom: "40px",
|
||||||
|
zIndex: 10001,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
onDrop={handleDrop}
|
||||||
|
onDragEnter={allowDrag}
|
||||||
|
onDragOver={allowDrag}
|
||||||
|
>
|
||||||
|
<Typography variant="h5">Drop file here</Typography>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
{showTopicUrl &&
|
{showTopicUrl &&
|
||||||
<ClosableRow disabled={disabled} onClose={() => {
|
<ClosableRow disabled={disabled} onClose={() => {
|
||||||
setTopicUrl(props.topicUrl);
|
setTopicUrl(props.topicUrl);
|
||||||
|
@ -203,7 +256,7 @@ const SendDialog = (props) => {
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{[5,4,3,2,1].map(priority =>
|
{[5,4,3,2,1].map(priority =>
|
||||||
<MenuItem value={priority}>
|
<MenuItem key={`priorityMenuItem${priority}`} value={priority}>
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<img src={priorities[priority].file} style={{marginRight: "8px"}}/>
|
<img src={priorities[priority].file} style={{marginRight: "8px"}}/>
|
||||||
<div>{priorities[priority].label}</div>
|
<div>{priorities[priority].label}</div>
|
||||||
|
@ -348,8 +401,8 @@ const SendDialog = (props) => {
|
||||||
</Typography>
|
</Typography>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogFooter status={statusText}>
|
<DialogFooter status={statusText}>
|
||||||
{sendRequest && <Button onClick={() => sendRequest.abort()}>Cancel sending</Button>}
|
{activeRequest && <Button onClick={() => activeRequest.abort()}>Cancel sending</Button>}
|
||||||
{!sendRequest &&
|
{!activeRequest &&
|
||||||
<>
|
<>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
label="Publish another"
|
label="Publish another"
|
||||||
|
|
Loading…
Reference in a new issue