Compare commits

...

4 Commits

Author SHA1 Message Date
e5443ba3fa fix generator 2024-12-03 15:56:49 +03:00
094b89bdd1 ability generator 2024-11-23 19:00:32 +03:00
3d98fc56d1 fix generator 2024-11-22 02:06:36 +03:00
1e5b935bb2 generator 2024-11-22 01:59:39 +03:00
18 changed files with 1049 additions and 1 deletions

42
package-lock.json generated
View File

@ -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",

View File

@ -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": [

View File

@ -0,0 +1,84 @@
const fs = require("fs");
const path = require("path");
// File path where the abilities are stored
const ABILITIES_FILE = path.join(__dirname, "./src/utils/hasAbilityFn.ts");
// Function to normalize the input name to UPPER_SNAKE_CASE (e.g., test_moaz => TEST_MOAZ, TestMoaz => TEST_MOAZ)
const normalizeToUpperSnakeCase = (input) => {
return input
.replace(/([a-z])([A-Z])/g, "$1_$2") // camelCase to snake_case
.replace(/[_\s]+/g, "_") // normalize multiple underscores or spaces
.toUpperCase(); // Convert to uppercase
};
// Function to capitalize the first letter of a word
const capitalizeFirstLetter = (word) => word.charAt(0).toUpperCase() + word.slice(1);
// Take the name dynamically from the terminal
const nameInput = process.argv[2];
if (!nameInput) {
console.error("Please provide a name as an argument.");
process.exit(1);
}
// Normalize input name (handle camelCase, snake_case, PascalCase)
const normalizedInput = normalizeToUpperSnakeCase(nameInput);
// Generate ability functions for the given name
const generateAbilityFunctions = (name) => {
const capitalized = capitalizeFirstLetter(name.toLowerCase());
return `
export const canAdd${capitalized} = hasAbility(
ABILITIES_ENUM.${name},
ABILITIES_VALUES_ENUM.STORE,
);
export const canEdit${capitalized} = hasAbility(
ABILITIES_ENUM.${name},
ABILITIES_VALUES_ENUM.UPDATE,
);
export const canDelete${capitalized} = hasAbility(
ABILITIES_ENUM.${name},
ABILITIES_VALUES_ENUM.DELETE,
);
export const canShow${capitalized} = hasAbility(
ABILITIES_ENUM.${name},
ABILITIES_VALUES_ENUM.SHOW,
);
export const canIndex${capitalized} = hasAbility(
ABILITIES_ENUM.${name},
ABILITIES_VALUES_ENUM.INDEX,
);
`.trim();
};
const updateAbilitiesFile = () => {
if (!fs.existsSync(ABILITIES_FILE)) {
console.error(`Error: File ${ABILITIES_FILE} does not exist.`);
return;
}
// Read the existing content of the file
const fileContent = fs.readFileSync(ABILITIES_FILE, "utf-8");
// Check for duplicates
const alreadyExists = fileContent.includes(`canAdd${capitalizeFirstLetter(normalizedInput)}`);
if (alreadyExists) {
console.log(`Abilities for "${normalizedInput}" already exist. No changes made.`);
return;
}
// Generate new abilities
const newAbilities = generateAbilityFunctions(normalizedInput);
// Append the new abilities at the end of the file
const updatedContent = `${fileContent.trim()}\n\n${newAbilities}\n`;
// Write the updated content back to the file
fs.writeFileSync(ABILITIES_FILE, updatedContent, "utf-8");
console.log(`Abilities for "${normalizedInput}" added successfully to hasAbilityFn.ts.`);
};
// Run the update
updateAbilitiesFile();

View File

@ -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 (
<>
<LayoutModel
status={status as QueryStatusEnum}
ModelEnum={ModalEnum.${capitalizeAllWord(fileName)}_ADD}
modelTitle="${fileName}"
handleSubmit={handleSubmit}
getInitialValues={getInitialValues({})}
getValidationSchema={getValidationSchema}
>
<ModelForm />
</LayoutModel>
</>
);
};
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() ;
}

View File

@ -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);
}

View File

