Skip to content

Commit

Permalink
feat: filename support open a file (#6304)
Browse files Browse the repository at this point in the history
* feat: filename support open a file

* feat: add currentRepoInfo

* feat: op code

---------

Co-authored-by: 杨国璇 <[email protected]>
  • Loading branch information
YangGuoXuan-0503 and 杨国璇 authored Jul 5, 2024
1 parent 024290a commit ae5b90e
Show file tree
Hide file tree
Showing 13 changed files with 302 additions and 80 deletions.
14 changes: 7 additions & 7 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@seafile/sdoc-editor": "1.0.11",
"@seafile/seafile-calendar": "0.0.12",
"@seafile/seafile-editor": "1.0.99",
"@seafile/sf-metadata-ui-component": "0.0.9",
"@seafile/sf-metadata-ui-component": "0.0.10",
"@uiw/codemirror-extensions-langs": "^4.19.4",
"@uiw/react-codemirror": "^4.19.4",
"chart.js": "2.9.4",
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/dir-view-mode/dir-column-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const propTypes = {
lastModified: PropTypes.string,
latestContributor: PropTypes.string,
onLinkClick: PropTypes.func.isRequired,
currentRepoInfo: PropTypes.object,
};

class DirColumnFile extends React.Component {
Expand Down Expand Up @@ -60,7 +61,7 @@ class DirColumnFile extends React.Component {
return (
<div className="w-100 h-100 o-hidden d-flex" style={{ paddingRight: 10, flexDirection: 'column', alignItems: 'center' }}>
<div className="" style={{ width: '100%', height: 10, zIndex: 7, transform: 'translateZ(1000px)', position: 'relative', background: '#fff' }}></div>
<SeafileMetadata repoID={this.props.repoID} />
<SeafileMetadata repoID={this.props.repoID} currentRepoInfo={this.props.currentRepoInfo} />
</div>
);
}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/dir-view-mode/dir-column-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ class DirColumnView extends React.Component {
isFileLoadedErr={this.props.isFileLoadedErr}
filePermission={this.props.filePermission}
content={this.props.content}
currentRepoInfo={this.props.currentRepoInfo}
lastModified={this.props.lastModified}
latestContributor={this.props.latestContributor}
onLinkClick={this.props.onLinkClick}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import Editor from './editor';

const EditorContainer = (props) => {
if (!props.column) return null;
return (<Editor { ...props } />);
};


EditorContainer.propTypes = {
table: PropTypes.object,
columns: PropTypes.array,
isGroupView: PropTypes.bool,
scrollTop: PropTypes.number,
scrollLeft: PropTypes.number,
firstEditorKeyDown: PropTypes.object,
openEditorMode: PropTypes.string,
portalTarget: PropTypes.any,
editorPosition: PropTypes.object,
record: PropTypes.object,
column: PropTypes.object,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
left: PropTypes.number.isRequired,
top: PropTypes.number.isRequired,
onCommit: PropTypes.func,
onCommitCancel: PropTypes.func,
};

export default EditorContainer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';

class EditorPortal extends React.Component {
static propTypes = {
children: PropTypes.node.isRequired,
target: PropTypes.instanceOf(Element).isRequired
};

// Keep track of when the modal element is added to the DOM
state = {
isMounted: false
};

el = document.createElement('div');

componentDidMount() {
this.props.target.appendChild(this.el);
// eslint-disable-next-line react/no-did-mount-set-state
this.setState({ isMounted: true });
}

componentWillUnmount() {
this.props.target.removeChild(this.el);
}

render() {
// Don't render the portal until the component has mounted,
// So the portal can safely access the DOM.
if (!this.state.isMounted) {
return null;
}

return ReactDOM.createPortal(
this.props.children,
this.el,
);
}
}

export default EditorPortal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import PropTypes from 'prop-types';
import { CellType } from '../../_basic';
import FileNameEditor from './file-name-editor';

const Editor = (props) => {

switch (props.column.type) {
case CellType.FILE_NAME: {
return (<FileNameEditor {...props} />);
}
default: {
return null;
}
}
};

Editor.propTypes = {
column: PropTypes.object.isRequired,
};

export default Editor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React, { useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { ModalPortal } from '@seafile/sf-metadata-ui-component';
import { PRIVATE_COLUMN_KEY } from '../../_basic';
import { Utils } from '../../../../utils/utils';
import ImageDialog from '../../../../components/dialog/image-dialog';
import { serviceURL, siteRoot, thumbnailSizeForOriginal } from '../../../../utils/constants';

const FileNameEditor = ({ column, record, onCommitCancel }) => {
const _isDir = useMemo(() => {
const isDirValue = record[PRIVATE_COLUMN_KEY.IS_DIR];
if (typeof isDirValue === 'string') return isDirValue.toUpperCase() === 'TRUE';
return isDirValue;
}, [record]);

const fileName = useMemo(() => {
const { key } = column;
return record[key];
}, [column, record]);

const fileType = useMemo(() => {
if (_isDir) return 'folder';
if (!fileName) return '';
const index = fileName.lastIndexOf('.');
if (index === -1) return '';
const suffix = fileName.slice(index).toLowerCase();
if (Utils.imageCheck(fileName)) return 'image';
if (suffix === '.sdoc') return 'sdoc';
return 'file';
}, [_isDir, fileName]);

const parentDir = useMemo(() => {
const value = record[PRIVATE_COLUMN_KEY.PARENT_DIR];
if (value === '/') return '';
return value;
}, [record]);

const repoID = useMemo(() => {
return window.sfMetadataContext.getSetting('repoID');
}, []);

const path = useMemo(() => {
return Utils.encodePath(Utils.joinPath(parentDir, fileName));
}, [parentDir, fileName]);

const url = useMemo(() => {
return `${siteRoot}lib/${repoID}/file${path}`;
}, [path, repoID]);

useEffect(() => {
if (fileType === 'image') return;
onCommitCancel && onCommitCancel();
}, [fileType, onCommitCancel]);

if (fileType === 'image') {
const fileExt = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase();
const isGIF = fileExt === 'gif';
const useThumbnail = window.sfMetadataContext.getSetting('currentRepoInfo')?.encrypted;
let src = '';
if (useThumbnail && !isGIF) {
src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`;
} else {
src = `${siteRoot}repo/${repoID}/raw${path}`;
}
const images = [
{ 'name': fileName, 'url': url, 'src': src },
];
return (
<ModalPortal>
<ImageDialog
imageItems={images}
imageIndex={0}
closeImagePopup={onCommitCancel}
moveToPrevImage={() => {}}
moveToNextImage={() => {}}
/>
</ModalPortal>
);
}

if (!fileType || fileType === 'sdoc') {
window.open(serviceURL + url);
} else {
window.open(window.location.href + Utils.encodePath(Utils.joinPath(parentDir, fileName)));
}
return null;
};

FileNameEditor.propTypes = {
column: PropTypes.object,
record: PropTypes.object,
onCommitCancel: PropTypes.func,
};

export default FileNameEditor;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import EditorPortal from './editor-portal';
import EditorContainer from './editor-container';

export {
EditorPortal,
EditorContainer,
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import toaster from '../../../../../../components/toast';
import { isFunction } from '../../../../_basic';
import { PRIVATE_COLUMN_KEY, isFunction } from '../../../../_basic';
import { isNameColumn } from '../../../../utils/column-utils';
import { TABLE_SUPPORT_EDIT_TYPE_MAP } from '../../../../constants';
import { isCellValueChanged } from '../../../../utils/cell-comparer';
Expand Down Expand Up @@ -75,9 +75,7 @@ class RecordCell extends React.Component {
};

onCellMouseDown = (e) => {
if (e.button === 2) {
return;
}
if (e.button === 2) return;
const { column, groupRecordIndex, recordIndex, cellMetaData } = this.props;
const cell = { idx: column.idx, groupRecordIndex, rowIdx: recordIndex };

Expand Down Expand Up @@ -133,9 +131,16 @@ class RecordCell extends React.Component {
toaster.warning(message);
};

isDir = () => {
const { record } = this.props;
const isDirValue = record[PRIVATE_COLUMN_KEY.IS_DIR];
if (typeof isDirValue === 'string') return isDirValue.toUpperCase() === 'TRUE';
return isDirValue;
};

render = () => {
const { frozen, record, column, needBindEvents, height, bgColor } = this.props;
const { key, name, left, width } = column;
const { key, left, width } = column;
const readonly = true;
const commentCount = isNameColumn(column) && this.getCommentCount();
const hasComment = !!commentCount;
Expand All @@ -151,15 +156,15 @@ class RecordCell extends React.Component {
cellStyle['backgroundColor'] = bgColor;
}

let cellValue = record[name] || record[key];
let cellValue = record[key];
const cellEvents = needBindEvents && this.getEvents();
const props = {
className,
style: cellStyle,
...cellEvents,
};
const cellContent = (
<CellFormatter readonly={readonly} value={cellValue} field={column} isDir={record['_is_dir'] === 'True'} />
<CellFormatter readonly={readonly} value={cellValue} field={column} isDir={this.isDir()} />
);

return (
Expand Down
Loading

0 comments on commit ae5b90e

Please sign in to comment.