visuddhinanda пре 3 година
родитељ
комит
1f88087677

+ 92 - 0
dashboard/src/components/studio/SelectCase.tsx

@@ -0,0 +1,92 @@
+import { Cascader } from "antd";
+import { useIntl } from "react-intl";
+
+interface CascaderOption {
+	value: string | number;
+	label: string;
+	children?: CascaderOption[];
+}
+
+const Widget = () => {
+	const intl = useIntl();
+	const case8 = [
+		{
+			value: "nom",
+			label: intl.formatMessage({ id: "dict.fields.type.nom.label" }),
+		},
+		{
+			value: "acc",
+			label: intl.formatMessage({ id: "dict.fields.type.acc.label" }),
+		},
+		{
+			value: "gen",
+			label: intl.formatMessage({ id: "dict.fields.type.gen.label" }),
+		},
+		{
+			value: "dat",
+			label: intl.formatMessage({ id: "dict.fields.type.dat.label" }),
+		},
+		{
+			value: "inst",
+			label: intl.formatMessage({ id: "dict.fields.type.inst.label" }),
+		},
+		{
+			value: "abl",
+			label: intl.formatMessage({ id: "dict.fields.type.abl.label" }),
+		},
+		{
+			value: "voc",
+			label: intl.formatMessage({ id: "dict.fields.type.voc.label" }),
+		},
+	];
+	const case2 = [
+		{
+			value: "sg",
+			label: intl.formatMessage({ id: "dict.fields.type.sg.label" }),
+			children: case8,
+		},
+		{
+			value: "pl",
+			label: intl.formatMessage({ id: "dict.fields.type.pl.label" }),
+			children: case8,
+		},
+	];
+	const case3 = [
+		{
+			value: "m",
+			label: intl.formatMessage({ id: "dict.fields.type.m.label" }),
+			children: case2,
+		},
+		{
+			value: "nt",
+			label: intl.formatMessage({ id: "dict.fields.type.nt.label" }),
+			children: case2,
+		},
+		{
+			value: "f",
+			label: intl.formatMessage({ id: "dict.fields.type.f.label" }),
+			children: case2,
+		},
+	];
+	const options: CascaderOption[] = [
+		{
+			value: ".n.",
+			label: intl.formatMessage({ id: "dict.fields.type.n.label" }),
+			children: case3,
+		},
+		{
+			value: ".ti.",
+			label: intl.formatMessage({ id: "dict.fields.type.ti.label" }),
+			children: case3,
+		},
+		{
+			value: ".v.",
+			label: intl.formatMessage({ id: "dict.fields.type.v.label" }),
+			children: case3,
+		},
+	];
+
+	return <Cascader options={options} placeholder="Please select case" />;
+};
+
+export default Widget;

+ 39 - 0
dashboard/src/components/studio/SelectLang.tsx

@@ -0,0 +1,39 @@
+import { Select } from "antd";
+import { useIntl } from "react-intl";
+
+const { Option } = Select;
+
+const onLangChange = (value: string) => {
+	console.log(`selected ${value}`);
+};
+
+const onLangSearch = (value: string) => {
+	console.log("search:", value);
+};
+
+const Widget = () => {
+	const intl = useIntl();
+
+	const data = [
+		{ value: "en", lable: intl.formatMessage({ id: "languages.en-US" }) },
+		{ value: "zh-Hans", lable: intl.formatMessage({ id: "languages.zh-Hans" }) },
+		{ value: "zh-Hant", lable: intl.formatMessage({ id: "languages.zh-Hant" }) },
+	];
+	const langOptions = data.map((d) => <Option value={d.value}>{d.lable}</Option>);
+	return (
+		<Select
+			showSearch
+			placeholder="Select a language"
+			optionFilterProp="children"
+			onChange={onLangChange}
+			onSearch={onLangSearch}
+			filterOption={(input, option) =>
+				(option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
+			}
+		>
+			{langOptions}
+		</Select>
+	);
+};
+
+export default Widget;

+ 91 - 0
dashboard/src/components/studio/SelectUser.txt

@@ -0,0 +1,91 @@
+/*
+import { Select, Spin } from "antd";
+import type { SelectProps } from "antd/es/select";
+import debounce from "lodash/debounce";
+import React, { useMemo, useRef, useState } from "react";
+
+export interface DebounceSelectProps<ValueType = any>
+	extends Omit<SelectProps<ValueType | ValueType[]>, "options" | "children"> {
+	fetchOptions: (search: string) => Promise<ValueType[]>;
+	debounceTimeout?: number;
+}
+
+function DebounceSelect<ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any>({
+	fetchOptions,
+	debounceTimeout = 800,
+	...props
+}: DebounceSelectProps<ValueType>) {
+	const [fetching, setFetching] = useState(false);
+	const [options, setOptions] = useState<ValueType[]>([]);
+	const fetchRef = useRef(0);
+
+	const debounceFetcher = useMemo(() => {
+		const loadOptions = (value: string) => {
+			fetchRef.current += 1;
+			const fetchId = fetchRef.current;
+			setOptions([]);
+			setFetching(true);
+
+			fetchOptions(value).then((newOptions) => {
+				if (fetchId !== fetchRef.current) {
+					// for fetch callback order
+					return;
+				}
+
+				setOptions(newOptions);
+				setFetching(false);
+			});
+		};
+
+		return debounce(loadOptions, debounceTimeout);
+	}, [fetchOptions, debounceTimeout]);
+
+	return (
+		<Select
+			labelInValue
+			filterOption={false}
+			onSearch={debounceFetcher}
+			notFoundContent={fetching ? <Spin size="small" /> : null}
+			{...props}
+			options={options}
+		/>
+	);
+}
+
+// Usage of DebounceSelect
+interface UserValue {
+	label: string;
+	value: string;
+}
+
+async function fetchUserList(username: string): Promise<UserValue[]> {
+	console.log("fetching user", username);
+
+	return fetch("https://randomuser.me/api/?results=5")
+		.then((response) => response.json())
+		.then((body) =>
+			body.results.map((user: { name: { first: string; last: string }; login: { username: string } }) => ({
+				label: `${user.name.first} ${user.name.last}`,
+				value: user.login.username,
+			}))
+		);
+}
+
+const Widget = () => {
+	const [value, setValue] = useState<UserValue[]>([]);
+
+	return (
+		<DebounceSelect
+			mode="multiple"
+			value={value}
+			placeholder="Select users"
+			fetchOptions={fetchUserList}
+			onChange={(newValue) => {
+				setValue(newValue as UserValue[]);
+			}}
+			style={{ width: "100%" }}
+		/>
+	);
+};
+
+export default Widget;

+ 3 - 0
documents/development/frontend/widget.md

@@ -0,0 +1,3 @@
+[图表 charts.ant](https://charts.ant.design/zh/examples/gallery)
+
+[日历组件 big-calendar](https://jquense.github.io/react-big-calendar/examples/index.html?path=/story/about-big-calendar--page)