feat(web): mobile UI improvements (#359)

* enhancement: improved alerts component contrast
enhancement: simplified and improved radio switch group look
fix: fixed inconsistent spacing in input components (there's still some work left to be done)
fix: made slideover panel display on full width on mobile devices
enhancement: made forms more accessible to mobile users, adapter changes in accordance with the previous input components fix
fix: fixed misspelling in NotificationForms filename
chore: cleaned up code
fix: made filter table top edges less round and improved look
fix: fixed a bug where when a modal/slideover component was opened, a 1px white bar would be shown in one of the modal parent elements (for the fix see L89 in screens/settings/DwonloadClient.tsx)
enhancement: improved responsiveness for irc network list

* Fixed 2 small comma warnings from ESLint

Co-authored-by: anonymous <anonymous>
This commit is contained in:
stacksmash76 2022-07-17 23:34:49 +02:00 committed by GitHub
parent f961115dac
commit 3da594ec75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 758 additions and 640 deletions

View file

@ -96,7 +96,7 @@ function FilterAddForm({ isOpen, toggle }: filterAddFormProps) {
<div
className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<div
className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:py-4">
<div>
<label
htmlFor="name"

View file

@ -50,24 +50,31 @@ function FormFieldsDefault() {
} = useFormikContext<InitialValues>();
return (
<Fragment>
<TextFieldWide name="host" label="Host" help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port"/>
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="host"
label="Host"
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port"
/>
<NumberFieldWide name="port" label="Port" help="WebUI port for qBittorrent and daemon port for Deluge"/>
<NumberFieldWide
name="port"
label="Port"
help="WebUI port for qBittorrent and daemon port for Deluge"
/>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:divide-gray-700">
<SwitchGroupWide name="tls" label="TLS"/>
<SwitchGroupWide name="tls" label="TLS" />
{tls && (
<Fragment>
<SwitchGroupWide name="tls_skip_verify" label="Skip TLS verification (insecure)"/>
</Fragment>
)}
</div>
{tls && (
<SwitchGroupWide
name="tls_skip_verify"
label="Skip TLS verification (insecure)"
/>
)}
<TextFieldWide name="username" label="Username"/>
<PasswordFieldWide name="password" label="Password"/>
</Fragment>
<TextFieldWide name="username" label="Username" />
<PasswordFieldWide name="password" label="Password" />
</div>
);
}
@ -77,22 +84,24 @@ function FormFieldsArr() {
} = useFormikContext<InitialValues>();
return (
<Fragment>
<TextFieldWide name="host" label="Host" help="Full url http(s)://domain.ltd and/or subdomain/subfolder"/>
<div className="flex flex-col space-y-4 px-1 mb-4 sm:py-0 sm:space-y-0">
<TextFieldWide
name="host"
label="Host"
help="Full url http(s)://domain.ltd and/or subdomain/subfolder"
/>
<PasswordFieldWide name="settings.apikey" label="API key"/>
<PasswordFieldWide name="settings.apikey" label="API key" />
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="settings.basic.auth" label="Basic auth"/>
</div>
<SwitchGroupWide name="settings.basic.auth" label="Basic auth" />
{settings.basic?.auth === true && (
<Fragment>
<TextFieldWide name="settings.basic.username" label="Username"/>
<PasswordFieldWide name="settings.basic.password" label="Password"/>
</Fragment>
<>
<TextFieldWide name="settings.basic.username" label="Username" />
<PasswordFieldWide name="settings.basic.password" label="Password" />
</>
)}
</Fragment>
</div>
);
}
@ -102,37 +111,42 @@ function FormFieldsQbit() {
} = useFormikContext<InitialValues>();
return (
<Fragment>
<TextFieldWide name="host" label="Host" help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port" />
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="host"
label="Host"
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd:port"
/>
{port > 0 && (
<NumberFieldWide name="port" label="Port" help="WebUI port for qBittorrent" />
<NumberFieldWide
name="port"
label="Port"
help="WebUI port for qBittorrent"
/>
)}
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:divide-gray-700">
<SwitchGroupWide name="tls" label="TLS" />
<SwitchGroupWide name="tls" label="TLS" />
{tls && (
<Fragment>
<SwitchGroupWide name="tls_skip_verify" label="Skip TLS verification (insecure)" />
</Fragment>
)}
</div>
{tls && (
<SwitchGroupWide
name="tls_skip_verify"
label="Skip TLS verification (insecure)"
/>
)}
<TextFieldWide name="username" label="Username" />
<PasswordFieldWide name="password" label="Password" />
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="settings.basic.auth" label="Basic auth" />
</div>
<SwitchGroupWide name="settings.basic.auth" label="Basic auth" />
{settings.basic?.auth === true && (
<Fragment>
<>
<TextFieldWide name="settings.basic.username" label="Username" />
<PasswordFieldWide name="settings.basic.password" label="Password" />
</Fragment>
</>
)}
</Fragment>
</div>
);
}
@ -142,24 +156,27 @@ function FormFieldsTransmission() {
} = useFormikContext<InitialValues>();
return (
<Fragment>
<TextFieldWide name="host" label="Host" help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd"/>
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="host"
label="Host"
help="Eg. client.domain.ltd, domain.ltd/client, domain.ltd"
/>
<NumberFieldWide name="port" label="Port" help="Port for Transmission"/>
<NumberFieldWide name="port" label="Port" help="Port for Transmission" />
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:divide-gray-700">
<SwitchGroupWide name="tls" label="TLS"/>
<SwitchGroupWide name="tls" label="TLS" />
{tls && (
<Fragment>
<SwitchGroupWide name="tls_skip_verify" label="Skip TLS verification (insecure)"/>
</Fragment>
)}
</div>
{tls && (
<SwitchGroupWide
name="tls_skip_verify"
label="Skip TLS verification (insecure)"
/>
)}
<TextFieldWide name="username" label="Username"/>
<PasswordFieldWide name="password" label="Password"/>
</Fragment>
<TextFieldWide name="username" label="Username" />
<PasswordFieldWide name="password" label="Password" />
</div>
);
}
@ -186,21 +203,17 @@ function FormFieldsRulesBasic() {
return (
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Rules</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Manage max downloads.
</p>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="settings.rules.enabled" label="Enabled"/>
</div>
<SwitchGroupWide name="settings.rules.enabled" label="Enabled"/>
{settings && settings.rules?.enabled === true && (
<Fragment>
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads"/>
</Fragment>
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads"/>
)}
</div>
);
@ -212,34 +225,38 @@ function FormFieldsRules() {
} = useFormikContext<InitialValues>();
return (
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Rules</Dialog.Title>
<div className="border-t border-gray-200 dark:border-gray-700 py-5 px-2">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">
Rules
</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Manage max downloads etc.
</p>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="settings.rules.enabled" label="Enabled"/>
</div>
<SwitchGroupWide name="settings.rules.enabled" label="Enabled" />
{settings.rules?.enabled === true && (
<Fragment>
<NumberFieldWide name="settings.rules.max_active_downloads" label="Max active downloads"/>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="settings.rules.ignore_slow_torrents" label="Ignore slow torrents"/>
</div>
<>
<NumberFieldWide
name="settings.rules.max_active_downloads"
label="Max active downloads"
/>
<SwitchGroupWide
name="settings.rules.ignore_slow_torrents"
label="Ignore slow torrents"
/>
{settings.rules?.ignore_slow_torrents === true && (
<Fragment>
<NumberFieldWide name="settings.rules.download_speed_threshold" label="Download speed threshold"
placeholder="in KB/s"
help="If download speed is below this when max active downloads is hit, download anyways. KB/s"/>
</Fragment>
<NumberFieldWide
name="settings.rules.download_speed_threshold"
label="Download speed threshold"
placeholder="in KB/s"
help="If download speed is below this when max active downloads is hit, download anyways. KB/s"
/>
)}
</Fragment>
</>
)}
</div>
);
@ -248,7 +265,7 @@ function FormFieldsRules() {
export const rulesComponentMap: componentMapType = {
DELUGE_V1: <FormFieldsRulesBasic/>,
DELUGE_V2: <FormFieldsRulesBasic/>,
QBITTORRENT: <FormFieldsRules/>,
QBITTORRENT: <FormFieldsRules/>
};
interface formButtonsProps {
@ -490,20 +507,14 @@ export function DownloadClientAddForm({ isOpen, toggle }: formProps) {
</div>
</div>
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide name="name" label="Name"/>
<div
className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:divide-gray-700">
<SwitchGroupWide name="enabled" label="Enabled"/>
</div>
<SwitchGroupWide name="enabled" label="Enabled"/>
<RadioFieldsetWide
name="type"
legend="Type"
options={DownloadClientTypeOptions}
/>
<div>{componentMap[values.type]}</div>
</div>
</div>
@ -697,17 +708,12 @@ export function DownloadClientUpdateForm({ client, isOpen, toggle }: updateFormP
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
<TextFieldWide name="name" label="Name"/>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="enabled" label="Enabled"/>
</div>
<SwitchGroupWide name="enabled" label="Enabled"/>
<RadioFieldsetWide
name="type"
legend="Type"
options={DownloadClientTypeOptions}
/>
<div>{componentMap[values.type]}</div>
</div>
</div>

View file

@ -116,7 +116,7 @@ export function FeedUpdateForm({ isOpen, toggle, feed }: UpdateProps) {
<div className="space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
<div
className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:py-4">
<div>
<label
htmlFor="type"

View file

@ -63,7 +63,7 @@ const IrcSettingFields = (ind: IndexerDefinition, indexer: string) => {
<Fragment>
{ind && ind.irc && ind.irc.settings && (
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">IRC</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-200">
Networks, channels and invite commands are configured automatically.
@ -94,7 +94,7 @@ const FeedSettingFields = (ind: IndexerDefinition, indexer: string) => {
<Fragment>
{ind && ind.torznab && ind.torznab.settings && (
<div className="">
<div className="px-6 space-y-1">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Torznab</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-200">
Torznab feed
@ -329,13 +329,13 @@ export function IndexerAddForm({ isOpen, toggle }: AddProps) {
</div>
<div className="py-6 space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
<div className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
<div className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:py-4">
<div>
<label
htmlFor="identifier"
className="block text-sm font-medium text-gray-900 dark:text-white"
>
Indexer
Indexer
</label>
</div>
<div className="sm:col-span-2">
@ -391,9 +391,7 @@ export function IndexerAddForm({ isOpen, toggle }: AddProps) {
</div>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="enabled" label="Enabled" />
</div>
<SwitchGroupWide name="enabled" label="Enabled" />
{SettingFields(indexer, values.identifier)}
@ -504,7 +502,7 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) {
...o,
[obj.name]: obj.value
} as Record<string, string>),
{} as Record<string, string>
{} as Record<string, string>
)
};
@ -519,16 +517,14 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) {
initialValues={initialValues}
>
{() => (
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 divide-y divide-gray-200 dark:divide-gray-700">
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
<div>
<label
htmlFor="name"
className="block text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2"
>
Name
</label>
</div>
<div className="py-2 space-y-6 sm:py-0 sm:space-y-0 divide-y divide-gray-200 dark:divide-gray-700">
<div className="space-y-1 p-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4">
<label
htmlFor="name"
className="block text-sm font-medium text-gray-900 dark:text-white sm:mt-px sm:pt-2"
>
Name
</label>
<Field name="name">
{({ field, meta }: FieldProps) => (
<div className="sm:col-span-2">
@ -542,11 +538,7 @@ export function IndexerUpdateForm({ isOpen, toggle, indexer }: UpdateProps) {
)}
</Field>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:sm:divide-gray-700">
<SwitchGroupWide name="enabled" label="Enabled" />
</div>
<SwitchGroupWide name="enabled" label="Enabled" />
{renderSettingFields(indexer.settings)}
</div>
)}

View file

@ -24,7 +24,7 @@ const ChannelsFieldArray = ({ channels }: ChannelsFieldArrayProps) => (
<div className="p-6">
<FieldArray name="channels">
{({ remove, push }) => (
<div className="flex flex-col border-2 border-dashed dark:border-gray-700 p-4">
<div className="flex flex-col space-y-2 border-2 border-dashed dark:border-gray-700 p-4">
{channels && channels.length > 0 ? (
channels.map((_channel: IrcChannel, index: number) => (
<div key={index} className="flex justify-between">
@ -68,7 +68,7 @@ const ChannelsFieldArray = ({ channels }: ChannelsFieldArrayProps) => (
))
) : (
<span className="text-center text-sm text-grey-darker dark:text-white">
No channels!
No channels!
</span>
)}
<button
@ -76,7 +76,7 @@ const ChannelsFieldArray = ({ channels }: ChannelsFieldArrayProps) => (
className="border dark:border-gray-600 dark:bg-gray-700 my-4 px-4 py-2 text-sm text-gray-700 dark:text-white hover:bg-gray-50 dark:hover:bg-gray-600 rounded self-center text-center"
onClick={() => push({ name: "", password: "" })}
>
Add Channel
Add Channel
</button>
</div>
)}
@ -159,34 +159,47 @@ export function IrcNetworkAddForm({ isOpen, toggle }: AddFormProps) {
validate={validate}
>
{(values) => (
<>
<TextFieldWide name="name" label="Name" placeholder="Name" required={true} />
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="name"
label="Name"
placeholder="Name"
required={true}
/>
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200 dark:sm:divide-gray-700">
<SwitchGroupWide name="enabled" label="Enabled" />
</div>
<div>
<TextFieldWide name="server" label="Server" placeholder="Address: Eg irc.server.net" required={true} />
<NumberFieldWide name="port" label="Port" placeholder="Eg 6667" required={true} />
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="tls" label="TLS" />
</div>
<PasswordFieldWide name="pass" label="Password" help="Network password" />
<TextFieldWide name="nickserv.account" label="NickServ Account" placeholder="NickServ Account" required={true} />
<PasswordFieldWide name="nickserv.password" label="NickServ Password" />
<PasswordFieldWide name="invite_command" label="Invite command" />
</div>
</div>
<SwitchGroupWide name="enabled" label="Enabled" />
<TextFieldWide
name="server"
label="Server"
placeholder="Address: Eg irc.server.net"
required={true}
/>
<NumberFieldWide
name="port"
label="Port"
placeholder="Eg 6667"
required={true}
/>
<SwitchGroupWide name="tls" label="TLS" />
<PasswordFieldWide
name="pass"
label="Password"
help="Network password"
/>
<TextFieldWide
name="nickserv.account"
label="NickServ Account"
placeholder="NickServ Account"
required={true}
/>
<PasswordFieldWide
name="nickserv.password"
label="NickServ Password"
/>
<PasswordFieldWide name="invite_command" label="Invite command" />
<ChannelsFieldArray channels={values.channels} />
</>
</div>
)}
</SlideOver>
);
@ -290,34 +303,51 @@ export function IrcNetworkUpdateForm({
validate={validate}
>
{(values) => (
<>
<TextFieldWide name="name" label="Name" placeholder="Name" required={true} />
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="name"
label="Name"
placeholder="Name"
required={true}
/>
<div className="py-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y dark:divide-gray-700">
<SwitchGroupWide name="enabled" label="Enabled" />
<TextFieldWide
name="server"
label="Server"
placeholder="Address: Eg irc.server.net"
required={true}
/>
<NumberFieldWide
name="port"
label="Port"
placeholder="Eg 6667"
required={true}
/>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0">
<SwitchGroupWide name="enabled" label="Enabled" />
</div>
<SwitchGroupWide name="tls" label="TLS" />
<div>
<TextFieldWide name="server" label="Server" placeholder="Address: Eg irc.server.net" required={true} />
<NumberFieldWide name="port" label="Port" placeholder="Eg 6667" required={true} />
<PasswordFieldWide
name="pass"
label="Password"
help="Network password"
/>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="tls" label="TLS" />
</div>
<TextFieldWide
name="nickserv.account"
label="NickServ Account"
placeholder="NickServ Account"
required={true}
/>
<PasswordFieldWide
name="nickserv.password"
label="NickServ Password"
/>
<PasswordFieldWide name="pass" label="Password" help="Network password" />
<TextFieldWide name="nickserv.account" label="NickServ Account" placeholder="NickServ Account" required={true} />
<PasswordFieldWide name="nickserv.password" label="NickServ Password" />
<PasswordFieldWide name="invite_command" label="Invite command" />
</div>
</div>
<PasswordFieldWide name="invite_command" label="Invite command" />
<ChannelsFieldArray channels={values.channels} />
</>
</div>
)}
</SlideOver>
);

View file

@ -62,11 +62,11 @@ const Option = (props: OptionProps) => {
function FormFieldsDiscord() {
return (
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<div className="border-t border-gray-200 dark:border-gray-700 py-4">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Create a <a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500">webhook integration</a> in your server.
Create a <a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400">webhook integration</a> in your server.
</p>
</div>
@ -82,11 +82,11 @@ function FormFieldsDiscord() {
function FormFieldsTelegram() {
return (
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<div className="border-t border-gray-200 dark:border-gray-700 py-4">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">Settings</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Read how to <a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500">create a bot</a>.
Read how to <a href="https://core.telegram.org/bots#3-how-do-i-create-a-bot" rel="noopener noreferrer" target="_blank" className="font-medium text-blue-500 underline underline-offset-1 hover:text-blue-400">create a bot</a>.
</p>
</div>
@ -161,9 +161,15 @@ export function NotificationAddForm({ isOpen, toggle }: AddProps) {
return (
<Transition.Root show={isOpen} as={Fragment}>
<Dialog as="div" static className="fixed inset-0 overflow-hidden" open={isOpen} onClose={toggle}>
<Dialog
as="div"
static
className="fixed inset-0 overflow-hidden"
open={isOpen}
onClose={toggle}
>
<div className="absolute inset-0 overflow-hidden">
<Dialog.Overlay className="absolute inset-0"/>
<Dialog.Overlay className="absolute inset-0" />
<div className="fixed inset-y-0 right-0 pl-10 max-w-full flex sm:pl-16">
<Transition.Child
@ -208,16 +214,20 @@ export function NotificationAddForm({ isOpen, toggle }: AddProps) {
onClick={toggle}
>
<span className="sr-only">Close panel</span>
<XIcon className="h-6 w-6" aria-hidden="true"/>
<XIcon className="h-6 w-6" aria-hidden="true" />
</button>
</div>
</div>
</div>
<TextFieldWide name="name" label="Name" required={true}/>
<div className="flex flex-col space-y-4 px-1 py-6 sm:py-0 sm:space-y-0">
<TextFieldWide
name="name"
label="Name"
required={true}
/>
<div className="space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
<div className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
<div className="flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4">
<div>
<label
htmlFor="type"
@ -232,10 +242,16 @@ export function NotificationAddForm({ isOpen, toggle }: AddProps) {
field,
form: { setFieldValue, resetForm }
}: FieldProps) => (
<Select {...field}
<Select
{...field}
isClearable={true}
isSearchable={true}
components={{ Input, Control, Menu, Option }}
components={{
Input,
Control,
Menu,
Option
}}
placeholder="Choose a type"
styles={{
singleValue: (base) => ({
@ -257,39 +273,39 @@ export function NotificationAddForm({ isOpen, toggle }: AddProps) {
const opt = option as SelectOption;
// setFieldValue("name", option?.label ?? "")
setFieldValue(field.name, opt.value ?? "");
setFieldValue(
field.name,
opt.value ?? ""
);
}}
options={NotificationTypeOptions}
/>
)}
</Field>
</div>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="enabled" label="Enabled"/>
</div>
<SwitchGroupWide name="enabled" label="Enabled" />
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<Dialog.Title
className="text-lg font-medium text-gray-900 dark:text-white">Events</Dialog.Title>
<div className="border-t mt-2 border-gray-200 dark:border-gray-700 py-4">
<div className="px-4 space-y-1">
<Dialog.Title className="text-lg font-medium text-gray-900 dark:text-white">
Events
</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
Select what events to trigger on
</p>
</div>
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:gap-4 sm:px-6 sm:py-5">
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:gap-4 sm:py-4">
<EventCheckBoxes />
</div>
</div>
</div>
{componentMap[values.type]}
</div>
<div className="flex-shrink-0 px-4 border-t border-gray-200 dark:border-gray-700 py-5 sm:px-6">
<div className="flex-shrink-0 px-4 border-t border-gray-200 dark:border-gray-700 py-4 sm:px-6">
<div className="space-x-3 flex justify-end">
<button
type="button"
@ -314,12 +330,11 @@ export function NotificationAddForm({ isOpen, toggle }: AddProps) {
</div>
</div>
<DEBUG values={values}/>
<DEBUG values={values} />
</Form>
)}
</Formik>
</div>
</Transition.Child>
</div>
</div>
@ -432,8 +447,8 @@ export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateP
<div>
<TextFieldWide name="name" label="Name" required={true}/>
<div className="space-y-4 divide-y divide-gray-200 dark:divide-gray-700">
<div className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 sm:py-5">
<div className="space-y-2 divide-y divide-gray-200 dark:divide-gray-700">
<div className="py-4 flex items-center justify-between space-y-1 px-4 sm:space-y-0 sm:grid sm:grid-cols-3 sm:gap-4 sm:py-4">
<div>
<label
htmlFor="type"
@ -477,13 +492,9 @@ export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateP
</Field>
</div>
</div>
<div className="py-6 px-6 space-y-6 sm:py-0 sm:space-y-0 sm:divide-y sm:divide-gray-200">
<SwitchGroupWide name="enabled" label="Enabled"/>
</div>
<div className="border-t border-gray-200 dark:border-gray-700 py-5">
<div className="px-6 space-y-1">
<SwitchGroupWide name="enabled" label="Enabled"/>
<div className="border-t border-gray-200 dark:border-gray-700 py-4">
<div className="px-4 space-y-1">
<Dialog.Title
className="text-lg font-medium text-gray-900 dark:text-white">Events</Dialog.Title>
<p className="text-sm text-gray-500 dark:text-gray-400">
@ -491,7 +502,7 @@ export function NotificationUpdateForm({ isOpen, toggle, notification }: UpdateP
</p>
</div>
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:gap-4 sm:px-6 sm:py-5">
<div className="space-y-1 px-4 sm:space-y-0 sm:grid sm:gap-4 sm:py-2">
<EventCheckBoxes />
</div>
</div>