mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-03 07:55:36 +00:00
[dir view, repo wiki mode] show images with popup (#2834)
* [dir view, repo wiki mode] show images with popup * [image pupup] modification
This commit is contained in:
25
frontend/package-lock.json
generated
25
frontend/package-lock.json
generated
@@ -4199,6 +4199,11 @@
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
|
||||
@@ -9940,6 +9945,15 @@
|
||||
"prop-types": "^15.6.0"
|
||||
}
|
||||
},
|
||||
"react-image-lightbox": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-image-lightbox/-/react-image-lightbox-5.1.0.tgz",
|
||||
"integrity": "sha512-R46QvffoDBscLQgTl4s3kFxVbnP7a+nIh7AXJNS0EXVeDaa6zKDKtIT+jFeEvs+F9oUHtZfenG1NHhTkO4hEOA==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.2",
|
||||
"react-modal": "^3.6.1"
|
||||
}
|
||||
},
|
||||
"react-immutable-proptypes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-immutable-proptypes/-/react-immutable-proptypes-2.1.0.tgz",
|
||||
@@ -9958,6 +9972,17 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.8.1.tgz",
|
||||
"integrity": "sha512-aLKeZM9pgXpIKVwopRHMuvqKWiBajkqisDA8UzocdCF6S4fyKVfLWmZR5G1Q0ODBxxxxf2XIwiCP8G/11GJAuw==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"react-moment": {
|
||||
"version": "0.7.9",
|
||||
"resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.7.9.tgz",
|
||||
|
@@ -28,6 +28,7 @@
|
||||
"react": "^16.4.2",
|
||||
"react-cookies": "^0.1.0",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-image-lightbox": "^5.1.0",
|
||||
"react-moment": "^0.7.9",
|
||||
"react-select": "^2.1.1",
|
||||
"reactstrap": "^6.4.0",
|
||||
|
@@ -195,6 +195,7 @@ class DirPanel extends React.Component {
|
||||
<DirentListView
|
||||
path={this.props.path}
|
||||
repoID={this.props.repoID}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
direntList={this.props.direntList}
|
||||
sortBy={this.props.sortBy}
|
||||
sortOrder={this.props.sortOrder}
|
||||
|
@@ -29,6 +29,7 @@ class DirView extends React.Component {
|
||||
pathExist: true,
|
||||
repoName: '',
|
||||
repoID: '',
|
||||
repoEncrypted: false,
|
||||
permission: true,
|
||||
libNeedDecrypt: false,
|
||||
isDirentSelected: false,
|
||||
@@ -76,7 +77,7 @@ class DirView extends React.Component {
|
||||
currentRepoInfo: repoInfo,
|
||||
repoID: repoInfo.repo_id,
|
||||
repoName: repoInfo.repo_name,
|
||||
encrypted: repoInfo.encrypted,
|
||||
repoEncrypted: repoInfo.encrypted,
|
||||
permission: repoInfo.permission === 'rw',
|
||||
libNeedDecrypt: res.data.lib_need_decrypt,
|
||||
});
|
||||
@@ -176,7 +177,7 @@ class DirView extends React.Component {
|
||||
dirID: res.headers.oid,
|
||||
});
|
||||
|
||||
if (!this.state.encrypted && direntList.length) {
|
||||
if (!this.state.repoEncrypted && direntList.length) {
|
||||
this.getThumbnails(repoID, path, this.state.direntList);
|
||||
}
|
||||
}).catch(() => {
|
||||
@@ -661,6 +662,7 @@ class DirView extends React.Component {
|
||||
errorMsg={this.state.errorMsg}
|
||||
repoID={this.state.repoID}
|
||||
repoName={this.state.repoName}
|
||||
repoEncrypted={this.state.repoEncrypted}
|
||||
permission={this.state.permission}
|
||||
isDirentListLoading={this.state.isDirentListLoading}
|
||||
isDirentSelected={this.state.isDirentSelected}
|
||||
|
@@ -113,7 +113,13 @@ class DirentListItem extends React.Component {
|
||||
|
||||
onItemClick = (e) => {
|
||||
e.preventDefault();
|
||||
this.props.onItemClick(this.props.dirent);
|
||||
|
||||
const dirent = this.props.dirent;
|
||||
if (Utils.imageCheck(dirent.name)) {
|
||||
this.props.showImagePopup(dirent);
|
||||
} else {
|
||||
this.props.onItemClick(dirent);
|
||||
}
|
||||
}
|
||||
|
||||
onItemDelete = (e) => {
|
||||
|
@@ -1,16 +1,21 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { siteRoot, gettext, thumbnailSizeForOriginal } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Loading from '../loading';
|
||||
import DirentListItem from './dirent-list-item';
|
||||
import ModalPortal from '../modal-portal';
|
||||
import CreateFile from '../../components/dialog/create-file-dialog';
|
||||
|
||||
import Lightbox from 'react-image-lightbox';
|
||||
import 'react-image-lightbox/style.css';
|
||||
|
||||
import '../../css/tip-for-new-md.css';
|
||||
|
||||
const propTypes = {
|
||||
path: PropTypes.string.isRequired,
|
||||
repoID: PropTypes.string.isRequired,
|
||||
repoEncrypted: PropTypes.bool.isRequired,
|
||||
isRepoOwner: PropTypes.bool,
|
||||
currentRepoInfo: PropTypes.object,
|
||||
isAllItemSelected: PropTypes.bool.isRequired,
|
||||
@@ -37,6 +42,11 @@ class DirentListView extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isItemFreezed: false,
|
||||
|
||||
isImagePopupOpen: false,
|
||||
imageItems: [],
|
||||
imageIndex: 0,
|
||||
|
||||
isCreateFileDialogShow: false,
|
||||
fileType: ''
|
||||
};
|
||||
@@ -91,6 +101,69 @@ class DirentListView extends React.Component {
|
||||
this.props.sortItems(sortBy, sortOrder);
|
||||
}
|
||||
|
||||
// for image popup
|
||||
prepareImageItems = () => {
|
||||
let items = this.props.direntList.filter((item) => {
|
||||
return Utils.imageCheck(item.name);
|
||||
});
|
||||
|
||||
const useThumbnail = !this.props.repoEncrypted;
|
||||
let prepareItem = (item) => {
|
||||
const name = item.name;
|
||||
|
||||
const fileExt = name.substr(name.lastIndexOf('.') + 1).toLowerCase();
|
||||
const isGIF = fileExt == 'gif';
|
||||
|
||||
const path = Utils.encodePath(Utils.joinPath(this.props.path, name));
|
||||
const repoID = this.props.repoID;
|
||||
let src;
|
||||
if (useThumbnail && !isGIF) {
|
||||
src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`;
|
||||
} else {
|
||||
src = `${siteRoot}repo/${repoID}/raw${path}`;
|
||||
}
|
||||
|
||||
return {
|
||||
'name': name,
|
||||
'url': `${siteRoot}lib/${repoID}/file${path}`,
|
||||
'src': src
|
||||
};
|
||||
}
|
||||
|
||||
return items.map((item) => { return prepareItem(item); });
|
||||
}
|
||||
|
||||
showImagePopup = (dirent) => {
|
||||
let items = this.props.direntList.filter((item) => {
|
||||
return Utils.imageCheck(item.name);
|
||||
});
|
||||
this.setState({
|
||||
isImagePopupOpen: true,
|
||||
imageItems: this.prepareImageItems(),
|
||||
imageIndex: items.indexOf(dirent)
|
||||
});
|
||||
}
|
||||
|
||||
moveToPrevImage = () => {
|
||||
const imageItemsLength = this.state.imageItems.length;
|
||||
this.setState((prevState) => ({
|
||||
imageIndex: (prevState.imageIndex + imageItemsLength - 1) % imageItemsLength
|
||||
}));
|
||||
}
|
||||
|
||||
moveToNextImage = () => {
|
||||
const imageItemsLength = this.state.imageItems.length;
|
||||
this.setState((prevState) => ({
|
||||
imageIndex: (prevState.imageIndex + 1) % imageItemsLength
|
||||
}));
|
||||
}
|
||||
|
||||
closeImagePopup = () => {
|
||||
this.setState({
|
||||
isImagePopupOpen: false
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { direntList, sortBy, sortOrder } = this.props;
|
||||
|
||||
@@ -124,7 +197,20 @@ class DirentListView extends React.Component {
|
||||
const sortByTime = sortBy == 'time';
|
||||
const sortIcon = sortOrder == 'asc' ? <span className="fas fa-caret-up"></span> : <span className="fas fa-caret-down"></span>;
|
||||
|
||||
// for image popup
|
||||
const imageItems = this.state.imageItems;
|
||||
const imageIndex = this.state.imageIndex;
|
||||
const imageItemsLength = imageItems.length;
|
||||
const imageCaption = imageItemsLength && (
|
||||
<Fragment>
|
||||
<span>{gettext("%curr% of %total%").replace('%curr%', imageIndex + 1).replace('%total%', imageItemsLength)}</span>
|
||||
<br />
|
||||
<a href={imageItems[imageIndex].url} target="_blank">{gettext("Open in New Tab")}</a>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -163,12 +249,33 @@ class DirentListView extends React.Component {
|
||||
onFreezedItem={this.onFreezedItem}
|
||||
onUnfreezedItem={this.onUnfreezedItem}
|
||||
onItemDetails={this.onItemDetails}
|
||||
showImagePopup={this.showImagePopup}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{this.state.isImagePopupOpen && (
|
||||
<Lightbox
|
||||
mainSrc={imageItems[imageIndex].src}
|
||||
imageTitle={imageItems[imageIndex].name}
|
||||
imageCaption={imageCaption}
|
||||
nextSrc={imageItems[(imageIndex + 1) % imageItemsLength].src}
|
||||
prevSrc={imageItems[(imageIndex + imageItemsLength - 1) % imageItemsLength].src}
|
||||
onCloseRequest={this.closeImagePopup}
|
||||
onMovePrevRequest={this.moveToPrevImage}
|
||||
onMoveNextRequest={this.moveToNextImage}
|
||||
imageLoadErrorMessage={gettext('The image could not be loaded.')}
|
||||
prevLabel={gettext("Previous (Left arrow key)")}
|
||||
nextLabel={gettext("Next (Right arrow key)")}
|
||||
closeLabel={gettext("Close (Esc)")}
|
||||
zoomInLabel={gettext('Zoom in')}
|
||||
zoomOutLabel={gettext('Zoom out')}
|
||||
/>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ const propTypes = {
|
||||
permission: PropTypes.string,
|
||||
hash: PropTypes.string,
|
||||
path: PropTypes.string.isRequired,
|
||||
repoEncrypted: PropTypes.bool.isRequired,
|
||||
// whether the file or dir corresponding to the path exist
|
||||
pathExist: PropTypes.bool.isRequired,
|
||||
isFileLoading: PropTypes.bool.isRequired,
|
||||
@@ -243,6 +244,7 @@ class MainPanel extends Component {
|
||||
<DirentListView
|
||||
path={this.props.path}
|
||||
repoID={repoID}
|
||||
repoEncrypted={this.props.repoEncrypted}
|
||||
direntList={this.props.direntList}
|
||||
sortBy={this.props.sortBy}
|
||||
sortOrder={this.props.sortOrder}
|
||||
|
@@ -28,6 +28,7 @@ class Wiki extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
repoEncrypted: false,
|
||||
path: '',
|
||||
pathExist: true,
|
||||
treeData: new Tree(),
|
||||
@@ -83,7 +84,7 @@ class Wiki extends Component {
|
||||
seafileAPI.getRepoInfo(repoID).then(res => {
|
||||
this.setState({
|
||||
libNeedDecrypt: res.data.lib_need_decrypt,
|
||||
encrypted: res.data.encrypted
|
||||
repoEncrypted: res.data.encrypted
|
||||
});
|
||||
|
||||
if (!res.data.lib_need_decrypt) {
|
||||
@@ -343,7 +344,7 @@ class Wiki extends Component {
|
||||
dirID: res.headers.oid,
|
||||
});
|
||||
|
||||
if (!this.state.encrypted && direntList.length) {
|
||||
if (!this.state.repoEncrypted && direntList.length) {
|
||||
this.getThumbnails(repoID, path, this.state.direntList);
|
||||
}
|
||||
});
|
||||
@@ -1000,6 +1001,7 @@ class Wiki extends Component {
|
||||
/>
|
||||
<MainPanel
|
||||
path={this.state.path}
|
||||
repoEncrypted={this.state.repoEncrypted}
|
||||
isViewFile={this.state.isViewFile}
|
||||
pathExist={this.state.pathExist}
|
||||
isDirentListLoading={this.state.isDirentListLoading}
|
||||
|
@@ -36,6 +36,7 @@ export const enableWiki = window.app.pageOptions.enableWiki;
|
||||
export const enableEncryptedLibrary = window.app.pageOptions.enableEncryptedLibrary === '1';
|
||||
export const enableRepoHistorySetting = window.app.pageOptions.enableRepoHistorySetting === '1';
|
||||
export const isSystemStaff = window.app.pageOptions.isSystemStaff;
|
||||
export const thumbnailSizeForOriginal = window.app.pageOptions.thumbnailSizeForOriginal;
|
||||
|
||||
// wiki
|
||||
export const slug = window.wiki ? window.wiki.config.slug : '';
|
||||
|
@@ -70,6 +70,7 @@
|
||||
enableEncryptedLibrary: '{{ enable_encrypted_library }}',
|
||||
enableRepoHistorySetting: '{{ enable_repo_history_setting }}',
|
||||
isSystemStaff: {% if request.user.is_staff %} true {% else %} false {% endif %},
|
||||
thumbnailSizeForOriginal: {{ thumbnail_size_for_original }},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
Reference in New Issue
Block a user