diff --git a/package-lock.json b/package-lock.json
index 8d577d7..9de3fe5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "dummyi",
- "version": "0.1.0",
+ "version": "0.2.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dummyi",
- "version": "0.1.0",
+ "version": "0.2.2",
"dependencies": {
"@douyinfe/semi-next": "^2.51.0",
"@douyinfe/semi-ui": "^2.51.0",
@@ -19,7 +19,7 @@
"@uiw/codemirror-extensions-langs": "^4.21.9",
"@uiw/codemirror-themes": "^4.21.9",
"@uiw/react-codemirror": "^4.21.20",
- "@vercel/analytics": "^1.0.2",
+ "@vercel/analytics": "^1.2.2",
"autoprefixer": "10.4.16",
"emoji-picker-react": "^4.5.3",
"eslint": "8.47.0",
@@ -49,7 +49,7 @@
"cypress": "^12.17.4",
"mini-css-extract-plugin": "^2.7.6",
"typescript": "^5.1.6",
- "webpack": "^5.88.2"
+ "webpack": "^5.90.3"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -1512,9 +1512,9 @@
}
},
"node_modules/@jridgewell/source-map": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz",
- "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz",
+ "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
@@ -1526,19 +1526,14 @@
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.18",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
- "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
- },
"node_modules/@lezer/common": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.2.tgz",
@@ -2008,9 +2003,9 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
- "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA=="
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
@@ -2307,9 +2302,24 @@
}
},
"node_modules/@vercel/analytics": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.0.2.tgz",
- "integrity": "sha512-BZFxVrv24VbNNl5xMxqUojQIegEeXMI6rX3rg1uVLYUEXsuKNBSAEQf4BWEcjQDp/8aYJOj6m8V4PUA3x/cxgg=="
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.2.2.tgz",
+ "integrity": "sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==",
+ "dependencies": {
+ "server-only": "^0.0.1"
+ },
+ "peerDependencies": {
+ "next": ">= 13",
+ "react": "^18 || ^19"
+ },
+ "peerDependenciesMeta": {
+ "next": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
},
"node_modules/@webassemblyjs/ast": {
"version": "1.11.5",
@@ -8074,13 +8084,18 @@
}
},
"node_modules/serialize-javascript": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
- "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dependencies": {
"randombytes": "^2.1.0"
}
},
+ "node_modules/server-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz",
+ "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="
+ },
"node_modules/set-function-name": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
@@ -8529,12 +8544,12 @@
}
},
"node_modules/terser": {
- "version": "5.17.1",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz",
- "integrity": "sha512-hVl35zClmpisy6oaoKALOpS0rDYLxRFLHhRuDlEGTKey9qHjS1w9GMORjuwIMt70Wan4lwsLYyWDVnWgF+KUEw==",
+ "version": "5.28.1",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.28.1.tgz",
+ "integrity": "sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==",
"dependencies": {
- "@jridgewell/source-map": "^0.3.2",
- "acorn": "^8.5.0",
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
@@ -8546,15 +8561,15 @@
}
},
"node_modules/terser-webpack-plugin": {
- "version": "5.3.7",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz",
- "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==",
+ "version": "5.3.10",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
+ "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.17",
+ "@jridgewell/trace-mapping": "^0.3.20",
"jest-worker": "^27.4.5",
"schema-utils": "^3.1.1",
"serialize-javascript": "^6.0.1",
- "terser": "^5.16.5"
+ "terser": "^5.26.0"
},
"engines": {
"node": ">= 10.13.0"
@@ -8579,9 +8594,9 @@
}
},
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz",
- "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
@@ -9032,18 +9047,18 @@
}
},
"node_modules/webpack": {
- "version": "5.88.2",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
- "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
+ "version": "5.90.3",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.3.tgz",
+ "integrity": "sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
- "@types/estree": "^1.0.0",
+ "@types/estree": "^1.0.5",
"@webassemblyjs/ast": "^1.11.5",
"@webassemblyjs/wasm-edit": "^1.11.5",
"@webassemblyjs/wasm-parser": "^1.11.5",
"acorn": "^8.7.1",
"acorn-import-assertions": "^1.9.0",
- "browserslist": "^4.14.5",
+ "browserslist": "^4.21.10",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.15.0",
"es-module-lexer": "^1.2.1",
@@ -9057,7 +9072,7 @@
"neo-async": "^2.6.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
- "terser-webpack-plugin": "^5.3.7",
+ "terser-webpack-plugin": "^5.3.10",
"watchpack": "^2.4.0",
"webpack-sources": "^3.2.3"
},
diff --git a/package.json b/package.json
index 7b9fbaf..e0590dc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "dummyi",
- "version": "0.2.2",
+ "version": "0.2.3",
"private": true,
"scripts": {
"dev": "next dev",
@@ -23,7 +23,7 @@
"@uiw/codemirror-extensions-langs": "^4.21.9",
"@uiw/codemirror-themes": "^4.21.9",
"@uiw/react-codemirror": "^4.21.20",
- "@vercel/analytics": "^1.0.2",
+ "@vercel/analytics": "^1.2.2",
"autoprefixer": "10.4.16",
"emoji-picker-react": "^4.5.3",
"eslint": "8.47.0",
@@ -53,6 +53,6 @@
"cypress": "^12.17.4",
"mini-css-extract-plugin": "^2.7.6",
"typescript": "^5.1.6",
- "webpack": "^5.88.2"
+ "webpack": "^5.90.3"
}
}
diff --git a/scripts/addNewFormatter.ts b/scripts/addNewFormatter.ts
index 23c6e12..7516ac0 100644
--- a/scripts/addNewFormatter.ts
+++ b/scripts/addNewFormatter.ts
@@ -25,7 +25,7 @@ const createFormatter = (formatterName: string, fileExtension: string) => {
const path = `./src/core/formatters/${formatterName}`;
// add formatter enum option
- enumUtils('./src/constants/enums.ts', 'ExportFormat', formatterName.toUpperCase(), formatterName.toLowerCase());
+ enumUtils('./src/constants/enums.ts', 'ExportFormat', formatterName.toUpperCase(), formatterName);
// create directory
fs.mkdirSync(path, {recursive: true});
diff --git a/scripts/addNewGenerator.ts b/scripts/addNewGenerator.ts
index e81710c..5403898 100644
--- a/scripts/addNewGenerator.ts
+++ b/scripts/addNewGenerator.ts
@@ -106,7 +106,7 @@ export const ${generatorName}GeneratorDefaultOptions:${generatorName}GeneratorOp
// -------------------------------------------------------------------------------------------------------------
// generate method
-export const generate = (options: any): GenerateResult => {
+export const generate = (options: ${generatorName}GeneratorOptions): GenerateResult => {
// TODO: implement your own generate method here
return {
@@ -125,9 +125,9 @@ export const ${generatorName}GeneratorOptionsComponent: React.FunctionComponent<
// TODO: implement your own options component here
return (
-
+ <>
NOT IMPLEMENTED
-
+ >
);
}`;
}
diff --git a/src/components/DevTools/src/GenerateResultsPreviewer.tsx b/src/components/DevTools/src/GenerateResultsPreviewer.tsx
index 595aa5a..5c90700 100644
--- a/src/components/DevTools/src/GenerateResultsPreviewer.tsx
+++ b/src/components/DevTools/src/GenerateResultsPreviewer.tsx
@@ -77,7 +77,7 @@ export const GenerateResultsPreviewer: React.FunctionComponent
-
+
{formatType}
{isError && ERROR}
diff --git a/src/components/InputPanel/src/InputPanel.tsx b/src/components/InputPanel/src/InputPanel.tsx
index 3f66bee..bdc375e 100644
--- a/src/components/InputPanel/src/InputPanel.tsx
+++ b/src/components/InputPanel/src/InputPanel.tsx
@@ -23,7 +23,7 @@ export const InputPanel: React.FunctionComponent = () => {
setPanelHeight(containerHeight);
- if (containerWidth > 1000) {
+ if (containerWidth > 900) {
setComponentSize(ComponentSize.LARGE);
} else if (containerWidth > 550) {
setComponentSize(ComponentSize.MEDIUM);
diff --git a/src/components/InputPanel/src/components/DataTypeSelectModal.tsx b/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
index 72a0037..2200c79 100644
--- a/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
+++ b/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
@@ -21,7 +21,7 @@ export interface DataTypeSelectModalProps {
export const DataTypeSelectModal: React.FunctionComponent = ({...props}) => {
const intl = useIntl();
- const {Title} = Typography;
+ const {Title, Text} = Typography;
const dispatch = useDispatch();
const [searchText, setSearchText] = React.useState(null);
const data = useMemo(() => getGeneratorList(searchText, intl), [intl, searchText]);
@@ -34,7 +34,7 @@ export const DataTypeSelectModal: React.FunctionComponent {
- dispatch(doChangeDataType(currentTargetDataFieldId,item.type));
+ dispatch(doChangeDataType(currentTargetDataFieldId, item.type));
onCancel();
}
@@ -106,7 +106,9 @@ export const DataTypeSelectModal: React.FunctionComponent (
- {example}
+
+ {example}
+
))
}
diff --git a/src/components/Utils/src/OptionsDatetimePicker.tsx b/src/components/Utils/src/OptionsDatetimePicker.tsx
new file mode 100644
index 0000000..cf6a92e
--- /dev/null
+++ b/src/components/Utils/src/OptionsDatetimePicker.tsx
@@ -0,0 +1,55 @@
+import React from "react";
+import {ErrorTooltip, InfoTooltip} from "@/components/Utils";
+import {useIntl} from "@/locale";
+import {isNullOrWhiteSpace} from "@/utils/stringUtils";
+import {DatePicker} from "@douyinfe/semi-ui";
+import {hasValue} from "@/utils/typeUtils";
+
+export interface OptionsDatetimePickerProps {
+ label: string | React.ReactNode;
+ type?: "date" | "dateTime" | "dateRange" | "dateTimeRange";
+ infoTooltip?: string | React.ReactNode;
+ errorMessage?: string;
+ value: string | number | Date | string[] | number[] | Date[];
+ onChange: (value: any) => void;
+ style?: React.CSSProperties;
+ required?: boolean;
+}
+
+export const OptionsDatetimePicker: React.FunctionComponent = ({...props}) => {
+ const {label, type, infoTooltip, errorMessage, value, style, onChange, required} = props;
+ const intl = useIntl();
+
+ // Add a new useState to manage the validation error message
+ const [validationError, setValidationError] = React.useState();
+
+ // Add effect to validate value when it changes or when required status changes
+ React.useEffect(() => {
+ if (required && !hasValue(value)) {
+ setValidationError(intl.formatMessage({id: 'error.input.isRequired'})); // Set default required error message or use props.errorMessage
+ } else {
+ setValidationError(undefined); // Clear error message when input is valid
+ }
+ }, [value, required]);
+
+ return (
+
+
+ {label}
+ {infoTooltip &&
+ {infoTooltip}
+ }
+
+
+ onChange(dateString)}
+ value={value}
+ style={style}
+ validateStatus={!isNullOrWhiteSpace(validationError || errorMessage) ? 'error' : 'default'}
+ />
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Utils/src/OptionsInput.tsx b/src/components/Utils/src/OptionsInput.tsx
index c54aeb4..61ff424 100644
--- a/src/components/Utils/src/OptionsInput.tsx
+++ b/src/components/Utils/src/OptionsInput.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import {ErrorTooltip, InfoTooltip} from "@/components/Utils";
import {Input} from "@douyinfe/semi-ui";
import {isNullOrWhiteSpace} from "@/utils/stringUtils";
+import {useIntl} from "@/locale";
export interface OptionsInputProps {
label: string | React.ReactNode;
@@ -11,10 +12,24 @@ export interface OptionsInputProps {
value: string;
onChange: (value: any) => void;
style?: React.CSSProperties;
+ required?: boolean; // Add this line for the new required prop
}
export const OptionsInput: React.FunctionComponent = ({...props}) => {
- const {label, infoTooltip, errorMessage, value, style, suffix, onChange} = props;
+ const {label, infoTooltip, errorMessage, value, style, suffix, onChange, required} = props;
+ const intl = useIntl();
+
+ // Add a new useState to manage the validation error message
+ const [validationError, setValidationError] = React.useState();
+
+ // Add effect to validate value when it changes or when required status changes
+ React.useEffect(() => {
+ if (required && isNullOrWhiteSpace(value)) {
+ setValidationError(intl.formatMessage({id: 'error.input.isRequired'})); // Set default required error message or use props.errorMessage
+ } else {
+ setValidationError(undefined); // Clear error message when input is valid
+ }
+ }, [value, required]);
return (
@@ -24,15 +39,15 @@ export const OptionsInput: React.FunctionComponent = ({...pro
{infoTooltip}
}
-
+
onChange(value)}
value={value}
style={style}
suffix={suffix}
- validateStatus={!isNullOrWhiteSpace(errorMessage) ? 'error' : 'default'}
+ validateStatus={!isNullOrWhiteSpace(validationError || errorMessage) ? 'error' : 'default'}
/>
)
-}
\ No newline at end of file
+}
diff --git a/src/components/Utils/src/OptionsSwitch.tsx b/src/components/Utils/src/OptionsSwitch.tsx
index 05eb65d..9c4acd7 100644
--- a/src/components/Utils/src/OptionsSwitch.tsx
+++ b/src/components/Utils/src/OptionsSwitch.tsx
@@ -27,7 +27,7 @@ export const OptionsSwitch: React.FunctionComponent = ({...p
diff --git a/src/constants/enums.ts b/src/constants/enums.ts
index 2b1bdaf..50de53a 100644
--- a/src/constants/enums.ts
+++ b/src/constants/enums.ts
@@ -1,12 +1,12 @@
-
// export format
export enum ExportFormatCategory {
- FILE_TYPES = "fileTypes",
+ FILE_TYPES = "file_types",
DATABASES = "databases",
- PROGRAMMING_LANGUAGES = "programmingLanguages",
+ PROGRAMMING_LANGUAGES = "programming_languages",
}
export enum ExportFormat {
+ TYPESCRIPT = "Typescript",
CSHARP = "C#",
SQL = "SQL",
CSV = "CSV",
@@ -17,17 +17,18 @@ export enum ExportFormat {
export enum ValueType {
STRING = "string",
- TEXT= "text",
+ TEXT = "text",
ONE_BIT = "1bit",
INT = "integer",
BIGINT = "bigint",
DOUBLE = "double",
BOOLEAN = "boolean",
INT_LIST = "int_list",
- STRING_LIST = "string_list"
+ STRING_LIST = "string_list",
+ DATE_TIME = "date_time"
}
-export enum ExportProcessStage{
+export enum ExportProcessStage {
PREVIEW = "preview",
GENERATING = "generating",
COMPLETED = "completed",
@@ -35,15 +36,20 @@ export enum ExportProcessStage{
// data types
export enum DataTypeCategory {
- ALL= "all",
+ ALL = "all",
BASIC = "basic",
PERSON = "person",
NETWORK = "network",
COMMERCE = "commerce",
+ DATETIME = "datetime"
}
export enum DataType {
IPADDRESS = "ipaddress",
+ BIRTHDAY = "birthday",
+ MONTH = "month",
+ WEEKDAY = "weekday",
+ DATETIME = "datetime",
URL = "url",
DOMAINSUFFIX = "domainsuffix",
DOMAINNAME = "domainname",
@@ -81,18 +87,18 @@ export enum Locales {
JA_JP = "ja-JP",
}
-export enum ComponentSize{
+export enum ComponentSize {
SMALL = "small",
MEDIUM = "medium",
LARGE = "large",
}
-export enum PreviewType{
+export enum PreviewType {
TABLE = "table",
RAW = "raw"
}
-export enum CollectionNodeType{
+export enum CollectionNodeType {
COLLECTION = "collection",
SCHEMA = "schema"
}
@@ -102,7 +108,7 @@ export enum EndOfLineChars {
CRLF = '\r\n'
}
-export enum Sex{
+export enum Sex {
ALL = "all",
MALE = "male",
FEMALE = "female"
diff --git a/src/core/formatters/CSharp/CSharp.tsx b/src/core/formatters/CSharp/CSharp.tsx
index 774bf00..ed4d198 100644
--- a/src/core/formatters/CSharp/CSharp.tsx
+++ b/src/core/formatters/CSharp/CSharp.tsx
@@ -4,8 +4,6 @@ import {OptionsInput, OptionsSelect, SelectOption} from "@/components/Utils";
import {FormattedMessage} from "@/locale";
import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
import {ValueType} from "@/constants/enums";
-import {GenerateResult} from "@/types/generator";
-import {hasValue} from "@/utils/typeUtils";
import {formatValueForCSharp} from "@/core/formatters/CSharp/CSharpFormatterUtils";
// -------------------------------------------------------------------------------------------------------------
@@ -66,13 +64,16 @@ export const format = (request: FormatRequest): string => {
fieldType = `long${field.emptyRate !== 0 ? "?" : ""}`;
break;
case ValueType.INT_LIST:
- fieldType = 'List'
+ fieldType = 'List';
break;
case ValueType.STRING_LIST:
- fieldType = 'List'
+ fieldType = 'List';
break;
case ValueType.ONE_BIT:
- fieldType = `int${field.emptyRate !== 0 ? "?" : ""}`
+ fieldType = `int${field.emptyRate !== 0 ? "?" : ""}`;
+ break;
+ case ValueType.DATE_TIME:
+ fieldType = `DateTime${field.emptyRate !== 0 ? "?" : ""}`
break;
// Add more cases as necessary
}
@@ -110,20 +111,16 @@ export const format = (request: FormatRequest): string => {
// Populate collection with values
values.forEach((value, index) => {
+ let fieldAssignments = sortedFieldIds.map(id => {
+ return ` ${fields[id].fieldName} = ${formatValueForCSharp(value[id], fields[id].valueType)}`;
+ }).join(',\n'); // Ensure each field assignment is on a new line
+
if (config.collectionType === CSharpCollectionType.ARRAY) {
// Array value assignment
- csharpCode += `${config.collectionName}[${index}] = new ${itemType} { `;
+ csharpCode += `${config.collectionName}[${index}] = new ${itemType} {\n${fieldAssignments}\n };\n`;
} else {
// Other collections value addition
- csharpCode += `${config.collectionName}.Add(new ${itemType} { `;
- }
-
- csharpCode += sortedFieldIds.map(id => `${fields[id].fieldName} = ${formatValueForCSharp(value[id], fields[id].valueType)}`).join(', ');
-
- if (config.collectionType === CSharpCollectionType.ARRAY) {
- csharpCode += ' };\n';
- } else {
- csharpCode += ' });\n';
+ csharpCode += `${config.collectionName}.Add(new ${itemType}\n{\n${fieldAssignments}\n});\n`;
}
});
@@ -156,6 +153,7 @@ export const CSharpConfigComponent: React.FC
/>
}
value={config.collectionName}
onChange={(v) => handleValueChange("collectionName", v)}
@@ -170,6 +168,7 @@ export const CSharpConfigComponent: React.FC
{
config.dtoClass && }
value={config.dtoClassName}
onChange={(v) => handleValueChange("dtoClassName", v)}
diff --git a/src/core/formatters/CSharp/CSharpFormatterUtils.ts b/src/core/formatters/CSharp/CSharpFormatterUtils.ts
index f3cfed2..8eea719 100644
--- a/src/core/formatters/CSharp/CSharpFormatterUtils.ts
+++ b/src/core/formatters/CSharp/CSharpFormatterUtils.ts
@@ -26,7 +26,20 @@ export function formatValueForCSharp(generateResult: GenerateResult, valueType:
return `new List { ${value.join(", ")} }`
case ValueType.STRING_LIST:
return `new List { ${value.map(item => `"${item}"`).join(', ')})} }`
+ case ValueType.DATE_TIME:
+ return `DateTime.Parse("${toCSharpDateTimeFormat(value)}")`
default:
return 'null'; // Or some other default case
}
+}
+
+export function toCSharpDateTimeFormat(date: Date): string {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是从0开始的
+ const day = String(date.getDate()).padStart(2, '0');
+
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}`;
}
\ No newline at end of file
diff --git a/src/core/formatters/JavaScript/Javascript.tsx b/src/core/formatters/JavaScript/Javascript.tsx
index 3957712..f7b3087 100644
--- a/src/core/formatters/JavaScript/Javascript.tsx
+++ b/src/core/formatters/JavaScript/Javascript.tsx
@@ -3,6 +3,7 @@ import {FormatRequest, FormatterConfigComponentInterface} from "@/types/formatte
import {FormattedMessage, useIntl} from "@/locale";
import {OptionsInput, OptionsSelect, SelectOption} from "@/components/Utils";
import {isNullOrWhiteSpace} from "@/utils/stringUtils";
+import {toJsonListStringWithoutQuotes} from "@/utils/formatterUtils";
// -------------------------------------------------------------------------------------------------------------
// types
@@ -38,30 +39,12 @@ export const format = (request: FormatRequest): string => {
return '';
}
- const jsonData = values.map(item => {
- const row: Record = {};
- for (const column of sortedFieldIds) {
- const field = fields[column];
- const {isDraft, fieldName} = field;
- const itemValue = item[column];
- let {value} = itemValue;
-
- if (!isDraft && value !== null) {
- if (typeof value === 'bigint') {
- value = value.toString();
- }
- row[fieldName] = value;
- }
- }
- return row;
- });
-
- let output = JSON.stringify(jsonData, null, 3);
+ let output = toJsonListStringWithoutQuotes(fields, sortedFieldIds, values);
return formatOutput(formatType, module, declarationKeyword, variableName, output);
};
-function formatOutput(formatType, module, declarationKeyword, variableName, output) {
+function formatOutput(formatType: JavascriptFormatterFormat, module: JavascriptModuleType, declarationKeyword: JavascriptDeclarationKeyword, variableName: string, output: string) {
switch (formatType) {
case JavascriptFormatterFormat.VARIABLE:
return formatVariableOutput(declarationKeyword, variableName, output);
@@ -72,14 +55,14 @@ function formatOutput(formatType, module, declarationKeyword, variableName, outp
}
}
-function formatVariableOutput(declarationKeyword, variableName, output) {
+function formatVariableOutput(declarationKeyword: JavascriptDeclarationKeyword, variableName: string, output: string) {
if (isNullOrWhiteSpace(variableName)) {
return '';
}
return `${declarationKeyword} ${variableName} = ${output};`;
}
-function formatExportOutput(module, output) {
+function formatExportOutput(module: JavascriptModuleType, output: string) {
switch (module) {
case JavascriptModuleType.ES6:
return `export default ${output};`;
diff --git a/src/core/formatters/Sql/Sql.tsx b/src/core/formatters/Sql/Sql.tsx
index d5fdd17..86d10df 100644
--- a/src/core/formatters/Sql/Sql.tsx
+++ b/src/core/formatters/Sql/Sql.tsx
@@ -1,8 +1,7 @@
import React from "react";
import {FormatRequest, FormatterConfigComponentInterface} from "@/types/formatter";
import {OptionsInput, OptionsNumberInput, OptionsSelect, SelectOption} from "@/components/Utils";
-import {FormattedMessage, useIntl} from "@/locale";
-import {isNullOrWhiteSpace} from "@/utils/stringUtils";
+import {FormattedMessage} from "@/locale";
import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
import {Divider} from "@douyinfe/semi-ui";
import {DataField} from "@/types/generator";
@@ -62,14 +61,16 @@ const addCreateTableColumn = (field: DataField, sqlType: SqlType) => {
fieldType = (sqlType === SqlType.ORACLE || sqlType === SqlType.IBMDB2) ? "CLOB" : "TEXT";
break;
case ValueType.ONE_BIT:
- fieldType = "TINYINT(1)";
- break;
case ValueType.BOOLEAN:
fieldType = "TINYINT(1)";
break;
case ValueType.BIGINT:
fieldType = "BIGINT";
break;
+ case ValueType.DATE_TIME: // Add this line
+ // Define default DATETIME format, then override per SQL type if necessary
+ fieldType = "DATETIME";
+ break;
default:
fieldType = "VARCHAR(255)";
break;
@@ -78,23 +79,29 @@ const addCreateTableColumn = (field: DataField, sqlType: SqlType) => {
// Apply SQL type-specific modifications
switch (sqlType) {
case SqlType.ORACLE:
- // Oracle-specific adaptations, e.g., use NUMBER instead of INT
+ // Oracle-specific adaptations
if (fieldType === "INT") {
fieldType = "NUMBER";
} else if (fieldType === "TINYINT(1)") {
fieldType = "NUMBER(1)";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TIMESTAMP"; // Or DATE, depending on your needs
}
break;
case SqlType.POSTGRES:
- // Postgres-specific adaptations, e.g., use BOOLEAN instead of TINYINT(1)
+ // Postgres-specific adaptations
if (fieldType === "TINYINT(1)") {
fieldType = "BOOLEAN";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TIMESTAMP"; // Or TIMESTAMP WITHOUT TIME ZONE, depending on your needs
}
break;
case SqlType.SQLITE:
- // SQLite uses a more dynamic type system
+ // SQLite adaptations
if (fieldType === "TINYINT(1)") {
fieldType = "INTEGER";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TEXT"; // SQLite uses TEXT for date and time types
}
break;
// Add cases for other SQL types as necessary
@@ -117,7 +124,29 @@ const formatValueForSQL = (value: any, sqlType: SqlType, valueType: ValueType):
case ValueType.INT_LIST:
return `'${value.join(", ")}'`
case ValueType.STRING_LIST:
- return `'${value.map(item => `"${item}"`).join(', ')}'`
+ return `'${value.map((item: string): string => `"${item}"`).join(', ')}'`
+ case ValueType.DATE_TIME:
+ let formattedDate: string;
+ // Assuming value is a JavaScript Date object for simplicity
+ const date = (value instanceof Date) ? value : new Date(value);
+
+ switch (sqlType) {
+ case SqlType.ORACLE:
+ // Oracle format: 'YYYY-MM-DD HH24:MI:SS'
+ formattedDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`;
+ break;
+ case SqlType.POSTGRES:
+ // PostgreSQL format: 'YYYY-MM-DD HH:MM:SS'
+ formattedDate = date.toISOString().slice(0, 19).replace('T', ' ');
+ break;
+ // Add additional cases for different SQL types as needed
+ default:
+ // Default to ISO format 'YYYY-MM-DD HH:MM:SS'
+ formattedDate = date.toISOString().slice(0, 19).replace('T', ' ');
+ break;
+ }
+
+ return `'${formattedDate}'`;
default:
return value;
}
@@ -149,8 +178,6 @@ const generateInsertStatements = (sqlType: SqlType, tableName: string, sortedFie
// Modify the format function to adapt to different SQL dialects
export const format = (request: FormatRequest): string => {
- console.log(request)
-
const {fields, values, config, sortedFieldIds} = request;
const {type, tableName, batchSize, dropTable, createTable, primaryKey, primaryKeyColumnName} = config;
@@ -201,24 +228,12 @@ export const format = (request: FormatRequest): string => {
export const SqlConfigComponent: React.FC = ({...props}) => {
const {config, onConfigChange} = props;
- const intl = useIntl();
// action
const handleValueChange = (field: string, value: any) => {
onConfigChange({...config, [field]: value})
}
- const [errorMessages, setErrorMessages] = React.useState({tableName: ''});
- React.useEffect(() => {
- const newErrorMessages = {...errorMessages};
- if (isNullOrWhiteSpace(config.tableName)) {
- newErrorMessages.tableName = intl.formatMessage({id: 'export.configurator.sql.tableName.required'});
- } else {
- newErrorMessages.tableName = '';
- }
- setErrorMessages(newErrorMessages);
- }, [config.tableName]);
-
return (
= (
handleValueChange('tableName', value)
}}
style={{width: '150px'}}
- errorMessage={errorMessages.tableName}
+ required
/>
= (
handleValueChange('primaryKeyColumnName', value)
}}
style={{width: '80px'}}
- errorMessage={errorMessages.tableName}
+ required
/>}
}
diff --git a/src/core/formatters/Typescript/Typescript.tsx b/src/core/formatters/Typescript/Typescript.tsx
new file mode 100644
index 0000000..7a645d1
--- /dev/null
+++ b/src/core/formatters/Typescript/Typescript.tsx
@@ -0,0 +1,136 @@
+import React from "react";
+import {FormatRequest, FormatterConfigComponentInterface} from "@/types/formatter";
+import {OptionsInput} from "@/components/Utils";
+import {OptionsRadio, RadioOption} from "@/components/Utils/src/OptionsRadio";
+import {FormattedMessage} from "@/locale";
+import {toJsonListStringWithoutQuotes} from "@/utils/formatterUtils";
+import {ValueType} from "@/constants/enums";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+
+export enum TypescriptDeclaration {
+ INTERFACE = "interface",
+ TYPE = "type"
+}
+
+export type TypescriptFormatterConfig = {
+ declaration: TypescriptDeclaration,
+ declarationName: string,
+ variableName: string
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+
+export const defaultTypescriptFormatterConfig: TypescriptFormatterConfig = {
+ declaration: TypescriptDeclaration.TYPE,
+ declarationName: "MyRecord",
+ variableName: "myData"
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// format method
+
+export const format = (request: FormatRequest): string => {
+ const {fields, values, sortedFieldIds, config} = request;
+ const {declaration, declarationName, variableName} = config as TypescriptFormatterConfig;
+
+ if (sortedFieldIds.length === 0 || values.length === 0) {
+ return '';
+ }
+
+ let output = '';
+
+ // type & interface
+ output += `export ${declaration} ${declarationName}${declaration === TypescriptDeclaration.TYPE ? " = " : ""} {\n`;
+ sortedFieldIds.forEach(id => {
+ const field = fields[id];
+ let fieldType = 'string'; // Default field type
+ switch (field.valueType) {
+ case ValueType.BIGINT:
+ case ValueType.DOUBLE:
+ case ValueType.ONE_BIT:
+ case ValueType.INT:
+ fieldType = `number`;
+ break;
+ case ValueType.BOOLEAN:
+ fieldType = 'boolean';
+ break;
+ case ValueType.INT_LIST:
+ fieldType = 'number[]'
+ break;
+ case ValueType.STRING_LIST:
+ fieldType = 'string[]'
+ break;
+ case ValueType.DATE_TIME:
+ fieldType = "Date"
+ break;
+ }
+ output += ` ${field.fieldName}${field.emptyRate !== 0 ? "?" : ""}: ${fieldType};\n`;
+ });
+ output += "}; \n\n"
+
+ // values
+ output += `export const ${variableName}: ${declarationName}[] = ${toJsonListStringWithoutQuotes(fields, sortedFieldIds, values)};`;
+
+ return output;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// config component
+
+export const TypescriptConfigComponent: React.FC = ({...props}) => {
+ const {config, onConfigChange} = props as {
+ config: TypescriptFormatterConfig
+ onConfigChange: typeof props.onConfigChange
+ }
+
+ // action
+ const handleValueChange = (field: string, value: any) => {
+ onConfigChange({...config, [field]: value})
+ }
+
+ // TODO: implement your own configs component here
+ return (
+
+ }
+ radioOptions={typescriptDeclarationTypeRadioOptions}
+ type={"button"}
+ value={config.declaration}
+ onChange={(v) => handleValueChange("declaration", v)}
+ style={{"width": "160px"}}
+ />
+
+ }
+ value={config.declarationName}
+ onChange={(v) => handleValueChange("declarationName", v)}
+ style={{"width": "155px"}}
+ />
+
+ }
+ value={config.variableName}
+ onChange={(v) => handleValueChange("variableName", v)}
+ style={{"width": "160px"}}
+ />
+
+
+ );
+}
+
+const typescriptDeclarationTypeRadioOptions: RadioOption[] = [
+ {
+ label: "type",
+ value: TypescriptDeclaration.TYPE
+ },
+ {
+ label: "interface",
+ value: TypescriptDeclaration.INTERFACE
+ }
+]
\ No newline at end of file
diff --git a/src/core/formatters/Typescript/index.ts b/src/core/formatters/Typescript/index.ts
new file mode 100644
index 0000000..54414d3
--- /dev/null
+++ b/src/core/formatters/Typescript/index.ts
@@ -0,0 +1,13 @@
+import {Formatter} from "@/types/formatter";
+import {ExportFormat, ExportFormatCategory} from "@/constants/enums";
+import {TypescriptConfigComponent, format, defaultTypescriptFormatterConfig} from "./Typescript";
+
+
+export const TypescriptFormatter: Formatter = {
+ type: ExportFormat.TYPESCRIPT,
+ category: ExportFormatCategory.PROGRAMMING_LANGUAGES,
+ format: format,
+ fileExtension: 'ts',
+ configComponent: TypescriptConfigComponent,
+ defaultConfig: defaultTypescriptFormatterConfig,
+}
\ No newline at end of file
diff --git a/src/core/formatters/index.ts b/src/core/formatters/index.ts
index 977032e..6833b12 100644
--- a/src/core/formatters/index.ts
+++ b/src/core/formatters/index.ts
@@ -1,3 +1,4 @@
+import {TypescriptFormatter} from "@/core/formatters/Typescript";
import {CSharpFormatter} from "@/core/formatters/CSharp";
import {SqlFormatter} from "@/core/formatters/Sql";
import {CsvFormatter} from "@/core/formatters/Csv";
@@ -8,6 +9,7 @@ import {XmlFormatter} from "@/core/formatters/Xml";
export const formatters = {
+ [ExportFormat.TYPESCRIPT]: TypescriptFormatter,
[ExportFormat.CSHARP]: CSharpFormatter,
[ExportFormat.SQL]: SqlFormatter,
[ExportFormat.CSV]: CsvFormatter,
diff --git a/src/core/generators/Birthday/Birthday.tsx b/src/core/generators/Birthday/Birthday.tsx
new file mode 100644
index 0000000..d7912d1
--- /dev/null
+++ b/src/core/generators/Birthday/Birthday.tsx
@@ -0,0 +1,143 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {DateTimeFormat, DateTimeFormatSelectOptions, formatDateTime} from "@/core/generators/DateTime/DateTime";
+import {OptionsNumberInput, OptionsSelect, SelectOption} from "@/components/Utils";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+import {ValueType} from "@/constants/enums";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+
+export enum BirthdayGeneratorMode {
+ AGE = "age",
+ YEAR = "year"
+}
+
+export interface BirthdayGeneratorOptions {
+ format: DateTimeFormat;
+ mode: BirthdayGeneratorMode;
+ minAge: number;
+ maxAge: number;
+ fromYear: number;
+ toYear: number;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const BirthdayGeneratorDefaultOptions: BirthdayGeneratorOptions = {
+ format: DateTimeFormat.DATETIME,
+ mode: BirthdayGeneratorMode.AGE,
+ minAge: 1,
+ maxAge: 80,
+ fromYear: 1960,
+ toYear: 2000,
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: BirthdayGeneratorOptions): GenerateResult => {
+
+ const value = faker.date.birthdate({
+ mode: options.mode,
+ min: options.mode === BirthdayGeneratorMode.AGE ? options.minAge : options.fromYear,
+ max: options.mode === BirthdayGeneratorMode.AGE ? options.maxAge : options.toYear,
+ refDate: Date.now()
+ })
+ const output = formatDateTime(value, options.format);
+
+ return {
+ value: output,
+ stringValue: (output instanceof Date) ? output.toISOString() : output.toString()
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const BirthdayGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: BirthdayGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ const handleChangeFormat = (format: DateTimeFormat) => {
+ if (format === DateTimeFormat.TIMESTAMP) {
+ handleOptionValueChange("format", format, ValueType.INT);
+ } else if (format === DateTimeFormat.TEXT) {
+ handleOptionValueChange("format", format, ValueType.STRING);
+ } else if (format === DateTimeFormat.DATETIME) {
+ handleOptionValueChange("format", format, ValueType.DATE_TIME);
+ }
+ }
+
+ return (
+ <>
+ }
+ selectOptions={BirthdayGeneratorModeSelectOptions}
+ value={options.mode}
+ onChange={(v) => handleOptionValueChange("mode", v)}
+ />
+
+ {options.mode === BirthdayGeneratorMode.AGE && <>
+ }
+ value={options.minAge}
+ onChange={(v) => handleOptionValueChange("minAge", v)}
+ style={{width: "70px"}}
+ min={0}
+ max={options.maxAge}
+ />
+
+ }
+ value={options.maxAge}
+ onChange={(v) => handleOptionValueChange("maxAge", v)}
+ style={{width: "70px"}}
+ min={options.minAge}
+ max={150}
+ />
+ >}
+
+
+ {options.mode === BirthdayGeneratorMode.YEAR && <>
+ }
+ value={options.fromYear}
+ onChange={(v) => handleOptionValueChange("fromYear", v)}
+ style={{width: "90px"}}
+ min={1000}
+ max={options.toYear}
+ />
+
+ }
+ value={options.toYear}
+ onChange={(v) => handleOptionValueChange("toYear", v)}
+ style={{width: "100px"}}
+ min={options.toYear}
+ max={2500}
+ />
+ >}
+
+ }
+ selectOptions={DateTimeFormatSelectOptions}
+ value={options.format}
+ onChange={handleChangeFormat}
+ style={{width: "200px"}}
+ />
+
+ >
+ );
+}
+
+const BirthdayGeneratorModeSelectOptions: SelectOption[] = [
+ {
+ label: ,
+ value: BirthdayGeneratorMode.AGE
+ }, {
+ label: ,
+ value: BirthdayGeneratorMode.YEAR
+ }
+]
\ No newline at end of file
diff --git a/src/core/generators/Birthday/index.ts b/src/core/generators/Birthday/index.ts
new file mode 100644
index 0000000..f915ab9
--- /dev/null
+++ b/src/core/generators/Birthday/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {BirthdayGeneratorDefaultOptions, BirthdayGeneratorOptionsComponent, generate} from "./Birthday";
+
+export const BirthdayGenerator: Generator = {
+ type: DataType.BIRTHDAY,
+ category: DataTypeCategory.PERSON,
+ generate: generate,
+ optionsComponent: BirthdayGeneratorOptionsComponent,
+ defaultOptions: BirthdayGeneratorDefaultOptions,
+ defaultValueType: ValueType.DATE_TIME,
+ exampleLines: ["1949-08-11T20:00:14.636Z", "-640186506999", "18-02-1968 20:14:50"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/DateTime/DateTime.tsx b/src/core/generators/DateTime/DateTime.tsx
new file mode 100644
index 0000000..ed66fe4
--- /dev/null
+++ b/src/core/generators/DateTime/DateTime.tsx
@@ -0,0 +1,189 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSelect, SelectOption} from "@/components/Utils";
+import {FormattedMessage} from "@/locale";
+import {OptionsDatetimePicker} from "@/components/Utils/src/OptionsDatetimePicker";
+import {faker} from "@faker-js/faker";
+import {ValueType} from "@/constants/enums";
+import style from "@/core/generators/Boolean/Boolean.module.scss";
+import {Tag} from "@douyinfe/semi-ui";
+import {toDateTimeString} from "@/utils/typeUtils";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export enum DateTimeTerms {
+ ANYTIME = "anytime",
+ BETWEEN = "between",
+ FUTURE = "future",
+ PAST = "past",
+ RECENT = "recent",
+ SOON = "soon"
+}
+
+export enum DateTimeFormat {
+ TEXT = "text",
+ TIMESTAMP = "timestamp",
+ DATETIME = "datetime"
+}
+
+export interface DateTimeGeneratorOptions {
+ terms: DateTimeTerms;
+ ref: Date | number | string;
+ format: DateTimeFormat;
+ timeRange: Date[] | number[] | string[];
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const DateTimeGeneratorDefaultOptions: DateTimeGeneratorOptions = {
+ terms: DateTimeTerms.ANYTIME,
+ ref: Date.now(),
+ format: DateTimeFormat.DATETIME,
+ timeRange: [new Date(2023, 0, 1), new Date()]
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: DateTimeGeneratorOptions): GenerateResult => {
+ const {terms, ref, format} = options;
+
+ let value: Date;
+ const fakerOptions = {refDate: ref}
+
+ switch (terms) {
+ case DateTimeTerms.FUTURE:
+ value = faker.date.future(fakerOptions);
+ break;
+ case DateTimeTerms.PAST:
+ value = faker.date.past(fakerOptions);
+ break;
+ case DateTimeTerms.RECENT:
+ value = faker.date.recent(fakerOptions);
+ break;
+ case DateTimeTerms.SOON:
+ value = faker.date.soon(fakerOptions);
+ break;
+ case DateTimeTerms.BETWEEN:
+ value = faker.date.between({from: options.timeRange[0], to: options.timeRange[1]});
+ break;
+ default:
+ value = faker.date.anytime(fakerOptions);
+ }
+
+ const output = formatDateTime(value, format);
+
+ return {
+ value: output,
+ stringValue: (output instanceof Date) ? output.toISOString() : output.toString()
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const DateTimeGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+
+ const {options, handleOptionValueChange} = props as {
+ options: DateTimeGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ const handleChangeFormat = (format: DateTimeFormat) => {
+ if (format === DateTimeFormat.TIMESTAMP) {
+ handleOptionValueChange("format", format, ValueType.INT);
+ } else if (format === DateTimeFormat.TEXT) {
+ handleOptionValueChange("format", format, ValueType.STRING);
+ } else if (format === DateTimeFormat.DATETIME) {
+ handleOptionValueChange("format", format, ValueType.DATE_TIME);
+ }
+ }
+
+ return (
+ <>
+ }
+ selectOptions={DateTimeTermsSelectOptions}
+ value={options.terms}
+ onChange={(v) => handleOptionValueChange("terms", v)}
+ style={{width: "130px"}}
+ />
+
+ {
+ options.terms === DateTimeTerms.BETWEEN ? }
+ type={'dateTimeRange'}
+ value={options.timeRange}
+ onChange={(v) => handleOptionValueChange("timeRange", v)}
+ style={{width: "260px"}}
+ required
+ />
+ :
+ }
+ infoTooltip={}
+ type={'dateTime'}
+ value={options.ref}
+ onChange={(v) => handleOptionValueChange("ref", v)}
+ style={{width: "185px"}}
+ required
+ />
+ }
+
+ }
+ selectOptions={DateTimeFormatSelectOptions}
+ value={options.format}
+ onChange={handleChangeFormat}
+ style={{width: "200px"}}
+ />
+ >
+ );
+}
+
+export const formatDateTime = (date: Date, format: DateTimeFormat) => {
+ switch (format) {
+ case DateTimeFormat.DATETIME:
+ return date;
+ case DateTimeFormat.TIMESTAMP:
+ return date.getTime();
+ case DateTimeFormat.TEXT:
+ return toDateTimeString(date);
+ }
+}
+
+export const DateTimeTermsSelectOptions: SelectOption[] = Object.values(DateTimeTerms).map((term) => {
+ return {
+ value: term,
+ label:
+ };
+})
+
+export const DateTimeFormatSelectOptions: SelectOption[] = [
+ {
+ value: DateTimeFormat.DATETIME,
+ label:
+ <>
+ Date
+
+ >
+ },
+ {
+ value: DateTimeFormat.TIMESTAMP,
+ label:
+ <>
+ number
+
+ >
+ },
+ {
+ value: DateTimeFormat.TEXT,
+ label:
+ <>
+ string
+
+ >
+ },
+
+]
\ No newline at end of file
diff --git a/src/core/generators/DateTime/index.ts b/src/core/generators/DateTime/index.ts
new file mode 100644
index 0000000..1251e07
--- /dev/null
+++ b/src/core/generators/DateTime/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {DateTimeGeneratorDefaultOptions, DateTimeGeneratorOptionsComponent, generate} from "./DateTime";
+
+export const DateTimeGenerator: Generator = {
+ type: DataType.DATETIME,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: DateTimeGeneratorOptionsComponent,
+ defaultOptions: DateTimeGeneratorDefaultOptions,
+ defaultValueType: ValueType.DATE_TIME,
+ exampleLines: ["1725842513046", "29-01-2025 20:15:40", "13-06-2023 08:16:09"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/Month/Month.tsx b/src/core/generators/Month/Month.tsx
new file mode 100644
index 0000000..314b1b1
--- /dev/null
+++ b/src/core/generators/Month/Month.tsx
@@ -0,0 +1,49 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export interface MonthGeneratorOptions {
+ abbreviated: boolean;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const MonthGeneratorDefaultOptions: MonthGeneratorOptions = {
+ abbreviated: false
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: MonthGeneratorOptions): GenerateResult => {
+ const {abbreviated} = options;
+ const value = faker.date.month({abbreviated:abbreviated})
+ return {
+ value: value,
+ stringValue: value
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const MonthGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: MonthGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ // TODO: implement your own options component here
+ return (
+ <>
+ }
+ value={options.abbreviated}
+ onChange={(v) => handleOptionValueChange("abbreviated", v)}
+ />
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/core/generators/Month/index.ts b/src/core/generators/Month/index.ts
new file mode 100644
index 0000000..825940f
--- /dev/null
+++ b/src/core/generators/Month/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {MonthGeneratorDefaultOptions, MonthGeneratorOptionsComponent, generate} from "./Month";
+
+export const MonthGenerator: Generator = {
+ type: DataType.MONTH,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: MonthGeneratorOptionsComponent,
+ defaultOptions: MonthGeneratorDefaultOptions,
+ defaultValueType: ValueType.STRING,
+ exampleLines: ["September", "Feb", "December"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/Number/Number.tsx b/src/core/generators/Number/Number.tsx
index 29a6119..f975519 100644
--- a/src/core/generators/Number/Number.tsx
+++ b/src/core/generators/Number/Number.tsx
@@ -95,18 +95,14 @@ export const NumberGeneratorOptionsComponent: React.FunctionComponent {
const newErrorMessages = {...errorMessages};
// min
- if (isNullOrWhiteSpace(options.min.toString())) {
- newErrorMessages.min = intl.formatMessage({id: 'dataType.number.min.errorMessage.empty'})
- } else if (options.min > options.max) {
+ if (options.min > options.max) {
newErrorMessages.min = intl.formatMessage({id: 'dataType.number.min.errorMessage.greaterThanMax'})
} else {
newErrorMessages.min = '';
}
// max
- if (isNullOrWhiteSpace(options.max.toString())) {
- newErrorMessages.max = intl.formatMessage({id: 'dataType.number.max.errorMessage.empty'})
- } else if (options.max < options.min) {
+ if (options.max < options.min) {
newErrorMessages.max = intl.formatMessage({id: 'dataType.number.max.errorMessage.lessThanMin'})
} else {
newErrorMessages.max = '';
diff --git a/src/core/generators/Url/Url.tsx b/src/core/generators/Url/Url.tsx
index a8e88bc..d5aa7f8 100644
--- a/src/core/generators/Url/Url.tsx
+++ b/src/core/generators/Url/Url.tsx
@@ -10,20 +10,22 @@ import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
// -------------------------------------------------------------------------------------------------------------
// types
type HTTPProtocolType = 'http' | 'https';
-export enum ProtocolGeneratorFormat{
+
+export enum ProtocolGeneratorFormat {
HTTP_PROTOCOL = 'http',
HTTPS_PROTOCOL = 'https'
}
+
export interface UrlGeneratorOptions {
- appendSlash: boolean;
- protocol:HTTPProtocolType;
+ appendSlash: boolean;
+ protocol: HTTPProtocolType;
}
// -------------------------------------------------------------------------------------------------------------
// default options
-export const UrlGeneratorDefaultOptions:UrlGeneratorOptions = {
- appendSlash:false,
- protocol:ProtocolGeneratorFormat.HTTPS_PROTOCOL
+export const UrlGeneratorDefaultOptions: UrlGeneratorOptions = {
+ appendSlash: false,
+ protocol: ProtocolGeneratorFormat.HTTPS_PROTOCOL
}
@@ -31,7 +33,7 @@ export const UrlGeneratorDefaultOptions:UrlGeneratorOptions = {
// generate method
export const generate = (options: any): GenerateResult => {
// TODO: implement your own generate method here
- const { appendSlash, protocol } = options;
+ const {appendSlash, protocol} = options;
const domain = faker.internet.domainName();
// Construct URL
let value = `${protocol}://${domain}`;
@@ -43,7 +45,7 @@ export const generate = (options: any): GenerateResult => {
value: value,
stringValue: value,
}
-
+
}
// -------------------------------------------------------------------------------------------------------------
@@ -56,15 +58,12 @@ export const UrlGeneratorOptionsComponent: React.FunctionComponent {
handleOptionValueChange("protocol", format);
}
-
-
+
return (
<>
-
-
}
+ label={}
value={options.appendSlash}
onChange={(v) => {
handleOptionValueChange('appendSlash', v);
@@ -72,25 +71,24 @@ export const UrlGeneratorOptionsComponent: React.FunctionComponent
-
}
+ label={}
selectOptions={protocolOptions}
value={options.protocol}
onChange={handleFormatChange} // This directly passes the selected value to handleFormatChange
- style={{ width: '210px' }}
-/>
+ style={{width: '110px'}}
+ />
>
);
}
const protocolOptions: SelectOption[] = [
{
- value:ProtocolGeneratorFormat.HTTPS_PROTOCOL,
+ value: ProtocolGeneratorFormat.HTTPS_PROTOCOL,
label: <>https>
},
{
- value:ProtocolGeneratorFormat.HTTP_PROTOCOL,
+ value: ProtocolGeneratorFormat.HTTP_PROTOCOL,
label: <>http>
}
]
\ No newline at end of file
diff --git a/src/core/generators/Weekday/Weekday.tsx b/src/core/generators/Weekday/Weekday.tsx
new file mode 100644
index 0000000..a9ed699
--- /dev/null
+++ b/src/core/generators/Weekday/Weekday.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export interface WeekdayGeneratorOptions {
+ abbreviated: boolean;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const WeekdayGeneratorDefaultOptions: WeekdayGeneratorOptions = {
+ abbreviated: false
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: WeekdayGeneratorOptions): GenerateResult => {
+ const {abbreviated} = options;
+ const value = faker.date.weekday({abbreviated: abbreviated})
+ return {
+ value: value,
+ stringValue: value
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const WeekdayGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: WeekdayGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ return (
+ <>
+ }
+ value={options.abbreviated}
+ onChange={(v) => handleOptionValueChange("abbreviated", v)}
+ />
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/core/generators/Weekday/index.ts b/src/core/generators/Weekday/index.ts
new file mode 100644
index 0000000..8fe15f1
--- /dev/null
+++ b/src/core/generators/Weekday/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {WeekdayGeneratorDefaultOptions, WeekdayGeneratorOptionsComponent, generate} from "./Weekday";
+
+export const WeekdayGenerator: Generator = {
+ type: DataType.WEEKDAY,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: WeekdayGeneratorOptionsComponent,
+ defaultOptions: WeekdayGeneratorDefaultOptions,
+ defaultValueType: ValueType.STRING,
+ exampleLines: ["Wednesday", "Wed", "Thursday"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/index.ts b/src/core/generators/index.ts
index 6ad7052..b490ee4 100644
--- a/src/core/generators/index.ts
+++ b/src/core/generators/index.ts
@@ -1,4 +1,8 @@
import {IpAddressGenerator} from "@/core/generators/IpAddress";
+import {BirthdayGenerator} from "@/core/generators/Birthday";
+import {MonthGenerator} from "@/core/generators/Month";
+import {WeekdayGenerator} from "@/core/generators/Weekday";
+import {DateTimeGenerator} from "@/core/generators/DateTime";
import {UrlGenerator} from "@/core/generators/Url";
import {DomainSuffixGenerator} from "@/core/generators/DomainSuffix";
import {DomainNameGenerator} from "@/core/generators/DomainName";
@@ -21,6 +25,10 @@ import {DataType} from "@/constants/enums";
export const generators = {
[DataType.IPADDRESS]: IpAddressGenerator,
+ [DataType.BIRTHDAY]: BirthdayGenerator,
+ [DataType.MONTH]: MonthGenerator,
+ [DataType.WEEKDAY]: WeekdayGenerator,
+ [DataType.DATETIME]: DateTimeGenerator,
[DataType.URL]: UrlGenerator,
[DataType.DOMAINSUFFIX]: DomainSuffixGenerator,
[DataType.DOMAINNAME]: DomainNameGenerator,
diff --git a/src/locale/index.tsx b/src/locale/index.tsx
index 0e53a80..06e9400 100644
--- a/src/locale/index.tsx
+++ b/src/locale/index.tsx
@@ -58,6 +58,7 @@ export type FormattedMessageProps = ReactIntlFormattedMessageProps;
}
\ No newline at end of file
diff --git a/src/locale/translations/en.ts b/src/locale/translations/en.ts
index b3bb870..e50a227 100644
--- a/src/locale/translations/en.ts
+++ b/src/locale/translations/en.ts
@@ -4,9 +4,9 @@ export const en = {
// export
// export category
- "export.category.fileTypes": "General file types",
- "export.category.databases" : "Databases",
- "export.category.programmingLanguages": "Programming languages",
+ "export.category.file_types": "General file types",
+ "export.category.databases": "Databases",
+ "export.category.programming_languages": "Programming languages",
// export format modal
"export.configurator.modal.title": "Format",
@@ -35,7 +35,7 @@ export const en = {
// csv
"export.configurator.csv.delimiter": "Delimiter",
- "export.configurator.csv.delimiter.required" : "Delimiter cannot be empty",
+ "export.configurator.csv.delimiter.required": "Delimiter cannot be empty",
"export.configurator.csv.includeHeader": "Include header",
"export.configurator.csv.endLineChar": "End of line characters",
@@ -76,25 +76,68 @@ export const en = {
"export.configurator.csharp.dtoClass": "Create DTO class",
"export.configurator.csharp.dtoClassName": "Class name",
+ // typescript
+ "export.configurator.typescript.declarationType": "Declaration type",
+ "export.configurator.typescript.declarationType.interface.name": "Interface name",
+ "export.configurator.typescript.declarationType.type.name": "Type name",
+ "export.configurator.typescript.variableName": "Variable name",
+
// -------------------------------------------------------------------------------------------------------------
// data types
-
// ipaddress
"dataType.ipaddress": "IP Address",
"dataType.ipaddress.types":"Types",
+ // birthday
+ "dataType.birthday": "Birthday",
+ "dataType.birthday.mode":"Mode",
+ "dataType.birthday.mode.age":"Age",
+ "dataType.birthday.mode.year":"Year",
+ "dataType.birthday.mode.minAge":"Min. Age",
+ "dataType.birthday.mode.maxAge":"Max. Age",
+ "dataType.birthday.mode.fromYear":"From year",
+ "dataType.birthday.mode.toYear":"To year",
+
+ // month
+ "dataType.month": "Month",
+ "dataType.month.abbreviated": "Abbreviated",
+
+ // weekday
+ "dataType.weekday": "Weekday",
+ "dataType.weekday.abbreviated": "Abbreviated",
+
+ // datetime
+ "dataType.datetime": "DateTime",
+ "dataType.datetime.terms": "Terms",
+ "dataType.datetime.terms.anytime": "Anytime",
+ "dataType.datetime.terms.between": "Between",
+ "dataType.datetime.terms.future": "Future",
+ "dataType.datetime.terms.past": "Past",
+ "dataType.datetime.terms.recent": "Recent past",
+ "dataType.datetime.terms.soon": "Soon",
+ "dataType.datetime.ref": "Reference date",
+ "dataType.datetime.ref.tooltip": "The date to use as reference point",
+ "dataType.datetime.format": "Format",
+ "dataType.datetime.format.text": "Text",
+ "dataType.datetime.format.timestamp": "Timestamp",
+ "dataType.datetime.format.datetime": "DateTime",
+ "dataType.datetime.timeRange": "Range",
+
+ // anytime
+ "dataType.anytime": "Anytime",
+
// url
"dataType.url": "Url",
"dataType.url.appendSlash.label": "Slash",
- "dataType.url.protocol.label":"Protocol",
+ "dataType.url.protocol.label": "Protocol",
// domainsuffix
"dataType.domainsuffix": "Domain Suffix",
// domainname
"dataType.domainname": "Domain Name",
-
+
// accountnumber
"dataType.accountnumber": "Account Number",
"dataType.accountnumber.length": "Length",
@@ -107,7 +150,7 @@ export const en = {
"dataType.color": "Color",
"dataType.color.kind.label": "Kind",
"dataType.color.format.label": "Format",
- "dataType.color.format.humanWord":"Human Word",
+ "dataType.color.format.humanWord": "Human Word",
// phone
"dataType.phone": "Phone Number",
@@ -157,9 +200,6 @@ export const en = {
"dataType.number.max.errorMessage.empty": "Max. value cannot be empty",
"dataType.number.max.errorMessage.lessThanMin": "Max. value cannot be less than min. value",
- // dateTime
- "dataType.dateTime": "Date time",
-
// boolean
"dataType.boolean": "Boolean",
"dataType.boolean.true.label": "Prob of True",
@@ -193,6 +233,7 @@ export const en = {
"dataType.category.person": "Person",
"dataType.category.commerce": "Commerce",
"dataType.category.network": "Network",
+ "dataType.category.datetime": "Datetime",
// -------------------------------------------------------------------------------------------------------------
// pages
@@ -242,6 +283,7 @@ export const en = {
"dataFields.type.modal.search.placeholder": "Search data type...",
// error pages
+ "error.input.isRequired": "This field is required",
"error.404.description": "Page does not exist",
"error.404.button.text": "Home page",
"error.general.description": "Oops! An error has occurred!",
diff --git a/src/locale/translations/jaJP.ts b/src/locale/translations/jaJP.ts
index f9f524d..b22809b 100644
--- a/src/locale/translations/jaJP.ts
+++ b/src/locale/translations/jaJP.ts
@@ -1,110 +1,220 @@
-// Translated by ChatGPT
export const jaJP = {
-
// -------------------------------------------------------------------------------------------------------------
// export
// export category
- "export.category.fileTypes": "一般的なファイルタイプ",
- "export.category.databases" : "Databases",
- "export.category.programmingLanguages": "プログラミング言語",
+ "export.category.file_types": "一般的な形式",
+ "export.category.databases": "データベース",
+ "export.category.programming_languages": "プログラミング言語",
// export format modal
- "export.configurator.modal.title": "エクスポート形式",
- "export.configurator.modal.closeButton.text": "閉じる",
+ "export.configurator.modal.title": "形式を生成",
+ "export.configurator.modal.confirmButton.text": "確認",
"export.configurator.config.label": "設定",
- "export.configurator.config.empty": "現在、このエクスポート形式の設定は利用できません。",
+ "export.configurator.config.empty": "この出力形式の設定は現在利用できません",
+
+ // export modal
+ "export.modal.title": "データを一括生成",
+ "export.modal.exportNumOfRows.label": "生成するデータ行数",
+ "export.modal.exportNumOfRows.empty": "データ行数を空にすることはできません",
+ "export.modal.exportFormat.label": "生成形式",
+ "export.modal.estimatedSize.label": "推定サイズ",
+ "export.modal.estimatedTime.label": "推定時間",
+ "export.modal.exportFileName.label": "ファイル名",
+ "export.modal.exportFileName.empty": "ファイル名は空にできません",
+ "export.modal.cancel.button.text": "キャンセル",
+ "export.modal.generate.button.text": "生成",
+ "export.modal.hide.button.text": "隠す",
+ "export.modal.terminate.button.text": "終了",
+ "export.modal.generating.rows.text": "行数",
+ "export.modal.generating.time.text": "時間",
+ "export.modal.generating.done.text": "完了",
+ "export.modal.toast.details.button.text": "詳細",
+ "export.modal.toast.download.button.text": "ダウンロード",
// csv
"export.configurator.csv.delimiter": "区切り文字",
- "export.configurator.csv.includeHeader": "ヘッダーを含める",
- "export.configurator.csv.endLineChar": "行末文字",
+ "export.configurator.csv.delimiter.required": "区切り文字を空にすることはできません",
+ "export.configurator.csv.includeHeader": "ヘッダを含む",
+ "export.configurator.csv.endLineChar": "行終了文字",
+
+ // xml
+ "export.configurator.xml.rootNodeName": "ルートノード",
+ "export.configurator.xml.childNodeName": "子ノード",
+ "export.configurator.xml.encoding": "エンコーディング",
+ "export.configurator.xml.indentSize": "インデントのサイズ",
+
+ // json
+ "export.configurator.json.insideArray": "配列内",
+ "export.configurator.json.includeNullValues": "null値を含む",
+
+ // javascript
+ "export.configurator.javascript.format": "形式",
+ "export.configurator.javascript.format.variable": "変数",
+ "export.configurator.javascript.format.export": "エクスポート",
+ "export.configurator.javascript.varName": "変数名",
+ "export.configurator.javascript.varName.required": "変数名を空にすることはできません",
+ "export.configurator.javascript.declarationKeyword": "宣言タイプ",
+ "export.configurator.javascript.module": "モジュール",
+
+ // sql
+ "export.configurator.sql.type": "データベースのタイプ",
+ "export.configurator.sql.tableName": "テーブル名",
+ "export.configurator.sql.tableName.required": "テーブル名を空にすることはできません",
+ "export.configurator.sql.statement": "SQLステートメント",
+ "export.configurator.sql.batchSize": "バッチサイズ",
+ "export.configurator.sql.includeDropTable": "`DROP TABLE` を含む",
+ "export.configurator.sql.includeCreateTable": "`CREATE TABLE` を含む",
+ "export.configurator.sql.includePrimaryKey": "主キーを含む",
+ "export.configurator.sql.primaryKeyColumnName": "主キーカラム名",
+
+ // c#
+ "export.configurator.csharp.collectionType": "コレクションタイプ",
+ "export.configurator.csharp.collectionName": "コレクションの変数名",
+ "export.configurator.csharp.dtoClass": "DTOクラスを作成",
+ "export.configurator.csharp.dtoClassName": "クラス名",
+
+ // typescript
+
+
+ "export.configurator.typescript.declarationType": "宣言のタイプ",
+ "export.configurator.typescript.declarationType.interface.name": "Interfaceの名前",
+ "export.configurator.typescript.declarationType.type.name": "Typeの名前",
+ "export.configurator.typescript.variableName": "変数名",
// -------------------------------------------------------------------------------------------------------------
// data types
-
-
-
+
// ipaddress
"dataType.ipaddress": "IpAddress",
+ // birthday
+ "dataType.birthday": "Birthday",
+
+ // month
+ "dataType.month": "Month",
+
+ // weekday
+ "dataType.weekday": "Weekday",
+
+ // datetimerange
+ "dataType.datetimerange": "DateTimeRange",
+
+ // datetime
+ "dataType.datetime": "DateTime",
+
+ // anytime
+ "dataType.anytime": "Anytime",
+
// url
- "dataType.url": "Url",
+ "dataType.url": "URL",
+ "dataType.url.appendSlash.label": "スラッシュ",
+ "dataType.url.protocol.label": "プロトコル",
// domainsuffix
- "dataType.domainsuffix": "DomainSuffix",
+ "dataType.domainsuffix": "ドメインサフィックス",
// domainname
- "dataType.domainname": "DomainName",
+ "dataType.domainname": "ドメイン名",
// accountnumber
- "dataType.accountnumber": "AccountNumber",
+ "dataType.accountnumber": "銀行口座番号",
+ "dataType.accountnumber.length": "長さ",
+ "dataType.accountnumber.empty": "長さは空にできません",
// accountname
- "dataType.accountname": "AccountName",
+ "dataType.accountname": "アカウント名",
// color
- "dataType.color": "Color",
+ "dataType.color": "色",
+ "dataType.color.kind.label": "タイプ",
+ "dataType.color.format.humanWord": "言葉での形式",
+ "dataType.color.format.label": "形式",
// phone
- "dataType.phone": "Phone Number",
- "dataType.phone.formats.label": "Formats",
- "dataType.phone.formats.tooltips": "Phone number format, please use \"#\" to represent digits, press Enter key to confirm",
+ "dataType.phone": "電話番号",
+ "dataType.phone.formats.label": "形式",
+ "dataType.phone.formats.tooltips": "電話番号の形式は、「#」を数字の代わりに使用してください。エンターキーで確定",
// emoji
- "dataType.emoji": "Emoji",
- "dataType.emoji.type": "Type",
- "dataType.emoji.type.all": "All",
- "dataType.emoji.type.smiley": "Smiley",
- "dataType.emoji.type.body" : "Body",
- "dataType.emoji.type.person" : "Person",
- "dataType.emoji.type.nature" : "Nature",
- "dataType.emoji.type.food" : "Food",
- "dataType.emoji.type.travel" : "Travel",
- "dataType.emoji.type.activity" : "Activity",
- "dataType.emoji.type.object" : "Object",
- "dataType.emoji.type.symbol" : "Symbol",
- "dataType.emoji.type.flag" : "Flag",
+ "dataType.emoji": "絵文字",
+ "dataType.emoji.type": "タイプ",
+ "dataType.emoji.type.all": "全て",
+ "dataType.emoji.type.smiley": "スマイリー",
+ "dataType.emoji.type.body": "ボディ",
+ "dataType.emoji.type.person": "人",
+ "dataType.emoji.type.nature": "自然",
+ "dataType.emoji.type.food": "食べ物",
+ "dataType.emoji.type.travel": "旅行",
+ "dataType.emoji.type.activity": "アクティビティ",
+ "dataType.emoji.type.object": "オブジェクト",
+ "dataType.emoji.type.symbol": "シンボル",
+ "dataType.emoji.type.flag": "フラグ",
// persontitle
- "dataType.persontitle": "PersonTitle",
+ "dataType.persontitle": "称号",
// middlename
- "dataType.middlename": "MiddleName",
+ "dataType.middlename": "ミドルネーム",
// lastname
- "dataType.lastname": "LastName",
+ "dataType.lastname": "姓",
// firstname
- "dataType.firstname": "FirstName",
+ "dataType.firstname": "名",
// sex
- "dataType.sex": "Sex",
-
- // data type category
- "dataType.category.all": "全て",
- "dataType.category.basic": "基本",
- "dataType.category.person": "個人",
- "dataType.category.commerce": "商業",
+ "dataType.sex": "性別",
// number
- "dataType.number": "数値",
+ "dataType.number": "数字",
"dataType.number.kind.label": "種類",
"dataType.number.precision.label": "精度",
"dataType.number.min.label": "最小値",
+ "dataType.number.min.tooltip": "生成するデータの最小値",
+ "dataType.number.min.errorMessage.empty": "最小値は空にできません",
+ "dataType.number.min.errorMessage.greaterThanMax": "最小値は最大値より大きくできません",
"dataType.number.max.label": "最大値",
+ "dataType.number.max.tooltip": "生成するデータの最大値",
+ "dataType.number.max.errorMessage.empty": "最大値は空にできません",
+ "dataType.number.max.errorMessage.lessThanMin": "最大値は最小値より小さくできません",
// dateTime
"dataType.dateTime": "日時",
// boolean
"dataType.boolean": "ブール値",
+ "dataType.boolean.true.label": "真の確率",
+ "dataType.boolean.true.tooltip": "真(true)を生成する確率",
+ "dataType.boolean.true.errorMessage.empty": "真の確率を空にすることはできません",
+ "dataType.boolean.format.label": "形式",
+
+ // full name
+ "dataType.fullName": "フルネーム",
+ "dataType.fullName.sex.label": "性別",
+ "dataType.fullName.sex.selectOptions.all": "男性、女性",
+ "dataType.fullName.sex.selectOptions.male": "男性",
+ "dataType.fullName.sex.selectOptions.female": "女性",
+ "dataType.fullName.firstName.label": "名",
+ "dataType.fullName.lastName.label": "姓",
- // person name
- "dataType.personName": "氏名",
+ //email
+ "dataType.email": "メールアドレス",
+ "dataType.email.provider.label": "メールプロバイダー",
+ "dataType.email.allowSpecialCharacters.label": "特殊文字を許可",
- // account mi,ner
- "dataType.accountNumber": "口座番号",
+ // company name
+ "dataType.companyName": "会社名",
+
+ // account number
+ "dataType.accountNumber": "アカウント番号",
+
+ // data type category
+ "dataType.category.all": "全て",
+ "dataType.category.basic": "基本",
+ "dataType.category.person": "人物",
+ "dataType.category.commerce": "商業",
+ "dataType.category.network": "ネットワーク",
// -------------------------------------------------------------------------------------------------------------
// pages
@@ -112,45 +222,52 @@ export const jaJP = {
// nav bar
"nav.item.home": "ホーム",
"nav.item.workspace": "ワークスペース",
- "nav.item.about": "について",
+ "nav.item.about": "紹介",
"nav.colorModeSwitchButton.switchToDarkMode.text": "ダークモードに切り替え",
"nav.colorModeSwitchButton.switchToLightMode.text": "ライトモードに切り替え",
"nav.languageSwitchButton.tooltip": "言語",
- "nav.languageSwitchModal.title": "言語の選択",
- "nav.languageSwitchModal.footer.chatGPT.text": "多言語翻訳はChatGPTによって生成されました",
+ "nav.languageSwitchModal.title": "言語を選択",
+ "nav.languageSwitchModal.footer.chatGPT.text": "多言語翻訳はChatGPTによって生成されます",
// workspace
"toolbar.numOfRowInput.suffix": "行",
- "toolbar.generateButton.text": "批量生成",
- "toolbar.panelsOrientationButton.tooltip.switchToColumn": "パネルを列に切り替え",
- "toolbar.panelsOrientationButton.tooltip.switchToRow": "パネルを行に切り替え",
- "toolbar.emptyPageButton.tooltip": "ワークスペースを空にする",
- "toolbar.emptyPageButton.confirmation.title": "ワークスペースを空にする",
- "toolbar.emptyPageButton.confirmation.text": "本当にワークスペースを空にしますか?設定したワークスペースの構成が失われます。",
- "toolbar.exportSchemaButton.tooltip": "スキーマのエクスポート",
- "toolbar.importSchemaButton.tooltip": "スキーマのインポート",
+ "toolbar.generateButton.text": "一括生成",
+ "toolbar.panelsOrientationButton.tooltip.switchToColumn": "パネルを横向きに切り替え",
+ "toolbar.panelsOrientationButton.tooltip.switchToRow": "パネルを縦向きに切り替え",
+ "toolbar.emptyPageButton.tooltip": "ワークスペースをクリア",
+ "toolbar.emptyPageButton.confirmation.title": "ワークスペースをクリアしますか?",
+ "toolbar.emptyPageButton.confirmation.text": "ワークスペースをクリアしますか?すべての設定が削除されます。",
+ "toolbar.exportSchemaButton.tooltip": "スキーマをエクスポート",
+ "toolbar.importSchemaButton.tooltip": "スキーマをインポート",
"preview.setting.regenerateButton.tooltip": "再生成",
"preview.setting.lineNumberSwitch.tooltip.show": "行番号を表示",
"preview.setting.lineNumberSwitch.tooltip.hide": "行番号を非表示",
- "preview.setting.lineWarpSwitch.tooltip.enable": "行の折り返しを有効にする",
- "preview.setting.lineWarpSwitch.tooltip.disable": "行の折り返しを無効にする",
+ "preview.setting.lineWarpSwitch.tooltip.enable": "自動改行を有効にする",
+ "preview.setting.lineWarpSwitch.tooltip.disable": "自動改行を無効にする",
"preview.setting.copyToClipboard.tooltip": "クリップボードにコピー",
"preview.setting.copyToClipboard.notification.success": "成功",
- "preview.setting.copyToClipboard.notification.content": "内容がクリップボードにコピーされました。",
- "preview.setting.rawView.text": "生データ",
- "preview.setting.tableView.text": "表形式",
- "dataFields.list.addNewFieldButton.text": "フィールドを追加",
+ "preview.setting.copyToClipboard.notification.content": "クリップボードにコピーされました",
+ "preview.setting.rawView.text": "原文",
+ "preview.setting.tableView.text": "テーブル",
+ "dataFields.list.addNewFieldButton.text": "新しいフィールドを追加",
+ "dataFields.list.noDataFields.text": "フィールドがまだありません",
+ "dataFields.list.createFirstField.text": "最初のフィールドを作成しましょう!",
"dataFields.input.fieldName.label": "フィールド名",
- "dataFields.input.type.label": "タイプ",
- "dataFields.input.type.placeholder": "タイプを選択",
- "dataFields.input.emptyRate.label": "空の確率",
+ "dataFields.input.fieldName.errorMessage.empty": "フィールド名は空にできません",
+ "dataFields.input.type.label": "データタイプ",
+ "dataFields.input.type.placeholder": "タイプを選択...",
+ "dataFields.input.emptyRate.label": "空値の確率",
+ "dataFields.input.emptyRate.tooltip": "空値(null)を生成する確率",
+ "dataFields.input.emptyRate.errorMessage.empty": "空値の確率は空にできません",
"dataFields.input.options.label": "オプション",
- "dataFields.type.modal.title": "データタイプ",
- "dataFields.type.modal.search.placeholder": "データタイプを検索...",
+ "dataFields.type.modal.title": "タイプを選択",
+ "dataFields.type.modal.search.placeholder": "タイプを検索...",
// error pages
+ "error.input.isRequired": "この項目は必須です",
"error.404.description": "ページが存在しません",
"error.404.button.text": "ホームページ",
- "error.general.description": "おっと!エラーが発生しました。",
+ "error.general.description": "おっと!エラーが発生しました!",
"error.general.button.text": "ホームページ",
-};
\ No newline at end of file
+
+}
diff --git a/src/locale/translations/zhCN.ts b/src/locale/translations/zhCN.ts
index 293aa09..b850f83 100644
--- a/src/locale/translations/zhCN.ts
+++ b/src/locale/translations/zhCN.ts
@@ -3,9 +3,11 @@ export const zhCN = {
// export
// export category
- "export.category.fileTypes": "常见格式",
+
+ "export.category.file_types": "常见格式",
"export.category.databases": "数据库",
- "export.category.programmingLanguages": "编程语言",
+ "export.category.programming_languages": "编程语言",
+
// export format modal
"export.configurator.modal.title": "生成格式",
@@ -57,14 +59,71 @@ export const zhCN = {
"export.configurator.javascript.declarationKeyword": "声明类型",
"export.configurator.javascript.module": "模块",
+ // sql
+ "export.configurator.sql.type": "数据库类型",
+ "export.configurator.sql.tableName": "表名",
+ "export.configurator.sql.tableName.required": "表名不能为空",
+ "export.configurator.sql.statement": "SQL语句",
+ "export.configurator.sql.batchSize": "批量大小",
+ "export.configurator.sql.includeDropTable": "包含 `DROP TABLE`",
+ "export.configurator.sql.includeCreateTable": "包含 `CREATE TABLE`",
+ "export.configurator.sql.includePrimaryKey": "包含主键",
+ "export.configurator.sql.primaryKeyColumnName": "主键列名",
+
+ // c#
+ "export.configurator.csharp.collectionType": "集合类型",
+ "export.configurator.csharp.collectionName": "集合变量名",
+ "export.configurator.csharp.dtoClass": "创建DTO类",
+ "export.configurator.csharp.dtoClassName": "类名",
+
+ // typescript
+ "export.configurator.typescript.declarationType": "结构声明类型",
+ "export.configurator.typescript.declarationType.interface.name": "Interface命名",
+ "export.configurator.typescript.declarationType.type.name": "Type命名",
+ "export.configurator.typescript.variableName": "变量名",
+
// -------------------------------------------------------------------------------------------------------------
// data types
-
// ipaddress
"dataType.ipaddress": "IP地址",
"dataType.ipaddress.types": "类型",
+ // birthday
+ "dataType.birthday": "生日",
+ "dataType.birthday.mode":"模式",
+ "dataType.birthday.mode.age":"年龄",
+ "dataType.birthday.mode.year":"出生年份",
+ "dataType.birthday.mode.minAge":"最小年龄",
+ "dataType.birthday.mode.maxAge":"最大年龄",
+ "dataType.birthday.mode.fromYear":"最小年份",
+ "dataType.birthday.mode.toYear":"最大年份",
+
+ // month
+ "dataType.month": "月份",
+ "dataType.month.abbreviated": "缩写",
+
+ // weekday
+ "dataType.weekday": "星期",
+ "dataType.weekday.abbreviated": "缩写",
+
+ // datetime
+ "dataType.datetime": "日期时间",
+ "dataType.datetime.terms": "条件",
+ "dataType.datetime.terms.anytime": "任意时间",
+ "dataType.datetime.terms.between": "区间",
+ "dataType.datetime.terms.future": "未来",
+ "dataType.datetime.terms.past": "过去",
+ "dataType.datetime.terms.recent": "不久之前",
+ "dataType.datetime.terms.soon": "不久之后",
+ "dataType.datetime.ref": "参考日期",
+ "dataType.datetime.ref.tooltip": "用于生成数据的参考日期",
+ "dataType.datetime.format": "格式",
+ "dataType.datetime.format.text": "文本",
+ "dataType.datetime.format.timestamp": "时间戳",
+ "dataType.datetime.format.datetime": "Date对象",
+ "dataType.datetime.timeRange": "区间",
+
// url
"dataType.url": "网址",
"dataType.url.appendSlash.label": "斜线",
@@ -138,9 +197,6 @@ export const zhCN = {
"dataType.number.max.errorMessage.empty": "最大值不能为空",
"dataType.number.max.errorMessage.lessThanMin": "最大值不能小于最小值",
- // dateTime
- "dataType.dateTime": "日期时间",
-
// boolean
"dataType.boolean": "布尔值",
"dataType.boolean.true.label": "真值概率",
@@ -174,6 +230,7 @@ export const zhCN = {
"dataType.category.person": "人物",
"dataType.category.commerce": "商业",
"dataType.category.network": "网络",
+ "dataType.category.datetime": "时间",
// -------------------------------------------------------------------------------------------------------------
// pages
@@ -223,6 +280,7 @@ export const zhCN = {
"dataFields.type.modal.search.placeholder": "搜索类型...",
// error pages
+ "error.input.isRequired": "此项不能为空",
"error.404.description": "页面不存在",
"error.404.button.text": "首页",
"error.general.description": "Oops! 出错了!",
diff --git a/src/pages/workspace/index.tsx b/src/pages/workspace/index.tsx
index baf1dc7..6a2b6d7 100644
--- a/src/pages/workspace/index.tsx
+++ b/src/pages/workspace/index.tsx
@@ -54,7 +54,7 @@ export default function Workspace() {
return (
<>
- {intl.formatMessage({id: "nav.item.workspace"})} - Duymmi
+ Dummyi - Mock Data Generator
diff --git a/src/utils/formatterUtils.ts b/src/utils/formatterUtils.ts
index 999bbcd..4e1f73b 100644
--- a/src/utils/formatterUtils.ts
+++ b/src/utils/formatterUtils.ts
@@ -1,7 +1,8 @@
import {FormatRequest, Formatter} from "@/types/formatter";
-import {ExportFormat} from "@/constants/enums";
+import {ExportFormat, ValueType} from "@/constants/enums";
import {formatters} from "@/core/formatters";
import {langs} from '@uiw/codemirror-extensions-langs';
+import {DataFieldList} from "@/types/generator";
// format data
export const formatData = (request: FormatRequest): string => {
@@ -86,7 +87,71 @@ export const getCodemirrorLanguagePluginByFormat = (format: ExportFormat): any =
return langs.sql();
case ExportFormat.CSHARP:
return langs.csharp();
+ case ExportFormat.TYPESCRIPT:
+ return langs.typescript();
default:
return langs.mathematica();
}
+}
+
+// Get json string without quotes in field names
+export function toJsonListStringWithoutQuotes(fields: DataFieldList, sortedFieldIds: string[], values: any[]): string {
+ const convert = (value: any, indent = 2): string => { // 改为直接处理任意值
+ const indentSpace = ' '.repeat(indent);
+ const nextIndentSpace = ' '.repeat(indent + 2);
+
+ if (Array.isArray(value)) { // 处理数组格式
+ const elements = value.map(element => convert(element, indent + 2));
+ return `[\n${nextIndentSpace}${elements.join(`,\n${nextIndentSpace}`)}\n${indentSpace}]`;
+ } else if (value instanceof Date) {
+ return `new Date("${toISOString(value)}")`
+ } else if (typeof value === 'object' && value !== null) { // 处理对象格式
+ const entries = Object.entries(value).map(([key, val]) => {
+ const formattedValue = convert(val, indent + 2);
+ return `${nextIndentSpace}${key}: ${formattedValue}`;
+ });
+ return `{\n${entries.join(',\n')}\n${indentSpace}}`;
+ } else { // 处理基础类型
+ return JSON.stringify(value);
+ }
+ };
+
+ let output = "[\n"; // 开始数组并添加换行符
+ values.forEach((item, index) => {
+ const row: Record = {}; // 允许任何类型的值
+ for (const column of sortedFieldIds) {
+ const field = fields[column];
+ const {isDraft, fieldName} = field;
+ const itemValue = item[column];
+ let {value} = itemValue;
+
+ if (!isDraft && value !== null) {
+ if (typeof value === 'bigint') {
+ value = value.toString(); // 处理 bigint 为字符串
+ }
+ row[fieldName] = value;
+ }
+ }
+ // 添加对象到数组,确保正确的缩进和换行
+ output += ` ${convert(row)}${index < values.length - 1 ? ',\n' : '\n'}`;
+ });
+
+ output += "]"; // 结束数组
+ return output;
+}
+
+
+function toISOString(date) {
+ // 获取日期部分
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是从0开始的
+ const day = String(date.getDate()).padStart(2, '0');
+
+ // 获取时间部分
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+ const seconds = String(date.getSeconds()).padStart(2, '0');
+
+ // 拼接成 YYYY-MM-DDTHH:mm:ss 格式
+ return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
}
\ No newline at end of file
diff --git a/src/utils/typeUtils.ts b/src/utils/typeUtils.ts
index b6f247c..1c50988 100644
--- a/src/utils/typeUtils.ts
+++ b/src/utils/typeUtils.ts
@@ -13,4 +13,19 @@ export const calculateByteSize = (str: string) => {
// check variable has value
export function hasValue(variable: any): boolean {
return variable !== null && variable !== undefined;
+}
+
+export function toDateString(date: Date): string {
+ const day = date.getDate().toString().padStart(2, '0');
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
+ const year = date.getFullYear();
+ return `${day}-${month}-${year}`;
+}
+
+export function toDateTimeString(date: Date): string {
+ const formattedDate = toDateString(date); // Reuse formatDate function
+ const hours = date.getHours().toString().padStart(2, '0');
+ const minutes = date.getMinutes().toString().padStart(2, '0');
+ const seconds = date.getSeconds().toString().padStart(2, '0');
+ return `${formattedDate} ${hours}:${minutes}:${seconds}`;
}
\ No newline at end of file