Skip to content

Commit

Permalink
feat(cloud-storage): cloud storage supports new directory (#1716)
Browse files Browse the repository at this point in the history
* feat(flat-components): add navigation component to the cloudStorage

* feat(flat-components): add new directory component to the cloudStorage

* refactor(flat-components): replace icons

* refactor(cloud-storage): the upload flow add directory name

* refactor(cloud-storage): add new button and add relate function of new directory

* chore(flat-components): add annotation

* refactor(flat-components): support rename directory

* refactor(cloud-storage): add relate function of new directory to cloud storage store

* refactor(flat-pages): refresh component when directory path change

* refactor(i18n): add i18n and error code

* refactor(flat-components): add the render conditional of the navigation component

* refactor(flat-components): add i18n to cloudStorageNavigation components

* refactor(cloud-storage): sort files of the cloud storage store

* chore(i18n): add i18n

* chore(cloud-storage): remove console log

* chore(i18n): add i18n of the new directory and rename directory error tips

* refactor(flat-components): remove unimportant comments and beautify the path value
  • Loading branch information
Cheerego7 authored Oct 13, 2022
1 parent 906aa03 commit c1d3823
Show file tree
Hide file tree
Showing 39 changed files with 764 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import { Button, Dropdown, Menu } from "antd";
import { CloudStorageFileTitle } from "../CloudStorageFileTitle";
import { CloudStorageFileName } from "../types";
import { CloudFile } from "@netless/flat-server-api";
import { DirectoryInfo } from "../../../containers/CloudStorageContainer";
import { useHistory } from "react-router-dom";

export interface CloudStorageFileListFileNameProps {
file: CloudFile;
index: number;
/** Is title clickable */
titleClickable?: boolean;
/** UUID of file that is under renaming */
renamingFileUUID?: string;
parentDirectoryPath?: string;
getPopupContainer: () => HTMLElement;
/** Render file menus item base on fileUUID */
fileMenus?: (
Expand All @@ -21,14 +25,15 @@ export interface CloudStorageFileListFileNameProps {
| void
| undefined
| null;
/** When file menu item clicked */
onItemMenuClick?: (fileUUID: string, menuKey: React.Key) => void;
/** When title is clicked */
onItemTitleClick?: (fileUUID: string) => void;
/** UUID of file that is under renaming */
renamingFileUUID?: string;
onItemMenuClick?: (
fileUUID: string,
menuKey: React.Key,
pushHistory: (path: string) => void,
) => void;
onItemTitleClick?: (fileUUID: string, pushHistory: (path: string) => void) => void;
/** Rename file. Empty name for cancelling */
onRename?: (fileUUID: string, fileName?: CloudStorageFileName) => void;
onNewDirectoryFile?: (directoryInfo: DirectoryInfo) => Promise<void>;
}

export const CloudStorageFileListFileName =
Expand All @@ -37,26 +42,37 @@ export const CloudStorageFileListFileName =
file,
index,
titleClickable,
renamingFileUUID,
parentDirectoryPath,
getPopupContainer,
fileMenus,
onItemMenuClick,
onItemTitleClick,
renamingFileUUID,
onRename,
onNewDirectoryFile,
}) {
const menuItems = fileMenus && fileMenus(file, index);
const fileConvertStep =
file.meta.whiteboardConvert?.convertStep ||
file.meta.whiteboardProjector?.convertStep;

const history = useHistory();
const pushHistory = (path: string): void => {
const search = new URLSearchParams({ path }).toString();
history.push({ search });
};

return (
<div className="cloud-storage-file-list-filename-container">
<CloudStorageFileTitle
convertStatus={fileConvertStep}
fileName={file.fileName}
fileUUID={file.fileUUID}
parentDirectoryPath={parentDirectoryPath}
renamingFileUUID={renamingFileUUID}
resourceType={file.resourceType}
titleClickable={titleClickable}
onNewDirectoryFile={onNewDirectoryFile}
onRename={onRename}
onTitleClick={onItemTitleClick}
/>
Expand All @@ -72,7 +88,9 @@ export const CloudStorageFileListFileName =
className: e.className,
label: e.name,
}))}
onClick={({ key }) => onItemMenuClick?.(file.fileUUID, key)}
onClick={({ key }) =>
onItemMenuClick?.(file.fileUUID, key, pushHistory)
}
/>
}
overlayClassName="cloud-storage-file-list-menu"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export interface CloudStorageFileListProps
| "onItemTitleClick"
| "renamingFileUUID"
| "onRename"
| "onNewDirectoryFile"
| "parentDirectoryPath"
> {
/** Cloud Storage List items */
files: CloudFile[];
Expand All @@ -48,6 +50,8 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
renamingFileUUID,
isLoadingData,
onRename,
onNewDirectoryFile,
parentDirectoryPath,
}) => {
const t = useTranslate();
const popupContainerRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -75,10 +79,12 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
fileMenus={fileMenus}
getPopupContainer={getPopupContainer}
index={index}
parentDirectoryPath={parentDirectoryPath}
renamingFileUUID={renamingFileUUID}
titleClickable={titleClickable}
onItemMenuClick={onItemMenuClick}
onItemTitleClick={onItemTitleClick}
onNewDirectoryFile={onNewDirectoryFile}
onRename={onRename}
/>
);
Expand All @@ -93,7 +99,9 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
showSorterTooltip: false,
render: function renderCloudStorageFileSize(fileSize: CloudFile["fileSize"]) {
const formattedSize = prettyBytes(fileSize);
return <span title={formattedSize}>{formattedSize}</span>;
return (
<span title={formattedSize}>{fileSize === 0 ? "-" : formattedSize}</span>
);
},
},
{
Expand All @@ -103,7 +111,6 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
width: 170,
sorter: (file1, file2) => file1.createAt.valueOf() - file2.createAt.valueOf(),
sortDirections: ["ascend", "descend", "ascend"],
defaultSortOrder: "descend",
showSorterTooltip: false,
render: function renderCloudStorageCreateAt(date: CloudFile["createAt"]) {
const formattedDate = format(date, "yyyy/MM/dd HH:mm");
Expand All @@ -112,14 +119,16 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
},
],
[
fileMenus,
t,
getPopupContainer,
fileMenus,
parentDirectoryPath,
renamingFileUUID,
titleClickable,
onItemMenuClick,
onItemTitleClick,
onNewDirectoryFile,
onRename,
renamingFileUUID,
titleClickable,
t,
],
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import checkSVG from "./icons/check.svg";
import crossSVG from "./icons/cross.svg";

