From 1e5b935bb2b77945ab784081e157890dc3ec33fc Mon Sep 17 00:00:00 2001 From: moaz_dw Date: Fri, 22 Nov 2024 01:59:39 +0300 Subject: [PATCH] generator --- package-lock.json | 42 ++++++ package.json | 8 +- .../FileGenerator/generateAddModal.js | 68 ++++++++++ src/Extensions/FileGenerator/generateApi.js | 45 +++++++ .../FileGenerator/generateColumn.js | 122 ++++++++++++++++++ .../FileGenerator/generateDashboard.js | 37 ++++++ .../FileGenerator/generateEditModal.js | 67 ++++++++++ .../FileGenerator/generateFilterForm.js | 47 +++++++ .../FileGenerator/generateFormUtils.js | 51 ++++++++ src/Extensions/FileGenerator/generateIndex.js | 44 +++++++ .../FileGenerator/generateModelEnum.js | 63 +++++++++ .../FileGenerator/generateModelForm.js | 38 ++++++ src/Extensions/FileGenerator/generatePage.js | 90 +++++++++++++ .../FileGenerator/generateParamsEnum.js | 39 ++++++ src/Extensions/FileGenerator/generateRoute.js | 83 ++++++++++++ src/Extensions/FileGenerator/generateTable.js | 58 +++++++++ src/Extensions/FileGenerator/generateType.js | 52 ++++++++ 17 files changed, 953 insertions(+), 1 deletion(-) create mode 100644 src/Extensions/FileGenerator/generateAddModal.js create mode 100644 src/Extensions/FileGenerator/generateApi.js create mode 100644 src/Extensions/FileGenerator/generateColumn.js create mode 100644 src/Extensions/FileGenerator/generateDashboard.js create mode 100644 src/Extensions/FileGenerator/generateEditModal.js create mode 100644 src/Extensions/FileGenerator/generateFilterForm.js create mode 100644 src/Extensions/FileGenerator/generateFormUtils.js create mode 100644 src/Extensions/FileGenerator/generateIndex.js create mode 100644 src/Extensions/FileGenerator/generateModelEnum.js create mode 100644 src/Extensions/FileGenerator/generateModelForm.js create mode 100644 src/Extensions/FileGenerator/generatePage.js create mode 100644 src/Extensions/FileGenerator/generateParamsEnum.js create mode 100644 src/Extensions/FileGenerator/generateRoute.js create mode 100644 src/Extensions/FileGenerator/generateTable.js create mode 100644 src/Extensions/FileGenerator/generateType.js diff --git a/package-lock.json b/package-lock.json index 28f6d37..ab6f08b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "react-window": "^1.8.10", "reactstrap": "^9.2.3", "sass": "^1.79.4", + "vite-plugin-env-compatible": "^2.0.1", "yup": "^1.4.0", "zustand": "^4.5.5" }, @@ -5275,6 +5276,19 @@ "csstype": "^3.0.2" } }, + "node_modules/dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -14656,6 +14670,15 @@ "vite": ">=2.0.0" } }, + "node_modules/vite-plugin-env-compatible": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vite-plugin-env-compatible/-/vite-plugin-env-compatible-2.0.1.tgz", + "integrity": "sha512-DRrOZTg/W44ojVQQfGSMPEgYQGzp5TeIpt9cpaK35hTOC/b2D7Ffl8/RIgK8vQ0mlnDIUgETcA173bnMEkyzdw==", + "dependencies": { + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -18867,6 +18890,16 @@ "csstype": "^3.0.2" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, "ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -25325,6 +25358,15 @@ "fs-extra": "^10.0.0" } }, + "vite-plugin-env-compatible": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/vite-plugin-env-compatible/-/vite-plugin-env-compatible-2.0.1.tgz", + "integrity": "sha512-DRrOZTg/W44ojVQQfGSMPEgYQGzp5TeIpt9cpaK35hTOC/b2D7Ffl8/RIgK8vQ0mlnDIUgETcA173bnMEkyzdw==", + "requires": { + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0" + } + }, "void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", diff --git a/package.json b/package.json index 1504d36..0b4e594 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "react-window": "^1.8.10", "reactstrap": "^9.2.3", "sass": "^1.79.4", + "vite-plugin-env-compatible": "^2.0.1", "yup": "^1.4.0", "zustand": "^4.5.5" }, @@ -46,7 +47,12 @@ "test": "vite jest", "preview": "vite preview", "eject": "react-scripts eject", - "format": "prettier --write ." + "format": "prettier --write .", + "g:api": "node src/Extensions/FileGenerator/generateApi.js", + "g:column": "node src/Extensions/FileGenerator/generateColumn.js", + "g:formutil": "node src/Extensions/FileGenerator/generateformUtils.js", + "g:page": "node src/Extensions/FileGenerator/generatePage.js", + "g:dashboard": "node src/Extensions/FileGenerator/generateDashboard.js " }, "eslintConfig": { "extends": [ diff --git a/src/Extensions/FileGenerator/generateAddModal.js b/src/Extensions/FileGenerator/generateAddModal.js new file mode 100644 index 0000000..566b27f --- /dev/null +++ b/src/Extensions/FileGenerator/generateAddModal.js @@ -0,0 +1,68 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + + + +let FileContainer = ` + +import React from "react"; +import { getInitialValues, getValidationSchema } from "./FormUtil"; +import { ModalEnum } from "../../../enums/Model"; +import LayoutModel from "../../../Layout/Dashboard/LayoutModel"; +import { QueryStatusEnum } from "../../../enums/QueryStatus"; +import ModelForm from "./ModelForm"; +import { useAdd${capitalizeFirstLetter(fileName)} } from "../../../api/${fileName}"; + +const AddModel: React.FC = () => { + const { mutate, status } = useAdd${capitalizeFirstLetter(fileName)}(); + + const handleSubmit = (values: any) => { + mutate({ + ...values, + }); + }; + return ( + <> + + + + + ); +}; + +export default AddModel; + + +` +fs.writeFileSync('src/Pages/'+fileName+"/Model"+"/"+"AddModel.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + + + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} + +function capitalizeAllWord(word) { + return (word).toUpperCase() ; +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateApi.js b/src/Extensions/FileGenerator/generateApi.js new file mode 100644 index 0000000..aecb13c --- /dev/null +++ b/src/Extensions/FileGenerator/generateApi.js @@ -0,0 +1,45 @@ +const fs = require('fs'); + +const fileName = process.argv[2] + + +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + + +let FileContainer = ` + +import useAddMutation from "./helper/useAddMutation"; +import useDeleteMutation from "./helper/useDeleteMutation"; +import useGetQuery from "./helper/useGetQuery"; +import useUpdateMutation from "./helper/useUpdateMutation"; + +const API = { + GET: "/${fileName}", + ADD: "/${fileName}", + DELETE: "/${fileName}", + UPDATE: "/${fileName}", +}; + +const KEY = "${fileName}"; + +export const useGetAll${capitalizeFirstLetter(fileName)} = (params?: any, options?: any) => + useGetQuery(KEY, API.GET, params, options); +export const useAdd${capitalizeFirstLetter(fileName)} = () => useAddMutation(KEY, API.ADD); +export const useUpdate${capitalizeFirstLetter(fileName)} = (params?: any) => useUpdateMutation(KEY, API.UPDATE); +export const useDelete${capitalizeFirstLetter(fileName)} = (params?: any) => + useDeleteMutation(KEY, API.DELETE); + +` +fs.writeFileSync('src/api/' + fileName + ".ts", + FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateColumn.js b/src/Extensions/FileGenerator/generateColumn.js new file mode 100644 index 0000000..279bb66 --- /dev/null +++ b/src/Extensions/FileGenerator/generateColumn.js @@ -0,0 +1,122 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + + + +let FileContainer = ` + +import { TableColumnsType } from "antd"; +import useModalHandler from "../../utils/useModalHandler"; +import { ModalEnum } from "../../enums/Model"; +import { useObjectToEdit } from "../../zustand/ObjectToEditState"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { + canDelete${capitalizeFirstLetter(fileName)}, + canEdit${capitalizeFirstLetter(fileName)}, + canShow${capitalizeFirstLetter(fileName)}, +} from "../../utils/hasAbilityFn"; +import ActionButtons from "../../Components/Table/ActionButtons"; +import ColumnsImage from "../../Components/Columns/ColumnsImage"; +import { ${capitalizeFirstLetter(fileName)} } from "../../types/${capitalizeFirstLetter(fileName)}"; +import { useFilterStateState } from "../../zustand/Filter"; + +export const useColumns = () => { + const { handel_open_model } = useModalHandler(); + + const { setObjectToEdit } = useObjectToEdit((state) => state); + const navigate = useNavigate(); + const { setFilter } = useFilterStateState(); + + const handelShow = (record: ${capitalizeFirstLetter(fileName)}) => { + setFilter({}); + navigate(record?.id); + }; + + const handelDelete = (data: ${capitalizeFirstLetter(fileName)}) => { + setObjectToEdit(data); + handel_open_model(ModalEnum?.${capitalizeAllWord(fileName)}_DELETE); + }; + + const handleEdit = (record: ${capitalizeFirstLetter(fileName)}) => { + setObjectToEdit(record); + handel_open_model(ModalEnum?.${capitalizeAllWord(fileName)}_EDIT); + }; + const [t] = useTranslation(); + + const columns: TableColumnsType<${capitalizeFirstLetter(fileName)}> = [ + { + title: t("columns.id"), + dataIndex: "id", + key: "id", + align: "center", + render: (_text, record) => record?.id, + }, + { + title: ("columns.name"), + dataIndex: "name", + key: "name", + align: "center", + render: (_text, record) => record?.name, + ellipsis: true, + }, + { + title: t("columns.image"), + dataIndex: "image", + key: "image", + align: "center", + render: (_text: any, record: ${capitalizeFirstLetter(fileName)}) => { + let str = record?.image; + + return ; + }, + }, + { + title: t("columns.procedure"), + key: "actions", + align: "center", + width: "25vw", + render: (_text, record, index) => { + return ( + handelDelete(record)} + onEdit={() => handleEdit(record)} + onShow={() => handelShow(record)} + /> + ); + }, + }, + ]; + + return columns; +}; + + +` +fs.writeFileSync('src/Pages/'+fileName+"/"+"useTableColumns.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} + +function capitalizeAllWord(word) { +return (word).toUpperCase() ; +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateDashboard.js b/src/Extensions/FileGenerator/generateDashboard.js new file mode 100644 index 0000000..8a86060 --- /dev/null +++ b/src/Extensions/FileGenerator/generateDashboard.js @@ -0,0 +1,37 @@ +const { execSync } = require('child_process'); + +const fileName = process.argv[2]; + +// Define commands +const commands = [ + `node src/Extensions/FileGenerator/generateApi.js ${fileName}`, + `node src/Extensions/FileGenerator/generatePage.js ${fileName}`, + `node src/Extensions/FileGenerator/generateTable.js ${fileName}`, + `node src/Extensions/FileGenerator/generateColumn.js ${fileName}`, + `node src/Extensions/FileGenerator/generateIndex.js ${fileName}`, + `node src/Extensions/FileGenerator/generateFormUtils.js ${fileName}`, + `node src/Extensions/FileGenerator/generateAddModal.js ${fileName}`, + `node src/Extensions/FileGenerator/generateEditModal.js ${fileName}`, + `node src/Extensions/FileGenerator/generateModelForm.js ${fileName}`, + `node src/Extensions/FileGenerator/generateFilterForm.js ${fileName}`, + `node src/Extensions/FileGenerator/generateType.js ${fileName}`, + `node src/Extensions/FileGenerator/generateParamsEnum.js ${fileName}`, + `node src/Extensions/FileGenerator/generateRoute.js ${fileName}`, + `node src/Extensions/FileGenerator/generateModelEnum.js ${fileName}` +]; + +// Execute each command sequentially +const runCommands = () => { + for (const command of commands) { + try { + console.log(`Running: ${command}`); + execSync(command, { stdio: 'inherit' }); + console.log(`${command} executed successfully.\n`); + } catch (error) { + console.error(`Error executing ${command}:`, error); + process.exit(1); // Exit if any command fails + } + } +}; + +runCommands(); diff --git a/src/Extensions/FileGenerator/generateEditModal.js b/src/Extensions/FileGenerator/generateEditModal.js new file mode 100644 index 0000000..641c227 --- /dev/null +++ b/src/Extensions/FileGenerator/generateEditModal.js @@ -0,0 +1,67 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +let FileContainer = ` + +import React from "react"; +import { getInitialValues, getValidationSchema } from "./FormUtil"; +import { ModalEnum } from "../../../enums/Model"; +import LayoutModel from "../../../Layout/Dashboard/LayoutModel"; +import ModelForm from "./ModelForm"; +import { QueryStatusEnum } from "../../../enums/QueryStatus"; +import { useObjectToEdit } from "../../../zustand/ObjectToEditState"; +import { useUpdate${capitalizeFirstLetter(fileName)} } from "../../../api/${fileName}"; +import { handelImageState } from "../../../utils/DataToSendImageState"; + +const EditModel: React.FC = () => { + const { mutate, status } = useUpdate${capitalizeFirstLetter(fileName)}(); + const { objectToEdit } = useObjectToEdit((state) => state); + + const handleSubmit = (values: any) => { + const Data_to_send = { ...values }; + const handelImage = handelImageState(Data_to_send, "icon"); + mutate(handelImage); + }; + + return ( + <> + + + + + ); +}; + +export default EditModel; + +` +fs.writeFileSync('src/Pages/'+fileName+"/Model"+"/"+"EditModel.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} + +function capitalizeAllWord(word) { + return (word).toUpperCase() ; +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateFilterForm.js b/src/Extensions/FileGenerator/generateFilterForm.js new file mode 100644 index 0000000..e65a716 --- /dev/null +++ b/src/Extensions/FileGenerator/generateFilterForm.js @@ -0,0 +1,47 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +let FileContainer = ` +import React from "react"; +import ValidationField from "../../../Components/ValidationField/ValidationField"; +import { Col, Row } from "reactstrap"; +import { useFormikContext } from "formik"; + +const FilterForm = () => { + const formik = useFormikContext(); + + return ( +
+ + + + + +
+ ); +}; + +export default FilterForm; + +` +fs.writeFileSync('src/Pages/' + fileName +"/Model"+"/"+"FilterForm.tsx", + FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + + + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateFormUtils.js b/src/Extensions/FileGenerator/generateFormUtils.js new file mode 100644 index 0000000..8ba2af6 --- /dev/null +++ b/src/Extensions/FileGenerator/generateFormUtils.js @@ -0,0 +1,51 @@ +const fs = require('fs'); +const path = require('path'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +const folderPath = path.join('src/Pages', fileName, 'Model'); + +// Ensure the directory exists (creates the folder if missing) +fs.mkdirSync(folderPath, { recursive: true }); + + +let FileContainer = ` + +import * as Yup from "yup"; +import { ${capitalizeFirstLetter(fileName)}, ${capitalizeFirstLetter(fileName)}InitialValues } from "../../../types/${capitalizeFirstLetter(fileName)}"; + +export const getInitialValues = ( + objectToEdit: Partial<${capitalizeFirstLetter(fileName)}>, +): ${capitalizeFirstLetter(fileName)}InitialValues => { + + return { + id: objectToEdit?.id, + name: objectToEdit?.name ?? "", + }; +}; + +export const getValidationSchema = () => { + // validate input + return Yup.object().shape({ + name: Yup.string().required("validation.required"), + }); +}; + +` + +fs.writeFileSync(path.join(folderPath, 'FormUtil.ts'), FileContainer); + + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateIndex.js b/src/Extensions/FileGenerator/generateIndex.js new file mode 100644 index 0000000..d37e917 --- /dev/null +++ b/src/Extensions/FileGenerator/generateIndex.js @@ -0,0 +1,44 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +const folderPath = 'src/Pages/'+fileName; + + +if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, { recursive: true }); +} + +let FileContainer = ` +import { useColumns } from "./useTableColumns"; +import Table from "./Table"; +import AddModalForm from "./Model/AddModel"; +import EditModalForm from "./Model/EditModel"; + +export { + Table, + useColumns, + AddModalForm, + EditModalForm, +}; + + +` + +fs.writeFileSync('src/Pages/'+fileName+"/"+"index.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateModelEnum.js b/src/Extensions/FileGenerator/generateModelEnum.js new file mode 100644 index 0000000..00050a1 --- /dev/null +++ b/src/Extensions/FileGenerator/generateModelEnum.js @@ -0,0 +1,63 @@ +const fs = require("fs"); +const path = require("path"); + +const MODEL_ENUM_FILE = "./src/enums/Model.ts"; // Path to the ModelEnum file + +// The new enums to be added +const newEnums = [ + { key: "TEST_EDIT", value: "TEST.edit" }, + { key: "TEST_ADD", value: "TEST.add" }, + { key: "TEST_DELETE", value: "TEST.delete" }, +]; + +// Function to generate the new enum entries +const generateEnumEntries = (enums) => { + return enums + .map(({ key, value }) => ` ${key} = "${value}",`) + .join("\n"); +}; + +// Function to update the ModelEnum file +const updateModelEnumFile = () => { + if (!fs.existsSync(MODEL_ENUM_FILE)) { + console.error(`Error: File ${MODEL_ENUM_FILE} does not exist.`); + return; + } + + // Read the existing content of the ModelEnum file + const fileContent = fs.readFileSync(MODEL_ENUM_FILE, "utf-8"); + + // Extract the current enums + const existingEnums = new Set(); + const enumRegex = /(\w+)\s*=\s*"([\w.]+)"/g; + let match; + while ((match = enumRegex.exec(fileContent)) !== null) { + existingEnums.add(match[1]); + } + + // Filter out enums that already exist + const uniqueEnums = newEnums.filter(({ key }) => !existingEnums.has(key)); + + if (uniqueEnums.length === 0) { + console.log("No new enums to add. All enums already exist."); + return; + } + + // Generate the new enum entries + const newEnumEntries = generateEnumEntries(uniqueEnums); + + // Insert the new enums before the closing brace of the ModelEnum + const updatedContent = fileContent.replace( + /export\s+enum\s+ModelEnum\s*{([\s\S]*?)}/, + (match, existingContent) => { + return `export enum ModelEnum {\n${existingContent.trim()}\n\n${newEnumEntries}\n}`; + } + ); + + // Write the updated content back to the file + fs.writeFileSync(MODEL_ENUM_FILE, updatedContent, "utf-8"); + + console.log("ModelEnum file updated successfully!"); +}; + +updateModelEnumFile(); diff --git a/src/Extensions/FileGenerator/generateModelForm.js b/src/Extensions/FileGenerator/generateModelForm.js new file mode 100644 index 0000000..ffc03bf --- /dev/null +++ b/src/Extensions/FileGenerator/generateModelForm.js @@ -0,0 +1,38 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +let FileContainer = ` + +import { Col, Row } from "reactstrap"; +import ValidationField from "../../../Components/ValidationField/ValidationField"; + +const ModelForm = () => { + return ( + + + + + + ); +}; + +export default ModelForm; + + + +` +fs.writeFileSync('src/Pages/' + fileName +"/Model"+"/"+"ModelForm.tsx", + FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + diff --git a/src/Extensions/FileGenerator/generatePage.js b/src/Extensions/FileGenerator/generatePage.js new file mode 100644 index 0000000..55d8248 --- /dev/null +++ b/src/Extensions/FileGenerator/generatePage.js @@ -0,0 +1,90 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +const folderPath = 'src/Pages/'+fileName; + + +if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, { recursive: true }); +} + + +let FileContainer = ` + +import { useTranslation } from "react-i18next"; +import { lazy, Suspense } from "react"; +import { Spin } from "antd"; +import useSetPageTitle from "../../Hooks/useSetPageTitle"; +import { ModalEnum } from "../../enums/Model"; +import { useDelete${capitalizeFirstLetter(fileName)} } from "../../api/${fileName}"; +import PageHeader from "../../Layout/Dashboard/PageHeader"; +import FilterLayout from "../../Layout/Dashboard/FilterLayout"; +import FilterForm from "./Model/FilterForm"; +import { canAdd${capitalizeFirstLetter(fileName)} } from "../../utils/hasAbilityFn"; + +const Table = lazy(() => import("./Table")); +const AddModalForm = lazy(() => import("./Model/AddModel")); +const EditModalForm = lazy(() => import("./Model/EditModel")); +const DeleteModalForm = lazy( + () => import("../../Layout/Dashboard/DeleteModels"), +); + +const TableHeader = () => { + const [t] = useTranslation(); + const deleteMutation = useDelete${capitalizeFirstLetter(fileName)}(); + + useSetPageTitle([ + { name: t('page_header.home'), path: "/" }, + { name: t('page_header.${fileName}'), path: "${fileName}" }, + ]); + + return ( +
+ }> + + } + filterTitle="table.${fileName}" + /> + + + + + + + ); +}; + +export default TableHeader; + +` + +fs.writeFileSync('src/Pages/'+fileName+"/"+"Page.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} + +function capitalizeAllWord(word) { + return (word).toUpperCase() ; +} \ No newline at end of file diff --git a/src/Extensions/FileGenerator/generateParamsEnum.js b/src/Extensions/FileGenerator/generateParamsEnum.js new file mode 100644 index 0000000..cb1dc3b --- /dev/null +++ b/src/Extensions/FileGenerator/generateParamsEnum.js @@ -0,0 +1,39 @@ +const fs = require('fs'); +const path = require('path'); + +// Function to capitalize and add "_ID" +function capitalizeAllWord(word) { + return word.toUpperCase() + "_ID"; +} + +const fileName = process.argv[2]; + +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +// Define the enum entry to add +const enumKey = capitalizeAllWord(fileName); +const enumValue = `${fileName.toLowerCase()}_id`; +const newEntry = ` ${enumKey} = "${enumValue}",\n`; + +// Path to the params.ts file in `src/enums/` +const paramsPath = path.join(__dirname, '../../enums/params.ts'); + +try { + // Read the current contents of params.ts + const fileContents = fs.readFileSync(paramsPath, 'utf-8'); + + // Insert the new entry before the closing brace of the enum + const updatedContents = fileContents.replace( + /(export enum ParamsEnum {\n)/, + `$1${newEntry}` + ); + + // Write the updated contents back to params.ts + fs.writeFileSync(paramsPath, updatedContents); + console.log(`Enum entry "${enumKey}" added successfully to params.ts.`); +} catch (error) { + console.error(`Error updating params.ts: ${error}`); +} diff --git a/src/Extensions/FileGenerator/generateRoute.js b/src/Extensions/FileGenerator/generateRoute.js new file mode 100644 index 0000000..d5514da --- /dev/null +++ b/src/Extensions/FileGenerator/generateRoute.js @@ -0,0 +1,83 @@ +const fs = require("fs"); +const path = require("path"); + +const ROUTES_FILE = "./src/Routes.tsx"; // Path to the file that contains the route definitions +const PAGES_FOLDER = "./src/Pages"; // Folder containing the pages + +// Helper to convert a name to PascalCase +const toPascalCase = (str) => + str.replace(/(^\w|_\w)/g, (match) => match.replace("_", "").toUpperCase()); + +// Helper to convert a name to lowercase snake_case +const toSnakeCase = (str) => + str.replace(/[A-Z]/g, (letter, idx) => (idx ? "_" : "") + letter.toLowerCase()); + +// Helper to dynamically create imports and route items +const generateRoutes = () => { + // Scan the pages folder for directories + const pageDirs = fs + .readdirSync(PAGES_FOLDER, { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name.toLowerCase()); // Normalize to lowercase + + // Use a Set to ensure no duplicates + const uniqueDirs = Array.from(new Set(pageDirs)); + + const imports = []; + const routes = []; + + uniqueDirs.forEach((page) => { + const componentName = toPascalCase(page); + const importPath = `./Pages/${page}/Page`; + const abilityEnum = toSnakeCase(page).toUpperCase(); + + // Add to imports + imports.push( + `const ${componentName} = React.lazy(() => import("${importPath}"));` + ); + + // Add to routes + routes.push(` + { + header: "page_header.${toSnakeCase(page)}", + element: <${componentName} />, + icon: , // Replace with actual icon + text: "sidebar.${toSnakeCase(page)}", + path: \`/\${ABILITIES_ENUM?.${abilityEnum}}\`, + abilities: ABILITIES_ENUM?.${abilityEnum}, + abilities_value: ABILITIES_VALUES_ENUM.INDEX, + prevPath: 0, + }, + `); + }); + + return { imports, routes }; +}; + +const updateRoutesFile = () => { + const { imports, routes } = generateRoutes(); + + // Remove duplicates from imports and routes + const uniqueImports = [...new Set(imports)]; + const uniqueRoutes = [...new Set(routes)]; + + // Read the existing file + const fileContent = fs.readFileSync(ROUTES_FILE, "utf-8"); + + // Replace the imports section + const updatedImports = fileContent.replace( + /\/\/ START: DYNAMIC IMPORTS[\s\S]*?\/\/ END: DYNAMIC IMPORTS/, + `// START: DYNAMIC IMPORTS\n${uniqueImports.join("\n")}\n// END: DYNAMIC IMPORTS` + ); + + // Replace the routes section + const updatedRoutes = updatedImports.replace( + /\/\/ START: DYNAMIC ROUTES[\s\S]*?\/\/ END: DYNAMIC ROUTES/, + `// START: DYNAMIC ROUTES\n${uniqueRoutes.join("\n")}\n// END: DYNAMIC ROUTES` + ); + + // Write the updated content back + fs.writeFileSync(ROUTES_FILE, updatedRoutes, "utf-8"); +}; + +updateRoutesFile(); diff --git a/src/Extensions/FileGenerator/generateTable.js b/src/Extensions/FileGenerator/generateTable.js new file mode 100644 index 0000000..7df9a70 --- /dev/null +++ b/src/Extensions/FileGenerator/generateTable.js @@ -0,0 +1,58 @@ +const fs = require('fs'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +const folderPath = 'src/Pages/'+fileName; + + +if (!fs.existsSync(folderPath)) { + fs.mkdirSync(folderPath, { recursive: true }); +} + +let FileContainer = ` + + +import { useColumns } from "./useTableColumns"; +import React from "react"; +import DataTable from "../../Layout/Dashboard/Table/DataTable"; +import { useGetAll${capitalizeFirstLetter(fileName)} } from "../../api/${fileName}"; +import { useFilterState } from "../../Components/Utils/Filter/FilterState"; +import { useFilterStateState } from "../../zustand/Filter"; + +const App: React.FC = () => { + const { filterState } = useFilterState(); + const { Filter } = useFilterStateState(); + const name = Filter?.name; + const sort_by = Filter?.sort_by; + + const response = useGetAll${capitalizeFirstLetter(fileName)}({ + pagination: true, + ...filterState, + name: filterState.name || name, + sort_by, + }); + + return ; +}; + +export default App; + +` + +fs.writeFileSync('src/Pages/'+fileName+"/"+"Table.tsx", +FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + + +function capitalizeFirstLetter(word) { + return (word).charAt(0).toUpperCase() + (word).slice(1); +} diff --git a/src/Extensions/FileGenerator/generateType.js b/src/Extensions/FileGenerator/generateType.js new file mode 100644 index 0000000..8ea1d57 --- /dev/null +++ b/src/Extensions/FileGenerator/generateType.js @@ -0,0 +1,52 @@ +const fs = require('fs'); +const path = require('path'); + +// Get the file name from the command line arguments +const fileName = process.argv[2]; + +// Check if a file name is provided +if (!fileName) { + console.error('Please provide a file name.'); + process.exit(1); +} + +// Define the directory path +const directoryPath = path.join('src', 'types'); + +// Ensure the directory exists +if (!fs.existsSync(directoryPath)) { + fs.mkdirSync(directoryPath, { recursive: true }); // Create the directory if it doesn't exist +} + +const FileContainer = ` + +import { Nullable } from "./App"; + +// Define the ${capitalizeFirstLetter(fileName)} interface + +export interface ${capitalizeFirstLetter(fileName)} { + id: number; + name: string; + image: string; +} + +export interface InitialValues { + id: number; + name: string; + image: string; +} + +export type ${capitalizeFirstLetter(fileName)}InitialValues = Partial>; + +`; + +fs.writeFileSync( + path.join(directoryPath, `${capitalizeFirstLetter(fileName)}.ts`), + FileContainer +); + +console.log(`File "${fileName}" generated successfully.`); + +function capitalizeFirstLetter(word) { + return word.charAt(0).toUpperCase() + word.slice(1); +}