Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(flat-components): add rename panel #474

Merged
merged 1 commit into from
Mar 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export interface CloudStorageFileListFileNameProps {
onItemMenuClick?: (fileUUID: string, menuKey: React.Key) => void;
/** When title is clicked */
onItemTitleClick?: (fileUUID: string) => void;
/** UUID of file that is under renaming */
renamingFileUUID?: string;
/** Rename file. Empty name for cancelling */
onRename?: (fileUUID: string, name: string) => void;
}

export const CloudStorageFileListFileName = React.memo<CloudStorageFileListFileNameProps>(
Expand All @@ -31,6 +35,8 @@ export const CloudStorageFileListFileName = React.memo<CloudStorageFileListFileN
fileMenus,
onItemMenuClick,
onItemTitleClick,
renamingFileUUID,
onRename,
}) {
const menuItems = fileMenus && fileMenus(file, index);

Expand All @@ -42,6 +48,8 @@ export const CloudStorageFileListFileName = React.memo<CloudStorageFileListFileN
titleClickable={titleClickable}
convertStatus={file.convert}
onTitleClick={onItemTitleClick}
renamingFileUUID={renamingFileUUID}
onRename={onRename}
/>
{menuItems && menuItems.length > 0 && (
<div className="cloud-storage-file-list-menu-btn-wrap">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ import {
export interface CloudStorageFileListProps
extends Pick<
CloudStorageFileListFileNameProps,
"fileMenus" | "onItemMenuClick" | "titleClickable" | "onItemTitleClick"
| "fileMenus"
| "onItemMenuClick"
| "titleClickable"
| "onItemTitleClick"
| "renamingFileUUID"
| "onRename"
> {
/** Cloud Storage List items */
files: CloudStorageFile[];
Expand All @@ -36,6 +41,8 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
onItemMenuClick,
titleClickable = false,
onItemTitleClick,
renamingFileUUID,
onRename,
}) => {
const popupContainerRef = useRef<HTMLDivElement>(null);
const getPopupContainer = useCallback(() => popupContainerRef.current || document.body, []);
Expand Down Expand Up @@ -65,6 +72,8 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
titleClickable={titleClickable}
onItemMenuClick={onItemMenuClick}
onItemTitleClick={onItemTitleClick}
renamingFileUUID={renamingFileUUID}
onRename={onRename}
/>
);
},
Expand Down Expand Up @@ -92,7 +101,15 @@ export const CloudStorageFileList: React.FC<CloudStorageFileListProps> = ({
},
},
],
[fileMenus, getPopupContainer, onItemMenuClick, onItemTitleClick, titleClickable],
[
fileMenus,
getPopupContainer,
onItemMenuClick,
onItemTitleClick,
onRename,
renamingFileUUID,
titleClickable,
],
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
position: relative;
display: flex;
align-items: center;
height: 2em;
}

