mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-08 02:10:24 +00:00
open file
This commit is contained in:
@@ -135,3 +135,9 @@ export const GALLERY_DATE_MODE = {
|
||||
};
|
||||
|
||||
export const UNCATEGORIZED = '_uncategorized';
|
||||
|
||||
export const FILE_TYPE = {
|
||||
MARKDOWN: 'markdown',
|
||||
SDOC: 'sdoc',
|
||||
IMAGE: 'image',
|
||||
};
|
||||
|
@@ -9,6 +9,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card:hover {
|
||||
@@ -16,6 +17,10 @@
|
||||
box-shadow: 0 0 6px #0000002e;
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card.readonly {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .sf-metadata-kanban-card-header {
|
||||
font-weight: 500;
|
||||
width: 100%;
|
||||
@@ -34,10 +39,6 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .sf-metadata-kanban-card-record .file-name-formatter-wrapper {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .sf-metadata-kanban-card-record .sf-metadata-kanban-card-record-name {
|
||||
margin-bottom: 4px;
|
||||
color: #666;
|
||||
@@ -76,7 +77,7 @@
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .sf-metadata-special-file-name-formatter:not(.sf-metadata-image-file-formatter) {
|
||||
margin-left: -2px;
|
||||
transform: translateX(-2px)
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .file-name-formatter .sf-metadata-file-icon {
|
||||
@@ -89,6 +90,7 @@
|
||||
}
|
||||
|
||||
.sf-metadata-kanban-card .sf-metadata-ui.file-name-formatter .sf-metadata-file-name:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #212529;
|
||||
}
|
||||
|
@@ -1,10 +1,11 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { getCellValueByColumn, isValidCellValue } from '../../../../../utils/cell';
|
||||
import Formatter from '../formatter';
|
||||
import { PRIVATE_COLUMN_KEY } from '../../../../../constants';
|
||||
import { FILE_TYPE } from '../../../../../constants';
|
||||
import { useMetadataView } from '../../../../../hooks/metadata-view';
|
||||
import { Utils } from '../../../../../../utils/utils';
|
||||
import { geRecordIdFromRecord, getCellValueByColumn, getFileNameFromRecord, getParentDirFromRecord, isValidCellValue } from '../../../../../utils/cell';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@@ -16,7 +17,10 @@ const Card = ({
|
||||
titleColumn,
|
||||
displayColumns,
|
||||
onCloseSettings,
|
||||
onOpenFile,
|
||||
}) => {
|
||||
const cardRef = useRef(null);
|
||||
|
||||
const { updateCurrentDirent, showDirentDetail } = useMetadataView();
|
||||
|
||||
const titleValue = getCellValueByColumn(record, titleColumn);
|
||||
@@ -24,8 +28,8 @@ const Card = ({
|
||||
const handleClick = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const name = record[PRIVATE_COLUMN_KEY.FILE_NAME];
|
||||
const path = record[PRIVATE_COLUMN_KEY.PARENT_DIR];
|
||||
const name = getFileNameFromRecord(record);
|
||||
const path = getParentDirFromRecord(record);
|
||||
updateCurrentDirent({
|
||||
type: 'file',
|
||||
name,
|
||||
@@ -36,14 +40,48 @@ const Card = ({
|
||||
showDirentDetail();
|
||||
}, [record, updateCurrentDirent, showDirentDetail, onCloseSettings]);
|
||||
|
||||
const getFileType = useCallback((fileName) => {
|
||||
if (!fileName) return '';
|
||||
const index = fileName.lastIndexOf('.');
|
||||
if (index === -1) return '';
|
||||
const suffix = fileName.slice(index).toLowerCase();
|
||||
if (suffix.indexOf(' ') > -1) return '';
|
||||
if (Utils.imageCheck(fileName)) return FILE_TYPE.IMAGE;
|
||||
if (Utils.isMarkdownFile(fileName)) return FILE_TYPE.MARKDOWN;
|
||||
if (Utils.isSdocFile(fileName)) return FILE_TYPE.SDOC;
|
||||
return '';
|
||||
}, []);
|
||||
|
||||
const handleClickFilename = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
console.log('click filename');
|
||||
}, []);
|
||||
|
||||
const fileName = getFileNameFromRecord(record);
|
||||
const fileType = getFileType(fileName);
|
||||
const parentDir = getParentDirFromRecord(record);
|
||||
const recordId = geRecordIdFromRecord(record);
|
||||
onOpenFile(fileType, fileName, parentDir, recordId);
|
||||
}, [record, getFileType, onOpenFile]);
|
||||
|
||||
useEffect(() => {
|
||||
const cardElement = cardRef.current;
|
||||
if (!cardElement) return;
|
||||
|
||||
const filenameElement = cardElement.querySelector('.file-name-formatter .sf-metadata-file-name');
|
||||
if (filenameElement) {
|
||||
filenameElement.addEventListener('click', handleClickFilename);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (filenameElement) {
|
||||
filenameElement.removeEventListener('click', handleClickFilename);
|
||||
}
|
||||
};
|
||||
}, [handleClickFilename]);
|
||||
|
||||
return (
|
||||
<article
|
||||
ref={cardRef}
|
||||
data-id={record._id}
|
||||
className={classnames('sf-metadata-kanban-card', { 'readonly': readonly })}
|
||||
onClick={handleClick}
|
||||
@@ -70,9 +108,7 @@ const Card = ({
|
||||
return (
|
||||
<div className="sf-metadata-kanban-card-record" key={column.key}>
|
||||
{displayColumnName && (<div className="sf-metadata-kanban-card-record-name">{column.name}</div>)}
|
||||
<div className='file-name-formatter-wrapper' onClick={handleClickFilename}>
|
||||
<Formatter value={value} column={column} record={record}/>
|
||||
</div>
|
||||
<Formatter value={value} column={column} record={record}/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -89,6 +125,7 @@ Card.propTypes = {
|
||||
titleColumn: PropTypes.object,
|
||||
displayColumns: PropTypes.array,
|
||||
onCloseSettings: PropTypes.func.isRequired,
|
||||
onOpenFile: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Card;
|
||||
|
@@ -24,6 +24,7 @@ const Board = ({
|
||||
onFreezed,
|
||||
onUnFreezed,
|
||||
onCloseSettings,
|
||||
onOpenFile,
|
||||
}) => {
|
||||
const [isDraggingOver, setDraggingOver] = useState(false);
|
||||
const boardName = useMemo(() => `sf_metadata_kanban_board_${board.key}`, [board]);
|
||||
@@ -84,6 +85,7 @@ const Board = ({
|
||||
titleColumn={titleColumn}
|
||||
displayColumns={displayColumns}
|
||||
onCloseSettings={onCloseSettings}
|
||||
onOpenFile={onOpenFile}
|
||||
/>
|
||||
);
|
||||
if (readonly) return CardElement;
|
||||
@@ -113,6 +115,7 @@ Board.propTypes = {
|
||||
onFreezed: PropTypes.func,
|
||||
onUnFreezed: PropTypes.func,
|
||||
onCloseSettings: PropTypes.func.isRequired,
|
||||
onOpenFile: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Board;
|
||||
|
@@ -3,19 +3,25 @@ import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useMetadataView } from '../../../hooks/metadata-view';
|
||||
import { useCollaborators } from '../../../hooks';
|
||||
import { CellType, KANBAN_SETTINGS_KEYS, UNCATEGORIZED } from '../../../constants';
|
||||
import { CellType, KANBAN_SETTINGS_KEYS, UNCATEGORIZED, FILE_TYPE } from '../../../constants';
|
||||
import { COLUMN_DATA_OPERATION_TYPE } from '../../../store/operations';
|
||||
import { gettext } from '../../../../utils/constants';
|
||||
import { gettext, siteRoot } from '../../../../utils/constants';
|
||||
import { checkIsPredefinedOption, getCellValueByColumn, isValidCellValue, geRecordIdFromRecord } from '../../../utils/cell';
|
||||
import { getColumnOptions, getColumnOriginName } from '../../../utils/column';
|
||||
import AddBoard from '../add-board';
|
||||
import EmptyTip from '../../../../components/empty-tip';
|
||||
import Board from './board';
|
||||
import { Utils } from '../../../../utils/utils';
|
||||
import { EVENT_BUS_TYPE } from '../../../../components/common/event-bus-type';
|
||||
import ImagePreviewer from '../../../components/cell-formatter/image-previewer';
|
||||
|
||||
import './index.css';
|
||||
import { getRowById } from '../../../utils/table';
|
||||
|
||||
const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
||||
const [haveFreezed, setHaveFreezed] = useState(false);
|
||||
const [isShowImagePreviewer, setIsShowImagePreviewer] = useState(false);
|
||||
const [record, setRecord] = useState(null);
|
||||
|
||||
const { metadata, store } = useMetadataView();
|
||||
const { collaborators } = useCollaborators();
|
||||
@@ -166,6 +172,61 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
||||
|
||||
const isEmpty = boards.length === 0;
|
||||
|
||||
const generateUrl = (fileName, parentDir) => {
|
||||
const repoID = window.sfMetadataContext.getSetting('repoID');
|
||||
const path = Utils.encodePath(Utils.joinPath(parentDir, fileName));
|
||||
return `${siteRoot}lib/${repoID}/file${path}`;
|
||||
};
|
||||
|
||||
const openMarkdown = (name, parentDir) => {
|
||||
window.sfMetadataContext.eventBus.dispatch(EVENT_BUS_TYPE.OPEN_MARKDOWN_DIALOG, parentDir, name);
|
||||
};
|
||||
|
||||
const openByNewWindow = (fileType, fileName, parentDir) => {
|
||||
if (!fileType) {
|
||||
const url = generateUrl(fileName, parentDir);
|
||||
window.open(url);
|
||||
} else {
|
||||
let pathname = window.location.pathname;
|
||||
if (pathname.endsWith('/')) {
|
||||
pathname = pathname.slice(0, -1);
|
||||
}
|
||||
window.open(window.location.origin + pathname + Utils.encodePath(Utils.joinPath(parentDir, fileName)));
|
||||
}
|
||||
};
|
||||
|
||||
const openSdoc = (fileName, parentDir) => {
|
||||
const url = generateUrl(fileName, parentDir);
|
||||
window.open(url);
|
||||
};
|
||||
|
||||
const openFile = (type, fileName, parentDir, recordId = null) => {
|
||||
switch (type) {
|
||||
case FILE_TYPE.MARKDOWN: {
|
||||
openMarkdown(fileName, parentDir);
|
||||
break;
|
||||
}
|
||||
case FILE_TYPE.SDOC: {
|
||||
openSdoc(fileName, parentDir);
|
||||
break;
|
||||
}
|
||||
case FILE_TYPE.IMAGE: {
|
||||
const record = getRowById(metadata, recordId);
|
||||
setRecord(record);
|
||||
setIsShowImagePreviewer(true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
openByNewWindow(type, fileName, parentDir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const closeImagePreviewer = () => {
|
||||
setIsShowImagePreviewer(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classnames('sf-metadata-view-kanban-boards', {
|
||||
'sf-metadata-view-kanban-boards-text-wrap': textWrap,
|
||||
@@ -194,6 +255,7 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
||||
onFreezed={onFreezed}
|
||||
onUnFreezed={onUnFreezed}
|
||||
onCloseSettings={onCloseSettings}
|
||||
onOpenFile={openFile}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
@@ -201,6 +263,7 @@ const Boards = ({ modifyRecord, modifyColumnData, onCloseSettings }) => {
|
||||
)}
|
||||
{!readonly && (<AddBoard groupByColumn={groupByColumn}/>)}
|
||||
</div>
|
||||
{isShowImagePreviewer && (<ImagePreviewer record={record} table={metadata} closeImagePopup={closeImagePreviewer} />)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user