import { Button, Input, InputRef } from "antd";
import { Button, Input, InputRef, message } from "antd";
import React, { useEffect, useRef, useState } from "react";
import { CloudStorageFileName } from "../types";
import { FileResourceType, ResourceType } from "@netless/flat-server-api";
import { checkInvalidDirectoryName } from "./utils";
import { useTranslate } from "@netless/flat-i18n";

export interface CloudStorageFileTitleRenameProps {
fileUUID: string;
fileName: string;
fileResourceType?: ResourceType;
/** Rename file. Empty name for cancelling */
onRename?: (fileUUID: string, fileName?: CloudStorageFileName) => void;
}

export const CloudStorageFileTitleRename =
/* @__PURE__ */ React.memo<CloudStorageFileTitleRenameProps>(
function CloudStorageFileTitleRename({ fileUUID, fileName, onRename }) {
function CloudStorageFileTitleRename({ fileUUID, fileName, fileResourceType, onRename }) {
// Antd docs uses any
const t = useTranslate();
const inputRef = useRef<any>();
const [oldName, ext] = splitFileName(fileName);
const [oldName, ext] = splitFileName(fileName, fileResourceType);
const [name, setText] = useState(oldName);

const onCancel = onRename && (() => onRename(fileUUID));
Expand All @@ -29,7 +34,13 @@ export const CloudStorageFileTitleRename =
// cancel on empty and same name
onRename(fileUUID);
} else {
onRename(fileUUID, { name, ext, fullName });
if (fileResourceType === FileResourceType.Directory) {
checkInvalidDirectoryName(name)
? message.error(t("invalid-directory-name-tips"))
: onRename(fileUUID, { name, ext, fullName });
} else {
onRename(fileUUID, { name, ext, fullName });
}
}
});

Expand Down Expand Up @@ -75,7 +86,10 @@ export const CloudStorageFileTitleRename =
);

/** split filename to name and extension */
function splitFileName(fileName: string): [string, string] {
function splitFileName(fileName: string, fileResourceType?: ResourceType): [string, string] {
if (fileResourceType === FileResourceType.Directory) {
return [fileName, ""];
}
const dotIndex = fileName.lastIndexOf(".");
return [fileName.substr(0, dotIndex), fileName.slice(dotIndex)];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import checkSVG from "./icons/check.svg";
import crossSVG from "./icons/cross.svg";

import { Button, Input, InputRef, message } from "antd";
import React, { useEffect, useRef, useState } from "react";
import { DirectoryInfo } from "../../../containers/CloudStorageContainer";
import { checkInvalidDirectoryName } from "./utils";
import { useTranslate } from "@netless/flat-i18n";

export interface CloudStorageNewDirectoryProps {
parentDirectoryPath: string;
onNewDirectory?: (directoryInfo: DirectoryInfo) => void;
}

export const CloudStorageNewDirectory = /* @__PURE__ */ React.memo<CloudStorageNewDirectoryProps>(
function CloudStorageNewDirectory({ parentDirectoryPath, onNewDirectory }) {
// Antd docs uses any
const t = useTranslate();
const inputRef = useRef<any>();
const [name, setText] = useState(t("new-directory"));

const onCancel =
onNewDirectory && (() => onNewDirectory({ directoryName: "", parentDirectoryPath }));
const onConfirm =
onNewDirectory &&
(() => {
checkInvalidDirectoryName(name)
? message.error(t("invalid-directory-name-tips"))
: onNewDirectory({ directoryName: name, parentDirectoryPath });
});

useEffect(() => {
const input: InputRef = inputRef.current;
if (input) {
input.focus();
input.select();
}
}, []);

return (
<>
<Input
ref={inputRef}
className="cloud-storage-file-title-rename-input"
size="small"
value={name}
onChange={e => setText(e.currentTarget.value)}
onPressEnter={onConfirm}
/>
<Button
className="cloud-storage-file-title-rename-btn"
shape="circle"
size="small"
type="text"
onClick={onConfirm}
>
<img alt="confirm" height={22} src={checkSVG} width={22} />
</Button>
<Button
className="cloud-storage-file-title-rename-btn"
shape="circle"
size="small"
type="text"
onClick={onCancel}
>
<img alt="cancel" height={22} src={crossSVG} width={22} />
</Button>
</>
);
},
);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c1d3823

Please sign in to comment.