MM-58529 Fix for AdditionalValues in SystemConsole (#27614)

* Reimplement display Timelimit modal

* update permission_description, add unit tests

* Update permission_group.tsx

* update tests, remove logging

* Update permission_description.tsx

* fix issue with link opening new window

* Update permission_description.tsx

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Scott Bishel 2024-08-06 16:31:07 -06:00 committed by GitHub
parent 2e004bb7bc
commit 5f8f1f8142
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 430 additions and 23 deletions

View File

@ -0,0 +1,167 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/admin_console/permission_schemes_settings/permission_description should allow select with link 1`] = `
<Provider
store={
Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
}
}
>
<PermissionDescription
description="This is the description"
id="defaultID"
inherited={
Object {
"name": "all_users",
}
}
selectRow={[MockFunction]}
>
<span
className="permission-description"
onClick={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<span
className="inherit-link-wrapper"
>
<FormattedMessage
defaultMessage="Inherited from <link>{name}</link>."
id="admin.permissions.inherited_from"
values={
Object {
"link": [Function],
"name": "All Members",
}
}
>
<span>
Inherited from
<a
key=".$.1"
>
All Members
</a>
.
</span>
</FormattedMessage>
</span>
<Overlay
animation={[Function]}
placement="top"
rootClose={false}
show={false}
target={null}
>
<Overlay
placement="top"
rootClose={false}
show={false}
target={null}
transition={[Function]}
/>
</Overlay>
</span>
</PermissionDescription>
</Provider>
`;
exports[`components/admin_console/permission_schemes_settings/permission_description should match snapshot if inherited 1`] = `
<ContextProvider
value={
Object {
"store": Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
},
"subscription": Subscription {
"handleChangeWrapper": [Function],
"listeners": Object {
"notify": [Function],
},
"onStateChange": [Function],
"parentSub": undefined,
"store": Object {
"clearActions": [Function],
"dispatch": [Function],
"getActions": [Function],
"getState": [Function],
"replaceReducer": [Function],
"subscribe": [Function],
},
"unsubscribe": null,
},
}
}
>
<PermissionDescription
description="This is the description"
id="defaultID"
inherited={
Object {
"name": "all_users",
}
}
selectRow={[MockFunction]}
/>
</ContextProvider>
`;
exports[`components/admin_console/permission_schemes_settings/permission_description should match snapshot with clickable link 1`] = `
<span
className="permission-description"
onClick={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
>
<span>
This is a clickable description
</span>
<Overlay
animation={[Function]}
placement="top"
rootClose={false}
show={false}
target={null}
>
<Tooltip>
<span>
This is a clickable description
</span>
</Tooltip>
</Overlay>
</span>
`;
exports[`components/admin_console/permission_schemes_settings/permission_description should match snapshot with default Props 1`] = `
<span
className="permission-description"
onClick={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
>
This is the description
<Overlay
animation={[Function]}
placement="top"
rootClose={false}
show={false}
target={null}
>
<Tooltip>
This is the description
</Tooltip>
</Overlay>
</span>
`;

View File

@ -668,3 +668,56 @@ exports[`components/admin_console/permission_schemes_settings/permission_group s
</div>
</div>
`;
exports[`components/admin_console/permission_schemes_settings/permission_group should match snapshot with additional values 1`] = `
<div
className="permission-group"
>
<div
className="permission-group-row "
id="uniqId"
onClick={[Function]}
>
<div
className="fa fa-caret-right permission-arrow open"
onClick={[Function]}
/>
<PermissionCheckbox
id="uniqId-checkbox"
value=""
/>
<span
className="permission-name"
>
name
</span>
<PermissionDescription
description=""
id="name"
selectRow={[MockFunction]}
/>
</div>
<div
className="permission-group-permissions open"
>
<PermissionRow
additionalValues={Object {}}
id="invite_user"
key="invite_user"
onChange={[Function]}
selectRow={[MockFunction]}
uniqId="uniqId-invite_user"
value=""
/>
<PermissionRow
additionalValues={Object {}}
id="add_user_to_team"
key="add_user_to_team"
onChange={[Function]}
selectRow={[MockFunction]}
uniqId="uniqId-add_user_to_team"
value=""
/>
</div>
</div>
`;

View File

@ -100,3 +100,40 @@ exports[`components/admin_console/permission_schemes_settings/permission_row sho
/>
</div>
`;
exports[`components/admin_console/permission_schemes_settings/permission_row should match snapshot with additional values 1`] = `
<div
className="permission-row"
id="uniqId"
onClick={[Function]}
>
<PermissionCheckbox
id="uniqId-checkbox"
value="checked"
/>
<span
className="permission-name"
>
id
</span>
<PermissionDescription
additionalValues={
Object {
"edit_post": Object {
"editTimeLimitButton": <Button
active={false}
block={false}
bsClass="btn"
bsStyle="default"
disabled={false}
onClick={[MockFunction]}
/>,
},
}
}
description=""
id="id"
selectRow={[MockFunction]}
/>
</div>
`;

View File

@ -0,0 +1,90 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {shallow} from 'enzyme';
import React from 'react';
import * as reactRedux from 'react-redux';
import {mountWithIntl} from 'tests/helpers/intl-test-helper';
import mockStore from 'tests/test_store';
import PermissionDescription from './permission_description';
describe('components/admin_console/permission_schemes_settings/permission_description', () => {
const defaultProps = {
id: 'defaultID',
selectRow: jest.fn(),
description: 'This is the description',
};
let store = mockStore();
beforeEach(() => {
const initialState = {
entities: {
general: {
config: {},
},
users: {
currentUserId: 'currentUserId',
},
},
};
store = mockStore(initialState);
});
test('should match snapshot with default Props', () => {
const wrapper = shallow(
<PermissionDescription
{...defaultProps}
/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot if inherited', () => {
const wrapper = shallow(
<reactRedux.Provider store={store}>
<PermissionDescription
{...defaultProps}
inherited={{
name: 'all_users',
}}
/>
</reactRedux.Provider>,
);
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot with clickable link', () => {
const description = (
<span>{'This is a clickable description'}</span>
);
const wrapper = shallow(
<PermissionDescription
{...defaultProps}
description={description}
/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should allow select with link', () => {
const selectRow = jest.fn();
const wrapper = mountWithIntl(
<reactRedux.Provider store={store}>
<PermissionDescription
{...defaultProps}
inherited={{
name: 'all_users',
}}
selectRow={selectRow}
/>
</reactRedux.Provider>,
);
expect(wrapper).toMatchSnapshot();
wrapper.find('a').simulate('click');
expect(selectRow).toBeCalled();
});
});

View File

@ -4,15 +4,12 @@
import React, {useState, useRef} from 'react';
import type {MouseEvent} from 'react';
import {Overlay} from 'react-bootstrap';
import {useIntl} from 'react-intl';
import {FormattedMessage, useIntl} from 'react-intl';
import type {Role} from '@mattermost/types/roles';
import FormattedMarkdownMessage from 'components/formatted_markdown_message';
import Tooltip from 'components/tooltip';
import {generateId} from 'utils/utils';
import type {AdditionalValues} from './permissions_tree/types';
import {rolesRolesStrings} from './strings/roles';
@ -32,7 +29,6 @@ const PermissionDescription = ({
inherited,
}: Props): JSX.Element => {
const [open, setOpen] = useState(false);
const randomId = generateId();
const contentRef = useRef<HTMLSpanElement>(null);
const intl = useIntl();
@ -57,12 +53,18 @@ const PermissionDescription = ({
let content: string | JSX.Element = '';
if (inherited && inherited.name) {
const formattedName = intl.formatMessage(rolesRolesStrings[inherited.name]);
content = (
<span className='inherit-link-wrapper'>
<FormattedMarkdownMessage
<FormattedMessage
id='admin.permissions.inherited_from'
defaultMessage='Inherited from [{name}]().'
values={{name: intl.formatMessage(rolesRolesStrings[inherited.name])}}
defaultMessage='Inherited from <link>{name}</link>.'
values={{
name: formattedName,
link: (text: string) => (
<a>{text}</a>
),
}}
/>
</span>
);
@ -75,7 +77,7 @@ const PermissionDescription = ({
placement='top'
target={(contentRef.current as HTMLSpanElement)}
>
<Tooltip id={randomId}>
<Tooltip>
{content}
</Tooltip>
</Overlay>

View File

@ -3,6 +3,7 @@
import {shallow} from 'enzyme';
import React from 'react';
import {Button} from 'react-bootstrap';
import PermissionGroup from 'components/admin_console/permission_schemes_settings/permission_group';
@ -111,6 +112,26 @@ describe('components/admin_console/permission_schemes_settings/permission_group'
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot with additional values', () => {
const ADDITIONAL_VALUES = {
edit_post: {
editTimeLimitButton: (
<Button
onClick={jest.fn()}
/>
),
},
};
const wrapper = shallow(
<PermissionGroup
{...defaultProps}
additionalValues={ADDITIONAL_VALUES}
/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should expand and collapse correctly, expanded by default, collapsed and then expanded again', () => {
const wrapper = shallow(
<PermissionGroup {...defaultProps}/>,

View File

@ -280,9 +280,17 @@ export default class PermissionGroup extends React.PureComponent<Props, State> {
classes += ' combined';
}
const additionalValuesProp = additionalValues?.[id] ? additionalValues[id] : undefined;
const name = groupRolesStrings[id] ? <FormattedMessage {...groupRolesStrings[id].name}/> : id;
const description = groupRolesStrings[id] ? <FormattedMessage {...groupRolesStrings[id].description}/> : '';
let description: React.JSX.Element | string = '';
if (groupRolesStrings[id]) {
description = (
<FormattedMessage
id={groupRolesStrings[id].description.id}
defaultMessage={groupRolesStrings[id].description.defaultMessage}
values={additionalValuesProp}
/>
);
}
return (
<div className='permission-group'>

View File

@ -3,6 +3,7 @@
import {shallow} from 'enzyme';
import React from 'react';
import {Button} from 'react-bootstrap';
import PermissionRow from 'components/admin_console/permission_schemes_settings/permission_row';
@ -55,6 +56,26 @@ describe('components/admin_console/permission_schemes_settings/permission_row',
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot with additional values', () => {
const ADDITIONAL_VALUES = {
edit_post: {
editTimeLimitButton: (
<Button
onClick={jest.fn()}
/>
),
},
};
const wrapper = shallow(
<PermissionRow
{...defaultProps}
additionalValues={ADDITIONAL_VALUES}
/>,
);
expect(wrapper).toMatchSnapshot();
});
test('should call onChange function on click', () => {
const onChange = jest.fn();
const wrapper = shallow(

View File

@ -43,7 +43,15 @@ const PermissionRow = ({
}, [readOnly, onChange, id]);
const name = permissionRolesStrings[id] ? <FormattedMessage {...permissionRolesStrings[id].name}/> : id;
const description = permissionRolesStrings[id] ? <FormattedMessage {...permissionRolesStrings[id].description}/> : '';
let description: React.JSX.Element | string = '';
if (permissionRolesStrings[id]) {
description = (
<FormattedMessage
id={permissionRolesStrings[id].description.id}
values={additionalValues}
/>
);
}
return (
<div

View File

@ -58,12 +58,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
>
<span>
<MemoizedFormattedMessage
defaultMessage="<linkTeamOverride>Team Override Schemes</linkTeamOverride> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
defaultMessage="<linkOverrideTeam>Team Override Schemes</linkOverrideTeam> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
id="admin.permissions.teamScheme.introBanner"
values={
Object {
"linkOverrideTeam": [Function],
"linkSystemScheme": [Function],
"linkTeamOverride": [Function],
}
}
/>
@ -433,12 +433,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
>
<span>
<MemoizedFormattedMessage
defaultMessage="<linkTeamOverride>Team Override Schemes</linkTeamOverride> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
defaultMessage="<linkOverrideTeam>Team Override Schemes</linkOverrideTeam> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
id="admin.permissions.teamScheme.introBanner"
values={
Object {
"linkOverrideTeam": [Function],
"linkSystemScheme": [Function],
"linkTeamOverride": [Function],
}
}
/>
@ -838,12 +838,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
>
<span>
<MemoizedFormattedMessage
defaultMessage="<linkTeamOverride>Team Override Schemes</linkTeamOverride> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
defaultMessage="<linkOverrideTeam>Team Override Schemes</linkOverrideTeam> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
id="admin.permissions.teamScheme.introBanner"
values={
Object {
"linkOverrideTeam": [Function],
"linkSystemScheme": [Function],
"linkTeamOverride": [Function],
}
}
/>
@ -1311,12 +1311,12 @@ exports[`components/admin_console/permission_schemes_settings/permission_team_sc
>
<span>
<MemoizedFormattedMessage
defaultMessage="<linkTeamOverride>Team Override Schemes</linkTeamOverride> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
defaultMessage="<linkOverrideTeam>Team Override Schemes</linkOverrideTeam> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>."
id="admin.permissions.teamScheme.introBanner"
values={
Object {
"linkOverrideTeam": [Function],
"linkSystemScheme": [Function],
"linkTeamOverride": [Function],
}
}
/>

View File

@ -606,9 +606,9 @@ class PermissionTeamSchemeSettings extends React.PureComponent<Props & RouteComp
<span>
<FormattedMessage
id='admin.permissions.teamScheme.introBanner'
defaultMessage='<linkTeamOverride>Team Override Schemes</linkTeamOverride> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>.'
defaultMessage='<linkOverrideTeam>Team Override Schemes</linkOverrideTeam> set the permissions for Team Admins, Channel Admins and other members in specific teams. Use a Team Override Scheme when specific teams need permission exceptions to the <linkSystemScheme>System Scheme</linkSystemScheme>.'
values={{
linkTeamOverride: (msg: React.ReactNode) => (
linkOverrideTeam: (msg: React.ReactNode) => (
<ExternalLink
href={DocLinks.ONBOARD_ADVANCED_PERMISSIONS}
location='permission_team_scheme_settings'

View File

@ -1619,7 +1619,7 @@
"admin.permissions.group.teams_team_scope.name": "Teams",
"admin.permissions.group.teams.description": "Create teams and manage members.",
"admin.permissions.group.teams.name": "Teams",
"admin.permissions.inherited_from": "Inherited from [{name}]().",
"admin.permissions.inherited_from": "Inherited from <link>{name}</link>.",
"admin.permissions.introBanner": "Permission Schemes set the default permissions for Team Admins, Channel Admins and everyone else. Learn more about permission schemes in our <link>documentation</link>.",
"admin.permissions.loadingMoreSchemes": "Loading...",
"admin.permissions.loadMoreSchemes": "Load more schemes",