import React from 'react';
import ReactDOM from 'react-dom';
import { Button, Dropdown, DropdownToggle, DropdownItem } from 'reactstrap';
import moment from 'moment';
import Account from './components/common/account';
import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle, thumbnailSizeForOriginal } from './utils/constants';
import { Utils } from './utils/utils';
import { seafileAPI } from './utils/seafile-api';
import Loading from './components/loading';
import toaster from './components/toast';
import ModalPortal from './components/modal-portal';
import ZipDownloadDialog from './components/dialog/zip-download-dialog';
import ImageDialog from './components/dialog/image-dialog';
import './css/shared-dir-view.css';
import './css/grid-view.css';
let loginUser = window.app.pageOptions.name;
const { token, trafficOverLimit, dirName, sharedBy, path, canDownload, mode, thumbnailSize, zipped } = window.shared.pageOptions;
const showDownloadIcon = !trafficOverLimit && canDownload;
class SharedDirView extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
errorMsg: '',
items: [],
sortBy: 'name', // 'name' or 'time' or 'size'
sortOrder: 'asc', // 'asc' or 'desc'
isZipDialogOpen: false,
zipFolderPath: '',
isImagePopupOpen: false,
imageItems: [],
imageIndex: 0
};
}
componentDidMount() {
if (trafficOverLimit) {
toaster.danger(gettext('File download is disabled: the share link traffic of owner is used up.'), {
duration: 3
});
}
seafileAPI.listSharedDir(token, path, thumbnailSize).then((res) => {
const items = res.data['dirent_list'];
this.setState({
isLoading: false,
errorMsg: '',
items: Utils.sortDirentsInSharedDir(items, this.state.sortBy, this.state.sortOrder)
});
this.getThumbnails();
}).catch((error) => {
let errorMsg = Utils.getErrorMsg(error);
this.setState({
isLoading: false,
errorMsg: errorMsg
});
});
}
sortItems = (sortBy, sortOrder) => {
this.setState({
sortBy: sortBy,
sortOrder: sortOrder,
items: Utils.sortDirentsInSharedDir(this.state.items, sortBy, sortOrder)
});
}
getThumbnails = () => {
let items = this.state.items.filter((item) => {
return !item.is_dir && Utils.imageCheck(item.file_name) && !item.encoded_thumbnail_src;
});
if (items.length == 0) {
return ;
}
const len = items.length;
const _this = this;
let getThumbnail = function(i) {
const curItem = items[i];
seafileAPI.getShareLinkThumbnail(token, curItem.file_path, thumbnailSize).then((res) => {
curItem.encoded_thumbnail_src = res.data.encoded_thumbnail_src;
}).catch((error) => {
// do nothing
}).then(() => {
if (i < len - 1) {
getThumbnail(++i);
} else {
// when done, `setState()`
_this.setState({
items: _this.state.items
});
}
});
};
getThumbnail(0);
}
renderPath = () => {
return (
{zipped.map((item, index) => {
if (index != zipped.length - 1) {
return (
{item.name}
/
);
}
})
}
{zipped[zipped.length - 1].name}
);
}
zipDownloadFolder = (folderPath) => {
this.setState({
isZipDialogOpen: true,
zipFolderPath: folderPath
});
}
closeZipDialog = () => {
this.setState({
isZipDialogOpen: false,
zipFolderPath: ''
});
}
// for image popup
prepareImageItem = (item) => {
const name = item.file_name;
const fileExt = name.substr(name.lastIndexOf('.') + 1).toLowerCase();
const isGIF = fileExt == 'gif';
let src;
const fileURL = `${siteRoot}d/${token}/files/?p=${encodeURIComponent(item.file_path)}`;
if (!isGIF) {
src = `${siteRoot}thumbnail/${token}/${thumbnailSizeForOriginal}${Utils.encodePath(item.file_path)}`;
} else {
src = `${fileURL}&raw=1`;
}
return {
'name': name,
'url': fileURL,
'src': src
};
}
showImagePopup = (curItem) => {
const items = this.state.items.filter((item) => {
return !item.is_dir && Utils.imageCheck(item.file_name);
});
const imageItems = items.map((item) => {
return this.prepareImageItem(item);
});
this.setState({
isImagePopupOpen: true,
imageItems: imageItems,
imageIndex: items.indexOf(curItem)
});
}
closeImagePopup = () => {
this.setState({
isImagePopupOpen: false
});
}
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
}));
}
render() {
const isDesktop = Utils.isDesktop();
const modeBaseClass = 'btn btn-secondary btn-icon sf-view-mode-btn';
return (
{loginUser &&
}
{dirName}
{gettext('Shared by: ')}{sharedBy}
{gettext('Current path: ')}{this.renderPath()}
{isDesktop &&
}
{showDownloadIcon &&
}
{this.state.isZipDialogOpen &&
}
{this.state.isImagePopupOpen &&
}
);
}
}
class Content extends React.Component {
sortByName = (e) => {
e.preventDefault();
const sortBy = 'name';
const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
}
sortByTime = (e) => {
e.preventDefault();
const sortBy = 'time';
const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
}
sortBySize = (e) => {
e.preventDefault();
const sortBy = 'size';
const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
}
render() {
const { isDesktop, isLoading, errorMsg, items, sortBy, sortOrder } = this.props;
if (isLoading) {
return ;
}
if (errorMsg) {
return
{errorMsg}
;
}
const tbody = (
{items.map((item, index) => {
return ;
})}
);
if (!isDesktop) {
return (
);
}
const sortIcon = ;
return mode == 'list' ? (
) : (
{items.map((item, index) => {
return ;
})}
);
}
}
class Item extends React.Component {
constructor(props) {
super(props);
this.state = {
isIconShown: false,
isOpMenuOpen: false
};
}
toggleOpMenu = () => {
this.setState({isOpMenuOpen: !this.state.isOpMenuOpen});
}
handleMouseOver = () => {
this.setState({isIconShown: true});
}
handleMouseOut = () => {
this.setState({isIconShown: false});
}
zipDownloadFolder = (e) => {
e.preventDefault();
this.props.zipDownloadFolder.bind(this, this.props.item.folder_path)();
}
handleFileClick = (e) => {
const item = this.props.item;
if (!Utils.imageCheck(item.file_name)) {
return;
}
e.preventDefault();
this.props.showImagePopup(item);
}
render() {
const { item, isDesktop } = this.props;
const { isIconShown } = this.state;
if (item.is_dir) {
return isDesktop ? (
}) |
{item.folder_name}
|
|
{moment(item.last_modified).fromNow()} |
{showDownloadIcon &&
}
|
) : (
}) |
{item.folder_name}
{moment(item.last_modified).fromNow()}
|
{showDownloadIcon &&
}
|
);
} else {
const fileURL = `${siteRoot}d/${token}/files/?p=${encodeURIComponent(item.file_path)}`;
const thumbnailURL = item.encoded_thumbnail_src ? `${siteRoot}${item.encoded_thumbnail_src}` : '';
return isDesktop ? (
{thumbnailURL ?
:
}
|
{item.file_name}
|
{Utils.bytesToSize(item.size)} |
{moment(item.last_modified).fromNow()} |
{showDownloadIcon &&
}
|
) : (
{thumbnailURL ?
:
}
|
{item.file_name}
{Utils.bytesToSize(item.size)}
{moment(item.last_modified).fromNow()}
|
{showDownloadIcon &&
}
|
);
}
}
}
class GridItem extends React.Component {
constructor(props) {
super(props);
this.state = {
isIconShown: false
};
}
handleMouseOver = () => {
this.setState({isIconShown: true});
}
handleMouseOut = () => {
this.setState({isIconShown: false});
}
zipDownloadFolder = (e) => {
e.preventDefault();
this.props.zipDownloadFolder.bind(this, this.props.item.folder_path)();
}
handleFileClick = (e) => {
const item = this.props.item;
if (!Utils.imageCheck(item.file_name)) {
return;
}
e.preventDefault();
this.props.showImagePopup(item);
}
render() {
const item = this.props.item;
const { isIconShown } = this.state;
if (item.is_dir) {
const folderURL = `?p=${encodeURIComponent(item.folder_path.substr(0, item.folder_path.length - 1))}&mode=${mode}`;
return (
{item.folder_name}
{showDownloadIcon &&
}
);
} else {
const fileURL = `${siteRoot}d/${token}/files/?p=${encodeURIComponent(item.file_path)}`;
const thumbnailURL = item.encoded_thumbnail_src ? `${siteRoot}${item.encoded_thumbnail_src}` : '';
return (
{thumbnailURL ?
:
}
{item.file_name}
{showDownloadIcon &&
}
);
}
}
}
ReactDOM.render(
,
document.getElementById('wrapper')
);