Put room settings form elements in fieldsets (#7311)
* override default fieldset styles Signed-off-by: Kerry Archibald <kerrya@element.io> * SettingsFieldset component Signed-off-by: Kerry Archibald <kerrya@element.io> * test settings fieldset Signed-off-by: Kerry Archibald <kerrya@element.io> * refactor SettingsFlag styles * use SettingsFieldset in room > securit settings * use fieldset in urlpreviewsettings Signed-off-by: Kerry Archibald <kerrya@element.io> * use SettingsFieldset in AliasSettings Signed-off-by: Kerry Archibald <kerrya@element.io> * fieldset in room > roles settings Signed-off-by: Kerry Archibald <kerrya@element.io> * css lint Signed-off-by: Kerry Archibald <kerrya@element.io> * run i18n Signed-off-by: Kerry Archibald <kerrya@element.io> * fussy order Signed-off-by: Kerry Archibald <kerrya@element.io> * default export Signed-off-by: Kerry Archibald <kerrya@element.io> * fix copyright headers Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
cba92c0e90
commit
2e3f225520
16 changed files with 385 additions and 147 deletions
|
@ -172,6 +172,21 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// override defaults
|
||||||
|
fieldset {
|
||||||
|
display: inline-block;
|
||||||
|
margin-inline: unset;
|
||||||
|
padding-block: unset;
|
||||||
|
padding-inline: unset;
|
||||||
|
min-inline-size: unset;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
padding-inline: unset;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
// .mx_textinput is a container for a text input
|
// .mx_textinput is a container for a text input
|
||||||
// + some other controls like buttons, ...
|
// + some other controls like buttons, ...
|
||||||
// it has the appearance of a text box so the controls
|
// it has the appearance of a text box so the controls
|
||||||
|
|
|
@ -159,6 +159,7 @@
|
||||||
@import "./views/elements/_RoomAliasField.scss";
|
@import "./views/elements/_RoomAliasField.scss";
|
||||||
@import "./views/elements/_SSOButtons.scss";
|
@import "./views/elements/_SSOButtons.scss";
|
||||||
@import "./views/elements/_ServerPicker.scss";
|
@import "./views/elements/_ServerPicker.scss";
|
||||||
|
@import "./views/elements/_SettingsFlag.scss";
|
||||||
@import "./views/elements/_Slider.scss";
|
@import "./views/elements/_Slider.scss";
|
||||||
@import "./views/elements/_Spinner.scss";
|
@import "./views/elements/_Spinner.scss";
|
||||||
@import "./views/elements/_StyledCheckbox.scss";
|
@import "./views/elements/_StyledCheckbox.scss";
|
||||||
|
@ -269,6 +270,7 @@
|
||||||
@import "./views/settings/_SecureBackupPanel.scss";
|
@import "./views/settings/_SecureBackupPanel.scss";
|
||||||
@import "./views/settings/_SetIdServer.scss";
|
@import "./views/settings/_SetIdServer.scss";
|
||||||
@import "./views/settings/_SetIntegrationManager.scss";
|
@import "./views/settings/_SetIntegrationManager.scss";
|
||||||
|
@import "./views/settings/_SettingsFieldset.scss";
|
||||||
@import "./views/settings/_SpellCheckLanguages.scss";
|
@import "./views/settings/_SpellCheckLanguages.scss";
|
||||||
@import "./views/settings/_ThemeChoicePanel.scss";
|
@import "./views/settings/_ThemeChoicePanel.scss";
|
||||||
@import "./views/settings/_UpdateCheckButton.scss";
|
@import "./views/settings/_UpdateCheckButton.scss";
|
||||||
|
|
|
@ -29,6 +29,8 @@ limitations under the License.
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-width: 580px;
|
min-width: 580px;
|
||||||
padding-right: 100px;
|
padding-right: 100px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
// Put some padding on the bottom to avoid the settings tab from
|
// Put some padding on the bottom to avoid the settings tab from
|
||||||
// colliding harshly with the dialog when scrolled down.
|
// colliding harshly with the dialog when scrolled down.
|
||||||
|
|
43
res/css/views/elements/_SettingsFlag.scss
Normal file
43
res/css/views/elements/_SettingsFlag.scss
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_SettingsFlag {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
.mx_ToggleSwitch {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SettingsFlag_label {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: $font-14px;
|
||||||
|
color: $primary-content;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SettingsFlag_microcopy {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: $font-12px;
|
||||||
|
line-height: $font-15px;
|
||||||
|
color: $secondary-content;
|
||||||
|
}
|
46
res/css/views/settings/_SettingsFieldset.scss
Normal file
46
res/css/views/settings/_SettingsFieldset.scss
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.mx_SettingsFieldset {
|
||||||
|
margin: 10px 80px 10px 0;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SettingsFieldset_legend {
|
||||||
|
font-size: $font-16px;
|
||||||
|
display: block;
|
||||||
|
font-weight: $font-semi-bold;
|
||||||
|
color: $primary-content;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_SettingsFieldset_description {
|
||||||
|
color: $settings-subsection-fg-color;
|
||||||
|
font-size: $font-14px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -93,16 +93,18 @@ export default class SettingsFlag extends React.Component<IProps, IState> {
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div className="mx_SettingsFlag">
|
<div className="mx_SettingsFlag">
|
||||||
<span className="mx_SettingsFlag_label">{ label }</span>
|
<label className="mx_SettingsFlag_label">
|
||||||
|
<span className="mx_SettingsFlag_labelText">{ label }</span>
|
||||||
|
{ description && <span className="mx_SettingsFlag_microcopy">
|
||||||
|
{ description }
|
||||||
|
</span> }
|
||||||
|
</label>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
checked={this.state.value}
|
checked={this.state.value}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
disabled={this.props.disabled || !canChange}
|
disabled={this.props.disabled || !canChange}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
/>
|
/>
|
||||||
{ description && <div className="mx_SettingsFlag_microcopy">
|
|
||||||
{ description }
|
|
||||||
</div> }
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import Modal from "../../../Modal";
|
||||||
import RoomPublishSetting from "./RoomPublishSetting";
|
import RoomPublishSetting from "./RoomPublishSetting";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import RoomAliasField from "../elements/RoomAliasField";
|
import RoomAliasField from "../elements/RoomAliasField";
|
||||||
|
import SettingsFieldset from "../settings/SettingsFieldset";
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -380,6 +381,17 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mx_AliasSettings'>
|
<div className='mx_AliasSettings'>
|
||||||
|
<SettingsFieldset
|
||||||
|
legend={_t("Published Addresses")}
|
||||||
|
description={<>
|
||||||
|
{ isSpaceRoom
|
||||||
|
? _t("Published addresses can be used by anyone on any server to join your space.")
|
||||||
|
: _t("Published addresses can be used by anyone on any server to join your room.") }
|
||||||
|
|
||||||
|
{ _t("To publish an address, it needs to be set as a local address first.") }
|
||||||
|
</>}
|
||||||
|
>
|
||||||
|
{ /*
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("Published Addresses") }</span>
|
<span className='mx_SettingsTab_subheading'>{ _t("Published Addresses") }</span>
|
||||||
<p>
|
<p>
|
||||||
{ isSpaceRoom
|
{ isSpaceRoom
|
||||||
|
@ -387,47 +399,46 @@ export default class AliasSettings extends React.Component<IProps, IState> {
|
||||||
: _t("Published addresses can be used by anyone on any server to join your room.") }
|
: _t("Published addresses can be used by anyone on any server to join your room.") }
|
||||||
|
|
||||||
{ _t("To publish an address, it needs to be set as a local address first.") }
|
{ _t("To publish an address, it needs to be set as a local address first.") }
|
||||||
</p>
|
</p> */ }
|
||||||
{ canonicalAliasSection }
|
{ canonicalAliasSection }
|
||||||
{ this.props.hidePublishSetting
|
{ this.props.hidePublishSetting
|
||||||
? null
|
? null
|
||||||
: <RoomPublishSetting
|
: <RoomPublishSetting
|
||||||
roomId={this.props.roomId}
|
roomId={this.props.roomId}
|
||||||
canSetCanonicalAlias={this.props.canSetCanonicalAlias}
|
canSetCanonicalAlias={this.props.canSetCanonicalAlias}
|
||||||
/> }
|
/> }
|
||||||
<datalist id="mx_AliasSettings_altRecommendations">
|
<datalist id="mx_AliasSettings_altRecommendations">
|
||||||
{ this.getLocalNonAltAliases().map(alias => {
|
{ this.getLocalNonAltAliases().map(alias => {
|
||||||
return <option value={alias} key={alias} />;
|
return <option value={alias} key={alias} />;
|
||||||
}) };
|
}) };
|
||||||
</datalist>
|
</datalist>
|
||||||
<EditableAliasesList
|
<EditableAliasesList
|
||||||
id="roomAltAliases"
|
id="roomAltAliases"
|
||||||
items={this.state.altAliases}
|
items={this.state.altAliases}
|
||||||
newItem={this.state.newAltAlias}
|
newItem={this.state.newAltAlias}
|
||||||
onNewItemChanged={this.onNewAltAliasChanged}
|
onNewItemChanged={this.onNewAltAliasChanged}
|
||||||
canRemove={this.props.canSetCanonicalAlias}
|
canRemove={this.props.canSetCanonicalAlias}
|
||||||
canEdit={this.props.canSetCanonicalAlias}
|
canEdit={this.props.canSetCanonicalAlias}
|
||||||
onItemAdded={this.onAltAliasAdded}
|
onItemAdded={this.onAltAliasAdded}
|
||||||
onItemRemoved={this.onAltAliasDeleted}
|
onItemRemoved={this.onAltAliasDeleted}
|
||||||
suggestionsListId="mx_AliasSettings_altRecommendations"
|
suggestionsListId="mx_AliasSettings_altRecommendations"
|
||||||
itemsLabel={_t('Other published addresses:')}
|
itemsLabel={_t('Other published addresses:')}
|
||||||
noItemsLabel={_t('No other published addresses yet, add one below')}
|
noItemsLabel={_t('No other published addresses yet, add one below')}
|
||||||
placeholder={_t('New published address (e.g. #alias:server)')}
|
placeholder={_t('New published address (e.g. #alias:server)')}
|
||||||
/>
|
/>
|
||||||
<span className='mx_SettingsTab_subheading mx_AliasSettings_localAliasHeader'>
|
</SettingsFieldset>
|
||||||
{ _t("Local Addresses") }
|
<SettingsFieldset legend={_t("Local Addresses")}
|
||||||
</span>
|
description={isSpaceRoom
|
||||||
<p>
|
|
||||||
{ isSpaceRoom
|
|
||||||
? _t("Set addresses for this space so users can find this space " +
|
? _t("Set addresses for this space so users can find this space " +
|
||||||
"through your homeserver (%(localDomain)s)", { localDomain })
|
"through your homeserver (%(localDomain)s)", { localDomain })
|
||||||
: _t("Set addresses for this room so users can find this room " +
|
: _t("Set addresses for this room so users can find this room " +
|
||||||
"through your homeserver (%(localDomain)s)", { localDomain }) }
|
"through your homeserver (%(localDomain)s)", { localDomain })}>
|
||||||
</p>
|
<details onToggle={this.onLocalAliasesToggled} open={this.state.detailsOpen}>
|
||||||
<details onToggle={this.onLocalAliasesToggled} open={this.state.detailsOpen}>
|
<summary>{ this.state.detailsOpen ? _t('Show less') : _t("Show more") }</summary>
|
||||||
<summary>{ this.state.detailsOpen ? _t('Show less') : _t("Show more") }</summary>
|
{ localAliasesList }
|
||||||
{ localAliasesList }
|
</details>
|
||||||
</details>
|
</SettingsFieldset>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
import SettingsFlag from "../elements/SettingsFlag";
|
import SettingsFlag from "../elements/SettingsFlag";
|
||||||
|
import SettingsFieldset from '../settings/SettingsFieldset';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
@ -96,18 +97,19 @@ export default class UrlPreviewSettings extends React.Component<IProps> {
|
||||||
roomId={roomId} />
|
roomId={roomId} />
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
const description = <>
|
||||||
<div>
|
<p>
|
||||||
<div className='mx_SettingsTab_subsectionText'>
|
{ _t('When someone puts a URL in their message, a URL preview can be shown to give more ' +
|
||||||
{ _t('When someone puts a URL in their message, a URL preview can be shown to give more ' +
|
|
||||||
'information about that link such as the title, description, and an image from the website.') }
|
'information about that link such as the title, description, and an image from the website.') }
|
||||||
</div>
|
</p>
|
||||||
<div className='mx_SettingsTab_subsectionText'>
|
<p>{ previewsForAccount }</p>
|
||||||
{ previewsForAccount }
|
</>;
|
||||||
</div>
|
|
||||||
|
return (
|
||||||
|
<SettingsFieldset legend={_t("URL Previews")} description={description}>
|
||||||
{ previewsForRoom }
|
{ previewsForRoom }
|
||||||
<label>{ previewsForRoomAccount }</label>
|
<label>{ previewsForRoomAccount }</label>
|
||||||
</div>
|
</SettingsFieldset>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
src/components/views/settings/SettingsFieldset.tsx
Normal file
31
src/components/views/settings/SettingsFieldset.tsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { ReactNode, HTMLAttributes } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface Props extends HTMLAttributes<HTMLFieldSetElement> {
|
||||||
|
// section title
|
||||||
|
legend: string | ReactNode;
|
||||||
|
description?: string | ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingsFieldset: React.FC<Props> = ({ legend, className, children, description, ...rest }) =>
|
||||||
|
<fieldset {...rest} className={classNames('mx_SettingsFieldset', className)}>
|
||||||
|
<legend className='mx_SettingsFieldset_legend'>{ legend }</legend>
|
||||||
|
{ description && <div className='mx_SettingsFieldset_description'>{ description }</div> }
|
||||||
|
{ children }
|
||||||
|
</fieldset>;
|
||||||
|
|
||||||
|
export default SettingsFieldset;
|
|
@ -66,15 +66,9 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
||||||
const canChangeGroups = room.currentState.mayClientSendStateEvent("m.room.related_groups", client);
|
const canChangeGroups = room.currentState.mayClientSendStateEvent("m.room.related_groups", client);
|
||||||
const groupsEvent = room.currentState.getStateEvents("m.room.related_groups", "");
|
const groupsEvent = room.currentState.getStateEvents("m.room.related_groups", "");
|
||||||
|
|
||||||
let urlPreviewSettings = <>
|
const urlPreviewSettings = SettingsStore.getValue(UIFeature.URLPreviews) ?
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("URL Previews") }</span>
|
<UrlPreviewSettings room={room} /> :
|
||||||
<div className='mx_SettingsTab_section'>
|
null;
|
||||||
<UrlPreviewSettings room={room} />
|
|
||||||
</div>
|
|
||||||
</>;
|
|
||||||
if (!SettingsStore.getValue(UIFeature.URLPreviews)) {
|
|
||||||
urlPreviewSettings = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let flairSection;
|
let flairSection;
|
||||||
if (SettingsStore.getValue(UIFeature.Flair)) {
|
if (SettingsStore.getValue(UIFeature.Flair)) {
|
||||||
|
@ -110,14 +104,12 @@ export default class GeneralRoomSettingsTab extends React.Component<IProps, ISta
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mx_SettingsTab_heading">{ _t("Room Addresses") }</div>
|
<div className="mx_SettingsTab_heading">{ _t("Room Addresses") }</div>
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<AliasSettings
|
||||||
<AliasSettings
|
roomId={this.props.roomId}
|
||||||
roomId={this.props.roomId}
|
canSetCanonicalAlias={canSetCanonical}
|
||||||
canSetCanonicalAlias={canSetCanonical}
|
canSetAliases={canSetAliases}
|
||||||
canSetAliases={canSetAliases}
|
canonicalAliasEvent={canonicalAliasEv}
|
||||||
canonicalAliasEvent={canonicalAliasEv}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mx_SettingsTab_heading">{ _t("Other") }</div>
|
<div className="mx_SettingsTab_heading">{ _t("Other") }</div>
|
||||||
{ flairSection }
|
{ flairSection }
|
||||||
{ urlPreviewSettings }
|
{ urlPreviewSettings }
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { RoomState } from "matrix-js-sdk/src/models/room-state";
|
||||||
import { compare } from "../../../../../utils/strings";
|
import { compare } from "../../../../../utils/strings";
|
||||||
import ErrorDialog from '../../../dialogs/ErrorDialog';
|
import ErrorDialog from '../../../dialogs/ErrorDialog';
|
||||||
import PowerSelector from "../../../elements/PowerSelector";
|
import PowerSelector from "../../../elements/PowerSelector";
|
||||||
|
import SettingsFieldset from '../../SettingsFieldset';
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import SettingsStore from "../../../../../settings/SettingsStore";
|
import SettingsStore from "../../../../../settings/SettingsStore";
|
||||||
|
@ -345,17 +346,15 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||||
|
|
||||||
if (privilegedUsers.length) {
|
if (privilegedUsers.length) {
|
||||||
privilegedUsersSection =
|
privilegedUsersSection =
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<SettingsFieldset legend={_t('Privileged Users')}>
|
||||||
<div className='mx_SettingsTab_subheading'>{ _t('Privileged Users') }</div>
|
{ privilegedUsers }
|
||||||
{ privilegedUsers }
|
</SettingsFieldset>;
|
||||||
</div>;
|
|
||||||
}
|
}
|
||||||
if (mutedUsers.length) {
|
if (mutedUsers.length) {
|
||||||
mutedUsersSection =
|
mutedUsersSection =
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<SettingsFieldset legend={_t('Muted Users')}>
|
||||||
<div className='mx_SettingsTab_subheading'>{ _t('Muted Users') }</div>
|
|
||||||
{ mutedUsers }
|
{ mutedUsers }
|
||||||
</div>;
|
</SettingsFieldset>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +363,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||||
if (banned.length) {
|
if (banned.length) {
|
||||||
const canBanUsers = currentUserLevel >= banLevel;
|
const canBanUsers = currentUserLevel >= banLevel;
|
||||||
bannedUsersSection =
|
bannedUsersSection =
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<SettingsFieldset legend={_t('Banned users')}>
|
||||||
<div className='mx_SettingsTab_subheading'>{ _t('Banned users') }</div>
|
|
||||||
<ul>
|
<ul>
|
||||||
{ banned.map((member) => {
|
{ banned.map((member) => {
|
||||||
const banEvent = member.events.member.getContent();
|
const banEvent = member.events.member.getContent();
|
||||||
|
@ -383,7 +381,7 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||||
);
|
);
|
||||||
}) }
|
}) }
|
||||||
</ul>
|
</ul>
|
||||||
</div>;
|
</SettingsFieldset>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const powerSelectors = Object.keys(powerLevelDescriptors).map((key, index) => {
|
const powerSelectors = Object.keys(powerLevelDescriptors).map((key, index) => {
|
||||||
|
@ -452,15 +450,17 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
|
||||||
{ privilegedUsersSection }
|
{ privilegedUsersSection }
|
||||||
{ mutedUsersSection }
|
{ mutedUsersSection }
|
||||||
{ bannedUsersSection }
|
{ bannedUsersSection }
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
<SettingsFieldset
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("Permissions") }</span>
|
legend={_t("Permissions")}
|
||||||
<p>{ isSpaceRoom
|
description={
|
||||||
? _t('Select the roles required to change various parts of the space')
|
isSpaceRoom
|
||||||
: _t('Select the roles required to change various parts of the room')
|
? _t('Select the roles required to change various parts of the space')
|
||||||
}</p>
|
: _t('Select the roles required to change various parts of the room')
|
||||||
|
}
|
||||||
|
>
|
||||||
{ powerSelectors }
|
{ powerSelectors }
|
||||||
{ eventPowerSelectors }
|
{ eventPowerSelectors }
|
||||||
</div>
|
</SettingsFieldset>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ import createRoom, { IOpts } from '../../../../../createRoom';
|
||||||
import CreateRoomDialog from '../../../dialogs/CreateRoomDialog';
|
import CreateRoomDialog from '../../../dialogs/CreateRoomDialog';
|
||||||
import JoinRuleSettings from "../../JoinRuleSettings";
|
import JoinRuleSettings from "../../JoinRuleSettings";
|
||||||
import ErrorDialog from "../../../dialogs/ErrorDialog";
|
import ErrorDialog from "../../../dialogs/ErrorDialog";
|
||||||
|
import SettingsFieldset from '../../SettingsFieldset';
|
||||||
|
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
@ -265,14 +266,11 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const description = _t("Decide who can join %(roomName)s.", {
|
||||||
|
roomName: room?.name,
|
||||||
|
});
|
||||||
|
|
||||||
return <div className="mx_SecurityRoomSettingsTab_joinRule">
|
return <SettingsFieldset legend={_t("Access")} description={description}>
|
||||||
<div className="mx_SettingsTab_subsectionText">
|
|
||||||
<span>{ _t("Decide who can join %(roomName)s.", {
|
|
||||||
roomName: room?.name,
|
|
||||||
}) }</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ aliasWarning }
|
{ aliasWarning }
|
||||||
|
|
||||||
<JoinRuleSettings
|
<JoinRuleSettings
|
||||||
|
@ -282,7 +280,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
closeSettingsFn={this.props.closeSettingsFn}
|
closeSettingsFn={this.props.closeSettingsFn}
|
||||||
promptUpgrade={true}
|
promptUpgrade={true}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</SettingsFieldset>;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onJoinRuleChangeError = (error: Error) => {
|
private onJoinRuleChangeError = (error: Error) => {
|
||||||
|
@ -330,6 +328,10 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
};
|
};
|
||||||
|
|
||||||
private renderHistory() {
|
private renderHistory() {
|
||||||
|
if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
const history = this.state.history;
|
const history = this.state.history;
|
||||||
const state = client.getRoom(this.props.roomId).currentState;
|
const state = client.getRoom(this.props.roomId).currentState;
|
||||||
|
@ -358,21 +360,18 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
const description = _t('Changes to who can read history will only apply to future messages in this room. ' +
|
||||||
<div>
|
'The visibility of existing history will be unchanged.');
|
||||||
<div>
|
|
||||||
{ _t('Changes to who can read history will only apply to future messages in this room. ' +
|
return (<SettingsFieldset legend={_t("Who can read history?")} description={description}>
|
||||||
'The visibility of existing history will be unchanged.') }
|
<StyledRadioGroup
|
||||||
</div>
|
name="historyVis"
|
||||||
<StyledRadioGroup
|
value={history}
|
||||||
name="historyVis"
|
onChange={this.onHistoryRadioToggle}
|
||||||
value={history}
|
disabled={!canChangeHistory}
|
||||||
onChange={this.onHistoryRadioToggle}
|
definitions={options}
|
||||||
disabled={!canChangeHistory}
|
/>
|
||||||
definitions={options}
|
</SettingsFieldset>);
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleAdvancedSection = () => {
|
private toggleAdvancedSection = () => {
|
||||||
|
@ -416,15 +415,7 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let historySection = (<>
|
const historySection = this.renderHistory();
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("Who can read history?") }</span>
|
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
|
||||||
{ this.renderHistory() }
|
|
||||||
</div>
|
|
||||||
</>);
|
|
||||||
if (!SettingsStore.getValue(UIFeature.RoomHistorySettings)) {
|
|
||||||
historySection = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let advanced;
|
let advanced;
|
||||||
if (room.getJoinRule() === JoinRule.Public) {
|
if (room.getJoinRule() === JoinRule.Public) {
|
||||||
|
@ -446,26 +437,17 @@ export default class SecurityRoomSettingsTab extends React.Component<IProps, ISt
|
||||||
<div className="mx_SettingsTab mx_SecurityRoomSettingsTab">
|
<div className="mx_SettingsTab mx_SecurityRoomSettingsTab">
|
||||||
<div className="mx_SettingsTab_heading">{ _t("Security & Privacy") }</div>
|
<div className="mx_SettingsTab_heading">{ _t("Security & Privacy") }</div>
|
||||||
|
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("Encryption") }</span>
|
<SettingsFieldset legend={_t("Encryption")} description={_t("Once enabled, encryption cannot be disabled.")}>
|
||||||
<div className='mx_SettingsTab_section mx_SecurityRoomSettingsTab_encryptionSection'>
|
<LabelledToggleSwitch
|
||||||
<div>
|
value={isEncrypted}
|
||||||
<div className='mx_SettingsTab_subsectionText'>
|
onChange={this.onEncryptionChange}
|
||||||
<span>{ _t("Once enabled, encryption cannot be disabled.") }</span>
|
label={_t("Encrypted")}
|
||||||
</div>
|
disabled={!canEnableEncryption}
|
||||||
<LabelledToggleSwitch
|
/>
|
||||||
value={isEncrypted}
|
|
||||||
onChange={this.onEncryptionChange}
|
|
||||||
label={_t("Encrypted")}
|
|
||||||
disabled={!canEnableEncryption}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{ encryptionSettings }
|
{ encryptionSettings }
|
||||||
</div>
|
</SettingsFieldset>
|
||||||
|
|
||||||
<span className='mx_SettingsTab_subheading'>{ _t("Access") }</span>
|
{ this.renderJoinRule() }
|
||||||
<div className='mx_SettingsTab_section mx_SettingsTab_subsectionText'>
|
|
||||||
{ this.renderJoinRule() }
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{ advanced }
|
{ advanced }
|
||||||
{ historySection }
|
{ historySection }
|
||||||
|
|
|
@ -98,15 +98,13 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn
|
||||||
if (space.getJoinRule() === JoinRule.Public) {
|
if (space.getJoinRule() === JoinRule.Public) {
|
||||||
addressesSection = <>
|
addressesSection = <>
|
||||||
<span className="mx_SettingsTab_subheading">{ _t("Address") }</span>
|
<span className="mx_SettingsTab_subheading">{ _t("Address") }</span>
|
||||||
<div className="mx_SettingsTab_section mx_SettingsTab_subsectionText">
|
<AliasSettings
|
||||||
<AliasSettings
|
roomId={space.roomId}
|
||||||
roomId={space.roomId}
|
canSetCanonicalAlias={canSetCanonical}
|
||||||
canSetCanonicalAlias={canSetCanonical}
|
canSetAliases={true}
|
||||||
canSetAliases={true}
|
canonicalAliasEvent={canonicalAliasEv}
|
||||||
canonicalAliasEvent={canonicalAliasEv}
|
hidePublishSetting={true}
|
||||||
hidePublishSetting={true}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1495,7 +1495,6 @@
|
||||||
"This room is bridging messages to the following platforms. <a>Learn more.</a>": "This room is bridging messages to the following platforms. <a>Learn more.</a>",
|
"This room is bridging messages to the following platforms. <a>Learn more.</a>": "This room is bridging messages to the following platforms. <a>Learn more.</a>",
|
||||||
"This room isn't bridging messages to any platforms. <a>Learn more.</a>": "This room isn't bridging messages to any platforms. <a>Learn more.</a>",
|
"This room isn't bridging messages to any platforms. <a>Learn more.</a>": "This room isn't bridging messages to any platforms. <a>Learn more.</a>",
|
||||||
"Bridges": "Bridges",
|
"Bridges": "Bridges",
|
||||||
"URL Previews": "URL Previews",
|
|
||||||
"Room Addresses": "Room Addresses",
|
"Room Addresses": "Room Addresses",
|
||||||
"Uploaded sound": "Uploaded sound",
|
"Uploaded sound": "Uploaded sound",
|
||||||
"Get notifications as set up in your <a>settings</a>": "Get notifications as set up in your <a>settings</a>",
|
"Get notifications as set up in your <a>settings</a>": "Get notifications as set up in your <a>settings</a>",
|
||||||
|
@ -1556,6 +1555,7 @@
|
||||||
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>",
|
"Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>": "Once enabled, encryption for a room cannot be disabled. Messages sent in an encrypted room cannot be seen by the server, only by the participants of the room. Enabling encryption may prevent many bots and bridges from working correctly. <a>Learn more about encryption.</a>",
|
||||||
"To link to this room, please add an address.": "To link to this room, please add an address.",
|
"To link to this room, please add an address.": "To link to this room, please add an address.",
|
||||||
"Decide who can join %(roomName)s.": "Decide who can join %(roomName)s.",
|
"Decide who can join %(roomName)s.": "Decide who can join %(roomName)s.",
|
||||||
|
"Access": "Access",
|
||||||
"Failed to update the join rules": "Failed to update the join rules",
|
"Failed to update the join rules": "Failed to update the join rules",
|
||||||
"Unknown failure": "Unknown failure",
|
"Unknown failure": "Unknown failure",
|
||||||
"Are you sure you want to make this encrypted room public?": "Are you sure you want to make this encrypted room public?",
|
"Are you sure you want to make this encrypted room public?": "Are you sure you want to make this encrypted room public?",
|
||||||
|
@ -1566,12 +1566,11 @@
|
||||||
"Members only (since they joined)": "Members only (since they joined)",
|
"Members only (since they joined)": "Members only (since they joined)",
|
||||||
"Anyone": "Anyone",
|
"Anyone": "Anyone",
|
||||||
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.",
|
"Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.": "Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged.",
|
||||||
"People with supported clients will be able to join the room without having a registered account.": "People with supported clients will be able to join the room without having a registered account.",
|
|
||||||
"Who can read history?": "Who can read history?",
|
"Who can read history?": "Who can read history?",
|
||||||
|
"People with supported clients will be able to join the room without having a registered account.": "People with supported clients will be able to join the room without having a registered account.",
|
||||||
"Security & Privacy": "Security & Privacy",
|
"Security & Privacy": "Security & Privacy",
|
||||||
"Once enabled, encryption cannot be disabled.": "Once enabled, encryption cannot be disabled.",
|
"Once enabled, encryption cannot be disabled.": "Once enabled, encryption cannot be disabled.",
|
||||||
"Encrypted": "Encrypted",
|
"Encrypted": "Encrypted",
|
||||||
"Access": "Access",
|
|
||||||
"Unable to revoke sharing for email address": "Unable to revoke sharing for email address",
|
"Unable to revoke sharing for email address": "Unable to revoke sharing for email address",
|
||||||
"Unable to share email address": "Unable to share email address",
|
"Unable to share email address": "Unable to share email address",
|
||||||
"Your email address hasn't been verified yet": "Your email address hasn't been verified yet",
|
"Your email address hasn't been verified yet": "Your email address hasn't been verified yet",
|
||||||
|
@ -1881,6 +1880,7 @@
|
||||||
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
|
"URL previews are disabled by default for participants in this room.": "URL previews are disabled by default for participants in this room.",
|
||||||
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.",
|
"In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.": "In encrypted rooms, like this one, URL previews are disabled by default to ensure that your homeserver (where the previews are generated) cannot gather information about links you see in this room.",
|
||||||
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
"When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.": "When someone puts a URL in their message, a URL preview can be shown to give more information about that link such as the title, description, and an image from the website.",
|
||||||
|
"URL Previews": "URL Previews",
|
||||||
"Back": "Back",
|
"Back": "Back",
|
||||||
"To proceed, please accept the verification request on your other login.": "To proceed, please accept the verification request on your other login.",
|
"To proceed, please accept the verification request on your other login.": "To proceed, please accept the verification request on your other login.",
|
||||||
"Waiting for %(displayName)s to accept…": "Waiting for %(displayName)s to accept…",
|
"Waiting for %(displayName)s to accept…": "Waiting for %(displayName)s to accept…",
|
||||||
|
|
46
test/components/views/settings/SettingsFieldset-test.tsx
Normal file
46
test/components/views/settings/SettingsFieldset-test.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { renderIntoDocument } from 'react-dom/test-utils';
|
||||||
|
|
||||||
|
import SettingsFieldset from '../../../../src/components/views/settings/SettingsFieldset';
|
||||||
|
|
||||||
|
describe('<SettingsFieldset />', () => {
|
||||||
|
const defaultProps = {
|
||||||
|
"legend": 'Who can read history?',
|
||||||
|
"children": <div>test</div>,
|
||||||
|
'data-test-id': 'test',
|
||||||
|
};
|
||||||
|
const getComponent = (props = {}) => {
|
||||||
|
const wrapper = renderIntoDocument<HTMLDivElement>(
|
||||||
|
<div><SettingsFieldset {...defaultProps} {...props} /></div>,
|
||||||
|
) as HTMLDivElement;
|
||||||
|
return wrapper.children[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
it('renders fieldset without description', () => {
|
||||||
|
expect(getComponent()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders fieldset with plain text description', () => {
|
||||||
|
const description = 'Changes to who can read history.';
|
||||||
|
expect(getComponent({ description })).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders fieldset with react description', () => {
|
||||||
|
const description = <><p>Test</p><a href='#'>a link</a></>;
|
||||||
|
expect(getComponent({ description })).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<SettingsFieldset /> renders fieldset with plain text description 1`] = `
|
||||||
|
<fieldset
|
||||||
|
class="mx_SettingsFieldset"
|
||||||
|
data-test-id="test"
|
||||||
|
>
|
||||||
|
<legend
|
||||||
|
class="mx_SettingsFieldset_legend"
|
||||||
|
>
|
||||||
|
Who can read history?
|
||||||
|
</legend>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsFieldset_description"
|
||||||
|
>
|
||||||
|
Changes to who can read history.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
test
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<SettingsFieldset /> renders fieldset with react description 1`] = `
|
||||||
|
<fieldset
|
||||||
|
class="mx_SettingsFieldset"
|
||||||
|
data-test-id="test"
|
||||||
|
>
|
||||||
|
<legend
|
||||||
|
class="mx_SettingsFieldset_legend"
|
||||||
|
>
|
||||||
|
Who can read history?
|
||||||
|
</legend>
|
||||||
|
<div
|
||||||
|
class="mx_SettingsFieldset_description"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Test
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
>
|
||||||
|
a link
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
test
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<SettingsFieldset /> renders fieldset without description 1`] = `
|
||||||
|
<fieldset
|
||||||
|
class="mx_SettingsFieldset"
|
||||||
|
data-test-id="test"
|
||||||
|
>
|
||||||
|
<legend
|
||||||
|
class="mx_SettingsFieldset_legend"
|
||||||
|
>
|
||||||
|
Who can read history?
|
||||||
|
</legend>
|
||||||
|
<div>
|
||||||
|
test
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
`;
|
Loading…
Reference in a new issue