Skip to content

Commit ed5f207

Browse files
committed
implement blob-based upload to markdown component (e.g., jupyter) in source mode
1 parent 4dcb1aa commit ed5f207

File tree

2 files changed

+27
-75
lines changed

2 files changed

+27
-75
lines changed

src/packages/frontend/editors/markdown-input/component.tsx

Lines changed: 26 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,8 @@
77
Markdown editor
88
*/
99

10-
// Note -- the old file upload used .chat-images for everything,
11-
// rather than a directory for each file.
12-
const AUX_FILE_EXT = "upload";
13-
1410
import * as CodeMirror from "codemirror";
1511
import { debounce, isEqual } from "lodash";
16-
import { join } from "path";
1712
import {
1813
CSSProperties,
1914
MutableRefObject,
@@ -25,7 +20,6 @@ import {
2520
useRef,
2621
useState,
2722
} from "react";
28-
2923
import { alert_message } from "@cocalc/frontend/alerts";
3024
import {
3125
ReactDOM,
@@ -36,21 +30,16 @@ import {
3630
import { SubmitMentionsRef } from "@cocalc/frontend/chat/types";
3731
import { A } from "@cocalc/frontend/components";
3832
import { IS_MOBILE } from "@cocalc/frontend/feature";
39-
import { Dropzone, FileUploadWrapper } from "@cocalc/frontend/file-upload";
33+
import { Dropzone, BlobUpload } from "@cocalc/frontend/file-upload";
4034
import { Cursors, CursorsType } from "@cocalc/frontend/jupyter/cursors";
4135
import Fragment, { FragmentId } from "@cocalc/frontend/misc/fragment-id";
4236
import { useProjectHasInternetAccess } from "@cocalc/frontend/project/settings/has-internet-access-hook";
43-
import {
44-
aux_file,
45-
len,
46-
path_split,
47-
trunc,
48-
trunc_middle,
49-
} from "@cocalc/util/misc";
37+
import { len, trunc, trunc_middle } from "@cocalc/util/misc";
5038
import { Complete, Item } from "./complete";
5139
import { useMentionableUsers } from "./mentionable-users";
5240
import { submit_mentions } from "./mentions";
5341
import { EditorFunctions } from "./multimode";
42+
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
5443

5544
type EventHandlerFunction = (cm: CodeMirror.Editor) => void;
5645

@@ -162,6 +151,7 @@ export function MarkdownInput(props: Props) {
162151
unregisterEditor,
163152
value,
164153
} = props;
154+
const { actions } = useFrameContext();
165155
const cm = useRef<CodeMirror.Editor>();
166156
const textarea_ref = useRef<HTMLTextAreaElement>(null);
167157
const editor_settings = useRedux(["account", "editor_settings"]);
@@ -579,7 +569,7 @@ export function MarkdownInput(props: Props) {
579569
}
580570
if (cm.current == null) return;
581571
const input = cm.current.getValue();
582-
const s = upload_temp_link(path, file);
572+
const s = upload_temp_link(file);
583573
if (input.indexOf(s) != -1) {
584574
// already have link.
585575
return;
@@ -588,11 +578,7 @@ export function MarkdownInput(props: Props) {
588578
saveValue();
589579
}
590580

591-
function upload_complete(file: {
592-
type: string;
593-
name: string;
594-
status: string;
595-
}): void {
581+
function upload_complete(file): void {
596582
if (path == null) {
597583
throw Error("path must be set if enableUploads is set.");
598584
}
@@ -608,7 +594,7 @@ export function MarkdownInput(props: Props) {
608594
}
609595
if (cm.current == null) return;
610596
const input = cm.current.getValue();
611-
const s0 = upload_temp_link(path, file);
597+
const s0 = upload_temp_link(file);
612598
let s1: string;
613599
if (file.status == "error") {
614600
s1 = "";
@@ -617,43 +603,13 @@ export function MarkdownInput(props: Props) {
617603
// users can cancel files when they are being uploaded.
618604
s1 = "";
619605
} else {
620-
s1 = upload_link(path, file);
606+
s1 = upload_link(file);
621607
}
622608
const newValue = input.replace(s0, s1);
623609
setValueNoJump(newValue);
624610
saveValue();
625611
}
626612

627-
function upload_removed(file: { name: string; type: string }): void {
628-
if (cm.current == null) return;
629-
if (project_id == null || path == null) {
630-
throw Error("project_id and path must be set if enableUploads is set.");
631-
}
632-
if (!current_uploads_ref.current?.[file.name]) {
633-
// it actually succeeded if this is not set -- it was removed
634-
// via upload_complete above.
635-
return;
636-
}
637-
delete current_uploads_ref.current[file.name];
638-
if (onUploadEnd != null) {
639-
onUploadEnd();
640-
}
641-
642-
const input = cm.current.getValue();
643-
const s = upload_link(path, file);
644-
if (input.indexOf(s) == -1) {
645-
// not there anymore; maybe user already submitted -- do nothing further.
646-
return;
647-
}
648-
const newValue = input.replace(s, "");
649-
setValueNoJump(newValue);
650-
saveValue();
651-
// delete from project itself
652-
const target = join(aux_file(path, AUX_FILE_EXT), file.name);
653-
// console.log("deleting target", target, { paths: [target] });
654-
redux.getProjectActions(project_id).delete_files({ paths: [target] });
655-
}
656-
657613
function handle_paste_event(_, e): void {
658614
// console.log("handle_paste_event", e);
659615
const items = e.clipboardData.items;
@@ -926,49 +882,45 @@ export function MarkdownInput(props: Props) {
926882
const event_handlers = {
927883
complete: upload_complete,
928884
sending: upload_sending,
929-
removedfile: upload_removed,
885+
error: (_, message) => {
886+
actions?.set_error(`${message}`);
887+
},
930888
};
931889
if (project_id == null || path == null) {
932890
throw Error("project_id and path must be set if enableUploads is set.");
933891
}
934892
body = (
935-
<FileUploadWrapper
893+
<BlobUpload
894+
show_upload={false}
936895
project_id={project_id}
937-
dest_path={aux_file(path, AUX_FILE_EXT)}
938896
event_handlers={event_handlers}
939897
style={{ height: "100%", width: "100%" }}
940898
dropzone_ref={dropzone_ref}
941899
close_preview_ref={upload_close_preview_ref}
900+
config={
901+
// only images work since when pasting other doc types
902+
// things blow up (due to conflict with codemirror?)
903+
{ acceptedFiles: "image/*" }
904+
}
942905
>
943906
{body}
944-
</FileUploadWrapper>
907+
</BlobUpload>
945908
);
946909
}
947910

948911
return body;
949912
}
950913

951-
function upload_target(path: string, file: { name: string }): string {
952-
// path to our upload target, but relative to path.
953-
return join(path_split(aux_file(path, AUX_FILE_EXT)).tail, file.name);
954-
}
955-
956-
function upload_temp_link(path: string, file: { name: string }): string {
957-
return `[Uploading...]\(${upload_target(path, file)}\)`;
914+
function upload_temp_link(file): string {
915+
return `[Uploading...]\(${file.name ?? file.upload?.filename ?? ""}\)`;
958916
}
959917

960-
function upload_link(
961-
path: string,
962-
file: { name: string; type: string },
963-
): string {
964-
const target = upload_target(path, file);
965-
if (file.type.indexOf("image") !== -1) {
966-
return `<img src=\"${target}\" style="max-width:100%" />`;
918+
function upload_link(file): string {
919+
const { url, dataURL, height, upload } = file;
920+
if (!height && !dataURL?.startsWith("data:image")) {
921+
return `[${upload.filename ? upload.filename : "file"}](${url})`;
967922
} else {
968-
// We use an a tag instead of [${file.name}](${target}) because for
969-
// some files (e.g,. word doc files) our markdown renderer inexplicably
970-
// does NOT render them as links!? a tags work though.
971-
return `<a href=\"${target}\">${file.name}</a>`;
923+
return `![](${url})`;
972924
}
973925
}
974926

src/packages/frontend/editors/slate/upload.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export default function useUpload(
5959
const updloadEventHandlers = useMemo(() => {
6060
return {
6161
error: (_, message) => {
62-
actions.set_error(`${message}`);
62+
actions?.set_error(`${message}`);
6363
},
6464
sending: ({ name }) => {
6565
actionsRef.current?.set_status?.(`Uploading ${name}...`);

0 commit comments

Comments
 (0)