import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
import { Link, navigate } from '@gatsbyjs/reach-router';
import { Utils } from '../../utils/utils';
import { gettext, siteRoot, isPro, username, folderPermEnabled, isSystemStaff, enableResetEncryptedRepoPassword, isEmailConfigured, enableRepoAutoDel, enableSeaTableIntegration } from '../../utils/constants';
import ModalPortal from '../../components/modal-portal';
import ShareDialog from '../../components/dialog/share-dialog';
import LibSubFolderPermissionDialog from '../../components/dialog/lib-sub-folder-permission-dialog';
import DeleteRepoDialog from '../../components/dialog/delete-repo-dialog';
import ChangeRepoPasswordDialog from '../../components/dialog/change-repo-password-dialog';
import ResetEncryptedRepoPasswordDialog from '../../components/dialog/reset-encrypted-repo-password-dialog';
import LibOldFilesAutoDelDialog from '../../components/dialog/lib-old-files-auto-del-dialog';
import RepoSeaTableIntegrationDialog from '../../components/dialog/repo-seatable-integration-dialog';
import Rename from '../rename';
import { seafileAPI } from '../../utils/seafile-api';
import LibHistorySettingDialog from '../dialog/lib-history-setting-dialog';
import toaster from '../toast';
import RepoAPITokenDialog from '../dialog/repo-api-token-dialog';
import RepoShareAdminDialog from '../dialog/repo-share-admin-dialog';
import RepoMonitoredIcon from '../../components/repo-monitored-icon';
const propTypes = {
currentViewMode: PropTypes.string,
currentGroup: PropTypes.object,
libraryType: PropTypes.string,
repo: PropTypes.object.isRequired,
isItemFreezed: PropTypes.bool.isRequired,
onFreezedItem: PropTypes.func.isRequired,
onUnfreezedItem: PropTypes.func.isRequired,
onItemUnshare: PropTypes.func.isRequired,
onItemRename: PropTypes.func,
onItemDelete: PropTypes.func,
onMonitorRepo: PropTypes.func
};
class SharedRepoListItem extends React.Component {
constructor(props) {
super(props);
this.state = {
highlight: false,
isOperationShow: false,
isItemMenuShow: false,
isAdvancedMenuShown: false,
isShowSharedDialog: false,
isRenaming: false,
isStarred: this.props.repo.starred,
isFolderPermissionDialogOpen: false,
isHistorySettingDialogShow: false,
isDeleteDialogShow: false,
isAPITokenDialogShow: false,
isRepoShareAdminDialogOpen: false,
isRepoDeleted: false,
isChangePasswordDialogShow: false,
isResetPasswordDialogShow: false,
isOldFilesAutoDelDialogOpen: false,
isSeaTableIntegrationShow: false,
};
this.isDeparementOnwerGroupMember = false;
}
onMouseEnter = () => {
if (!this.props.isItemFreezed) {
this.setState({
highlight: true,
isOperationShow: true,
});
}
};
onMouseOver = () => {
if (!this.props.isItemFreezed) {
this.setState({
highlight: true,
isOperationShow: true,
});
}
};
onMouseLeave = () => {
if (!this.props.isItemFreezed) {
this.setState({
highlight: false,
isOperationShow: false,
});
}
};
clickOperationMenuToggle = (e) => {
this.toggleOperationMenu(e);
};
onDropdownToggleKeyDown = (e) => {
if (e.key == 'Enter' || e.key == 'Space') {
this.clickOperationMenuToggle(e);
}
};
toggleOperationMenu = (e) => {
let dataset = e.target ? e.target.dataset : null;
if (dataset && dataset.toggle && dataset.toggle === 'Rename') {
this.setState({isItemMenuShow: !this.state.isItemMenuShow});
return;
}
this.setState(
{isItemMenuShow: !this.state.isItemMenuShow},
() => {
if (this.state.isItemMenuShow) {
this.props.onFreezedItem();
} else {
this.props.onUnfreezedItem();
this.setState({
highlight: false,
isOperationShow: false,
});
}
}
);
};
toggleAdvancedMenuShown = (e) => {
this.setState({ isAdvancedMenuShown: true });
};
toggleAdvancedMenu = (e) => {
e.stopPropagation();
this.setState({ isAdvancedMenuShown: !this.state.isAdvancedMenuShown }, () => {
this.toggleOperationMenu(e);
});
};
onDropDownMouseMove = (e) => {
if (this.state.isAdvancedMenuShown && e.target && e.target.className === 'dropdown-item') {
this.setState({
isAdvancedMenuShown: false
});
}
};
getRepoComputeParams = () => {
const { repo, currentViewMode } = this.props;
const useBigLibaryIcon = currentViewMode == 'grid';
const iconUrl = Utils.getLibIconUrl(repo, useBigLibaryIcon);
let iconTitle = Utils.getLibIconTitle(repo);
let libPath = `${siteRoot}library/${repo.repo_id}/${Utils.encodePath(repo.repo_name)}/`;
return { iconUrl, iconTitle, libPath };
};
onMenuItemKeyDown = (e) => {
if (e.key == 'Enter' || e.key == 'Space') {
this.onMenuItemClick(e);
}
};
onMenuItemClick = (e) => {
let operation = e.target.dataset.toggle;
switch(operation) {
case 'Rename':
this.onItemRenameToggle();
break;
case 'Folder Permission':
this.onItemFolderPermissionToggle();
break;
case 'Share':
this.onItemShare();
break;
case 'Unshare':
this.onItemUnshare();
break;
case 'History Setting':
this.onHistorySettingToggle();
break;
case 'API Token':
this.onAPITokenToggle();
break;
case 'Share Admin':
this.toggleRepoShareAdminDialog();
break;
case 'Change Password':
this.onChangePasswordToggle();
break;
case 'Reset Password':
this.onResetPasswordToggle();
break;
case 'Watch File Changes':
this.watchFileChanges();
break;
case 'Unwatch File Changes':
this.unwatchFileChanges();
break;
case 'Old Files Auto Delete':
this.toggleOldFilesAutoDelDialog();
break;
case 'SeaTable integration':
this.onSeaTableIntegrationToggle();
break;
// no default
}
};
watchFileChanges = () => {
const { repo } = this.props;
seafileAPI.monitorRepo(repo.repo_id).then(() => {
this.props.onMonitorRepo(repo, true);
}).catch(error => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
};
unwatchFileChanges = () => {
const { repo } = this.props;
seafileAPI.unMonitorRepo(repo.repo_id).then(() => {
this.props.onMonitorRepo(repo, false);
}).catch(error => {
let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage);
});
};
onItemRenameToggle = () => {
this.props.onFreezedItem();
this.setState({
isRenaming: !this.state.isRenaming,
isOperationShow: !this.state.isOperationShow
});
};
onRenameConfirm = (name) => {
this.props.onItemRename(this.props.repo, name);
this.onRenameCancel();
};
onRenameCancel = () => {
this.props.onUnfreezedItem();
this.setState({isRenaming: !this.state.isRenaming});
};
onItemFolderPermissionToggle = () => {
this.setState({isFolderPermissionDialogOpen: !this.state.isFolderPermissionDialogOpen});
};
onHistorySettingToggle = () => {
this.setState({isHistorySettingDialogShow: !this.state.isHistorySettingDialogShow});
};
onItemShare = (e) => {
e.preventDefault();
this.setState({isShowSharedDialog: true});
};
onItemUnshare = (e) => {
e.preventDefault();
this.props.onItemUnshare(this.props.repo);
};
onItemDeleteToggle = (e) => {
e.preventDefault();
this.setState({isDeleteDialogShow: !this.state.isDeleteDialogShow});
};
onItemDelete = () => {
const { currentGroup, repo } = this.props;
if (!currentGroup) { // repo can not be deleted in share all module
return;
}
const groupID = currentGroup.id;
seafileAPI.deleteGroupOwnedLibrary(groupID, repo.repo_id).then(() => {
this.setState({
isRepoDeleted: true,
isDeleteDialogShow: false,
});
this.props.onItemDelete(repo);
let name = repo.repo_name;
var msg = gettext('Successfully deleted {name}.').replace('{name}', name);
toaster.success(msg);
}).catch((error) => {
let errMessage = Utils.getErrorMsg(error);
if (errMessage === gettext('Error')) {
let name = repo.repo_name;
errMessage = gettext('Failed to delete {name}.').replace('{name}', name);
}
toaster.danger(errMessage);
this.setState({isRepoDeleted: false});
});
};
toggleShareDialog = () => {
this.setState({isShowSharedDialog: false});
};
toggleRepoShareAdminDialog = () => {
this.setState({isRepoShareAdminDialogOpen: !this.state.isRepoShareAdminDialogOpen});
};
toggleOldFilesAutoDelDialog = () => {
this.setState({isOldFilesAutoDelDialogOpen: !this.state.isOldFilesAutoDelDialogOpen});
};
onSeaTableIntegrationToggle = () => {
this.setState({isSeaTableIntegrationShow: !this.state.isSeaTableIntegrationShow});
};
onAPITokenToggle = () => {
this.setState({isAPITokenDialogShow: !this.state.isAPITokenDialogShow});
};
onChangePasswordToggle = () => {
this.setState({isChangePasswordDialogShow: !this.state.isChangePasswordDialogShow});
};
onResetPasswordToggle = () => {
this.setState({isResetPasswordDialogShow: !this.state.isResetPasswordDialogShow});
};
translateMenuItem = (menuItem) => {
let translateResult = '';
switch(menuItem) {
case 'Rename':
translateResult = gettext('Rename');
break;
case 'Folder Permission':
translateResult = gettext('Folder Permission');
break;
case 'Unshare':
translateResult = gettext('Unshare');
break;
case 'Share':
translateResult = gettext('Share');
break;
case 'History Setting':
translateResult = gettext('History Setting');
break;
case 'Share Admin':
translateResult = gettext('Share Admin');
break;
case 'Change Password':
translateResult = gettext('Change Password');
break;
case 'Reset Password':
translateResult = gettext('Reset Password');
break;
case 'Watch File Changes':
translateResult = gettext('Watch File Changes');
break;
case 'Unwatch File Changes':
translateResult = gettext('Unwatch File Changes');
break;
case 'Old Files Auto Delete':
translateResult = gettext('Auto Deletion Setting');
break;
case 'API Token':
translateResult = 'API Token'; // translation is not needed here
break;
case 'Advanced':
translateResult = gettext('Advanced');
break;
case 'SeaTable integration':
translateResult = gettext('SeaTable integration');
break;
default:
break;
}
return translateResult;
};
getAdvancedOperations = () => {
const operations = [];
operations.push('API Token');
if (enableRepoAutoDel) {
operations.push('Old Files Auto Delete');
}
if (enableSeaTableIntegration) {
operations.push('SeaTable integration');
}
return operations;
};
generatorOperations = () => {
let { repo, currentGroup } = this.props;
//todo this have a bug; use current api is not return admins param;
let isStaff = currentGroup && currentGroup.admins && currentGroup.admins.indexOf(username) > -1; //for group repolist;
let isRepoOwner = repo.owner_email === username;
let isAdmin = repo.is_admin;
let operations = [];
if (isPro) {
if (repo.owner_email.indexOf('@seafile_group') != -1) {
// is group admin
if (isStaff) {
if (repo.owner_email == currentGroup.id + '@seafile_group') {
this.isDeparementOnwerGroupMember = true;
operations = ['Rename'];
if (folderPermEnabled) {
operations.push('Folder Permission');
}
operations.push('Share Admin', 'Divider');
if (repo.encrypted) {
operations.push('Change Password');
}
if (repo.encrypted && enableResetEncryptedRepoPassword && isEmailConfigured) {
operations.push('Reset Password');
}
if (repo.permission == 'r' || repo.permission == 'rw') {
const monitorOp = repo.monitored ? 'Unwatch File Changes' : 'Watch File Changes';
operations.push(monitorOp);
}
operations.push('Divider', 'History Setting');
if (Utils.isDesktop()) {
operations.push('Advanced');
}
return operations;
} else {
operations.push('Unshare');
}
}
} else {
if (isRepoOwner || isAdmin) {
operations.push('Share');
}
if (isStaff || isRepoOwner || isAdmin) {
operations.push('Unshare');
}
}
if (repo.permission == 'r' || repo.permission == 'rw') {
const monitorOp = repo.monitored ? 'Unwatch File Changes' : 'Watch File Changes';
operations.push(monitorOp);
}
} else {
if (isRepoOwner) {
operations.push('Share');
}
if (isStaff || isRepoOwner) {
operations.push('Unshare');
}
}
return operations;
};
generatorMobileMenu = () => {
let operations = [];
if (this.props.libraryType && this.props.libraryType === 'public') {
let isRepoOwner = this.props.repo.owner_email === username;
if (isSystemStaff || isRepoOwner) {
operations.push('Unshare');
}
} else {
operations = this.generatorOperations();
if (this.isDeparementOnwerGroupMember) {
operations.unshift('Unshare');
operations.unshift('Share');
}
}
if (!operations.length) {
return null;
}
return (