Per SETTINGS-AUDIT (all three tiers approved 2026-10-23): Dead settings: - panelOutbound, ipLimitAllowlist (+ orphan parser job), outboundDownThreshold - tg fake events outbound.down/outbound.up/xray.crash (no publisher in lite) - phantom routing sub-tabs (Happ/Clash/Incy) and subJsonRules direct-rules tab (no backend keys); subHideSettings moved to the subscription info tab first Upstream remnants: - ldap* / smtp* model+schema keys, EmailNotifications orphan component - twoFactorEnable/twoFactorToken + login-page probe (no backend handler) - externalTrafficInform* Newly approved removals: - JSON subscription family (producer, routes, UA auto-detect, mux/finalmask/ observatory) and Clash subscription family (producer, routes, UA detect) - SubBalancer (table, service, controller, settings tab) - subThemeDir (subscription page falls back to the built-in template) - datepicker jalalian option (gregorian only; Persian picker removed) JSON/Clash endpoints now 404; link-format output pinned by regression tests. Guarded keys untouched: webListen/webPort/webBasePath/certs, tg* chain, expireDiff/trafficDiff/tgBotProxy, subHideSettings, pageSize/tgLang.
84 lines
2.3 KiB
TypeScript
84 lines
2.3 KiB
TypeScript
import { useState } from 'react';
|
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
import { Typography } from 'antd';
|
|
import dayjs from 'dayjs';
|
|
import type { Dayjs } from 'dayjs';
|
|
|
|
import { setDatepicker } from '@/hooks/useDatepicker';
|
|
import { ThemeProvider } from '@/hooks/useTheme';
|
|
|
|
import DateTimePicker from './DateTimePicker';
|
|
|
|
setDatepicker('gregorian');
|
|
|
|
function ClientExpiryDemo() {
|
|
const [value, setValue] = useState<Dayjs | null>(dayjs('2026-12-31 23:59:59'));
|
|
return (
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
|
<DateTimePicker value={value} onChange={setValue} placeholder="Expiry date" />
|
|
<Typography.Text type="secondary">
|
|
{value
|
|
? `user1@node-de expiryTime: ${value.valueOf()}`
|
|
: 'user1@node-de expiryTime: 0 (never expires)'}
|
|
</Typography.Text>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const meta = {
|
|
title: 'Form/DateTimePicker',
|
|
component: DateTimePicker,
|
|
tags: ['autodocs'],
|
|
parameters: {
|
|
layout: 'padded',
|
|
docs: {
|
|
description: {
|
|
component:
|
|
'Date/time picker used for client and inbound expiry dates, rendered with the AntD DatePicker.',
|
|
},
|
|
},
|
|
},
|
|
decorators: [
|
|
(Story) => (
|
|
<ThemeProvider>
|
|
<Story />
|
|
</ThemeProvider>
|
|
),
|
|
],
|
|
argTypes: {
|
|
value: { description: 'Selected moment as a Dayjs instance, or null when unset.' },
|
|
onChange: { description: 'Called with the picked Dayjs value, or null when cleared.' },
|
|
showTime: { description: 'Include an hour/minute/second selector alongside the date.' },
|
|
format: { description: 'Display format for the Gregorian picker input.' },
|
|
placeholder: { description: 'Input placeholder shown while no value is set.' },
|
|
disabled: { description: 'Disables the input and hides the clear button.' },
|
|
},
|
|
} satisfies Meta<typeof DateTimePicker>;
|
|
|
|
export default meta;
|
|
|
|
type Story = StoryObj<typeof meta>;
|
|
|
|
export const Empty: Story = {
|
|
args: {
|
|
value: null,
|
|
onChange: () => undefined,
|
|
placeholder: 'Leave blank to never expire',
|
|
},
|
|
};
|
|
|
|
export const ClientExpiry: Story = {
|
|
args: { value: null, onChange: () => undefined },
|
|
render: () => <ClientExpiryDemo />,
|
|
};
|
|
|
|
export const DateOnly: Story = {
|
|
args: {
|
|
value: dayjs('2026-08-01'),
|
|
onChange: () => undefined,
|
|
showTime: false,
|
|
format: 'YYYY-MM-DD',
|
|
placeholder: 'Start date',
|
|
},
|
|
};
|