为Q Builder增加保存草稿的功能。

This commit is contained in:
徐涛 2025-03-31 06:16:03 +08:00
parent 2638bbd99a
commit efb2237135
2 changed files with 69 additions and 40 deletions

View File

@ -30,6 +30,12 @@
.parameter_input { .parameter_input {
max-width: 8em; max-width: 8em;
} }
.button_row {
display: flex;
flex-direction: row;
align-items: center;
gap: var(--spacing-s);
}
h5 { h5 {
font-size: var(--font-size-m); font-size: var(--font-size-m);
line-height: 1.7em; line-height: 1.7em;

View File

@ -3,6 +3,7 @@ import { every, isEmpty, isNil } from 'lodash-es';
import { useActionState, useMemo } from 'react'; import { useActionState, useMemo } from 'react';
import { useColorFunction } from '../../../ColorFunctionContext'; import { useColorFunction } from '../../../ColorFunctionContext';
import { FloatColorPicker } from '../../../components/FloatColorPicker'; import { FloatColorPicker } from '../../../components/FloatColorPicker';
import { NotificationType, useNotification } from '../../../components/Notifications';
import { ScrollArea } from '../../../components/ScrollArea'; import { ScrollArea } from '../../../components/ScrollArea';
import { VSegmentedControl } from '../../../components/VSegmentedControl'; import { VSegmentedControl } from '../../../components/VSegmentedControl';
import { SchemeContent } from '../../../models'; import { SchemeContent } from '../../../models';
@ -17,6 +18,7 @@ type QSchemeBuilderProps = {
}; };
export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps) { export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps) {
const { showToast } = useNotification();
const { colorFn } = useColorFunction(); const { colorFn } = useColorFunction();
const updateScheme = useUpdateScheme(scheme.id); const updateScheme = useUpdateScheme(scheme.id);
const defaultSetting = useMemo(() => { const defaultSetting = useMemo(() => {
@ -77,25 +79,7 @@ export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps
return []; return [];
}, []); }, []);
const [errMsg, handleSubmitAction] = useActionState<Map<string, string>, FormData>( const collectSchemeSource = (formData: FormData): QSchemeSource => {
(_state, formData) => {
const errMsg = new Map<string, string>();
const requiredFields = [
'primary',
'danger',
'success',
'warn',
'info',
'foreground',
'background',
];
for (const field of requiredFields) {
if (!formData.get(field)) {
errMsg.set(field, 'This color is required for scheme generating.');
}
}
if (!isEmpty(errMsg)) return errMsg;
try {
const schemeSetting = new SchemeSetting( const schemeSetting = new SchemeSetting(
new ColorShifting( new ColorShifting(
Number(formData.get('hover_chroma')) / 100, Number(formData.get('hover_chroma')) / 100,
@ -121,8 +105,7 @@ export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps
Number(formData.get('wacg')) as WACGSetting, Number(formData.get('wacg')) as WACGSetting,
); );
const dumpedSetting = schemeSetting.toJsValue() as QSchemeSetting; const dumpedSetting = schemeSetting.toJsValue() as QSchemeSetting;
return {
const source: QSchemeSource = {
primary: defaultEmptyFormData(formData, 'primary', null), primary: defaultEmptyFormData(formData, 'primary', null),
secondary: defaultEmptyFormData(formData, 'secondary', null), secondary: defaultEmptyFormData(formData, 'secondary', null),
tertiary: defaultEmptyFormData(formData, 'tertiary', null), tertiary: defaultEmptyFormData(formData, 'tertiary', null),
@ -135,6 +118,43 @@ export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps
background: defaultEmptyFormData(formData, 'background', null), background: defaultEmptyFormData(formData, 'background', null),
setting: dumpedSetting, setting: dumpedSetting,
}; };
};
const [, handleDraftAction] = useActionState<Map<string, string>, FormData>(
(_state, formData) => {
const errMsg = new Map<string, string>();
const source = collectSchemeSource(formData);
updateScheme((prev) => {
prev.schemeStorage.source = source;
return prev;
});
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>();
const requiredFields = [
'primary',
'danger',
'success',
'warn',
'info',
'foreground',
'background',
];
for (const field of requiredFields) {
if (!formData.get(field)) {
errMsg.set(field, 'This color is required for scheme generating.');
}
}
if (!isEmpty(errMsg)) return errMsg;
try {
const source = collectSchemeSource(formData);
const generatedScheme = every([source.secondary, source.tertiary, source.accent], isNil) const generatedScheme = every([source.secondary, source.tertiary, source.accent], isNil)
? colorFn?.generate_q_scheme_automatically( ? colorFn?.generate_q_scheme_automatically(
source.primary ?? '', source.primary ?? '',
@ -352,10 +372,13 @@ export function QSchemeBuilder({ scheme, onBuildCompleted }: QSchemeBuilderProps
defaultValue={defaultSetting?.wacg_follows} defaultValue={defaultSetting?.wacg_follows}
/> />
</div> </div>
<div style={{ gridColumn: '2 / span 2' }}> <div className={styles.button_row} style={{ gridColumn: '2 / span 2' }}>
<button type="submit" className="primary"> <button type="submit" className="primary">
Build Scheme Build Scheme
</button> </button>
<button type="submit" className="secondary" formAction={handleDraftAction}>
Save Draft
</button>
</div> </div>
</form> </form>
</ScrollArea> </ScrollArea>