Skip to content

Commit 767e397

Browse files
committed
frontend UI for creating snapshots
1 parent d3f6233 commit 767e397

File tree

14 files changed

+313
-20
lines changed

14 files changed

+313
-20
lines changed

src/packages/file-server/btrfs/subvolume-snapshots.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import getLogger from "@cocalc/backend/logger";
44
import { join } from "path";
55
import { SnapshotCounts, updateRollingSnapshots } from "./snapshots";
66
import { ConatError } from "@cocalc/conat/core/client";
7+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
78

8-
export const SNAPSHOTS = ".snapshots";
99
const logger = getLogger("file-server:btrfs:subvolume-snapshots");
1010

1111
export class SubvolumeSnapshots {

src/packages/file-server/btrfs/test/rustic.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { before, after, fs } from "./setup";
22
import { type Subvolume } from "../subvolume";
3+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
34

45
beforeAll(before);
56

@@ -22,7 +23,7 @@ describe("test rustic backups", () => {
2223
expect(Math.abs(Date.now() - v[0].time.valueOf())).toBeLessThan(10000);
2324
const { id } = v[0];
2425
const w = await vol.rustic.ls({ id });
25-
expect(w).toEqual([".snapshots", "a.txt"]);
26+
expect(w).toEqual([SNAPSHOTS, "a.txt"]);
2627
});
2728

2829
it("delete a.txt, then restore it from the backup", async () => {
@@ -42,7 +43,7 @@ describe("test rustic backups", () => {
4243
const { id } = v[1];
4344
const w = await vol.rustic.ls({ id });
4445
expect(w).toEqual([
45-
".snapshots",
46+
SNAPSHOTS,
4647
"a.txt",
4748
"my-dir",
4849
"my-dir/file.txt",

src/packages/file-server/btrfs/test/subvolume.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { before, after, fs, sudo } from "./setup";
22
import { wait } from "@cocalc/backend/conat/test/util";
33
import { randomBytes } from "crypto";
44
import { type Subvolume } from "../subvolume";
5+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
56

67
beforeAll(before);
78

@@ -95,7 +96,7 @@ describe("the filesystem operations", () => {
9596

9697
it("unlink (delete) our file", async () => {
9798
await vol.fs.unlink("a.txt");
98-
expect(await vol.fs.readdir("")).toEqual([".snapshots"]);
99+
expect(await vol.fs.readdir("")).toEqual([SNAPSHOTS]);
99100
});
100101

101102
it("snapshot still exists", async () => {

src/packages/frontend/frame-editors/time-travel-editor/actions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import type { Document } from "@cocalc/sync/editor/generic/types";
3333
import LRUCache from "lru-cache";
3434
import { reuseInFlight } from "@cocalc/util/reuse-in-flight";
3535
import { until } from "@cocalc/util/async-utils";
36+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
3637

3738
const EXTENSION = ".time-travel";
3839

@@ -362,7 +363,7 @@ export class TimeTravelActions extends CodeEditorActions<TimeTravelState> {
362363

363364
open_snapshots = (): void => {
364365
// log("open_snapshots");
365-
this.redux.getProjectActions(this.project_id).open_directory(".snapshots");
366+
this.redux.getProjectActions(this.project_id).open_directory(SNAPSHOTS);
366367
};
367368

368369
exportEditHistory = async (): Promise<string> => {

src/packages/frontend/project/explorer/action-bar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import * as misc from "@cocalc/util/misc";
2323
import { COLORS } from "@cocalc/util/theme";
2424
import { DirectoryListingEntry } from "@cocalc/util/types";
2525
import { VisibleMDLG } from "@cocalc/frontend/components";
26+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
2627

2728
const ROW_INFO_STYLE = {
2829
color: COLORS.GRAY,
@@ -168,7 +169,7 @@ export function ActionBar({
168169
const disabled =
169170
isDisabledSnapshots(name) &&
170171
(current_path != null
171-
? current_path.startsWith(".snapshots")
172+
? current_path.startsWith(SNAPSHOTS)
172173
: undefined);
173174
const obj = file_actions[name];
174175
const handle_click = (_e: React.MouseEvent) => {

src/packages/frontend/project/explorer/action-box.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { in_snapshot_path } from "../utils";
3535
import CreateArchive from "./create-archive";
3636
import Download from "./download";
3737
import RenameFile from "./rename-file";
38+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
3839

3940
export const PRE_STYLE = {
4041
marginBottom: "15px",
@@ -167,7 +168,7 @@ export function ActionBox({
167168
href=""
168169
onClick={(e) => {
169170
e.preventDefault();
170-
actions.open_directory(".snapshots");
171+
actions.open_directory(SNAPSHOTS);
171172
}}
172173
>
173174
~/.snapshots

src/packages/frontend/project/explorer/explorer.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ export function Explorer() {
122122
"show_custom_software_reset",
123123
);
124124
const show_library = useTypedRedux({ project_id }, "show_library");
125+
const disableExplorerKeyhandler = useTypedRedux(
126+
{ project_id },
127+
"disableExplorerKeyhandler",
128+
);
125129

126130
const [shiftIsDown, setShiftIsDown] = useState<boolean>(false);
127131

@@ -169,7 +173,7 @@ export function Explorer() {
169173

170174
const { val: clicked, inc: clickedOnExplorer } = useCounter();
171175
useEffect(() => {
172-
if (listing == null || file_action) {
176+
if (listing == null || file_action || disableExplorerKeyhandler) {
173177
return;
174178
}
175179
const handleKeyDown = (e): void => {
@@ -232,7 +236,15 @@ export function Explorer() {
232236
$(window).off("keydown", handleKeyDown);
233237
$(window).off("keyup", handleKeyUp);
234238
};
235-
}, [project_id, current_path, listing, file_action, flyout, clicked]);
239+
}, [
240+
project_id,
241+
current_path,
242+
listing,
243+
file_action,
244+
flyout,
245+
clicked,
246+
disableExplorerKeyhandler,
247+
]);
236248

237249
if (actions == null || project_map == null) {
238250
return <Loading />;

src/packages/frontend/project/explorer/misc-side-buttons.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { Space } from "antd";
77
import { join } from "path";
88
import { defineMessage, useIntl } from "react-intl";
9-
import { Button, ButtonToolbar } from "@cocalc/frontend/antd-bootstrap";
9+
import { Button } from "@cocalc/frontend/antd-bootstrap";
1010
import { Icon, Tip, VisibleLG } from "@cocalc/frontend/components";
1111
import LinkRetry from "@cocalc/frontend/components/link-retry";
1212
import { useStudentProjectFunctionality } from "@cocalc/frontend/course";
@@ -17,6 +17,8 @@ import { KUCALC_COCALC_COM } from "@cocalc/util/db-schema/site-defaults";
1717
import { useProjectContext } from "@cocalc/frontend/project/context";
1818
import { useTypedRedux } from "@cocalc/frontend/app-framework";
1919
import { type JSX, type MouseEvent } from "react";
20+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
21+
import Snapshots from "@cocalc/frontend/project/snapshots";
2022

2123
const SHOW_SERVER_LAUNCHERS = false;
2224

@@ -51,7 +53,7 @@ export function MiscSideButtons() {
5153

5254
const handle_backup = (e: MouseEvent): void => {
5355
e.preventDefault();
54-
actions?.open_directory(".snapshots");
56+
actions?.open_directory(SNAPSHOTS);
5557
track("snapshots", { action: "open", where: "explorer" });
5658
};
5759

@@ -79,7 +81,7 @@ export function MiscSideButtons() {
7981
}
8082
return (
8183
<Button bsSize="small" onClick={handle_backup}>
82-
<Icon name="life-saver" />{" "}
84+
<Icon name="disk-round" />{" "}
8385
<VisibleLG>
8486
<span style={{ fontSize: 12 }}>Backups</span>
8587
</VisibleLG>
@@ -168,10 +170,9 @@ export function MiscSideButtons() {
168170
}
169171

170172
return (
171-
<ButtonToolbar
172-
style={{ whiteSpace: "nowrap", padding: "0" }}
173-
className="pull-right"
174-
>
173+
<Space className="pull-right">
174+
{(current_path == SNAPSHOTS ||
175+
current_path.startsWith(SNAPSHOTS + "/")) && <Snapshots />}
175176
{SHOW_SERVER_LAUNCHERS && (
176177
<Space.Compact>
177178
{render_jupyterlab_button()}
@@ -190,6 +191,6 @@ export function MiscSideButtons() {
190191
<TourButton project_id={project_id} />
191192
</Space.Compact>
192193
</div>
193-
</ButtonToolbar>
194+
</Space>
194195
);
195196
}

src/packages/frontend/project/page/flyouts/file-list-item.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
} from "@cocalc/util/misc";
3838
import { COLORS } from "@cocalc/util/theme";
3939
import { FLYOUT_DEFAULT_WIDTH_PX, FLYOUT_PADDING } from "./consts";
40+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
4041

4142
const FILE_ITEM_SELECTED_STYLE: CSS = {
4243
backgroundColor: COLORS.BLUE_LLL, // bit darker than .cc-project-flyout-file-item:hover
@@ -415,7 +416,7 @@ export const FileListItem = React.memo((props: Readonly<FileListItemProps>) => {
415416
if (key === "download" && !item.isDir) continue;
416417
const disabled =
417418
isDisabledSnapshots(key) &&
418-
(current_path?.startsWith(".snapshots") ?? false);
419+
(current_path?.startsWith(SNAPSHOTS) ?? false);
419420

420421
const { name, icon, hideFlyout } = FILE_ACTIONS[key];
421422
if (hideFlyout) return;

src/packages/frontend/project/page/flyouts/files-controls.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { human_readable_size, path_split, plural } from "@cocalc/util/misc";
2323
import { COLORS } from "@cocalc/util/theme";
2424
import { PANEL_STYLE_BOTTOM, PANEL_STYLE_TOP } from "./consts";
2525
import { useSingleFile } from "./utils";
26+
import { SNAPSHOTS } from "@cocalc/util/consts/snapshots";
2627

2728
interface FilesSelectedControlsProps {
2829
checked_files: immutable.Set<string>;
@@ -205,7 +206,7 @@ export function FilesSelectedControls({
205206
{names.map((name) => {
206207
const disabled =
207208
isDisabledSnapshots(name) &&
208-
(current_path?.startsWith(".snapshots") ?? false);
209+
(current_path?.startsWith(SNAPSHOTS) ?? false);
209210

210211
const { name: actionName, icon, hideFlyout } = FILE_ACTIONS[name];
211212
const title = intl.formatMessage(actionName);

0 commit comments

Comments
 (0)