diff --git a/frontend/src/components/dir-view-mode/dir-list-view.js b/frontend/src/components/dir-view-mode/dir-list-view.js
index 4fce0d6057..0d8439cf04 100644
--- a/frontend/src/components/dir-view-mode/dir-list-view.js
+++ b/frontend/src/components/dir-view-mode/dir-list-view.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
import DirentNoneView from '../../components/dirent-list-view/dirent-none-view';
import RepoInfoBar from '../../components/repo-info-bar';
import DirentListView from '../../components/dirent-list-view/dirent-list-view';
+import Loading from '../loading';
const propTypes = {
path: PropTypes.string.isRequired,
@@ -71,43 +72,46 @@ class DirListView extends React.Component {
onFileTagChanged={this.props.onFileTagChanged}
/>
)}
-
+ {this.props.isDirentListLoading ? (
+
+ ) : (
+
+ )}
);
}
diff --git a/frontend/src/components/dirent-list-view/dirent-list-item.js b/frontend/src/components/dirent-list-view/dirent-list-item.js
index e8044016e9..107660efec 100644
--- a/frontend/src/components/dirent-list-view/dirent-list-item.js
+++ b/frontend/src/components/dirent-list-view/dirent-list-item.js
@@ -819,17 +819,18 @@ class DirentListItem extends React.Component {
onMouseDown={this.onItemMouseDown}
onContextMenu={this.onItemContextMenu}
>
-
+ |
{}}
checked={isSelected}
aria-label={isSelected ? gettext('Unselect this item') : gettext('Select this item')}
/>
|
-
+ |
{dirent.starred !== undefined &&
}
|
-
+ |
{(this.canPreview && dirent.encoded_thumbnail_src) ?
 :
diff --git a/frontend/src/components/dirent-list-view/dirent-list-view.js b/frontend/src/components/dirent-list-view/dirent-list-view.js
index 91543ad21e..400eef1394 100644
--- a/frontend/src/components/dirent-list-view/dirent-list-view.js
+++ b/frontend/src/components/dirent-list-view/dirent-list-view.js
@@ -4,7 +4,6 @@ import { siteRoot, gettext, username, enableSeadoc, thumbnailSizeForOriginal, th
import { Utils } from '../../utils/utils';
import TextTranslation from '../../utils/text-translation';
import URLDecorator from '../../utils/url-decorator';
-import Loading from '../loading';
import toaster from '../toast';
import ModalPortal from '../modal-portal';
import CreateFile from '../dialog/create-file-dialog';
@@ -27,7 +26,6 @@ const propTypes = {
repoID: PropTypes.string.isRequired,
currentRepoInfo: PropTypes.object,
isAllItemSelected: PropTypes.bool.isRequired,
- isDirentListLoading: PropTypes.bool.isRequired,
direntList: PropTypes.array.isRequired,
sortBy: PropTypes.string.isRequired,
sortOrder: PropTypes.string.isRequired,
@@ -82,6 +80,7 @@ class DirentListView extends React.Component {
activeDirent: null,
isListDropTipShow: false,
isShowDirentsDraggablePreview: false,
+ containerWidth: 0,
};
this.enteredCounter = 0; // Determine whether to enter the child element to avoid dragging bubbling bugs。
@@ -102,12 +101,20 @@ class DirentListView extends React.Component {
const { modify } = customPermission.permission;
this.canDrop = modify;
}
+
+ this.containerRef = null;
}
componentDidMount() {
this.unsubscribeEvent = this.props.eventBus.subscribe(EVENT_BUS_TYPE.RESTORE_IMAGE, this.recalculateImageItems);
+ this.resizeObserver = new ResizeObserver(this.handleResize);
+ this.containerRef && this.resizeObserver.observe(this.containerRef);
}
+ handleResize = () => {
+ this.setState({ containerWidth: this.containerRef.offsetWidth - 32 });
+ };
+
recalculateImageItems = () => {
if (!this.state.isImagePopupOpen) return;
let imageItems = this.props.direntList
@@ -122,6 +129,7 @@ class DirentListView extends React.Component {
componentWillUnmount() {
this.unsubscribeEvent();
+ this.containerRef && this.resizeObserver.unobserve(this.containerRef);
}
freezeItem = () => {
@@ -680,10 +688,7 @@ class DirentListView extends React.Component {
render() {
const { direntList, sortBy, sortOrder } = this.props;
-
- if (this.props.isDirentListLoading) {
- return ( );
- }
+ const { containerWidth } = this.state;
// sort
const sortByName = sortBy == 'name';
@@ -704,13 +709,14 @@ class DirentListView extends React.Component {
onDragOver={this.onTableDragOver}
onDragLeave={this.onTableDragLeave}
onDrop={this.tableDrop}
+ ref={ref => this.containerRef = ref}
>
{direntList.length > 0 &&
{isDesktop ? (
-
+ |
|
- {/* icon */} |
- {/* star */} |
- {gettext('Name')} {sortByName && sortIcon} |
- {/* tag */} |
- {/* operation */} |
- {gettext('Size')} {sortBySize && sortIcon} |
- {gettext('Last Update')} {sortByTime && sortIcon} |
+ {/* star */} |
+ {/* icon */} |
+ {gettext('Name')} {sortByName && sortIcon} |
+ {/* tag */} |
+ {/* operation */} |
+ {gettext('Size')} {sortBySize && sortIcon} |
+ {gettext('Last Update')} {sortByTime && sortIcon} |
) : (
diff --git a/frontend/src/metadata/components/cell-editors/file-name-editor.js b/frontend/src/metadata/components/cell-editors/file-name-editor.js
index 97f9cb013d..333b9cab73 100644
--- a/frontend/src/metadata/components/cell-editors/file-name-editor.js
+++ b/frontend/src/metadata/components/cell-editors/file-name-editor.js
@@ -37,9 +37,12 @@ const FileNameEditor = React.forwardRef((props, ref) => {
if (mode === EDITOR_TYPE.PREVIEWER) {
const fileType = getFileType();
+ const repoID = window.sfMetadataContext.getSetting('repoID');
+ const repoInfo = window.sfMetadataContext.getSetting('repoInfo');
+
if (fileType === 'image') {
return (
-
+
);
}
diff --git a/frontend/src/metadata/components/cell-formatter/image-previewer.js b/frontend/src/metadata/components/cell-formatter/image-previewer.js
index 7fb5d7ce22..4b7c90d1cb 100644
--- a/frontend/src/metadata/components/cell-formatter/image-previewer.js
+++ b/frontend/src/metadata/components/cell-formatter/image-previewer.js
@@ -9,14 +9,11 @@ import { Utils } from '../../../utils/utils';
import { siteRoot, thumbnailSizeForOriginal, fileServerRoot, thumbnailDefaultSize } from '../../../utils/constants';
import { getFileNameFromRecord, getParentDirFromRecord, getRecordIdFromRecord } from '../../utils/cell';
-const ImagePreviewer = (props) => {
- const { record, table, closeImagePopup } = props;
+const ImagePreviewer = ({ record, table, repoID, repoInfo, closeImagePopup }) => {
const [imageIndex, setImageIndex] = useState(0);
const [imageItems, setImageItems] = useState([]);
useEffect(() => {
- const repoID = window.sfMetadataContext.getSetting('repoID');
- const repoInfo = window.sfMetadataContext.getSetting('repoInfo');
const newImageItems = table.rows
.filter((row) => Utils.imageCheck(getFileNameFromRecord(row)))
.map((row) => {
@@ -40,7 +37,7 @@ const ImagePreviewer = (props) => {
};
});
setImageItems(newImageItems);
- }, [table]);
+ }, [table, repoID, repoInfo]);
useEffect(() => {
if (imageItems.length > 0) {
@@ -98,9 +95,10 @@ const ImagePreviewer = (props) => {
};
ImagePreviewer.propTypes = {
- table: PropTypes.object,
- column: PropTypes.object,
record: PropTypes.object,
+ table: PropTypes.object,
+ repoID: PropTypes.string,
+ repoInfo: PropTypes.object,
closeImagePopup: PropTypes.func,
};
diff --git a/frontend/src/metadata/constants/column/icon.js b/frontend/src/metadata/constants/column/icon.js
index 8465254366..b4861ab66d 100644
--- a/frontend/src/metadata/constants/column/icon.js
+++ b/frontend/src/metadata/constants/column/icon.js
@@ -39,6 +39,7 @@ const COLUMNS_ICON_NAME = {
[CellType.GEOLOCATION]: 'Geolocation',
[CellType.RATE]: 'Rate',
[CellType.LINK]: 'Link',
+ [CellType.TAGS]: 'Tag',
};
export {
diff --git a/frontend/src/metadata/utils/cell/core.js b/frontend/src/metadata/utils/cell/core.js
index 350f2833bf..e497c964a9 100644
--- a/frontend/src/metadata/utils/cell/core.js
+++ b/frontend/src/metadata/utils/cell/core.js
@@ -1,4 +1,6 @@
import { PRIVATE_COLUMN_KEY, PRIVATE_COLUMN_KEYS } from '../../constants';
+import { siteRoot } from '../../../utils/constants';
+import { Utils } from '../../../utils/utils';
/**
* @param {any} value
@@ -59,3 +61,18 @@ export const getFileMTimeFromRecord = record => {
export const getTagsFromRecord = record => {
return record ? record[PRIVATE_COLUMN_KEY.TAGS] : '';
};
+
+const _getParentDir = (record) => {
+ const parentDir = getParentDirFromRecord(record);
+ if (parentDir === '/') {
+ return '';
+ }
+ return parentDir;
+};
+
+export const getFilePathByRecord = (repoID, record) => {
+ const parentDir = _getParentDir(record);
+ const fileName = getFileNameFromRecord(record);
+ const path = Utils.encodePath(Utils.joinPath(parentDir, fileName));
+ return siteRoot + 'lib/' + repoID + '/file' + path;
+};
diff --git a/frontend/src/metadata/utils/open-file.js b/frontend/src/metadata/utils/open-file.js
index 2263a4b138..18310c0586 100644
--- a/frontend/src/metadata/utils/open-file.js
+++ b/frontend/src/metadata/utils/open-file.js
@@ -2,7 +2,6 @@ import { getFileNameFromRecord, getParentDirFromRecord } from './cell';
import { checkIsDir } from './row';
import { Utils } from '../../utils/utils';
import { siteRoot } from '../../utils/constants';
-import { EVENT_BUS_TYPE } from '../../components/common/event-bus-type';
const FILE_TYPE = {
FOLDER: 'folder',
@@ -32,23 +31,28 @@ const _getParentDir = (record) => {
return parentDir;
};
-const _generateUrl = (fileName, parentDir) => {
- const repoID = window.sfMetadataContext.getSetting('repoID');
+const _generateUrl = (repoID, fileName, parentDir) => {
const path = Utils.encodePath(Utils.joinPath(parentDir, fileName));
return `${siteRoot}lib/${repoID}/file${path}`;
};
const _openUrl = (url) => {
+ const isWeChat = Utils.isWeChat();
+ if (isWeChat) {
+ location.href = url;
+ return;
+ }
window.open(url);
};
-const _openMarkdown = (fileName, parentDir, eventBus) => {
- eventBus && eventBus.dispatch(EVENT_BUS_TYPE.OPEN_MARKDOWN, parentDir, fileName);
+const _openMarkdown = (repoID, fileName, parentDir) => {
+ const url = _generateUrl(repoID, fileName, parentDir);
+ _openUrl(url);
};
-const _openByNewWindow = (fileName, parentDir, fileType) => {
+const _openByNewWindow = (repoID, fileName, parentDir, fileType) => {
if (!fileType) {
- const url = _generateUrl(fileName, parentDir);
+ const url = _generateUrl(repoID, fileName, parentDir);
_openUrl(url);
return;
}
@@ -59,16 +63,16 @@ const _openByNewWindow = (fileName, parentDir, fileType) => {
_openUrl(window.location.origin + pathname + Utils.encodePath(Utils.joinPath(parentDir, fileName)));
};
-const _openSdoc = (fileName, parentDir) => {
- const url = _generateUrl(fileName, parentDir);
+const _openSdoc = (repoID, fileName, parentDir) => {
+ const url = _generateUrl(repoID, fileName, parentDir);
_openUrl(url);
};
-const _openOthers = (fileName, parentDir, fileType) => {
- _openByNewWindow(fileName, parentDir, fileType);
+const _openOthers = (repoID, fileName, parentDir, fileType) => {
+ _openByNewWindow(repoID, fileName, parentDir, fileType);
};
-export const openFile = (record, eventBus, _openImage = () => {}) => {
+export const openFile = (repoID, record, _openImage = () => {}) => {
if (!record) return;
const fileName = getFileNameFromRecord(record);
const isDir = checkIsDir(record);
@@ -77,11 +81,11 @@ export const openFile = (record, eventBus, _openImage = () => {}) => {
switch (fileType) {
case FILE_TYPE.MARKDOWN: {
- _openMarkdown(fileName, parentDir, eventBus);
+ _openMarkdown(repoID, fileName, parentDir);
break;
}
case FILE_TYPE.SDOC: {
- _openSdoc(fileName, parentDir);
+ _openSdoc(repoID, fileName, parentDir);
break;
}
case FILE_TYPE.IMAGE: {
@@ -89,7 +93,7 @@ export const openFile = (record, eventBus, _openImage = () => {}) => {
break;
}
default: {
- _openOthers(fileName, parentDir, fileType);
+ _openOthers(repoID, fileName, parentDir, fileType);
break;
}
}
diff --git a/frontend/src/metadata/views/kanban/boards/board/card/index.css b/frontend/src/metadata/views/kanban/boards/board/card/index.css
index 28fd3ef8a7..4db250ea94 100644
--- a/frontend/src/metadata/views/kanban/boards/board/card/index.css
+++ b/frontend/src/metadata/views/kanban/boards/board/card/index.css
@@ -12,7 +12,7 @@
user-select: none;
}
-.smooth-dnd-container.vertical .sf-metadata-kanban-card:last-child {
+.smooth-dnd-container.vertical .smooth-dnd-draggable-wrapper:last-child .sf-metadata-kanban-card {
margin-bottom: 0;
}
diff --git a/frontend/src/metadata/views/kanban/boards/index.js b/frontend/src/metadata/views/kanban/boards/index.js
index f3c17bca37..31b34e3985 100644
--- a/frontend/src/metadata/views/kanban/boards/index.js
+++ b/frontend/src/metadata/views/kanban/boards/index.js
@@ -176,7 +176,8 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
}, []);
const onOpenFile = useCallback((record) => {
- openFile(record, window.sfMetadataContext.eventBus, () => {
+ const repoID = window.sfMetadataContext.getSetting('repoID');
+ openFile(repoID, record, () => {
currentImageRef.current = record;
setImagePreviewerVisible(true);
});
@@ -222,6 +223,8 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
}, [isDirentDetailShow]);
const isEmpty = boards.length === 0;
+ const repoID = window.sfMetadataContext.getSetting('repoID');
+ const repoInfo = window.sfMetadataContext.getSetting('repoInfo');
return (
- {isImagePreviewerVisible && ()}
+ {isImagePreviewerVisible && (
+
+ )}
);
};
diff --git a/frontend/src/metadata/views/table/table-main/records/record/cell/operation-btn/file-name-operation-btn/index.js b/frontend/src/metadata/views/table/table-main/records/record/cell/operation-btn/file-name-operation-btn/index.js
index 7d117e93db..a71c0811a9 100644
--- a/frontend/src/metadata/views/table/table-main/records/record/cell/operation-btn/file-name-operation-btn/index.js
+++ b/frontend/src/metadata/views/table/table-main/records/record/cell/operation-btn/file-name-operation-btn/index.js
@@ -21,7 +21,8 @@ const FileNameOperationBtn = ({ column, record, ...props }) => {
const handelClick = (event) => {
event.stopPropagation();
event.nativeEvent.stopImmediatePropagation();
- openFile(record, window.sfMetadataContext.eventBus, () => {
+ const repoID = window.sfMetadataContext.getSetting('repoID');
+ openFile(repoID, record, () => {
window.sfMetadataContext.eventBus.dispatch(METADATA_EVENT_BUS_TYPE.OPEN_EDITOR, EDITOR_TYPE.PREVIEWER);
});
};
diff --git a/frontend/src/pages/lib-content-view/lib-content-view.js b/frontend/src/pages/lib-content-view/lib-content-view.js
index 074bfadf67..e07c4e512d 100644
--- a/frontend/src/pages/lib-content-view/lib-content-view.js
+++ b/frontend/src/pages/lib-content-view/lib-content-view.js
@@ -447,14 +447,6 @@ class LibContentView extends React.Component {
window.history.pushState({ url: url, path: path }, path, url);
};
- openMarkDown = (parentDir, fileName) => {
- let filePath = Utils.joinPath(parentDir, fileName);
- let repoID = this.props.repoID;
- const w = window.open('about:blank');
- const url = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(filePath);
- w.location.href = url;
- };
-
showFile = (filePath, noRedirection) => {
let repoID = this.props.repoID;
@@ -517,10 +509,6 @@ class LibContentView extends React.Component {
path: filePath,
viewId: viewId,
isDirentDetailShow: viewType === VIEW_TYPE.GALLERY ? this.state.isDirentDetailShow : false,
- }, () => {
- setTimeout(() => {
- this.unsubscribeEventBus = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.OPEN_MARKDOWN, this.openMarkDown);
- }, 1);
});
const url = `${siteRoot}library/${repoID}/${encodeURIComponent(repoInfo.repo_name)}/?view=${encodeURIComponent(viewId)}`;
window.history.pushState({ url: url, path: '' }, '', url);
diff --git a/frontend/src/tag/hooks/tag-view.js b/frontend/src/tag/hooks/tag-view.js
index aba5b2ca2f..f658f9e4d0 100644
--- a/frontend/src/tag/hooks/tag-view.js
+++ b/frontend/src/tag/hooks/tag-view.js
@@ -45,6 +45,7 @@ export const TagViewProvider = ({ repoID, tagID, children, ...params }) => {
tagFiles,
repoID,
tagID,
+ repoInfo: params.repoInfo,
deleteFilesCallback: params.deleteFilesCallback,
renameFileCallback: params.renameFileCallback,
updateCurrentDirent: params.updateCurrentDirent,
diff --git a/frontend/src/tag/tags-tree-view/index.js b/frontend/src/tag/tags-tree-view/index.js
index 2f5f7d309c..6e974736df 100644
--- a/frontend/src/tag/tags-tree-view/index.js
+++ b/frontend/src/tag/tags-tree-view/index.js
@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect, useMemo, useRef } from 'react';
+import React, { useEffect, useMemo, useRef } from 'react';
import PropTypes from 'prop-types';
import { useTags } from '../hooks';
import Tag from './tag';
@@ -19,8 +19,7 @@ const updateFavicon = () => {
const TagsTreeView = ({ userPerm, currentPath }) => {
const originalTitle = useRef('');
- // const {} = { }
- const { tagsData, selectTag, deleteTags, duplicateTag, updateTag } = useTags();
+ const { tagsData, selectTag } = useTags();
const tags = useMemo(() => {
if (!tagsData) return [];
@@ -32,16 +31,6 @@ const TagsTreeView = ({ userPerm, currentPath }) => {
return true;
}, [userPerm]);
- const deleteTag = useCallback((tagId, isSelected) => {
- if (isSelected) {
- const currentTagIndex = tagsData.row_ids.indexOf(tagId);
- const lastTagId = tagsData.row_ids[currentTagIndex - 1];
- const lastTag = getRowById(tagsData, lastTagId);
- selectTag(lastTag);
- }
- deleteTags([tagId]);
- }, [tagsData, deleteTags, selectTag]);
-
useEffect(() => {
originalTitle.current = document.title;
}, []);
@@ -105,13 +94,8 @@ const TagsTreeView = ({ userPerm, currentPath }) => {
selectTag(tag, isSelected)}
- onDelete={() => deleteTag(id, isSelected)}
- onCopy={() => duplicateTag(id)}
- onUpdateTag={updateTag}
/>
);
})}
diff --git a/frontend/src/tag/tags-tree-view/tag/index.css b/frontend/src/tag/tags-tree-view/tag/index.css
index 4e8773c22f..e5a41875f3 100644
--- a/frontend/src/tag/tags-tree-view/tag/index.css
+++ b/frontend/src/tag/tags-tree-view/tag/index.css
@@ -1,8 +1,8 @@
.tag-tree-node .tag-tree-node-color {
- height: 12px;
- width: 12px;
+ height: 10px;
+ width: 10px;
border-radius: 50%;
- transform: translateY(2px);
+ transform: translateY(3px);
}
.tag-tree-node .tag-tree-node-text {
@@ -14,11 +14,22 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
+ flex: 1;
}
.tag-tree-node .tag-tree-node-text .tag-tree-node-count {
color: #666;
font-size: 14px;
margin-left: 8px;
- margin-right: 8px;
+ padding-right: 14px;
+ min-width: 36px;
+ text-align: right;
+}
+
+.metadata-tree-view .tag-tree-node .tag-tree-node-text {
+ width: calc(100%);
+}
+
+.metadata-tree-view .tag-tree-node .right-icon:hover {
+ background-color: unset;
}
diff --git a/frontend/src/tag/tags-tree-view/tag/index.js b/frontend/src/tag/tags-tree-view/tag/index.js
index 27bf8b21df..04d024ce67 100644
--- a/frontend/src/tag/tags-tree-view/tag/index.js
+++ b/frontend/src/tag/tags-tree-view/tag/index.js
@@ -1,227 +1,51 @@
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
-import { Input } from 'reactstrap';
-import { gettext } from '../../../utils/constants';
-import ItemDropdownMenu from '../../../components/dropdown-menu/item-dropdown-menu';
-import { isMobile } from '../../../utils/utils';
-import { getTagColor, getTagName, getTagId, getTagFilesCount, isValidTagName } from '../../utils';
-import { isEnter } from '../../../metadata/utils/hotkey';
-import toaster from '../../../components/toast';
-import { PRIVATE_COLUMN_KEY } from '../../constants';
+import { getTagColor, getTagName, getTagFilesCount } from '../../utils';
import './index.css';
-const Tag = ({
- userPerm,
- isSelected,
- tag,
- tags,
- onClick,
- onDelete,
- onCopy,
- onUpdateTag,
-}) => {
+const Tag = ({ isSelected, tag, onClick }) => {
const tagName = useMemo(() => getTagName(tag), [tag]);
const tagColor = useMemo(() => getTagColor(tag), [tag]);
- const tagId = useMemo(() => getTagId(tag), [tag]);
const tagCount = useMemo(() => getTagFilesCount(tag), [tag]);
const [highlight, setHighlight] = useState(false);
- const [freeze, setFreeze] = useState(false);
- const [isRenaming, setRenaming] = useState(false);
- const [inputValue, setInputValue] = useState('');
-
- const inputRef = useRef(null);
-
- const otherTagsName = useMemo(() => {
- return tags.filter(tagItem => getTagId(tagItem) !== tagId).map(tagItem => getTagName(tagItem));
- }, [tags, tagId]);
-
- const canUpdate = useMemo(() => {
- if (userPerm !== 'rw' && userPerm !== 'admin') return false;
- return true;
- }, [userPerm]);
-
- const operations = useMemo(() => {
- if (!canUpdate) return [];
- const value = [
- { key: 'rename', value: gettext('Rename') },
- { key: 'duplicate', value: gettext('Duplicate') },
- { key: 'delete', value: gettext('Delete') }
- ];
- return value;
- }, [canUpdate]);
const onMouseEnter = useCallback(() => {
- if (freeze) return;
setHighlight(true);
- }, [freeze]);
+ }, []);
const onMouseOver = useCallback(() => {
- if (freeze) return;
setHighlight(true);
- }, [freeze]);
+ }, []);
const onMouseLeave = useCallback(() => {
- if (freeze) return;
- setHighlight(false);
- }, [freeze]);
-
- const freezeItem = useCallback(() => {
- setFreeze(true);
- }, []);
-
- const unfreezeItem = useCallback(() => {
- setFreeze(false);
setHighlight(false);
}, []);
- const operationClick = useCallback((operationKey) => {
- switch (operationKey) {
- case 'rename': {
- setInputValue(tagName);
- setRenaming(true);
- return;
- }
- case 'duplicate': {
- onCopy();
- return;
- }
- case 'delete': {
- onDelete();
- return;
- }
- default: {
- return;
- }
- }
- }, [tagName, onDelete, onCopy]);
-
- const renameTag = useCallback((name, failCallback) => {
- onUpdateTag(tagId, { [PRIVATE_COLUMN_KEY.TAG_NAME]: name }, {
- success_callback: () => {
- setRenaming(false);
- if (!isSelected) return;
- document.title = `${name} - Seafile`;
- },
- fail_callback: (error) => {
- failCallback(error);
- if (!isSelected) return;
- document.title = `${tagName} - Seafile`;
- }
- });
- }, [onUpdateTag, isSelected, tagId, tagName]);
-
- const handleSubmit = useCallback((event) => {
- event.preventDefault();
- event.stopPropagation();
- const { isValid, message } = isValidTagName(inputValue, otherTagsName);
- if (!isValid) {
- toaster.danger(message);
- return;
- }
- if (message === tagName) {
- setRenaming(false);
- return;
- }
- renameTag(message);
- }, [tagName, inputValue, otherTagsName, renameTag]);
-
- const onChange = useCallback((e) => {
- setInputValue(e.target.value);
- }, []);
-
- const onKeyDown = useCallback((event) => {
- if (isEnter(event)) {
- handleSubmit(event);
- unfreezeItem();
- }
- }, [handleSubmit, unfreezeItem]);
-
- const onInputClick = useCallback((event) => {
- event.stopPropagation();
- event.nativeEvent.stopImmediatePropagation();
- }, []);
-
- useEffect(() => {
- if (isRenaming && inputRef.current) {
- inputRef.current.focus();
- inputRef.current.select();
- }
- }, [isRenaming]);
-
- useEffect(() => {
- const handleClickOutside = (event) => {
- if (inputRef.current && !inputRef.current.contains(event.target)) {
- handleSubmit(event);
- }
- };
-
- if (isRenaming) {
- document.addEventListener('mousedown', handleClickOutside);
- } else {
- document.removeEventListener('mousedown', handleClickOutside);
- }
-
- return () => {
- document.removeEventListener('mousedown', handleClickOutside);
- };
- }, [isRenaming, handleSubmit]);
-
return (
- <>
- onClick(tag)}
- >
-
-
- {isRenaming ? (
- setRenaming(false)}
- onClick={onInputClick}
- onKeyDown={onKeyDown}
- />
- ) : (
- <>{tagName}>
- )}
-
- {` (${tagCount})`}
-
-
- |