-
Couldn't load subscription status.
- Fork 8
Fix create-publisher modal background to use dark theme #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0582e6c
5370f07
5c2fba5
7fb2032
764dbee
08190d6
53d4844
fc6f2ef
d5588ee
a9fe129
3d6bf7e
c96b3e3
e1f3da2
be855c1
2b39824
6280fc2
06d5341
a2037d3
8085629
874ac91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import { Meta, StoryObj } from '@storybook/nextjs-vite' | ||
| import { Breadcrumb, Card } from 'flowbite-react' | ||
| import { HiHome } from 'react-icons/hi' | ||
| import CreatePublisherFormContent from '@/components/publisher/CreatePublisherFormContent' | ||
|
|
||
| const CreatePublisherPageLayout = () => { | ||
| const handleSuccess = (username: string) => { | ||
| console.log('Publisher created successfully:', username) | ||
| // In a real scenario, this would navigate to the publisher page | ||
| } | ||
|
|
||
| const handleCancel = () => { | ||
| console.log('Create publisher cancelled') | ||
| // In a real scenario, this would navigate back | ||
| } | ||
|
|
||
| return ( | ||
| <div className="p-4 bg-gray-900 min-h-screen"> | ||
| <div className="py-4"> | ||
| <Breadcrumb> | ||
| <Breadcrumb.Item | ||
| href="/" | ||
| icon={HiHome} | ||
| onClick={(e) => { | ||
| e.preventDefault() | ||
| console.log('Navigate to home') | ||
| }} | ||
| className="dark" | ||
| > | ||
| Home | ||
| </Breadcrumb.Item> | ||
| <Breadcrumb.Item className="dark"> | ||
| Create Publisher | ||
| </Breadcrumb.Item> | ||
| </Breadcrumb> | ||
| </div> | ||
|
|
||
| <section className="p-0"> | ||
| <div className="flex items-center justify-center px-0 py-4 mx-auto"> | ||
| <div className="w-full mx-auto shadow sm:max-w-lg"> | ||
| <Card className="p-2 bg-gray-800 border border-gray-700 md:p-6 rounded-2xl"> | ||
| <CreatePublisherFormContent | ||
| onSuccess={handleSuccess} | ||
| onCancel={handleCancel} | ||
| showTitle={true} | ||
| /> | ||
| </Card> | ||
| </div> | ||
| </div> | ||
| </section> | ||
| </div> | ||
| ) | ||
| } | ||
|
|
||
| const meta: Meta<typeof CreatePublisherPageLayout> = { | ||
| title: 'Pages/Publishers/CreatePublisherPage', | ||
| component: CreatePublisherPageLayout, | ||
| parameters: { | ||
| layout: 'fullscreen', | ||
| }, | ||
| } | ||
|
|
||
| export default meta | ||
| type Story = StoryObj<typeof CreatePublisherPageLayout> | ||
|
|
||
| export const Default: Story = {} |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,164 @@ | ||||||
| import { isAxiosError } from 'axios' | ||||||
| import { Button, TextInput } from 'flowbite-react' | ||||||
| import { useRouter } from 'next/router' | ||||||
| import React, { useState } from 'react' | ||||||
| import { toast } from 'react-toastify' | ||||||
| import { useNextTranslation } from 'src/hooks/i18n' | ||||||
| import { customThemeTextInput } from 'utils/comfyTheme' | ||||||
| import { useCreatePublisher, useValidatePublisher } from '@/src/api/generated' | ||||||
|
|
||||||
| type CreatePublisherFormContentProps = { | ||||||
| onSuccess?: (username: string) => void | ||||||
| onCancel?: () => void | ||||||
| showTitle?: boolean | ||||||
| } | ||||||
|
|
||||||
| const CreatePublisherFormContent: React.FC<CreatePublisherFormContentProps> = ({ | ||||||
| onSuccess, | ||||||
| onCancel, | ||||||
| showTitle = false, | ||||||
| }) => { | ||||||
| const { t } = useNextTranslation() | ||||||
| const router = useRouter() | ||||||
| const [username, setUsername] = useState('') | ||||||
| const [displayName, setDisplayName] = useState('') | ||||||
| const [publisherValidationError, setPublisherValidationError] = useState('') | ||||||
|
|
||||||
| const { | ||||||
| data, | ||||||
| isLoading: isLoadingValidation, | ||||||
| error, | ||||||
| } = useValidatePublisher({ | ||||||
| username: username, | ||||||
| }) | ||||||
| const createPublisherMutation = useCreatePublisher() | ||||||
|
|
||||||
| const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => { | ||||||
| event.preventDefault() | ||||||
| createPublisherMutation.mutate( | ||||||
| { | ||||||
| data: { | ||||||
| id: username, | ||||||
| name: displayName, | ||||||
| }, | ||||||
| }, | ||||||
| { | ||||||
| onError: (error) => { | ||||||
| toast.error( | ||||||
| t('Could not create publisher. Please try again.') | ||||||
| ) | ||||||
| }, | ||||||
| onSuccess: () => { | ||||||
| toast.success('Publisher created successfully!') | ||||||
| if (onSuccess) { | ||||||
| onSuccess(username) | ||||||
| } else { | ||||||
| router.push(`/publishers/${username}`) | ||||||
| } | ||||||
| }, | ||||||
| } | ||||||
| ) | ||||||
| } | ||||||
|
|
||||||
| React.useEffect(() => { | ||||||
| if (isAxiosError(error)) { | ||||||
| setPublisherValidationError(error.response?.data?.message) | ||||||
| } else { | ||||||
| setPublisherValidationError('') | ||||||
| } | ||||||
| }, [error]) | ||||||
|
|
||||||
| return ( | ||||||
| <> | ||||||
| {showTitle && ( | ||||||
| <h2 className="text-2xl font-bold text-white mb-4"> | ||||||
| {t('Create Publisher')} | ||||||
| </h2> | ||||||
| )} | ||||||
| <p className="flex justify-center text-sm font-medium text-gray-400 "> | ||||||
| {t( | ||||||
| 'Register a publisher to begin distributing custom nodes on Comfy.' | ||||||
| )} | ||||||
| </p> | ||||||
|
|
||||||
| <form | ||||||
| className="mt-4 space-y-4 lg:space-y-6" | ||||||
| onSubmit={handleSubmit} | ||||||
| > | ||||||
| <div> | ||||||
| <label className="block mb-1 text-xs font-bold text-white"> | ||||||
| {t('Username')} | ||||||
| </label> | ||||||
| <TextInput | ||||||
| id="name" | ||||||
| placeholder={t('E.g. janedoe55')} | ||||||
| required | ||||||
| theme={customThemeTextInput} | ||||||
| type="text" | ||||||
| sizing="sm" | ||||||
| value={username} | ||||||
| onChange={(e) => setUsername(e.target.value)} | ||||||
| color={ | ||||||
| !isLoadingValidation && publisherValidationError | ||||||
| ? 'failure' | ||||||
| : 'success' | ||||||
| } | ||||||
| helperText={ | ||||||
| <> | ||||||
| {isLoadingValidation && ( | ||||||
| <>{t('Checking username...')}</> | ||||||
| )} | ||||||
| {!isLoadingValidation && | ||||||
| publisherValidationError && ( | ||||||
| <> | ||||||
| <span className="font-medium"></span>{' '} | ||||||
| {publisherValidationError} | ||||||
| </> | ||||||
| )} | ||||||
| </> | ||||||
| } | ||||||
| /> | ||||||
| </div> | ||||||
| <div> | ||||||
| <label className="block mb-1 text-xs font-bold text-white"> | ||||||
| {t('Display Name')} | ||||||
| </label> | ||||||
| <TextInput | ||||||
| sizing="sm" | ||||||
| theme={customThemeTextInput} | ||||||
| id="displayName" | ||||||
| className="border-gray-700 " | ||||||
| placeholder={t('E.g. Jane Doe')} | ||||||
| required | ||||||
| type="text" | ||||||
| value={displayName} | ||||||
| onChange={(e) => setDisplayName(e.target.value)} | ||||||
| /> | ||||||
| </div> | ||||||
|
|
||||||
| <div className="flex center gap-4"> | ||||||
|
||||||
| <div className="flex center gap-4"> | |
| <div className="flex justify-center gap-4"> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import type { Meta, StoryObj } from '@storybook/nextjs-vite' | ||
| import CreatePublisherModal from './CreatePublisherModal' | ||
|
|
||
| // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export | ||
| const meta: Meta<typeof CreatePublisherModal> = { | ||
| title: 'Components/Publisher/CreatePublisherModal', | ||
| component: CreatePublisherModal, | ||
| parameters: { | ||
| // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout | ||
| layout: 'centered', | ||
| }, | ||
| // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs | ||
| tags: ['autodocs'], | ||
| // More on argTypes: https://storybook.js.org/docs/api/argtypes | ||
| argTypes: { | ||
| open: { control: 'boolean' }, | ||
| onCloseModal: { action: 'onCloseModal' }, | ||
| onSuccess: { action: 'onSuccess' }, | ||
| }, | ||
| // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args | ||
| args: { | ||
| open: true, | ||
| onCloseModal: () => {}, | ||
| }, | ||
| } | ||
|
|
||
| export default meta | ||
| type Story = StoryObj<typeof meta> | ||
|
|
||
| // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args | ||
| export const Default: Story = { | ||
| args: { | ||
| open: true, | ||
| }, | ||
| } | ||
|
|
||
| export const Closed: Story = { | ||
| args: { | ||
| open: false, | ||
| }, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This empty span with only a className serves no purpose and should be removed. The space character following it can be achieved through other means if needed.