Skip to content

Commit 32cb2a4

Browse files
committed
course: slightly improve creating a new directory (for purposes of a course)
1 parent 21d5aec commit 32cb2a4

File tree

2 files changed

+97
-40
lines changed

2 files changed

+97
-40
lines changed

src/packages/frontend/components/error.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export default function ShowError({
2222
message={message}
2323
type="error"
2424
description={
25-
<div style={{ maxHeight: "150px", overflow: "auto" }}>{err}</div>
25+
<div style={{ maxHeight: "150px", overflow: "auto", textWrap: "wrap" }}>
26+
{err}
27+
</div>
2628
}
2729
onClose={() => setError?.("")}
2830
closable={setError != null}

src/packages/frontend/project/directory-selector.tsx

Lines changed: 94 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ Component that allows a user to select a directory in a project.
1010
*/
1111

1212
import { join } from "path";
13-
import { Button, Card, Checkbox, Input, Tooltip } from "antd";
13+
import { Button, Card, Checkbox, Input, InputRef, Modal, Tooltip } from "antd";
1414
import {
1515
CSSProperties,
1616
ReactNode,
1717
useCallback,
1818
useEffect,
19+
useRef,
1920
useState,
2021
} from "react";
2122
import { Icon, Loading } from "@cocalc/frontend/components";
@@ -26,6 +27,7 @@ import { delay } from "awaiting";
2627
import { redux, useTypedRedux } from "@cocalc/frontend/app-framework";
2728
import useIsMountedRef from "@cocalc/frontend/app-framework/is-mounted-hook";
2829
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
30+
import ShowError from "@cocalc/frontend/components/error";
2931

3032
const NEW_FOLDER = "New Folder";
3133

@@ -419,6 +421,7 @@ function Subdirs(props) {
419421
project_id,
420422
showHidden,
421423
style,
424+
toggleSelection,
422425
} = props;
423426
const x = directoryListings?.get(path);
424427
const v = x?.toJS?.();
@@ -457,6 +460,7 @@ function Subdirs(props) {
457460
path={path}
458461
computeServerId={computeServerId}
459462
directoryListings={directoryListings}
463+
toggleSelection={toggleSelection}
460464
/>,
461465
);
462466
return (
@@ -467,62 +471,113 @@ function Subdirs(props) {
467471
}
468472
}
469473

474+
async function getValidPath(
475+
project_id,
476+
target,
477+
directoryListings,
478+
computeServerId,
479+
) {
480+
if (
481+
await pathExists(project_id, target, directoryListings, computeServerId)
482+
) {
483+
let i: number = 1;
484+
while (
485+
await pathExists(
486+
project_id,
487+
target + ` (${i})`,
488+
directoryListings,
489+
computeServerId,
490+
)
491+
) {
492+
i += 1;
493+
}
494+
target += ` (${i})`;
495+
}
496+
return target;
497+
}
498+
470499
function CreateDirectory({
471500
computeServerId,
472501
project_id,
473502
path,
474503
directoryListings,
504+
toggleSelection,
475505
}) {
476-
return (
477-
<div
478-
style={{ cursor: "pointer", color: "#666" }}
479-
key={"...-create-dir"}
480-
onClick={async () => {
481-
let target = path + (path != "" ? "/" : "") + NEW_FOLDER;
482-
if (
483-
await pathExists(
506+
const [error, setError] = useState<string>("");
507+
const [open, setOpen] = useState<boolean>(false);
508+
const [value, setValue] = useState<string>(NEW_FOLDER);
509+
const input_ref = useRef<InputRef>(null);
510+
511+
useEffect(() => {
512+
if (!open) {
513+
return;
514+
}
515+
const target = path + (path != "" ? "/" : "") + value;
516+
(async () => {
517+
try {
518+
setValue(
519+
await getValidPath(
484520
project_id,
485521
target,
486522
directoryListings,
487523
computeServerId,
488-
)
489-
) {
490-
let i: number = 1;
491-
while (
492-
await pathExists(
493-
project_id,
494-
target + ` (${i})`,
495-
directoryListings,
496-
computeServerId,
497-
)
498-
) {
499-
i += 1;
500-
}
501-
target += ` (${i})`;
502-
}
503-
try {
504-
await exec({
505-
command: "mkdir",
506-
args: ["-p", target],
507-
project_id,
508-
compute_server_id: computeServerId,
509-
filesystem: true,
510-
});
511-
} catch (err) {
512-
alert_message({ type: "error", message: err.toString() });
513-
}
514-
}}
515-
>
524+
),
525+
);
526+
input_ref.current?.select();
527+
} catch (err) {
528+
setError(`${err}`);
529+
}
530+
})();
531+
}, [open]);
532+
533+
const createFolder = async () => {
534+
setOpen(false);
535+
try {
536+
await exec({
537+
command: "mkdir",
538+
args: ["-p", value],
539+
project_id,
540+
compute_server_id: computeServerId,
541+
filesystem: true,
542+
});
543+
toggleSelection(value);
544+
} catch (err) {
545+
setError(`${err}`);
546+
}
547+
};
548+
549+
return (
550+
<div style={{ color: "#666" }} key={"...-create-dir"}>
516551
<Tooltip
517552
title="Create a new directory (double click to rename)"
518553
placement="left"
519554
mouseEnterDelay={0.9}
520555
>
521-
<Button size="small" type="text" style={{ color: "#666" }}>
556+
<Modal open={open} onOk={createFolder} onCancel={() => setOpen(false)}>
557+
<Input
558+
ref={input_ref}
559+
title="Create Folder"
560+
style={{ marginTop: "30px" }}
561+
value={value}
562+
onChange={(e) => setValue(e.target.value)}
563+
onPressEnter={createFolder}
564+
autoFocus
565+
/>
566+
</Modal>
567+
<Button
568+
size="small"
569+
type="text"
570+
style={{ color: "#666" }}
571+
disabled={open}
572+
onClick={() => {
573+
setOpen(true);
574+
}}
575+
>
522576
<Icon name="plus" style={{ marginRight: "5px" }} /> Create{" "}
523-
{NEW_FOLDER}
577+
{NEW_FOLDER}...
524578
</Button>
525579
</Tooltip>
580+
<ShowError error={error} setError={setError} />
526581
</div>
527582
);
528583
}

0 commit comments

Comments
 (0)