From ca4dee899bfd6748ee92ece00b4d3a75bbf668d7 Mon Sep 17 00:00:00 2001 From: llj Date: Wed, 16 Jan 2019 17:45:46 +0800 Subject: [PATCH] [dir view, repo wiki mode] show images with popup (#2834) * [dir view, repo wiki mode] show images with popup * [image pupup] modification --- frontend/package-lock.json | 25 ++++ frontend/package.json | 1 + frontend/src/components/dir-view/dir-panel.js | 1 + frontend/src/components/dir-view/dir-view.js | 6 +- .../dirent-list-view/dirent-list-item.js | 8 +- .../dirent-list-view/dirent-list-view.js | 109 +++++++++++++++++- .../src/pages/repo-wiki-mode/main-panel.js | 2 + frontend/src/repo-wiki-mode.js | 6 +- frontend/src/utils/constants.js | 1 + seahub/templates/base_for_react.html | 1 + 10 files changed, 154 insertions(+), 6 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c6ef4a08ce..28fb3d1655 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -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", diff --git a/frontend/package.json b/frontend/package.json index ffc7541414..852f0a44bd 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/frontend/src/components/dir-view/dir-panel.js b/frontend/src/components/dir-view/dir-panel.js index ca58bfb42e..3d2c93322b 100644 --- a/frontend/src/components/dir-view/dir-panel.js +++ b/frontend/src/components/dir-view/dir-panel.js @@ -195,6 +195,7 @@ class DirPanel extends React.Component { { @@ -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} 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 77d896b054..9873246e13 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-item.js +++ b/frontend/src/components/dirent-list-view/dirent-list-item.js @@ -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) => { 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 95420024fd..07376ee661 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-view.js +++ b/frontend/src/components/dirent-list-view/dirent-list-view.js @@ -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' ? : ; + // for image popup + const imageItems = this.state.imageItems; + const imageIndex = this.state.imageIndex; + const imageItemsLength = imageItems.length; + const imageCaption = imageItemsLength && ( + + {gettext("%curr% of %total%").replace('%curr%', imageIndex + 1).replace('%total%', imageItemsLength)} +
+ {gettext("Open in New Tab")} +
+ ); + return ( + @@ -163,12 +249,33 @@ class DirentListView extends React.Component { onFreezedItem={this.onFreezedItem} onUnfreezedItem={this.onUnfreezedItem} onItemDetails={this.onItemDetails} + showImagePopup={this.showImagePopup} /> ); }) }
+ + {this.state.isImagePopupOpen && ( + + )} +
); } } diff --git a/frontend/src/pages/repo-wiki-mode/main-panel.js b/frontend/src/pages/repo-wiki-mode/main-panel.js index 6a2e8996d8..af505ef4c3 100644 --- a/frontend/src/pages/repo-wiki-mode/main-panel.js +++ b/frontend/src/pages/repo-wiki-mode/main-panel.js @@ -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 { { 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 { />