diff --git a/README.md b/README.md index 5b4ae070..f91dcd13 100644 --- a/README.md +++ b/README.md @@ -419,6 +419,7 @@ Everything else should work the same including layer targeting. ### June 17, 2024 - Performance optimizations for batch preparation +- Added some docs via a popup for items in the simple ui explaining what settings do. Still a WIP ### June 16, 2024 - Hide control images in the UI when viewing datasets diff --git a/ui/src/app/jobs/new/SimpleJob.tsx b/ui/src/app/jobs/new/SimpleJob.tsx index ca587564..0b8b3e47 100644 --- a/ui/src/app/jobs/new/SimpleJob.tsx +++ b/ui/src/app/jobs/new/SimpleJob.tsx @@ -47,6 +47,7 @@ export default function SimpleJob({ setJobConfig(value, 'config.name')} placeholder="Enter training name" disabled={runId !== null} @@ -55,12 +56,14 @@ export default function SimpleJob({ setGpuIDs(value)} options={gpuList.map((gpu: any) => ({ value: `${gpu.index}`, label: `GPU #${gpu.index}` }))} /> { if (value?.trim() === '') { value = null; @@ -120,6 +123,7 @@ export default function SimpleJob({ { if (value?.trim() === '') { value = null; @@ -185,22 +189,20 @@ export default function SimpleJob({ max={1024} required /> - { - modelArch?.disableSections?.includes('network.conv') ? null : ( - { - console.log('onChange', value); - setJobConfig(value, 'config.process[0].network.conv'); - setJobConfig(value, 'config.process[0].network.conv_alpha'); - }} - placeholder="eg. 16" - min={0} - max={1024} - /> - ) - } + {modelArch?.disableSections?.includes('network.conv') ? null : ( + { + console.log('onChange', value); + setJobConfig(value, 'config.process[0].network.conv'); + setJobConfig(value, 'config.process[0].network.conv_alpha'); + }} + placeholder="eg. 16" + min={0} + max={1024} + /> + )} )} diff --git a/ui/src/app/layout.tsx b/ui/src/app/layout.tsx index 50f8d79a..e45363f9 100644 --- a/ui/src/app/layout.tsx +++ b/ui/src/app/layout.tsx @@ -7,6 +7,7 @@ import ConfirmModal from '@/components/ConfirmModal'; import SampleImageModal from '@/components/SampleImageModal'; import { Suspense } from 'react'; import AuthWrapper from '@/components/AuthWrapper'; +import DocModal from '@/components/DocModal'; export const dynamic = 'force-dynamic'; @@ -38,6 +39,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) + diff --git a/ui/src/components/DocModal.tsx b/ui/src/components/DocModal.tsx new file mode 100644 index 00000000..bfdd6bf4 --- /dev/null +++ b/ui/src/components/DocModal.tsx @@ -0,0 +1,59 @@ +'use client'; +import { createGlobalState } from 'react-global-hooks'; +import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'; +import React from 'react'; +import { ConfigDoc } from '@/types'; + +export const docState = createGlobalState(null); + +export const openDoc = (doc: ConfigDoc) => { + docState.set({ ...doc }); +}; + +export default function DocModal() { + const [doc, setDoc] = docState.use(); + const isOpen = !!doc; + + const onClose = () => { + setDoc(null); + }; + + return ( + + + +
+
+ +
+
+
+ + {doc?.title || 'Confirm Action'} + +
{doc?.description}
+
+
+
+
+ +
+
+
+
+
+ ); +} diff --git a/ui/src/components/formInputs.tsx b/ui/src/components/formInputs.tsx index a9908bd0..a556a266 100644 --- a/ui/src/components/formInputs.tsx +++ b/ui/src/components/formInputs.tsx @@ -3,6 +3,10 @@ import React, { forwardRef } from 'react'; import classNames from 'classnames'; import dynamic from 'next/dynamic'; +import { CircleHelp } from 'lucide-react'; +import { getDoc } from '@/docs'; +import { openDoc } from '@/components/DocModal'; + const Select = dynamic(() => import('react-select'), { ssr: false }); const labelClasses = 'block text-xs mb-1 mt-2 text-gray-300'; @@ -11,6 +15,7 @@ const inputClasses = export interface InputProps { label?: string; + docKey?: string; className?: string; placeholder?: string; required?: boolean; @@ -24,10 +29,20 @@ export interface TextInputProps extends InputProps { } export const TextInput = forwardRef( - ({ label, value, onChange, placeholder, required, disabled, type = 'text', className }, ref) => { + ({ label, value, onChange, placeholder, required, disabled, type = 'text', className, docKey = null }, ref) => { + const doc = getDoc(docKey); return (
- {label && } + {label && ( + + )} { - const { label, value, onChange, placeholder, required, min, max } = props; + const { label, value, onChange, placeholder, required, min, max, docKey = null } = props; + const doc = getDoc(docKey); // Add controlled internal state to properly handle partial inputs const [inputValue, setInputValue] = React.useState(value ?? ''); @@ -68,7 +84,16 @@ export const NumberInput = (props: NumberInputProps) => { return (
- {label && } + {label && ( + + )} { - const { label, value, onChange, options } = props; + const { label, value, onChange, options, docKey = null } = props; + const doc = getDoc(docKey); const selectedOption = options.find(option => option.value === value); return (
{ 'opacity-30 cursor-not-allowed': props.disabled, })} > - {label && } + {label && ( + + )}