为M2 Builder增加保存草稿的功能。
This commit is contained in:
		| @@ -23,6 +23,12 @@ | ||||
|       align-items: center; | ||||
|       gap: var(--spacing-s); | ||||
|     } | ||||
|     .button_row { | ||||
|       display: flex; | ||||
|       flex-direction: row; | ||||
|       align-items: center; | ||||
|       gap: var(--spacing-s); | ||||
|     } | ||||
|     h5 { | ||||
|       font-size: var(--font-size-m); | ||||
|       line-height: 1.7em; | ||||
|   | ||||
| @@ -2,8 +2,12 @@ import { includes, isEmpty, isNil, merge } from 'lodash-es'; | ||||
| import { useActionState, useCallback, useMemo, useState } from 'react'; | ||||
| import { useColorFunction } from '../../../ColorFunctionContext'; | ||||
| import { FloatColorPicker } from '../../../components/FloatColorPicker'; | ||||
| import { NotificationType, useNotification } from '../../../components/Notifications'; | ||||
| import { ScrollArea } from '../../../components/ScrollArea'; | ||||
| import { MaterialDesign2SchemeStorage } from '../../../material-2-scheme'; | ||||
| import { | ||||
|   MaterialDesign2SchemeSource, | ||||
|   MaterialDesign2SchemeStorage, | ||||
| } from '../../../material-2-scheme'; | ||||
| import { SchemeContent } from '../../../models'; | ||||
| import { useUpdateScheme } from '../../../stores/schemes'; | ||||
| import { mapToObject } from '../../../utls'; | ||||
| @@ -16,6 +20,7 @@ type M2SchemeBuilderProps = { | ||||
| }; | ||||
|  | ||||
| export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProps) { | ||||
|   const { showToast } = useNotification(); | ||||
|   const { colorFn } = useColorFunction(); | ||||
|   const updateScheme = useUpdateScheme(scheme.id); | ||||
|   const originalColors = useMemo(() => { | ||||
| @@ -35,45 +40,67 @@ export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProp | ||||
|         .filter((c) => !includes(deleted, c)), | ||||
|     [originalColors, newColors, deleted], | ||||
|   ); | ||||
|   const colectSchemeSource = (formData: FormData): MaterialDesign2SchemeSource => { | ||||
|     const primaryColor = formData.get('primary') as string; | ||||
|     const secondaryColor = formData.get('secondary') as string; | ||||
|     const errorColor = formData.get('error') as string; | ||||
|     const customColors: Record<string, string> = {}; | ||||
|     for (const key of colorKeys) { | ||||
|       const name = formData.get(`name_${key}`) as string; | ||||
|       const color = formData.get(`color_${key}`) as string; | ||||
|       if (isNil(name) || isEmpty(name) || isNil(color) || isEmpty(color)) continue; | ||||
|       customColors[name] = color; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|       primary: isNil(primaryColor) || isEmpty(primaryColor) ? null : primaryColor, | ||||
|       secondary: isNil(secondaryColor) || isEmpty(secondaryColor) ? null : secondaryColor, | ||||
|       error: isNil(errorColor) || isEmpty(errorColor) ? null : errorColor, | ||||
|       custom_colors: customColors, | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   const [, handleDraftAction] = useActionState<Map<string, string>, FormData>( | ||||
|     (_state, formData) => { | ||||
|       const errMsg = new Map<string, string>(); | ||||
|  | ||||
|       const collectedSource = colectSchemeSource(formData); | ||||
|       updateScheme((prev) => { | ||||
|         prev.schemeStorage.source = collectedSource; | ||||
|         return prev; | ||||
|       }); | ||||
|       setNewColors([]); | ||||
|  | ||||
|       showToast(NotificationType.SUCCESS, 'Scheme draft saved!', 'tabler:device-floppy', 3000); | ||||
|  | ||||
|       return errMsg; | ||||
|     }, | ||||
|     new Map<string, string>(), | ||||
|   ); | ||||
|   const [errMsg, handleSubmitAction] = useActionState<Map<string, string>, FormData>( | ||||
|     (_state, formData) => { | ||||
|       const errMsg = new Map<string, string>(); | ||||
|       try { | ||||
|         const primaryColor = formData.get('primary') as string; | ||||
|         if (isNil(primaryColor) || isEmpty(primaryColor)) { | ||||
|         const collected = colectSchemeSource(formData); | ||||
|         if (isNil(collected.primary) || isEmpty(collected.primary)) { | ||||
|           errMsg.set('primary', 'Primary color is required'); | ||||
|         } | ||||
|         const secondaryColor = formData.get('secondary') as string; | ||||
|         if (isNil(secondaryColor) || isEmpty(secondaryColor)) { | ||||
|         if (isNil(collected.secondary) || isEmpty(collected.secondary)) { | ||||
|           errMsg.set('secondary', 'Secondary color is required'); | ||||
|         } | ||||
|         const errorColor = formData.get('error') as string; | ||||
|         if (isNil(errorColor) || isEmpty(errorColor)) { | ||||
|         if (isNil(collected.error) || isEmpty(collected.error)) { | ||||
|           errMsg.set('error', 'Error color is required'); | ||||
|         } | ||||
|         if (!isEmpty(errMsg)) return errMsg; | ||||
|  | ||||
|         const customColors: Record<string, string> = {}; | ||||
|         for (const key of colorKeys) { | ||||
|           const name = formData.get(`name_${key}`) as string; | ||||
|           const color = formData.get(`color_${key}`) as string; | ||||
|           if (isNil(name) || isEmpty(name) || isNil(color) || isEmpty(color)) continue; | ||||
|           customColors[name] = color; | ||||
|         } | ||||
|         const generatedScheme = colorFn?.generate_material_design_2_scheme( | ||||
|           primaryColor, | ||||
|           secondaryColor, | ||||
|           errorColor, | ||||
|           customColors, | ||||
|           collected.primary, | ||||
|           collected.secondary, | ||||
|           collected.error, | ||||
|           collected.custom_colors, | ||||
|         ); | ||||
|         updateScheme((prev) => { | ||||
|           prev.schemeStorage.source = { | ||||
|             primary: primaryColor, | ||||
|             secondary: secondaryColor, | ||||
|             error: errorColor, | ||||
|             custom_colors: customColors, | ||||
|           }; | ||||
|           prev.schemeStorage.source = collected; | ||||
|           prev.schemeStorage.scheme = merge(generatedScheme[0], { | ||||
|             light: { custom_colors: mapToObject(generatedScheme[0].light.custom_colors) }, | ||||
|             dark: { custom_colors: mapToObject(generatedScheme[0].dark.custom_colors) }, | ||||
| @@ -168,10 +195,13 @@ export function M2SchemeBuilder({ scheme, onBuildComplete }: M2SchemeBuilderProp | ||||
|               onDelete={(index) => setDeleted((prev) => [...prev, index])} | ||||
|             /> | ||||
|           ))} | ||||
|         <div style={{ gridColumn: '2 / span 2' }}> | ||||
|         <div className={styles.button_row} style={{ gridColumn: '2 / span 2' }}> | ||||
|           <button type="submit" className="primary"> | ||||
|             Build Scheme | ||||
|           </button> | ||||
|           <button type="submit" className="secondary" formAction={handleDraftAction}> | ||||
|             Save Draft | ||||
|           </button> | ||||
|         </div> | ||||
|       </form> | ||||
|     </ScrollArea> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user