.cloud-storage-file-list-menu-btn-wrap {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ ConvertError.args = {
convertStatus: "error",
};

export const Rename: Story<CloudStorageFileTitleProps> = args => (
<CloudStorageFileTitle {...args} />
);
Rename.args = {
fileUUID: faker.random.uuid(),
fileName: faker.random.word() + ".doc",
convertStatus: "success",
};
Rename.args.renamingFileUUID = Rename.args.fileUUID;

export const FileTitles: Story<CloudStorageFileTitleProps> = ({ onTitleClick }) => {
const renderFileTitles = (fileType: string, exts: string[]): React.ReactElement => (
<div className="column is-one-quarter-tablet">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import checkSVG from "./icons/check.svg";
import crossSVG from "./icons/cross.svg";

import { Button, Input } from "antd";
import React, { useEffect, useRef, useState } from "react";

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

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

const onCancel = onRename && (() => onRename(fileUUID, ""));
const onConfirm =
onRename &&
(() => {
const newFileName = newName + ext;
onRename(fileUUID, newFileName === fileName ? "" : newFileName);
});

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

return (
<>
<Input
ref={inputRef}
size="small"
className="cloud-storage-file-title-rename-input"
value={newName}
onChange={e => setText(e.currentTarget.value)}
onPressEnter={onConfirm}
/>
<Button
type="text"
shape="circle"
size="small"
className="cloud-storage-file-title-rename-btn"
onClick={onConfirm}
>
<img src={checkSVG} width={22} height={22} alt="confirm" />
</Button>
<Button
type="text"
shape="circle"
size="small"
className="cloud-storage-file-title-rename-btn"
onClick={onCancel}
>
<img src={crossSVG} width={22} height={22} alt="cancel" />
</Button>
</>
);
},
);

/** split filename to name and extension */
function splitFileName(fileName: string): [string, string] {
const dotIndex = fileName.lastIndexOf(".");
return [fileName.substr(0, dotIndex), fileName.slice(dotIndex)];
}
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.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import convertErrorSVG from "./icons/convert-error.svg";
import React from "react";
import classNames from "classnames";
import { CloudStorageConvertStatusType } from "../types";
import { CloudStorageFileTitleRename } from "./CloudStorageFileTitleRename";

export interface CloudStorageFileTitleProps
extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement> {
Expand All @@ -25,6 +26,10 @@ export interface CloudStorageFileTitleProps
titleClickable?: boolean;
/** When title is clicked */
onTitleClick?: (fileUUID: string) => void;
/** UUID of file that is under renaming */
renamingFileUUID?: string;
/** Rename file. Empty name for cancelling */
onRename?: (fileUUID: string, name: string) => void;
}

/**
Expand All @@ -37,6 +42,8 @@ export const CloudStorageFileTitle = React.memo<CloudStorageFileTitleProps>(
convertStatus,
titleClickable = false,
onTitleClick,
renamingFileUUID,
onRename,
...restProps
}) {
const isConverting = convertStatus === "converting";
Expand Down Expand Up @@ -78,7 +85,13 @@ export const CloudStorageFileTitle = React.memo<CloudStorageFileTitleProps>(
/>
) : null}
</span>
{titleClickable ? (
{renamingFileUUID === fileUUID ? (
<CloudStorageFileTitleRename
fileUUID={fileUUID}
fileName={fileName}
onRename={onRename}
/>
) : titleClickable ? (
<a
className="cloud-storage-file-title-content"
onClick={e => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@
user-select: none;
}

.cloud-storage-file-title-rename-input {
width: 200px;
max-width: 80%;
box-shadow: none;
border-radius: 4px;
height: 30px;
margin-left: 5px;
}

.cloud-storage-file-title-rename-btn {
margin-left: 5px;
}

.cloud-storage-file-title-converting,
.cloud-storage-file-title-convert-error {
position: absolute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const fakeStoreImplProps = [
"onUploadRetry",
"onItemMenuClick",
"onItemTitleClick",
"onNewFileName",
] as const;

type FakeStoreImplProps = typeof fakeStoreImplProps[number];
Expand All @@ -38,8 +39,9 @@ class FakeStore extends CloudStorageStore {
onUploadCancel;
onUploadPanelClose;
onUploadRetry;
onItemMenuClick;
onItemMenuClick: FakeStoreConfig["onItemMenuClick"];
onItemTitleClick;
onNewFileName: FakeStoreConfig["onNewFileName"];

constructor(config: FakeStoreConfig) {
super();
Expand All @@ -49,8 +51,20 @@ class FakeStore extends CloudStorageStore {
this.onUploadCancel = config.onUploadCancel;
this.onUploadPanelClose = config.onUploadPanelClose;
this.onUploadRetry = config.onUploadRetry;
this.onItemMenuClick = config.onItemMenuClick;
this.onItemMenuClick = (fileUUID, menuKey) => {
if (menuKey === "rename") {
this.setRenamePanel(fileUUID);
}
config.onItemMenuClick(fileUUID, menuKey);
};
this.onItemTitleClick = config.onItemTitleClick;
this.onNewFileName = (fileUUID, name) => {
const file = this.files.find(file => file.fileUUID === fileUUID);
if (file) {
file.fileName = name;
}
config.onNewFileName(fileUUID, name);
};

makeObservable(
this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export const CloudStorageFileListContainer = observer<CloudStorageFileListContai
fileMenus={store.fileMenus}
onItemMenuClick={store.onItemMenuClick}
onItemTitleClick={store.onItemTitleClick}
renamingFileUUID={store.renamingFileUUID}
onRename={store.onRename}
/>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export abstract class CloudStorageStore {
uploadStatusesMap = observable.map</** fileUUID */ string, CloudStorageUploadStatus>();
/** It changes when user toggles the expand button */
isUploadPanelExpand = false;
/** UUID of file that is under renaming */
renamingFileUUID?: string = "";

/** Number of total upload */
get uploadTotalCount(): number {
Expand Down Expand Up @@ -93,6 +95,7 @@ export abstract class CloudStorageStore {
files: observable,
selectedFileUUIDs: observable,
isUploadPanelExpand: observable,
renamingFileUUID: observable,

uploadFinishedCount: computed,
uploadTotalCount: computed,
Expand All @@ -106,6 +109,10 @@ export abstract class CloudStorageStore {
});
}

setRenamePanel = (fileUUID?: string): void => {
this.renamingFileUUID = fileUUID;
};

setPanelExpand = (isExpand: boolean): void => {
this.isUploadPanelExpand = isExpand;
};
Expand All @@ -119,6 +126,16 @@ export abstract class CloudStorageStore {
this.selectedFileUUIDs = fileUUIDs;
};

/** When a rename event is received. Could be empty. Put business logic in `onNewFileName` instead. */
onRename = (fileUUID: string, name: string): void => {
// hide rename panel
this.renamingFileUUID = "";

if (name) {
this.onNewFileName(fileUUID, name);
}
};

/** Render file menus item base on fileUUID */
abstract fileMenus: (
file: CloudStorageFile,
Expand All @@ -145,4 +162,7 @@ export abstract class CloudStorageStore {

/** Stop uploading a file */
abstract onUploadCancel(fileUUID: string): void;

/** When a filename is changed to a meaningful new name */
abstract onNewFileName(fileUUID: string, name: string): void;
}