коммит произвёл
GitHub
родитель
c0ea57ac6c
Коммит
36ac3a43b1
@@ -58,6 +58,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
@@ -183,6 +190,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
@@ -301,6 +315,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
@@ -426,6 +447,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
@@ -551,6 +579,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
@@ -692,6 +727,13 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_post",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_edit_file_attachment",
|
||||
"permissions": Array [
|
||||
"edit_file_attachment",
|
||||
],
|
||||
},
|
||||
Object {
|
||||
"combined": true,
|
||||
"id": "guest_delete_post",
|
||||
|
||||
@@ -30,6 +30,7 @@ const GuestPermissionsTree = ({license, onToggle, readOnly, scope, selectRow, pa
|
||||
const defaultPermissions = [
|
||||
Permissions.CREATE_PRIVATE_CHANNEL,
|
||||
Permissions.EDIT_POST,
|
||||
Permissions.EDIT_FILE_ATTACHMENT,
|
||||
Permissions.DELETE_POST,
|
||||
{
|
||||
id: 'guest_' + Permissions.CREATE_POST,
|
||||
|
||||
@@ -18,6 +18,7 @@ export const GUEST_INCLUDED_PERMISSIONS = [
|
||||
Permissions.REMOVE_REACTION,
|
||||
Permissions.READ_CHANNEL,
|
||||
Permissions.UPLOAD_FILE,
|
||||
Permissions.EDIT_FILE_ATTACHMENT,
|
||||
Permissions.USE_CHANNEL_MENTIONS,
|
||||
Permissions.USE_GROUP_MENTIONS,
|
||||
Permissions.CREATE_POST,
|
||||
|
||||
@@ -128,6 +128,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -322,6 +323,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -513,6 +515,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -715,6 +718,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -917,6 +921,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -1119,6 +1124,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
@@ -1328,6 +1334,7 @@ exports[`components/admin_console/permission_schemes_settings/permission_tree sh
|
||||
"edit_others_posts",
|
||||
],
|
||||
},
|
||||
"edit_file_attachment",
|
||||
Object {
|
||||
"id": "delete_posts",
|
||||
"permissions": Array [
|
||||
|
||||
@@ -130,6 +130,16 @@ describe('components/admin_console/permission_schemes_settings/permission_tree',
|
||||
}
|
||||
});
|
||||
|
||||
test('should include edit_file_attachment in the posts permission group', () => {
|
||||
const wrapper = shallow(
|
||||
<PermissionsTree {...defaultProps}/>,
|
||||
);
|
||||
|
||||
const groups = wrapper.find(PermissionGroup).first().prop('permissions') as Array<Group | Permission>;
|
||||
expect(groups[6].id).toBe('posts');
|
||||
expect(groups[6].permissions).toContain('edit_file_attachment');
|
||||
});
|
||||
|
||||
test('should hide disabbled integration options', () => {
|
||||
const wrapper = shallow(
|
||||
<PermissionsTree
|
||||
|
||||
@@ -160,6 +160,7 @@ export default class PermissionsTree extends React.PureComponent<Props, State> {
|
||||
Permissions.EDIT_OTHERS_POSTS,
|
||||
],
|
||||
},
|
||||
Permissions.EDIT_FILE_ATTACHMENT,
|
||||
{
|
||||
id: 'delete_posts',
|
||||
permissions: [
|
||||
|
||||
@@ -125,6 +125,16 @@ export const groupRolesStrings: Record<string, Record<string, MessageDescriptor>
|
||||
defaultMessage: 'Add and delete reactions on posts.',
|
||||
},
|
||||
}),
|
||||
guest_edit_file_attachment: defineMessages({
|
||||
name: {
|
||||
id: 'admin.permissions.group.guest_edit_file_attachment.name',
|
||||
defaultMessage: 'Edit Attachments',
|
||||
},
|
||||
description: {
|
||||
id: 'admin.permissions.group.guest_edit_file_attachment.description',
|
||||
defaultMessage: 'Allow users to add or remove file attachments when editing posts.',
|
||||
},
|
||||
}),
|
||||
guest_create_post: defineMessages({
|
||||
name: {
|
||||
id: 'admin.permissions.group.guest_create_post.name',
|
||||
|
||||
@@ -405,6 +405,16 @@ export const permissionRolesStrings: Record<string, Record<string, MessageDescri
|
||||
defaultMessage: 'Upload file',
|
||||
},
|
||||
}),
|
||||
edit_file_attachment: defineMessages({
|
||||
name: {
|
||||
id: 'admin.permissions.permission.edit_file_attachment.name',
|
||||
defaultMessage: 'Edit Attachments',
|
||||
},
|
||||
description: {
|
||||
id: 'admin.permissions.permission.edit_file_attachment.description',
|
||||
defaultMessage: 'Allow users to add or remove file attachments when editing posts.',
|
||||
},
|
||||
}),
|
||||
use_channel_mentions: defineMessages({
|
||||
name: {
|
||||
id: 'admin.permissions.permission.use_channel_mentions.name',
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {useCallback, useRef, useState} from 'react';
|
||||
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import type {ServerError} from '@mattermost/types/errors';
|
||||
import type {FileInfo} from '@mattermost/types/files';
|
||||
|
||||
import Permissions from 'mattermost-redux/constants/permissions';
|
||||
import {getChannel} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
import {sortFileInfos} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import {getCurrentLocale} from 'selectors/i18n';
|
||||
@@ -17,6 +21,7 @@ import FileUpload from 'components/file_upload';
|
||||
import type {FileUpload as FileUploadClass, TextEditorLocationType} from 'components/file_upload/file_upload';
|
||||
import type TextboxClass from 'components/textbox/textbox';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
import type {PostDraft} from 'types/store/draft';
|
||||
|
||||
const getFileCount = (draft: PostDraft) => {
|
||||
@@ -36,12 +41,25 @@ const useUploadFiles = (
|
||||
setServerError: (err: (ServerError & { submittedMessage?: string }) | null) => void,
|
||||
isPostBeingEdited?: boolean,
|
||||
): [React.ReactNode, React.ReactNode] => {
|
||||
const intl = useIntl();
|
||||
const locale = useSelector(getCurrentLocale);
|
||||
const canEditAttachments = useSelector((state: GlobalState) => {
|
||||
const channel = getChannel(state, channelId);
|
||||
return channel ? haveIChannelPermission(state, channel.team_id, channel.id, Permissions.EDIT_FILE_ATTACHMENT) : true;
|
||||
});
|
||||
const editAttachmentsDisabled = isPostBeingEdited && !canEditAttachments;
|
||||
|
||||
const [uploadsProgressPercent, setUploadsProgressPercent] = useState<{ [clientID: string]: FilePreviewInfo }>({});
|
||||
|
||||
const fileUploadRef = useRef<FileUploadClass>(null);
|
||||
|
||||
const removeTooltip = useMemo(() => {
|
||||
return editAttachmentsDisabled ? intl.formatMessage({
|
||||
id: 'file_preview.no_edit_permission',
|
||||
defaultMessage: 'Post attachments cannot be edited',
|
||||
}) : undefined;
|
||||
}, [editAttachmentsDisabled, intl]);
|
||||
|
||||
const handleFileUploadChange = useCallback(() => {
|
||||
focusTextbox();
|
||||
}, [focusTextbox]);
|
||||
@@ -146,9 +164,10 @@ const useUploadFiles = (
|
||||
attachmentPreview = (
|
||||
<FilePreview
|
||||
fileInfos={draft.fileInfos}
|
||||
onRemove={removePreview}
|
||||
onRemove={editAttachmentsDisabled ? undefined : removePreview}
|
||||
uploadsInProgress={draft.uploadsInProgress}
|
||||
uploadsProgressPercent={uploadsProgressPercent}
|
||||
disabledRemoveTooltip={removeTooltip}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -160,7 +179,7 @@ const useUploadFiles = (
|
||||
postType = isThreadView ? 'thread' : 'comment';
|
||||
}
|
||||
|
||||
const fileUploadJSX = isDisabled ? null : (
|
||||
const fileUploadJSX = (isDisabled || editAttachmentsDisabled) ? null : (
|
||||
<FileUpload
|
||||
ref={fileUploadRef}
|
||||
fileCount={getFileCount(draft)}
|
||||
|
||||
@@ -6,6 +6,8 @@ import React from 'react';
|
||||
|
||||
import {getFileUrl} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
import FilePreview from './file_preview';
|
||||
|
||||
describe('FilePreview', () => {
|
||||
@@ -141,4 +143,53 @@ describe('FilePreview', () => {
|
||||
expect(wrapper.find('img').find({src: getFileUrl(fileId)}).exists()).toBe(true);
|
||||
expect(wrapper.find('div').find('.file-icon.generic').exists()).toBe(false);
|
||||
});
|
||||
|
||||
test('should render disabled remove button with tooltip when onRemove is absent and disabledRemoveTooltip is provided', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
onRemove: undefined,
|
||||
uploadsInProgress: [],
|
||||
disabledRemoveTooltip: 'You do not have permission to edit file attachments',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<FilePreview {...props}/>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('.file-preview__remove--disabled').exists()).toBe(true);
|
||||
expect(wrapper.find('a.file-preview__remove').exists()).toBe(false);
|
||||
expect(wrapper.find(WithTooltip).prop('title')).toBe('You do not have permission to edit file attachments');
|
||||
});
|
||||
|
||||
test('should render normal remove button when onRemove is defined', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
onRemove: jest.fn(),
|
||||
uploadsInProgress: [],
|
||||
disabledRemoveTooltip: 'tooltip text',
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<FilePreview {...props}/>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('a.file-preview__remove').exists()).toBe(true);
|
||||
expect(wrapper.find('.file-preview__remove--disabled').exists()).toBe(false);
|
||||
});
|
||||
|
||||
test('should not render any remove button when onRemove is absent and no disabledRemoveTooltip', () => {
|
||||
const props = {
|
||||
...baseProps,
|
||||
onRemove: undefined,
|
||||
uploadsInProgress: [],
|
||||
disabledRemoveTooltip: undefined,
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<FilePreview {...props}/>,
|
||||
);
|
||||
|
||||
expect(wrapper.find('a.file-preview__remove').exists()).toBe(false);
|
||||
expect(wrapper.find('.file-preview__remove--disabled').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {FileInfo} from '@mattermost/types/files';
|
||||
import {getFileThumbnailUrl, getFileUrl} from 'mattermost-redux/utils/file_utils';
|
||||
|
||||
import FilenameOverlay from 'components/file_attachment/filename_overlay';
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
import Constants, {FileTypes} from 'utils/constants';
|
||||
import * as Utils from 'utils/utils';
|
||||
@@ -28,7 +29,8 @@ type Props = {
|
||||
fileInfos: FilePreviewInfo[];
|
||||
uploadsInProgress?: string[];
|
||||
uploadsProgressPercent?: {[clientID: string]: FilePreviewInfo};
|
||||
}
|
||||
disabledRemoveTooltip?: string;
|
||||
};
|
||||
|
||||
export default class FilePreview extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
@@ -90,9 +92,7 @@ export default class FilePreview extends React.PureComponent<Props> {
|
||||
key={info.id}
|
||||
className={className}
|
||||
>
|
||||
<div className='post-image__thumbnail'>
|
||||
{previewImage}
|
||||
</div>
|
||||
<div className='post-image__thumbnail'>{previewImage}</div>
|
||||
<div className='post-image__details'>
|
||||
<div className='post-image__detail_wrapper'>
|
||||
<div className='post-image__detail'>
|
||||
@@ -101,12 +101,18 @@ export default class FilePreview extends React.PureComponent<Props> {
|
||||
compactDisplay={false}
|
||||
canDownload={false}
|
||||
/>
|
||||
{info.extension && <span className='post-image__type'>{info.extension.toUpperCase()}</span>}
|
||||
<span className='post-image__size'>{Utils.fileSizeToString(info.size)}</span>
|
||||
{info.extension && (
|
||||
<span className='post-image__type'>
|
||||
{info.extension.toUpperCase()}
|
||||
</span>
|
||||
)}
|
||||
<span className='post-image__size'>
|
||||
{Utils.fileSizeToString(info.size)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{Boolean(this.props.onRemove) && (
|
||||
{this.props.onRemove && (
|
||||
<a
|
||||
className='file-preview__remove'
|
||||
onClick={this.handleRemove.bind(this, info.id)}
|
||||
@@ -114,6 +120,17 @@ export default class FilePreview extends React.PureComponent<Props> {
|
||||
<i className='icon icon-close'/>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{!this.props.onRemove && this.props.disabledRemoveTooltip && (
|
||||
<WithTooltip
|
||||
title={this.props.disabledRemoveTooltip}
|
||||
isVertical={true}
|
||||
>
|
||||
<span className='file-preview__remove file-preview__remove--disabled'>
|
||||
<i className='icon icon-close'/>
|
||||
</span>
|
||||
</WithTooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
|
||||
@@ -1857,6 +1857,8 @@
|
||||
"admin.permissions.group.guest_create_private_channel.name": "Create Channels",
|
||||
"admin.permissions.group.guest_delete_post.description": "Author's own posts can be deleted.",
|
||||
"admin.permissions.group.guest_delete_post.name": "Delete Own Posts",
|
||||
"admin.permissions.group.guest_edit_file_attachment.description": "Allow users to add or remove file attachments when editing posts.",
|
||||
"admin.permissions.group.guest_edit_file_attachment.name": "Edit Attachments",
|
||||
"admin.permissions.group.guest_edit_post.description": "{editTimeLimitButton} after posting, allow users to edit their own posts.",
|
||||
"admin.permissions.group.guest_edit_post.name": "Edit Own Posts",
|
||||
"admin.permissions.group.guest_reactions.description": "Add and delete reactions on posts.",
|
||||
@@ -1941,6 +1943,8 @@
|
||||
"admin.permissions.permission.delete_public_channel.name": "Archive Channels",
|
||||
"admin.permissions.permission.edit_custom_group.description": "Rename custom groups.",
|
||||
"admin.permissions.permission.edit_custom_group.name": "Edit",
|
||||
"admin.permissions.permission.edit_file_attachment.description": "Allow users to add or remove file attachments when editing posts.",
|
||||
"admin.permissions.permission.edit_file_attachment.name": "Edit Attachments",
|
||||
"admin.permissions.permission.edit_other_users.description": "Edit other users",
|
||||
"admin.permissions.permission.edit_other_users.name": "Edit other users",
|
||||
"admin.permissions.permission.edit_others_posts.description": "Allow users to edit others' posts.",
|
||||
@@ -4229,6 +4233,7 @@
|
||||
"file_preview_modal_main_nav.file": "{count, number} of {total, number}",
|
||||
"file_preview_modal_main_nav.nextAriaLabel": "Next file",
|
||||
"file_preview_modal_main_nav.prevAriaLabel": "Previous file",
|
||||
"file_preview.no_edit_permission": "Post attachments cannot be edited",
|
||||
"file_search_result_item.copy_link": "Copy link",
|
||||
"file_search_result_item.download": "Download",
|
||||
"file_search_result_item.more_actions": "More Actions",
|
||||
|
||||
@@ -42,6 +42,7 @@ const values = {
|
||||
REMOVE_OTHERS_REACTIONS: 'remove_others_reactions',
|
||||
PERMANENT_DELETE_USER: 'permanent_delete_user',
|
||||
UPLOAD_FILE: 'upload_file',
|
||||
EDIT_FILE_ATTACHMENT: 'edit_file_attachment',
|
||||
GET_PUBLIC_LINK: 'get_public_link',
|
||||
MANAGE_WEBHOOKS: 'manage_webhooks',
|
||||
MANAGE_OTHERS_WEBHOOKS: 'manage_others_webhooks',
|
||||
|
||||
@@ -69,6 +69,15 @@
|
||||
background: rgba(var(--button-bg-rgb), 0.08);
|
||||
color: functions.v(button-bg);
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1254,6 +1254,7 @@ export const PermissionsScope = {
|
||||
[Permissions.REMOVE_OTHERS_REACTIONS]: 'channel_scope',
|
||||
[Permissions.PERMANENT_DELETE_USER]: 'system_scope',
|
||||
[Permissions.UPLOAD_FILE]: 'channel_scope',
|
||||
[Permissions.EDIT_FILE_ATTACHMENT]: 'channel_scope',
|
||||
[Permissions.GET_PUBLIC_LINK]: 'system_scope',
|
||||
[Permissions.MANAGE_INCOMING_WEBHOOKS]: 'team_scope',
|
||||
[Permissions.MANAGE_OTHERS_INCOMING_WEBHOOKS]: 'team_scope',
|
||||
@@ -1350,6 +1351,7 @@ export const DefaultRolePermissions = {
|
||||
Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS,
|
||||
Permissions.DELETE_POST,
|
||||
Permissions.EDIT_POST,
|
||||
Permissions.EDIT_FILE_ATTACHMENT,
|
||||
Permissions.USE_CHANNEL_MENTIONS,
|
||||
Permissions.USE_GROUP_MENTIONS,
|
||||
Permissions.CREATE_CUSTOM_GROUP,
|
||||
@@ -1439,6 +1441,7 @@ export const DefaultRolePermissions = {
|
||||
],
|
||||
guests: [
|
||||
Permissions.EDIT_POST,
|
||||
Permissions.EDIT_FILE_ATTACHMENT,
|
||||
Permissions.ADD_REACTION,
|
||||
Permissions.REMOVE_REACTION,
|
||||
Permissions.USE_CHANNEL_MENTIONS,
|
||||
|
||||
Ссылка в новой задаче
Block a user