@ -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 <ColumnsImage src={str} />;
},
},
{
title: t("columns.procedure"),
key: "actions",
align: "center",
width: "25vw",
render: (_text, record, index) => {
return (
<ActionButtons
canDelete={canDelete${capitalizeFirstLetter(fileName)}}
canEdit={canEdit${capitalizeFirstLetter(fileName)}}
canShow={canShow${capitalizeFirstLetter(fileName)}}
index={index}
onDelete={() => 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() ;
}

View File

@ -0,0 +1,39 @@
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}`,
// `node src/Extensions/FileGenerator/generateAbility.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();

View File

@ -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 (
<>
<LayoutModel
status={status as QueryStatusEnum}
ModelEnum={ModalEnum.${capitalizeAllWord(fileName)}_EDIT}
modelTitle="${fileName}"
handleSubmit={handleSubmit}
getInitialValues={getInitialValues(objectToEdit)}
getValidationSchema={getValidationSchema}
isAddModal={false}
>
<ModelForm />
</LayoutModel>
</>
);
};
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() ;
}

View File

@ -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 (
<div>
<Row>
<Col>
<ValidationField placeholder="name" label="name" name="name" />
</Col>
</Row>
</div>
);
};
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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -0,0 +1,73 @@
const fs = require("fs");
const path = require("path");
// Path to the ModalEnum file
const MODEL_ENUM_FILE = "./src/enums/Model.ts";
// Function to convert input to UPPER_SNAKE_CASE
const toUpperSnakeCase = (input) => {
return input
.replace(/([a-z])([A-Z])/g, "$1_$2") // Convert camelCase to snake_case
.replace(/[_\s]+/g, "_") // Normalize underscores or spaces
.toUpperCase(); // Convert to uppercase
};
// Take the name dynamically from the terminal
const nameInput = process.argv[2];
if (!nameInput) {
console.error("Please provide a name as an argument.");
process.exit(1);
}
// Generate the enum entries for the given name
const generateEnumEntries = (name) => {
const baseName = toUpperSnakeCase(name);
return [
` ${baseName}_EDIT = "${baseName.toLowerCase()}.edit",`,
` ${baseName}_ADD = "${baseName.toLowerCase()}.add",`,
` ${baseName}_DELETE = "${baseName.toLowerCase()}.delete",`
].join("\n");
};
// Update the ModalEnum 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 file
const fileContent = fs.readFileSync(MODEL_ENUM_FILE, "utf-8");
// Generate the new entries for the given name
const newEntries = generateEnumEntries(nameInput);
// Check if any of the new keys already exist in the file
const existingKeys = Array.from(
fileContent.matchAll(/(\w+)\s*=\s*".+?"/g),
(match) => match[1]
);
const baseName = toUpperSnakeCase(nameInput);
const duplicateKeys = existingKeys.filter((key) =>
[`${baseName}_EDIT`, `${baseName}_ADD`, `${baseName}_DELETE`].includes(key)
);
if (duplicateKeys.length > 0) {
console.log(`The keys ${duplicateKeys.join(", ")} already exist. No changes made.`);
return;
}
// Inject the new entries before the closing brace of the enum
const updatedContent = fileContent.replace(
/(export enum ModalEnum {\n)/,
`$1${newEntries}\n`
);
// Write the updated content back to the file
fs.writeFileSync(MODEL_ENUM_FILE, updatedContent, "utf-8");
console.log(`Enum entries for "${nameInput}" added successfully to ModalEnum.`);
};
updateModelEnumFile();

View File

@ -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 (
<Row className="w-100">
<Col>
<ValidationField name="name" placeholder="name" label="name" />
</Col>
</Row>
);
};
export default ModelForm;
`
fs.writeFileSync('src/Pages/' + fileName +"/Model"+"/"+"ModelForm.tsx",
FileContainer
);
console.log(`File "${fileName}" generated successfully.`);

View File

@ -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 (
<div className="TableWithHeader">
<Suspense fallback={<Spin />}>
<PageHeader
pageTitle="${fileName}"
ModelAbility={ModalEnum?.${capitalizeAllWord(fileName)}_ADD}
canAdd={canAdd${capitalizeFirstLetter(fileName)}}
/>
<FilterLayout
sub_children={<FilterForm />}
filterTitle="table.${fileName}"
/>
<Table />
<AddModalForm />
<EditModalForm />
<DeleteModalForm
deleteMutation={deleteMutation}
ModelEnum={ModalEnum?.${capitalizeAllWord(fileName)}_DELETE}
/>
</Suspense>
</div>
);
};
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() ;
}

View File

@ -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}`);
}

View File

@ -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: <DefaultIcon />, // 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();

View File

@ -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 <DataTable response={response} useColumns={useColumns} />;
};
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);
}

View File

@ -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<Nullable<InitialValues>>;
`;
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);
}