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 28d65d62b7..cf6661e03b 100644 --- a/frontend/src/components/dirent-list-view/dirent-list-item.js +++ b/frontend/src/components/dirent-list-view/dirent-list-item.js @@ -59,21 +59,6 @@ class DirentListItem extends React.Component { constructor(props) { super(props); - this.state = { - isOperationShow: false, - highlight: false, - isZipDialogOpen: false, - isMoveDialogShow: false, - isCopyDialogShow: false, - isShareDialogShow: false, - isMutipleOperation: false, - isShowTagTooltip: false, - isDragTipShow: false, - isDropTipshow: false, - isEditFileTagShow: false, - isPermissionDialogOpen: false, - isOpMenuOpen: false // for mobile - }; const { dirent } = this.props; const { isCustomPermission, customPermission } = Utils.getUserPermission(dirent.permission); @@ -86,6 +71,23 @@ class DirentListItem extends React.Component { this.canPreview = preview || modify; this.canDrag = modify; } + + this.state = { + isOperationShow: false, + highlight: false, + isZipDialogOpen: false, + isMoveDialogShow: false, + isCopyDialogShow: false, + isShareDialogShow: false, + isMutipleOperation: false, + canDrag: this.canDrag, + isShowTagTooltip: false, + isDragTipShow: false, + isDropTipshow: false, + isEditFileTagShow: false, + isPermissionDialogOpen: false, + isOpMenuOpen: false // for mobile + }; } componentWillReceiveProps(nextProps) { @@ -115,7 +117,7 @@ class DirentListItem extends React.Component { isOperationShow: true, }); } - if (this.canDrag) { + if (this.state.canDrag) { this.setState({isDragTipShow: true}); } } @@ -127,7 +129,7 @@ class DirentListItem extends React.Component { isOperationShow: true, }); } - if (this.canDrag) { + if (this.state.canDrag) { this.setState({isDragTipShow: true}); } } @@ -314,6 +316,7 @@ class DirentListItem extends React.Component { this.setState({ isOperationShow: false, isRenameing: true, + canDrag: false }); } @@ -323,7 +326,10 @@ class DirentListItem extends React.Component { } onRenameCancel = () => { - this.setState({isRenameing: false}); + this.setState({ + isRenameing: false, + canDrag: this.canDrag // set it back to the initial value + }); this.unfreezeItem(); } @@ -479,7 +485,7 @@ class DirentListItem extends React.Component { } onItemDragStart = (e) => { - if (Utils.isIEBrower() || !this.canDrag) { + if (Utils.isIEBrower() || !this.state.canDrag) { return false; } e.dataTransfer.effectAllowed = 'move'; @@ -509,7 +515,7 @@ class DirentListItem extends React.Component { } onItemDragEnter = (e) => { - if (Utils.isIEBrower() || !this.canDrag) { + if (Utils.isIEBrower() || !this.state.canDrag) { return false; } if (this.props.dirent.type === 'dir') { @@ -519,7 +525,7 @@ class DirentListItem extends React.Component { } onItemDragOver = (e) => { - if (Utils.isIEBrower() || !this.canDrag) { + if (Utils.isIEBrower() || !this.state.canDrag) { return false; } if (e.dataTransfer.dropEffect === 'copy') { @@ -530,7 +536,7 @@ class DirentListItem extends React.Component { } onItemDragLeave = (e) => { - if (Utils.isIEBrower() || !this.canDrag) { + if (Utils.isIEBrower() || !this.state.canDrag) { return false; } @@ -541,7 +547,7 @@ class DirentListItem extends React.Component { } onItemDragDrop = (e) => { - if (Utils.isIEBrower() || !this.canDrag) { + if (Utils.isIEBrower() || !this.state.canDrag) { return false; } this.setState({isDropTipshow: false}); @@ -698,10 +704,11 @@ class DirentListItem extends React.Component { let lockedInfo = gettext('locked by {name}').replace('{name}', dirent.lock_owner_name); const isDesktop = Utils.isDesktop(); + const { canDrag } = this.state; const desktopItem = ( { let value = Utils.sharePermsExplanation(explanation); if (!value) { @@ -120,6 +125,7 @@ class SharePermissionEditor extends React.Component { return ( { + event.nativeEvent.stopImmediatePropagation(); + this.setState({isShowPermEditor: true}); + } + render() { if (this.state.unshared) { return null; } const item = this.props.item; - let { share_permission, isOpIconShown, isPermSelectDialogOpen } = this.state; + let { share_permission, share_permission_name, isOpIconShown, isPermSelectDialogOpen, isShowPermEditor } = this.state; let is_readonly = false; if (share_permission == 'r' || share_permission == 'preview') { @@ -201,14 +208,31 @@ class Item extends Component { {item.user_name} : item.group_name} - + {!isShowPermEditor && ( +
+ {Utils.sharePerms(share_permission) || share_permission_name} + {isOpIconShown && ( + + + )} +
+ )} + {isShowPermEditor && ( + + )} diff --git a/frontend/src/pages/share-admin/libraries.js b/frontend/src/pages/share-admin/libraries.js index 01388efba2..7d70963e81 100644 --- a/frontend/src/pages/share-admin/libraries.js +++ b/frontend/src/pages/share-admin/libraries.js @@ -83,11 +83,13 @@ class Item extends Component { let item = this.props.item; this.state = { share_permission: item.share_permission, + share_permission_name: item.share_permission_name, is_admin: item.is_admin, isOpIconShown: false, isOpMenuOpen: false, // for mobile isPermSelectDialogOpen: false, // for mobile - unshared: false + unshared: false, + isShowPermEditor: false, }; let permissions = ['rw', 'r']; this.permissions = permissions; @@ -171,12 +173,17 @@ class Item extends Component { }); } + onEditPermission = (event) => { + event.nativeEvent.stopImmediatePropagation(); + this.setState({isShowPermEditor: true}); + } + render() { if (this.state.unshared) { return null; } - let { share_permission, is_admin, isOpIconShown, isPermSelectDialogOpen } = this.state; + let { share_permission, share_permission_name, is_admin, isOpIconShown, isPermSelectDialogOpen, isShowPermEditor } = this.state; let item = this.props.item; Object.assign(item, { share_permission: share_permission, @@ -215,14 +222,31 @@ class Item extends Component { {item.share_type == 'personal' ? {shareTo} : shareTo} - + {!isShowPermEditor && ( +
+ {Utils.sharePerms(share_permission) || share_permission_name} + {isOpIconShown && ( + + + )} +
+ )} + {isShowPermEditor && ( + + )} diff --git a/seahub/api2/endpoints/shared_folders.py b/seahub/api2/endpoints/shared_folders.py index 70ae1c4596..1216932c2e 100644 --- a/seahub/api2/endpoints/shared_folders.py +++ b/seahub/api2/endpoints/shared_folders.py @@ -16,9 +16,11 @@ from seahub.api2.throttling import UserRateThrottle from seahub.profile.models import Profile from seahub.utils import is_org_context from seahub.base.templatetags.seahub_tags import email2nickname +from seahub.share.models import CustomSharePermissions logger = logging.getLogger(__name__) + class SharedFolders(APIView): authentication_classes = (TokenAuthentication, SessionAuthentication) @@ -48,11 +50,26 @@ class SharedFolders(APIView): error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + repo_id_list = [] + for repo in shared_repos: + + if repo.is_virtual: + continue + + repo_id = repo.repo_id + repo_id_list.append(repo_id) + + custom_permission_dict = {} + custom_permissions = CustomSharePermissions.objects.filter(repo_id__in=repo_id_list) + for custom_permission in custom_permissions: + custom_id = f'custom-{custom_permission.id}' + custom_permission_dict[custom_id] = custom_permission.name + returned_result = [] shared_repos.sort(key=lambda x: x.repo_name) for repo in shared_repos: if not repo.is_virtual: - continue + continue result = {} result['repo_id'] = repo.origin_repo_id @@ -61,6 +78,7 @@ class SharedFolders(APIView): result['folder_name'] = repo.name result['share_type'] = repo.share_type result['share_permission'] = repo.permission + result['share_permission_name'] = custom_permission_dict.get(repo.permission, '') if repo.share_type == 'personal': result['user_name'] = email2nickname(repo.user) @@ -73,10 +91,15 @@ class SharedFolders(APIView): if not group: if is_org_context(request): seafile_api.org_unshare_subdir_for_group(org_id, - repo.repo_id, repo.origin_path, username, repo.group_id) + repo.repo_id, + repo.origin_path, + username, + repo.group_id) else: - seafile_api.unshare_subdir_for_group( - repo.repo_id, repo.origin_path, username, repo.group_id) + seafile_api.unshare_subdir_for_group(repo.repo_id, + repo.origin_path, + username, + repo.group_id) continue result['group_id'] = repo.group_id diff --git a/seahub/api2/endpoints/shared_repos.py b/seahub/api2/endpoints/shared_repos.py index 69a40e59d0..d9fb9ec8f3 100644 --- a/seahub/api2/endpoints/shared_repos.py +++ b/seahub/api2/endpoints/shared_repos.py @@ -17,13 +17,15 @@ from seahub.profile.models import Profile from seahub.utils import is_org_context, is_valid_username, send_perm_audit_msg from seahub.utils.repo import get_available_repo_perms from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email -from seahub.share.models import ExtraSharePermission, ExtraGroupsSharePermission +from seahub.share.models import ExtraSharePermission, ExtraGroupsSharePermission, \ + CustomSharePermissions from seahub.share.utils import update_user_dir_permission, update_group_dir_permission,\ check_user_share_out_permission, check_group_share_out_permission, \ normalize_custom_permission_name logger = logging.getLogger(__name__) + class SharedRepos(APIView): authentication_classes = (TokenAuthentication, SessionAuthentication) @@ -55,13 +57,29 @@ class SharedRepos(APIView): error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) + repo_id_list = [] + for repo in shared_repos: + + if repo.is_virtual: + continue + + repo_id = repo.repo_id + repo_id_list.append(repo_id) + + custom_permission_dict = {} + custom_permissions = CustomSharePermissions.objects.filter(repo_id__in=repo_id_list) + for custom_permission in custom_permissions: + custom_id = f'custom-{custom_permission.id}' + custom_permission_dict[custom_id] = custom_permission.name + returned_result = [] shared_repos.sort(key=lambda x: x.repo_name) usernames = [] gids = [] + for repo in shared_repos: if repo.is_virtual: - continue + continue result = {} result['repo_id'] = repo.repo_id @@ -69,6 +87,7 @@ class SharedRepos(APIView): result['encrypted'] = repo.encrypted result['share_type'] = repo.share_type result['share_permission'] = repo.permission + result['share_permission_name'] = custom_permission_dict.get(repo.permission, '') result['modifier_email'] = repo.last_modifier result['modifier_name'] = email2nickname(repo.last_modifier) result['modifier_contact_email'] = email2contact_email(repo.last_modifier) @@ -163,7 +182,7 @@ class SharedRepo(APIView): return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('modify-repo-perm', username, - shared_to, repo_id, '/', permission) + shared_to, repo_id, '/', permission) if share_type == 'group': group_id = request.data.get('group_id', None) @@ -194,7 +213,7 @@ class SharedRepo(APIView): return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('modify-repo-perm', username, - group_id, repo_id, '/', permission) + group_id, repo_id, '/', permission) if share_type == 'public': @@ -215,7 +234,7 @@ class SharedRepo(APIView): return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('modify-repo-perm', username, - 'all', repo_id, '/', permission) + 'all', repo_id, '/', permission) return Response({'success': True}) @@ -279,7 +298,7 @@ class SharedRepo(APIView): return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) send_perm_audit_msg('delete-repo-perm', username, user, - repo_id, '/', permission) + repo_id, '/', permission) if share_type == 'group': group_id = request.GET.get('group_id', None) @@ -295,7 +314,6 @@ class SharedRepo(APIView): permission = check_group_share_out_permission(repo_id, '/', group_id, is_org) - try: if is_org: seaserv.del_org_group_repo(repo_id, org_id, group_id)