mirror of
https://github.com/lingble/twenty.git
synced 2025-10-28 19:32:28 +00:00
Stories and SSL Configuration docs update (#8551)
This commit is contained in:
@@ -51,6 +51,7 @@ export const SettingsOptionCardContentCounter = ({
|
||||
onChange={onChange}
|
||||
minValue={minValue}
|
||||
maxValue={maxValue}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</StyledSettingsOptionCardContent>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { SettingsOptionCardContentCounter } from '@/settings/components/SettingsOptions/SettingsOptionCardContentCounter';
|
||||
import styled from '@emotion/styled';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { ComponentDecorator, IconUsers } from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 480px;
|
||||
`;
|
||||
|
||||
const SettingsOptionCardContentCounterWrapper = (
|
||||
args: React.ComponentProps<typeof SettingsOptionCardContentCounter>,
|
||||
) => {
|
||||
const [value, setValue] = useState(args.value);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<SettingsOptionCardContentCounter
|
||||
value={value}
|
||||
onChange={setValue}
|
||||
Icon={args.Icon}
|
||||
title={args.title}
|
||||
description={args.description}
|
||||
divider={args.divider}
|
||||
disabled={args.disabled}
|
||||
minValue={args.minValue}
|
||||
maxValue={args.maxValue}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const meta: Meta<typeof SettingsOptionCardContentCounterWrapper> = {
|
||||
title: 'Modules/Settings/SettingsOptionCardContentCounter',
|
||||
component: SettingsOptionCardContentCounterWrapper,
|
||||
decorators: [ComponentDecorator],
|
||||
parameters: {
|
||||
maxWidth: 800,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SettingsOptionCardContentCounterWrapper>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
Icon: IconUsers,
|
||||
title: 'Team Members',
|
||||
description: 'Set the maximum number of team members',
|
||||
value: 5,
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
onChange: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutIcon: Story = {
|
||||
args: {
|
||||
title: 'Items Per Page',
|
||||
description: 'Configure the number of items shown per page',
|
||||
value: 20,
|
||||
minValue: 10,
|
||||
maxValue: 50,
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
Icon: IconUsers,
|
||||
title: 'Disabled Counter',
|
||||
description: 'This counter is currently disabled',
|
||||
value: 3,
|
||||
disabled: true,
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
|
||||
import styled from '@emotion/styled';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
ComponentDecorator,
|
||||
IconLanguage,
|
||||
IconLayoutKanban,
|
||||
IconList,
|
||||
IconNotes,
|
||||
IconTable,
|
||||
IconUsers,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 480px;
|
||||
`;
|
||||
|
||||
type SelectValue = string | number | boolean | null;
|
||||
|
||||
const SettingsOptionCardContentSelectWrapper = <Value extends SelectValue>(
|
||||
args: React.ComponentProps<typeof SettingsOptionCardContentSelect<Value>>,
|
||||
) => {
|
||||
const [value, setValue] = useState<Value>(args.value);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<SettingsOptionCardContentSelect
|
||||
value={value}
|
||||
onChange={(newValue) => setValue(newValue as Value)}
|
||||
Icon={args.Icon}
|
||||
title={args.title}
|
||||
description={args.description}
|
||||
divider={args.divider}
|
||||
disabled={args.disabled}
|
||||
options={args.options}
|
||||
selectClassName={args.selectClassName}
|
||||
dropdownId={args.dropdownId}
|
||||
fullWidth={args.fullWidth}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const meta: Meta<typeof SettingsOptionCardContentSelectWrapper> = {
|
||||
title: 'Modules/Settings/SettingsOptionCardContentSelect',
|
||||
component: SettingsOptionCardContentSelectWrapper,
|
||||
decorators: [ComponentDecorator],
|
||||
parameters: {
|
||||
maxWidth: 800,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SettingsOptionCardContentSelectWrapper>;
|
||||
|
||||
export const StringSelect: Story = {
|
||||
args: {
|
||||
Icon: IconLanguage,
|
||||
title: 'Language',
|
||||
description: 'Select your preferred language',
|
||||
value: 'en',
|
||||
options: [
|
||||
{ value: 'en', label: 'English' },
|
||||
{ value: 'fr', label: 'French' },
|
||||
{ value: 'es', label: 'Spanish' },
|
||||
],
|
||||
dropdownId: 'language-select',
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
onChange: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const NumberSelect: Story = {
|
||||
args: {
|
||||
Icon: IconNotes,
|
||||
title: 'Items Per Page',
|
||||
description: 'Number of items to display per page',
|
||||
value: 25,
|
||||
options: [
|
||||
{ value: 10, label: '10' },
|
||||
{ value: 25, label: '25' },
|
||||
{ value: 50, label: '50' },
|
||||
{ value: 100, label: '100' },
|
||||
],
|
||||
dropdownId: 'page-size-select',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithIconOptions: Story = {
|
||||
args: {
|
||||
Icon: IconUsers,
|
||||
title: 'Team View',
|
||||
description: 'Select how to display team members',
|
||||
value: 'grid',
|
||||
options: [
|
||||
{ value: 'list', label: 'List View', Icon: IconList },
|
||||
{ value: 'kanban', label: 'Kanban View', Icon: IconLayoutKanban },
|
||||
{ value: 'table', label: 'Table View', Icon: IconTable },
|
||||
],
|
||||
dropdownId: 'view-select',
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
Icon: IconUsers,
|
||||
title: 'Disabled Select',
|
||||
description: 'This select is currently disabled',
|
||||
disabled: true,
|
||||
value: 'option1',
|
||||
options: [
|
||||
{ value: 'option1', label: 'Option 1' },
|
||||
{ value: 'option2', label: 'Option 2' },
|
||||
{ value: 'option3', label: 'Option 3' },
|
||||
],
|
||||
dropdownId: 'disabled-select',
|
||||
},
|
||||
};
|
||||
|
||||
export const FullWidth: Story = {
|
||||
args: {
|
||||
title: 'Full Width Select',
|
||||
description: 'This select uses the full width of the dropdown',
|
||||
value: 'short',
|
||||
options: [
|
||||
{ value: 'short', label: 'Short option' },
|
||||
{
|
||||
value: 'very-long',
|
||||
label: 'This is a very long option that needs more space',
|
||||
},
|
||||
{
|
||||
value: 'another-long',
|
||||
label: 'Another long option that extends the width',
|
||||
},
|
||||
],
|
||||
dropdownId: 'full-width-select',
|
||||
fullWidth: true,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import styled from '@emotion/styled';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import {
|
||||
ComponentDecorator,
|
||||
IconBell,
|
||||
IconLock,
|
||||
IconRobot,
|
||||
IconUsers,
|
||||
} from 'twenty-ui';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 480px;
|
||||
`;
|
||||
|
||||
const SettingsOptionCardContentToggleWrapper = (
|
||||
args: React.ComponentProps<typeof SettingsOptionCardContentToggle>,
|
||||
) => {
|
||||
const [checked, setChecked] = useState(args.checked);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<SettingsOptionCardContentToggle
|
||||
checked={checked}
|
||||
onChange={setChecked}
|
||||
Icon={args.Icon}
|
||||
title={args.title}
|
||||
description={args.description}
|
||||
divider={args.divider}
|
||||
disabled={args.disabled}
|
||||
advancedMode={args.advancedMode}
|
||||
/>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const meta: Meta<typeof SettingsOptionCardContentToggleWrapper> = {
|
||||
title: 'Modules/Settings/SettingsOptionCardContentToggle',
|
||||
component: SettingsOptionCardContentToggleWrapper,
|
||||
decorators: [ComponentDecorator],
|
||||
parameters: {
|
||||
maxWidth: 800,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SettingsOptionCardContentToggleWrapper>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
Icon: IconBell,
|
||||
title: 'Notifications',
|
||||
description: 'Receive notifications about important updates',
|
||||
checked: true,
|
||||
},
|
||||
argTypes: {
|
||||
Icon: { control: false },
|
||||
onChange: { control: false },
|
||||
},
|
||||
};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
Icon: IconLock,
|
||||
title: 'Locked Setting',
|
||||
description: 'This setting is currently unavailable',
|
||||
checked: false,
|
||||
disabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const AdvancedMode: Story = {
|
||||
args: {
|
||||
Icon: IconRobot,
|
||||
title: 'Advanced Features',
|
||||
description: 'Enable experimental features',
|
||||
checked: true,
|
||||
advancedMode: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutIcon: Story = {
|
||||
args: {
|
||||
title: 'Simple Toggle',
|
||||
description: 'A basic toggle without an icon',
|
||||
checked: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithoutDescription: Story = {
|
||||
args: {
|
||||
Icon: IconUsers,
|
||||
title: 'Team Access',
|
||||
checked: false,
|
||||
},
|
||||
};
|
||||
@@ -105,6 +105,14 @@ By default, Twenty runs on `localhost` at port `3000`. To access it via an exter
|
||||
- **Domain/IP:** This is the domain name or IP address where your application is accessible.
|
||||
- **Port:** Include the port number if you're not using the default ports (`80` for `http`, `443` for `https`).
|
||||
|
||||
### SSL Requirements
|
||||
|
||||
SSL (HTTPS) is required for certain browser features to work properly. While these features might work during local development (as browsers treat localhost differently), a proper SSL setup is needed when hosting Twenty on a regular domain.
|
||||
|
||||
For example, the clipboard API might require a secure context - some features like copy buttons throughout the application might not work without HTTPS enabled.
|
||||
|
||||
We strongly recommend setting up Twenty behind a reverse proxy with SSL termination for optimal security and functionality.
|
||||
|
||||
#### Configuring `SERVER_URL`
|
||||
|
||||
1. **Determine Your Access URL**
|
||||
|
||||
Reference in New Issue
Block a user