Remove duplicative Toggle component (#3028)
fix: Tidy some styling and spacing issues in settings
This commit is contained in:
@@ -31,7 +31,7 @@ const RealButton = styled.button<{
|
|||||||
!props.borderOnHover &&
|
!props.borderOnHover &&
|
||||||
`
|
`
|
||||||
svg {
|
svg {
|
||||||
fill: ${props.iconColor || props.theme.buttonText};
|
fill: ${props.iconColor || "currentColor"};
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ const RealButton = styled.button<{
|
|||||||
props.borderOnHover
|
props.borderOnHover
|
||||||
? ""
|
? ""
|
||||||
: `svg {
|
: `svg {
|
||||||
fill: ${props.iconColor || props.theme.buttonNeutralText};
|
fill: ${props.iconColor || "currentColor"};
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ const RealButton = styled.button<{
|
|||||||
color: ${props.theme.textTertiary};
|
color: ${props.theme.textTertiary};
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: ${props.theme.textTertiary};
|
fill: currentColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
@@ -162,7 +162,7 @@ const Button = <T extends React.ElementType = "button">(
|
|||||||
<Inner hasIcon={hasIcon} hasText={hasText} disclosure={disclosure}>
|
<Inner hasIcon={hasIcon} hasText={hasText} disclosure={disclosure}>
|
||||||
{hasIcon && icon}
|
{hasIcon && icon}
|
||||||
{hasText && <Label hasIcon={hasIcon}>{children || value}</Label>}
|
{hasText && <Label hasIcon={hasIcon}>{children || value}</Label>}
|
||||||
{disclosure && <ExpandedIcon />}
|
{disclosure && <ExpandedIcon color="currentColor" />}
|
||||||
</Inner>
|
</Inner>
|
||||||
</RealButton>
|
</RealButton>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class GroupListItem extends React.Component<Props> {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
actions={
|
actions={
|
||||||
<Flex align="center">
|
<Flex align="center" gap={8}>
|
||||||
{showFacepile && (
|
{showFacepile && (
|
||||||
<Facepile
|
<Facepile
|
||||||
onClick={this.handleMembersModalOpen}
|
onClick={this.handleMembersModalOpen}
|
||||||
@@ -69,7 +69,6 @@ class GroupListItem extends React.Component<Props> {
|
|||||||
overflow={overflow}
|
overflow={overflow}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{renderActions({
|
{renderActions({
|
||||||
openMembersModal: this.handleMembersModalOpen,
|
openMembersModal: this.handleMembersModalOpen,
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import styled from "styled-components";
|
|||||||
const HelpText = styled.p<{ small?: boolean }>`
|
const HelpText = styled.p<{ small?: boolean }>`
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
color: ${(props) => props.theme.textSecondary};
|
color: ${(props) => props.theme.textSecondary};
|
||||||
font-size: ${(props) => (props.small ? "13px" : "inherit")};
|
font-size: ${(props) => (props.small ? "14px" : "inherit")};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default HelpText;
|
export default HelpText;
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export const Outline = styled(Flex)<{
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background: ${(props) => props.theme.background};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const LabelText = styled.div`
|
export const LabelText = styled.div`
|
||||||
|
|||||||
@@ -1,20 +1,35 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import HelpText from "~/components/HelpText";
|
||||||
import { LabelText } from "~/components/Input";
|
import { LabelText } from "~/components/Input";
|
||||||
|
|
||||||
type Props = {
|
type Props = React.HTMLAttributes<HTMLInputElement> & {
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
name?: string;
|
||||||
|
note?: React.ReactNode;
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
|
onChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
|
||||||
id?: string;
|
id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function Switch({ width = 38, height = 20, label, disabled, ...props }: Props) {
|
function Switch({
|
||||||
|
width = 32,
|
||||||
|
height = 18,
|
||||||
|
label,
|
||||||
|
disabled,
|
||||||
|
className,
|
||||||
|
note,
|
||||||
|
...props
|
||||||
|
}: Props) {
|
||||||
const component = (
|
const component = (
|
||||||
<Wrapper width={width} height={height}>
|
<Input
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
className={label ? undefined : className}
|
||||||
|
>
|
||||||
<HiddenInput
|
<HiddenInput
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
width={width}
|
width={width}
|
||||||
@@ -23,34 +38,45 @@ function Switch({ width = 38, height = 20, label, disabled, ...props }: Props) {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
<Slider width={width} height={height} />
|
<Slider width={width} height={height} />
|
||||||
</Wrapper>
|
</Input>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (label) {
|
if (label) {
|
||||||
return (
|
return (
|
||||||
<Label disabled={disabled} htmlFor={props.id}>
|
<Wrapper>
|
||||||
{component}
|
<Label disabled={disabled} htmlFor={props.id} className={className}>
|
||||||
<LabelText>{label}</LabelText>
|
{component}
|
||||||
</Label>
|
<InlineLabelText>{label}</InlineLabelText>
|
||||||
|
</Label>
|
||||||
|
{note && <HelpText small>{note}</HelpText>}
|
||||||
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
padding-bottom: 8px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const InlineLabelText = styled(LabelText)`
|
||||||
|
padding-bottom: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
const Label = styled.label<{ disabled?: boolean }>`
|
const Label = styled.label<{ disabled?: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
${(props) => (props.disabled ? `opacity: 0.75;` : "")}
|
${(props) => (props.disabled ? `opacity: 0.75;` : "")}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.label<{ width: number; height: number }>`
|
const Input = styled.label<{ width: number; height: number }>`
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: ${(props) => props.width}px;
|
width: ${(props) => props.width}px;
|
||||||
height: ${(props) => props.height}px;
|
height: ${(props) => props.height}px;
|
||||||
margin-bottom: 4px;
|
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Slider = styled.span<{ width: number; height: number }>`
|
const Slider = styled.span<{ width: number; height: number }>`
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
import * as React from "react";
|
|
||||||
import { VisuallyHidden } from "reakit/VisuallyHidden";
|
|
||||||
import styled from "styled-components";
|
|
||||||
import HelpText from "~/components/HelpText";
|
|
||||||
|
|
||||||
export type Props = {
|
|
||||||
checked?: boolean;
|
|
||||||
label?: React.ReactNode;
|
|
||||||
labelHidden?: boolean;
|
|
||||||
className?: string;
|
|
||||||
name?: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
|
|
||||||
note?: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
const LabelText = styled.span`
|
|
||||||
font-weight: 500;
|
|
||||||
margin-left: 10px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
padding-bottom: 8px;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Label = styled.label`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
user-select: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SlideToggle = styled.label`
|
|
||||||
cursor: pointer;
|
|
||||||
text-indent: -9999px;
|
|
||||||
width: 26px;
|
|
||||||
height: 14px;
|
|
||||||
background: ${(props) => props.theme.slate};
|
|
||||||
display: block;
|
|
||||||
border-radius: 10px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 2px;
|
|
||||||
left: 2px;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
background: ${(props) => props.theme.white};
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: width 100ms ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:after {
|
|
||||||
width: 12px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const HiddenInput = styled.input`
|
|
||||||
height: 0;
|
|
||||||
width: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
|
|
||||||
&:checked + ${SlideToggle} {
|
|
||||||
background: ${(props) => props.theme.primary};
|
|
||||||
}
|
|
||||||
|
|
||||||
&:checked + ${SlideToggle}:after {
|
|
||||||
left: calc(100% - 2px);
|
|
||||||
transform: translateX(-100%);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
let inputId = 0;
|
|
||||||
|
|
||||||
export default function Toggle({
|
|
||||||
label,
|
|
||||||
labelHidden,
|
|
||||||
note,
|
|
||||||
className,
|
|
||||||
...rest
|
|
||||||
}: Props) {
|
|
||||||
const wrappedLabel = <LabelText>{label}</LabelText>;
|
|
||||||
const [id] = React.useState(`checkbox-input-${inputId++}`);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Wrapper className={className}>
|
|
||||||
<Label>
|
|
||||||
<HiddenInput type="checkbox" id={id} {...rest} />
|
|
||||||
<SlideToggle htmlFor={id} />
|
|
||||||
{label &&
|
|
||||||
(labelHidden ? (
|
|
||||||
<VisuallyHidden>{wrappedLabel}</VisuallyHidden>
|
|
||||||
) : (
|
|
||||||
wrappedLabel
|
|
||||||
))}
|
|
||||||
</Label>
|
|
||||||
{note && <HelpText small>{note}</HelpText>}
|
|
||||||
</Wrapper>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -38,7 +38,7 @@ import Separator from "~/components/ContextMenu/Separator";
|
|||||||
import Template from "~/components/ContextMenu/Template";
|
import Template from "~/components/ContextMenu/Template";
|
||||||
import Flex from "~/components/Flex";
|
import Flex from "~/components/Flex";
|
||||||
import Modal from "~/components/Modal";
|
import Modal from "~/components/Modal";
|
||||||
import Toggle from "~/components/Toggle";
|
import Switch from "~/components/Switch";
|
||||||
import { actionToMenuItem } from "~/actions";
|
import { actionToMenuItem } from "~/actions";
|
||||||
import {
|
import {
|
||||||
pinDocument,
|
pinDocument,
|
||||||
@@ -453,10 +453,12 @@ function DocumentMenu({
|
|||||||
<Separator />
|
<Separator />
|
||||||
<Style>
|
<Style>
|
||||||
<ToggleMenuItem
|
<ToggleMenuItem
|
||||||
|
width={26}
|
||||||
|
height={14}
|
||||||
label={t("Full width")}
|
label={t("Full width")}
|
||||||
checked={document.fullWidth}
|
checked={document.fullWidth}
|
||||||
onChange={(ev) => {
|
onChange={(ev) => {
|
||||||
document.fullWidth = ev.target.checked;
|
document.fullWidth = ev.currentTarget.checked;
|
||||||
document.save();
|
document.save();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -526,8 +528,8 @@ function DocumentMenu({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ToggleMenuItem = styled(Toggle)`
|
const ToggleMenuItem = styled(Switch)`
|
||||||
span {
|
* {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: ${(props) => props.theme.textSecondary};
|
color: ${(props) => props.theme.textSecondary};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const CollectionEdit = ({ collectionId, onSubmit }: Props) => {
|
|||||||
so often might confuse your team mates.
|
so often might confuse your team mates.
|
||||||
</Trans>
|
</Trans>
|
||||||
</HelpText>
|
</HelpText>
|
||||||
<Flex>
|
<Flex gap={8}>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
label={t("Name")}
|
label={t("Name")}
|
||||||
@@ -101,7 +101,6 @@ const CollectionEdit = ({ collectionId, onSubmit }: Props) => {
|
|||||||
autoFocus
|
autoFocus
|
||||||
flex
|
flex
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconPicker onChange={handleChange} color={color} icon={icon} />
|
<IconPicker onChange={handleChange} color={color} icon={icon} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<InputSelect
|
<InputSelect
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class CollectionNew extends React.Component<Props> {
|
|||||||
for example.
|
for example.
|
||||||
</Trans>
|
</Trans>
|
||||||
</HelpText>
|
</HelpText>
|
||||||
<Flex>
|
<Flex gap={8}>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
label={t("Name")}
|
label={t("Name")}
|
||||||
@@ -132,7 +132,6 @@ class CollectionNew extends React.Component<Props> {
|
|||||||
autoFocus
|
autoFocus
|
||||||
flex
|
flex
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IconPicker
|
<IconPicker
|
||||||
onOpen={this.handleIconPickerOpen}
|
onOpen={this.handleIconPickerOpen}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
@@ -143,29 +142,20 @@ class CollectionNew extends React.Component<Props> {
|
|||||||
<InputSelectPermission
|
<InputSelectPermission
|
||||||
value={this.permission}
|
value={this.permission}
|
||||||
onChange={this.handlePermissionChange}
|
onChange={this.handlePermissionChange}
|
||||||
short
|
note={t(
|
||||||
|
"This is the default level of access, you can give individual users or groups more access once the collection is created."
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
<HelpText>
|
|
||||||
<Trans>
|
|
||||||
This is the default level of access given to team members, you can
|
|
||||||
give specific users or groups more access once the collection is
|
|
||||||
created.
|
|
||||||
</Trans>
|
|
||||||
</HelpText>
|
|
||||||
{teamSharingEnabled && (
|
{teamSharingEnabled && (
|
||||||
<>
|
<Switch
|
||||||
<Switch
|
id="sharing"
|
||||||
id="sharing"
|
label={t("Public document sharing")}
|
||||||
label={t("Public document sharing")}
|
onChange={this.handleSharingChange}
|
||||||
onChange={this.handleSharingChange}
|
checked={this.sharing}
|
||||||
checked={this.sharing}
|
note={t(
|
||||||
/>
|
"When enabled any documents within this collection can be shared publicly on the internet."
|
||||||
<HelpText>
|
)}
|
||||||
<Trans>
|
/>
|
||||||
When enabled, documents can be shared publicly on the internet.
|
|
||||||
</Trans>
|
|
||||||
</HelpText>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Button type="submit" disabled={this.isSaving || !this.name}>
|
<Button type="submit" disabled={this.isSaving || !this.name}>
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ const CollectionGroupMemberListItem = ({
|
|||||||
labelHidden
|
labelHidden
|
||||||
nude
|
nude
|
||||||
/>
|
/>
|
||||||
<Spacer />
|
|
||||||
<CollectionGroupMemberMenu
|
<CollectionGroupMemberMenu
|
||||||
onMembers={openMembersModal}
|
onMembers={openMembersModal}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
@@ -65,14 +64,12 @@ const CollectionGroupMemberListItem = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Spacer = styled.div`
|
|
||||||
width: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Select = styled(InputSelect)`
|
const Select = styled(InputSelect)`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
color: ${(props) => props.theme.textSecondary};
|
||||||
|
|
||||||
select {
|
select {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ import MemberMenu from "~/menus/MemberMenu";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
user: User;
|
user: User;
|
||||||
membership?: Membership | null | undefined;
|
membership?: Membership | undefined;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
onAdd?: () => any;
|
onAdd?: () => void;
|
||||||
onRemove?: () => any;
|
onRemove?: () => void;
|
||||||
onUpdate?: (permission: string) => any;
|
onUpdate?: (permission: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const MemberListItem = ({
|
const MemberListItem = ({
|
||||||
@@ -62,7 +62,7 @@ const MemberListItem = ({
|
|||||||
}
|
}
|
||||||
image={<Avatar src={user.avatarUrl} size={32} />}
|
image={<Avatar src={user.avatarUrl} size={32} />}
|
||||||
actions={
|
actions={
|
||||||
<Flex align="center">
|
<Flex align="center" gap={8}>
|
||||||
{onUpdate && (
|
{onUpdate && (
|
||||||
<Select
|
<Select
|
||||||
label={t("Permissions")}
|
label={t("Permissions")}
|
||||||
@@ -77,7 +77,6 @@ const MemberListItem = ({
|
|||||||
)}
|
)}
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<>
|
<>
|
||||||
<Spacer />
|
|
||||||
{onRemove && <MemberMenu onRemove={onRemove} />}
|
{onRemove && <MemberMenu onRemove={onRemove} />}
|
||||||
{onAdd && (
|
{onAdd && (
|
||||||
<Button onClick={onAdd} neutral>
|
<Button onClick={onAdd} neutral>
|
||||||
@@ -92,14 +91,12 @@ const MemberListItem = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Spacer = styled.div`
|
|
||||||
width: 8px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Select = styled(InputSelect)`
|
const Select = styled(InputSelect)`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
color: ${(props) => props.theme.textSecondary};
|
||||||
|
|
||||||
select {
|
select {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Time from "~/components/Time";
|
|||||||
type Props = {
|
type Props = {
|
||||||
user: User;
|
user: User;
|
||||||
canEdit: boolean;
|
canEdit: boolean;
|
||||||
onAdd: () => any;
|
onAdd: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UserListItem = ({ user, onAdd, canEdit }: Props) => {
|
const UserListItem = ({ user, onAdd, canEdit }: Props) => {
|
||||||
|
|||||||
@@ -203,10 +203,9 @@ function CollectionPermissions({ collection }: Props) {
|
|||||||
<InputSelectPermission
|
<InputSelectPermission
|
||||||
onChange={handleChangePermission}
|
onChange={handleChangePermission}
|
||||||
value={collection.permission || ""}
|
value={collection.permission || ""}
|
||||||
short
|
|
||||||
nude
|
nude
|
||||||
/>
|
/>
|
||||||
<PermissionExplainer>
|
<PermissionExplainer small>
|
||||||
{!collection.permission && (
|
{!collection.permission && (
|
||||||
<Trans
|
<Trans
|
||||||
defaults="The <em>{{ collectionName }}</em> collection is private. Team members have no access to it by default."
|
defaults="The <em>{{ collectionName }}</em> collection is private. Team members have no access to it by default."
|
||||||
@@ -248,20 +247,21 @@ function CollectionPermissions({ collection }: Props) {
|
|||||||
onChange={handleSharingChange}
|
onChange={handleSharingChange}
|
||||||
checked={sharing && teamSharingEnabled}
|
checked={sharing && teamSharingEnabled}
|
||||||
disabled={!teamSharingEnabled}
|
disabled={!teamSharingEnabled}
|
||||||
|
note={
|
||||||
|
teamSharingEnabled ? (
|
||||||
|
<Trans>
|
||||||
|
When enabled, documents can be shared publicly on the internet.
|
||||||
|
</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>
|
||||||
|
Public sharing is currently disabled in the team security
|
||||||
|
settings.
|
||||||
|
</Trans>
|
||||||
|
)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<HelpText>
|
|
||||||
{teamSharingEnabled ? (
|
|
||||||
<Trans>
|
|
||||||
When enabled, documents can be shared publicly on the internet.
|
|
||||||
</Trans>
|
|
||||||
) : (
|
|
||||||
<Trans>
|
|
||||||
Public sharing is currently disabled in the team security settings.
|
|
||||||
</Trans>
|
|
||||||
)}
|
|
||||||
</HelpText>
|
|
||||||
<Labeled label={t("Additional access")}>
|
<Labeled label={t("Additional access")}>
|
||||||
<Actions>
|
<Actions gap={8}>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleAddGroupModalOpen}
|
onClick={handleAddGroupModalOpen}
|
||||||
@@ -269,7 +269,7 @@ function CollectionPermissions({ collection }: Props) {
|
|||||||
neutral
|
neutral
|
||||||
>
|
>
|
||||||
{t("Add groups")}
|
{t("Add groups")}
|
||||||
</Button>{" "}
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleAddMemberModalOpen}
|
onClick={handleAddMemberModalOpen}
|
||||||
@@ -358,7 +358,7 @@ const PermissionExplainer = styled(HelpText)`
|
|||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Actions = styled.div`
|
const Actions = styled(Flex)`
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ import useStores from "~/hooks/useStores";
|
|||||||
import useToasts from "~/hooks/useToasts";
|
import useToasts from "~/hooks/useToasts";
|
||||||
|
|
||||||
const MAX_INVITES = 20;
|
const MAX_INVITES = 20;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
onSubmit: () => void;
|
onSubmit: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InviteRequest = {
|
type InviteRequest = {
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
@@ -55,6 +57,7 @@ function Invite({ onSubmit }: Props) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const predictedDomain = user.email.split("@")[1];
|
const predictedDomain = user.email.split("@")[1];
|
||||||
const can = policies.abilities(team.id);
|
const can = policies.abilities(team.id);
|
||||||
|
|
||||||
const handleSubmit = React.useCallback(
|
const handleSubmit = React.useCallback(
|
||||||
async (ev: React.SyntheticEvent) => {
|
async (ev: React.SyntheticEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@@ -76,6 +79,7 @@ function Invite({ onSubmit }: Props) {
|
|||||||
},
|
},
|
||||||
[onSubmit, showToast, invites, t, users]
|
[onSubmit, showToast, invites, t, users]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleChange = React.useCallback((ev, index) => {
|
const handleChange = React.useCallback((ev, index) => {
|
||||||
setInvites((prevInvites) => {
|
setInvites((prevInvites) => {
|
||||||
const newInvites = [...prevInvites];
|
const newInvites = [...prevInvites];
|
||||||
@@ -83,6 +87,7 @@ function Invite({ onSubmit }: Props) {
|
|||||||
return newInvites;
|
return newInvites;
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleAdd = React.useCallback(() => {
|
const handleAdd = React.useCallback(() => {
|
||||||
if (invites.length >= MAX_INVITES) {
|
if (invites.length >= MAX_INVITES) {
|
||||||
showToast(
|
showToast(
|
||||||
@@ -105,6 +110,7 @@ function Invite({ onSubmit }: Props) {
|
|||||||
return newInvites;
|
return newInvites;
|
||||||
});
|
});
|
||||||
}, [showToast, invites, t]);
|
}, [showToast, invites, t]);
|
||||||
|
|
||||||
const handleRemove = React.useCallback(
|
const handleRemove = React.useCallback(
|
||||||
(ev: React.SyntheticEvent, index: number) => {
|
(ev: React.SyntheticEvent, index: number) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@@ -116,12 +122,14 @@ function Invite({ onSubmit }: Props) {
|
|||||||
},
|
},
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleCopy = React.useCallback(() => {
|
const handleCopy = React.useCallback(() => {
|
||||||
setLinkCopied(true);
|
setLinkCopied(true);
|
||||||
showToast(t("Share link copied"), {
|
showToast(t("Share link copied"), {
|
||||||
type: "success",
|
type: "success",
|
||||||
});
|
});
|
||||||
}, [showToast, t]);
|
}, [showToast, t]);
|
||||||
|
|
||||||
const handleRoleChange = React.useCallback((role: Role, index: number) => {
|
const handleRoleChange = React.useCallback((role: Role, index: number) => {
|
||||||
setInvites((prevInvites) => {
|
setInvites((prevInvites) => {
|
||||||
const newInvites = [...prevInvites];
|
const newInvites = [...prevInvites];
|
||||||
@@ -129,6 +137,7 @@ function Invite({ onSubmit }: Props) {
|
|||||||
return newInvites;
|
return newInvites;
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
{team.guestSignin ? (
|
{team.guestSignin ? (
|
||||||
@@ -180,9 +189,6 @@ function Invite({ onSubmit }: Props) {
|
|||||||
</Button>
|
</Button>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
</Flex>
|
</Flex>
|
||||||
<p>
|
|
||||||
<hr />
|
|
||||||
</p>
|
|
||||||
</CopyBlock>
|
</CopyBlock>
|
||||||
)}
|
)}
|
||||||
{invites.map((invite, index) => (
|
{invites.map((invite, index) => (
|
||||||
@@ -253,6 +259,9 @@ function Invite({ onSubmit }: Props) {
|
|||||||
const CopyBlock = styled("div")`
|
const CopyBlock = styled("div")`
|
||||||
margin: 2em 0;
|
margin: 2em 0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
background: ${(props) => props.theme.secondaryBackground};
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px 16px 8px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Remove = styled("div")`
|
const Remove = styled("div")`
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useTranslation, Trans } from "react-i18next";
|
|||||||
import Heading from "~/components/Heading";
|
import Heading from "~/components/Heading";
|
||||||
import HelpText from "~/components/HelpText";
|
import HelpText from "~/components/HelpText";
|
||||||
import Scene from "~/components/Scene";
|
import Scene from "~/components/Scene";
|
||||||
import Toggle from "~/components/Toggle";
|
import Switch from "~/components/Switch";
|
||||||
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
||||||
import useStores from "~/hooks/useStores";
|
import useStores from "~/hooks/useStores";
|
||||||
import useToasts from "~/hooks/useToasts";
|
import useToasts from "~/hooks/useToasts";
|
||||||
@@ -44,7 +44,7 @@ function Features() {
|
|||||||
the experience for all team members.
|
the experience for all team members.
|
||||||
</Trans>
|
</Trans>
|
||||||
</HelpText>
|
</HelpText>
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Collaborative editing")}
|
label={t("Collaborative editing")}
|
||||||
name="collaborativeEditing"
|
name="collaborativeEditing"
|
||||||
checked={data.collaborativeEditing}
|
checked={data.collaborativeEditing}
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ const Profile = () => {
|
|||||||
required
|
required
|
||||||
short
|
short
|
||||||
/>
|
/>
|
||||||
<br />
|
|
||||||
<InputSelect
|
<InputSelect
|
||||||
label={t("Language")}
|
label={t("Language")}
|
||||||
options={languageOptions}
|
options={languageOptions}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Heading from "~/components/Heading";
|
|||||||
import HelpText from "~/components/HelpText";
|
import HelpText from "~/components/HelpText";
|
||||||
import InputSelect from "~/components/InputSelect";
|
import InputSelect from "~/components/InputSelect";
|
||||||
import Scene from "~/components/Scene";
|
import Scene from "~/components/Scene";
|
||||||
import Toggle from "~/components/Toggle";
|
import Switch from "~/components/Switch";
|
||||||
import env from "~/env";
|
import env from "~/env";
|
||||||
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
||||||
import useStores from "~/hooks/useStores";
|
import useStores from "~/hooks/useStores";
|
||||||
@@ -69,7 +69,7 @@ function Security() {
|
|||||||
</Trans>
|
</Trans>
|
||||||
</HelpText>
|
</HelpText>
|
||||||
|
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Allow email authentication")}
|
label={t("Allow email authentication")}
|
||||||
name="guestSignin"
|
name="guestSignin"
|
||||||
checked={data.guestSignin}
|
checked={data.guestSignin}
|
||||||
@@ -81,7 +81,7 @@ function Security() {
|
|||||||
}
|
}
|
||||||
disabled={!env.EMAIL_ENABLED}
|
disabled={!env.EMAIL_ENABLED}
|
||||||
/>
|
/>
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Public document sharing")}
|
label={t("Public document sharing")}
|
||||||
name="sharing"
|
name="sharing"
|
||||||
checked={data.sharing}
|
checked={data.sharing}
|
||||||
@@ -90,7 +90,7 @@ function Security() {
|
|||||||
"When enabled, documents can be shared publicly on the internet by any team member"
|
"When enabled, documents can be shared publicly on the internet by any team member"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Rich service embeds")}
|
label={t("Rich service embeds")}
|
||||||
name="documentEmbeds"
|
name="documentEmbeds"
|
||||||
checked={data.documentEmbeds}
|
checked={data.documentEmbeds}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import NotificationSetting from "~/models/NotificationSetting";
|
import NotificationSetting from "~/models/NotificationSetting";
|
||||||
import Toggle from "~/components/Toggle";
|
import Switch from "~/components/Switch";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
setting?: NotificationSetting;
|
setting?: NotificationSetting;
|
||||||
@@ -20,7 +20,7 @@ const NotificationListItem = ({
|
|||||||
description,
|
description,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return (
|
return (
|
||||||
<Toggle
|
<Switch
|
||||||
label={title}
|
label={title}
|
||||||
name={event}
|
name={event}
|
||||||
checked={!!setting}
|
checked={!!setting}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import Flex from "~/components/Flex";
|
|||||||
import HelpText from "~/components/HelpText";
|
import HelpText from "~/components/HelpText";
|
||||||
import ListItem from "~/components/List/Item";
|
import ListItem from "~/components/List/Item";
|
||||||
import Popover from "~/components/Popover";
|
import Popover from "~/components/Popover";
|
||||||
import Toggle from "~/components/Toggle";
|
import Switch from "~/components/Switch";
|
||||||
import useToasts from "~/hooks/useToasts";
|
import useToasts from "~/hooks/useToasts";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -82,13 +82,13 @@ function SlackListItem({ integration, collection }: Props) {
|
|||||||
<Events>
|
<Events>
|
||||||
<h3>{t("Notifications")}</h3>
|
<h3>{t("Notifications")}</h3>
|
||||||
<HelpText>{t("These events should be posted to Slack")}</HelpText>
|
<HelpText>{t("These events should be posted to Slack")}</HelpText>
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Document published")}
|
label={t("Document published")}
|
||||||
name="documents.publish"
|
name="documents.publish"
|
||||||
checked={integration.events.includes("documents.publish")}
|
checked={integration.events.includes("documents.publish")}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
<Toggle
|
<Switch
|
||||||
label={t("Document updated")}
|
label={t("Document updated")}
|
||||||
name="documents.update"
|
name="documents.update"
|
||||||
checked={integration.events.includes("documents.update")}
|
checked={integration.events.includes("documents.update")}
|
||||||
|
|||||||
Reference in New Issue
Block a user