Skip to content

Commit

Permalink
表单的成功状态!
Browse files Browse the repository at this point in the history
  • Loading branch information
kalxd committed Feb 1, 2024
1 parent 482830d commit 3d76c03
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 29 deletions.
81 changes: 66 additions & 15 deletions src/data/form.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,101 @@
import * as m from "mithril";
import { Either, Just, Maybe, Nothing } from "purify-ts";
import { ValidatorResult, ValidatorError } from "../data/internal/error";
import { Mutable, mutable } from "./internal/lens";
import { Mutable, mutable, Prism } from "./internal/lens";
import { _just } from "./lens";

export interface FormInit {
_tag: "FormInit";
}

const formInitValue: FormInit = {
_tag: "FormInit"
};

export interface FormLoading {
_tag: "FormLoading";
};

const formLoadingValue: FormLoading = {
_tag: "FormLoading"
};

export interface FormResult {
_tag: "FormResult";
_value: Maybe<ValidatorError>;
}

const mkFormResult = (value: Maybe<ValidatorError>): FormResult => ({
_tag: "FormResult",
_value: value
});

export type FormState = FormInit | FormLoading | FormResult;

const _isloading = (): Prism<FormState, boolean> => ({
get: s => Just(s._tag === "FormLoading"),
set: (s, _) => Just(s)
});

const _result = (): Prism<FormState, Maybe<ValidatorError>> => ({
get: s => {
if (s._tag === "FormResult") {
return Just(s._value);
}
else {
return Nothing;
}
},
set: (s, _) => Just(s)
});

export interface FormMutable<T> extends Mutable<T> {
validate: <R>(f: (data: T) => ValidatorResult<R>) => Promise<Either<ValidatorError, R>>;
resetErr: () => void;
resetTip: () => void;
reset: () => void;
getErr: () => Maybe<ValidatorError>;
getResult: () => Maybe<Maybe<ValidatorError>>;
isValidating: () => boolean;
}

export const formMut = <T>(state: T): FormMutable<T> => {
const err = mutable<Maybe<ValidatorError>>(Nothing);
const formState = mutable<FormState>(formInitValue);
const mut = mutable(state);
const isProcessing = mutable<boolean>(false);

const validate: FormMutable<T>["validate"] = async f => {
isProcessing.set(true);
formState.set(formLoadingValue);
m.redraw();

const s = mut.get();
const r = await f(s);

r.ifLeft(e => err.set(Just(e)));
isProcessing.set(false);
const es = r.swap().toMaybe();

formState.set(mkFormResult(es));
m.redraw();
return r;
};

const resetErr: FormMutable<T>["resetErr"] = () => {
err.set(Nothing);
const resetTip: FormMutable<T>["resetTip"] = () => {
formState.set(formInitValue);
};

const reset: FormMutable<T>["reset"] = () => {
resetErr();
resetTip();
mut.set(state);
};

const getErr: FormMutable<T>["getErr"] = err.get;
const getResult: FormMutable<T>["getResult"] = () =>
formState.prism(_result()).get();

const isValidating: FormMutable<T>["isValidating"] = isProcessing.get;
const isValidating: FormMutable<T>["isValidating"] = () =>
formState.prism(_isloading()).get().orDefault(false);

return {
...mut,
validate,
resetErr,
resetTip,
reset,
getErr,
getResult,
isValidating
};
};
40 changes: 26 additions & 14 deletions src/module/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Maybe } from "purify-ts";
import { LoadingShape, Size, StateLevel } from "../data/var";
import { FormMutable } from "../data/form";
import { Message } from "../element/message";
import { ValidatorError } from "../data";

export interface FormAttr<T> {
loading?: LoadingShape;
Expand All @@ -12,6 +13,19 @@ export interface FormAttr<T> {
formdata?: FormMutable<T>;
}

const renderSuccuss = (callback: () => void): m.Vnode =>
m(Message, { state: StateLevel.Positive }, [
m("i.close.icon", { onclick: callback }),
m("div.header", "操作成功!")
]);

const renderFailure = (callback: () => void, xs: ValidatorError): m.Vnode =>
m(Message, { state: StateLevel.Negative }, [
m("i.close.icon", { onclick: callback }),
m("div.header", "提交操作不成功!"),
m("ul.list", xs.map(a => m("li", a)))
]);

export const Form = <T>(): m.Component<FormAttr<T>> => {
return {
view: ({ attrs, children }) => {
Expand All @@ -24,22 +38,20 @@ export const Form = <T>(): m.Component<FormAttr<T>> => {
loadShape,
selectKlass("inverted", attrs.isInvert),
Maybe.fromNullable(attrs.size),
fd.chain(fd => fd.getErr()).map(_ => "error")
fd.chain(fd => fd.getResult()).map(_ => "error")
]);

const errMsg = fd.chain(data => {
const onclick = () => data.resetErr();

return data.getErr().map(msg => m(
Message,
{ state: StateLevel.Error },
[
m("i.close.icon", { onclick }),
m("div.header", "提交数据验证出错"),
m("ul.list", msg.map(a => m("li", a)))
]
));
});
const errMsg = fd
.filter(d => !d.isValidating())
.map(data => {
const onclick = () => data.resetTip();
return data.getResult()
.map(v => v.caseOf({
Just: xs => renderFailure(onclick, xs),
Nothing: () => renderSuccuss(onclick)
}))
.extract();
});

return m("div.ui.form", { class: klass }, [
(children as m.Children),
Expand Down

0 comments on commit 3d76c03

Please sign in to comment.