diff --git a/package.json b/package.json index 8ea8bdf..7b9fbaf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dummyi", - "version": "0.2.1", + "version": "0.2.2", "private": true, "scripts": { "dev": "next dev", diff --git a/public/images/exportFormats/dark/sql.svg b/public/images/exportFormats/dark/SQL.svg similarity index 100% rename from public/images/exportFormats/dark/sql.svg rename to public/images/exportFormats/dark/SQL.svg diff --git a/public/images/exportFormats/light/sql.svg b/public/images/exportFormats/light/SQL.svg similarity index 100% rename from public/images/exportFormats/light/sql.svg rename to public/images/exportFormats/light/SQL.svg 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/src/components/Navbar/src/NavBar.tsx b/src/components/Navbar/src/NavBar.tsx index 54336c5..dacf568 100644 --- a/src/components/Navbar/src/NavBar.tsx +++ b/src/components/Navbar/src/NavBar.tsx @@ -101,11 +101,12 @@ export const NavBar: FunctionComponent = () => { - { - isLoggedIn - ? - : - } + + {/*{*/} + {/* isLoggedIn*/} + {/* ? */} + {/* : */} + {/*}*/} 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/constants/enums.ts b/src/constants/enums.ts index 36ad087..918d080 100644 --- a/src/constants/enums.ts +++ b/src/constants/enums.ts @@ -1,12 +1,13 @@ // 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", @@ -43,6 +44,7 @@ export enum DataTypeCategory { } export enum DataType { + URL = "url", DOMAINSUFFIX = "domainsuffix", DOMAINNAME = "domainname", ACCOUNTNUMBER = "accountnumber", diff --git a/src/core/formatters/CSharp/CSharp.tsx b/src/core/formatters/CSharp/CSharp.tsx index 774bf00..cff70b9 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,13 @@ 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; // Add more cases as necessary } @@ -110,20 +108,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 +150,7 @@ export const CSharpConfigComponent: React.FC /> } value={config.collectionName} onChange={(v) => handleValueChange("collectionName", v)} @@ -170,6 +165,7 @@ export const CSharpConfigComponent: React.FC { config.dtoClass && } value={config.dtoClassName} onChange={(v) => handleValueChange("dtoClassName", v)} 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..161922c 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"; @@ -149,8 +148,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 +198,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..5d5f286 --- /dev/null +++ b/src/core/formatters/Typescript/Typescript.tsx @@ -0,0 +1,133 @@ +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; + } + 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/Url/Url.tsx b/src/core/generators/Url/Url.tsx new file mode 100644 index 0000000..d5aa7f8 --- /dev/null +++ b/src/core/generators/Url/Url.tsx @@ -0,0 +1,94 @@ +import React from "react"; +import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator"; +import {faker} from "@faker-js/faker"; +import {Tag} from "@douyinfe/semi-ui"; +import {OptionsSelect, SelectOption} from "@/components/Utils"; +import {FormattedMessage} from "@/locale"; +import style from '../Boolean/Boolean.module.scss'; +import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch"; + +// ------------------------------------------------------------------------------------------------------------- +// types +type HTTPProtocolType = 'http' | 'https'; + +export enum ProtocolGeneratorFormat { + HTTP_PROTOCOL = 'http', + HTTPS_PROTOCOL = 'https' +} + +export interface UrlGeneratorOptions { + appendSlash: boolean; + protocol: HTTPProtocolType; +} + +// ------------------------------------------------------------------------------------------------------------- +// default options +export const UrlGeneratorDefaultOptions: UrlGeneratorOptions = { + appendSlash: false, + protocol: ProtocolGeneratorFormat.HTTPS_PROTOCOL + +} + +// ------------------------------------------------------------------------------------------------------------- +// generate method +export const generate = (options: any): GenerateResult => { + // TODO: implement your own generate method here + const {appendSlash, protocol} = options; + const domain = faker.internet.domainName(); + // Construct URL + let value = `${protocol}://${domain}`; + if (appendSlash) { + value += '/'; + } + //return random http or https + return { + value: value, + stringValue: value, + } + +} + +// ------------------------------------------------------------------------------------------------------------- +// options component +export const UrlGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => { + const {options, handleOptionValueChange} = props as { + options: UrlGeneratorOptions, + handleOptionValueChange: typeof props.handleOptionValueChange + }; + const handleFormatChange = (format: ProtocolGeneratorFormat) => { + handleOptionValueChange("protocol", format); + } + + + return ( + <> + } + value={options.appendSlash} + onChange={(v) => { + handleOptionValueChange('appendSlash', v); + }} + size={'large'} + /> + + } + selectOptions={protocolOptions} + value={options.protocol} + onChange={handleFormatChange} // This directly passes the selected value to handleFormatChange + style={{width: '110px'}} + /> + + ); +} + +const protocolOptions: SelectOption[] = [ + { + value: ProtocolGeneratorFormat.HTTPS_PROTOCOL, + label: <>https + }, + { + value: ProtocolGeneratorFormat.HTTP_PROTOCOL, + label: <>http + } +] \ No newline at end of file diff --git a/src/core/generators/Url/index.ts b/src/core/generators/Url/index.ts new file mode 100644 index 0000000..baa012c --- /dev/null +++ b/src/core/generators/Url/index.ts @@ -0,0 +1,14 @@ +import {Generator} from "@/types/generator"; +import {DataType, DataTypeCategory, ValueType} from "@/constants/enums"; +import {UrlGeneratorDefaultOptions, UrlGeneratorOptionsComponent, generate} from "./Url"; + +export const UrlGenerator: Generator = { + type: DataType.URL, + category: DataTypeCategory.NETWORK, + generate: generate, + optionsComponent: UrlGeneratorOptionsComponent, + defaultOptions: UrlGeneratorDefaultOptions, + defaultValueType: ValueType.STRING, + exampleLines: ["https://slim-site.name", "https://tinyurl.com", "https://soft-snow.com"] +} + \ No newline at end of file diff --git a/src/core/generators/index.ts b/src/core/generators/index.ts index 25ae4bf..8d6ffd1 100644 --- a/src/core/generators/index.ts +++ b/src/core/generators/index.ts @@ -1,3 +1,4 @@ +import {UrlGenerator} from "@/core/generators/Url"; import {DomainSuffixGenerator} from "@/core/generators/DomainSuffix"; import {DomainNameGenerator} from "@/core/generators/DomainName"; import {AccountNumberGenerator} from "@/core/generators/AccountNumber"; @@ -18,6 +19,7 @@ import {CompanyNameGenerator} from "@/core/generators/CompanyName"; import {DataType} from "@/constants/enums"; export const generators = { + [DataType.URL]: UrlGenerator, [DataType.DOMAINSUFFIX]: DomainSuffixGenerator, [DataType.DOMAINNAME]: DomainNameGenerator, [DataType.ACCOUNTNUMBER]: AccountNumberGenerator, 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 2345f7a..bcbef4e 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,15 +76,27 @@ 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 - + + + // url + "dataType.url": "Url", + "dataType.url.appendSlash.label": "Slash", + "dataType.url.protocol.label": "Protocol", + // domainsuffix "dataType.domainsuffix": "Domain Suffix", // domainname "dataType.domainname": "Domain Name", - + // accountnumber "dataType.accountnumber": "Account Number", "dataType.accountnumber.length": "Length", @@ -97,7 +109,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", @@ -232,6 +244,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 5878a25..3653901 100644 --- a/src/locale/translations/jaJP.ts +++ b/src/locale/translations/jaJP.ts @@ -23,6 +23,10 @@ export const jaJP = { // ------------------------------------------------------------------------------------------------------------- // data types + + // url + "dataType.url": "Url", + // domainsuffix "dataType.domainsuffix": "DomainSuffix", diff --git a/src/locale/translations/zhCN.ts b/src/locale/translations/zhCN.ts index 9b8ad44..2cdb78d 100644 --- a/src/locale/translations/zhCN.ts +++ b/src/locale/translations/zhCN.ts @@ -3,9 +3,9 @@ export const zhCN = { // export // export category - "export.category.fileTypes": "常见格式", - "export.category.databases" : "数据库", - "export.category.programmingLanguages": "编程语言", + "export.category.file_types": "常见格式", + "export.category.databases": "数据库", + "export.category.programming_languages": "编程语言", // export format modal "export.configurator.modal.title": "生成格式", @@ -34,7 +34,7 @@ export const zhCN = { // csv "export.configurator.csv.delimiter": "分隔符", - "export.configurator.csv.delimiter.required" : "分隔符不可为空", + "export.configurator.csv.delimiter.required": "分隔符不可为空", "export.configurator.csv.includeHeader": "包含表头", "export.configurator.csv.endLineChar": "行结束符", @@ -57,9 +57,38 @@ 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 - + + + // url + "dataType.url": "网址", + "dataType.url.appendSlash.label": "斜线", + "dataType.url.protocol.label": "传输协议", + // domainsuffix "dataType.domainsuffix": "域名后缀", @@ -77,7 +106,7 @@ export const zhCN = { // color "dataType.color": "颜色", "dataType.color.kind.label": "类型", - "dataType.color.format.humanWord":"词语", + "dataType.color.format.humanWord": "词语", "dataType.color.format.label": "格式", // phone @@ -90,15 +119,15 @@ export const zhCN = { "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" : "国旗", + "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": "人物称谓", @@ -120,11 +149,11 @@ export const zhCN = { "dataType.number.kind.label": "种类", "dataType.number.precision.label": "精度", "dataType.number.min.label": "最小值", - "dataType.number.min.tooltip":"生成数据的最小值", + "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.tooltip": "生成数据的最大值", "dataType.number.max.errorMessage.empty": "最大值不能为空", "dataType.number.max.errorMessage.lessThanMin": "最大值不能小于最小值", @@ -213,6 +242,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..ad475d2 100644 --- a/src/utils/formatterUtils.ts +++ b/src/utils/formatterUtils.ts @@ -2,6 +2,7 @@ import {FormatRequest, Formatter} from "@/types/formatter"; import {ExportFormat} 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,53 @@ 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(); } -} \ No newline at end of file +} + +// 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 (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; +}