From 3f7c2310355efed2a6b4dce0b8352e05162f209c Mon Sep 17 00:00:00 2001 From: dariojorge Date: Tue, 17 Jun 2025 00:24:50 +0100 Subject: [PATCH 1/4] settings for the scripthub path and scripthub cards for the script arguments --- package.json | 15 +- src/app/fragments/input/input.tsx | 39 +++++ src/app/model/card-data-model.ts | 7 + src/app/model/data-list.ts | 1 + src/app/model/input-class.ts | 6 + src/app/model/input-model.ts | 10 ++ src/app/model/settings-model.ts | 3 + src/app/scripthub/arg-list.tsx | 92 ------------ src/app/scripthub/card-component.tsx | 201 ++++++++++++++++++++++++++ src/app/scripthub/script-hub.tsx | 33 +---- src/app/settings/settings-form.tsx | 70 +++++++++ src/app/settings/settings.styles.scss | 59 ++++++++ src/app/settings/settings.tsx | 7 +- src/app/utils/Utils.ts | 67 +++++++-- 14 files changed, 472 insertions(+), 138 deletions(-) create mode 100644 src/app/fragments/input/input.tsx create mode 100644 src/app/model/card-data-model.ts create mode 100644 src/app/model/input-class.ts create mode 100644 src/app/model/input-model.ts create mode 100644 src/app/model/settings-model.ts delete mode 100644 src/app/scripthub/arg-list.tsx create mode 100644 src/app/scripthub/card-component.tsx create mode 100644 src/app/settings/settings-form.tsx create mode 100644 src/app/settings/settings.styles.scss diff --git a/package.json b/package.json index 63097c7..a0ee3fa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "insomnia-script-hub", "private": true, - "version": "0.0.240", + "version": "0.0.476", "main": "dist/index.js", "insomnia": { "name": "script-hub", @@ -31,11 +31,14 @@ } }, "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@mui/material": "^7.1.1", "prop-types": "^15.5.7", - "react-json-tree": "^0.19.0", - "react-json-view-lite": "^1.4.0", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-json-tree": "^0.19.0", + "react-json-view-lite": "^1.4.0" }, "devDependencies": { "@seald-io/nedb": "^4.0.4", @@ -50,10 +53,10 @@ "eslint": "^8.44.0", "eslint-plugin-react": "^7.32.2", "npm-watch": "^0.11.0", + "react-resizable-panels": "^2.0.20", "request": "^2.88.0", "rimraf": "^5.0.1", "sass": "^1.63.6", - "semver": "^7.3.8", - "react-resizable-panels": "^2.0.20" + "semver": "^7.3.8" } } \ No newline at end of file diff --git a/src/app/fragments/input/input.tsx b/src/app/fragments/input/input.tsx new file mode 100644 index 0000000..7a54501 --- /dev/null +++ b/src/app/fragments/input/input.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import { InputClass } from "../../model/input-class"; + +const InputImpl = (props: { id: React.Key, title: string, name: string, value: string }) => { + return ( +
+ + +
+ ) +} + +export const Input = InputImpl; + +const InputUpdateImpl = (props: { id: React.Key, title: string, name: string, updateInput: (arg: any) => React.MouseEventHandler }) => { + return ( + <> + + + + ) +} + +export const InputUpdate = (props: { inputClass: InputClass, updateInput: any }) => { + return ( + <> + + + ) +} \ No newline at end of file diff --git a/src/app/model/card-data-model.ts b/src/app/model/card-data-model.ts new file mode 100644 index 0000000..8a7289a --- /dev/null +++ b/src/app/model/card-data-model.ts @@ -0,0 +1,7 @@ +interface CardData { + id: number; + title: string; + selectedOption: string; + options: Data[]; + filePath: string; +} \ No newline at end of file diff --git a/src/app/model/data-list.ts b/src/app/model/data-list.ts index 50da713..701c945 100644 --- a/src/app/model/data-list.ts +++ b/src/app/model/data-list.ts @@ -1,5 +1,6 @@ interface DataList { types: Data[]; + type: string; } interface Data { diff --git a/src/app/model/input-class.ts b/src/app/model/input-class.ts new file mode 100644 index 0000000..edb4849 --- /dev/null +++ b/src/app/model/input-class.ts @@ -0,0 +1,6 @@ +export class InputClass { + id!: number; + title!: string; + name!: string; + value!: string; +} \ No newline at end of file diff --git a/src/app/model/input-model.ts b/src/app/model/input-model.ts new file mode 100644 index 0000000..73f9587 --- /dev/null +++ b/src/app/model/input-model.ts @@ -0,0 +1,10 @@ +interface InputList { + inputList: Input[]; +} + +interface Input { + id: React.Key; + title: string; + name: string; + value: string; +} \ No newline at end of file diff --git a/src/app/model/settings-model.ts b/src/app/model/settings-model.ts new file mode 100644 index 0000000..7450dc2 --- /dev/null +++ b/src/app/model/settings-model.ts @@ -0,0 +1,3 @@ +interface SettingsModel { + scriptHubPath: string; +} \ No newline at end of file diff --git a/src/app/scripthub/arg-list.tsx b/src/app/scripthub/arg-list.tsx deleted file mode 100644 index 38a8021..0000000 --- a/src/app/scripthub/arg-list.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { createRoot } from "react-dom/client"; -import { Dropdown } from "../utils/dropdown/dropdown"; -import { firstElement, getElementByType, readFileDataList } from "../utils/Utils"; -const os = require('os'); -const homeDir = os.homedir(); - -const settingsFilename: string = 'settings.json'; -const scriptHubBasePathName: string = `${homeDir}/Documents/Confi/ScriptsHub/`; -let scriptTypePathName = ""; -let scriptTypeData: DataList; -let operationsData: DataList; - - -const ArgList = (props: { argList: any[] }) => { - const [scriptType, setScriptType] = useState(""); - const [operation, setOperation] = useState(""); - - useEffect(() => { - scriptTypeData = readFileDataList(scriptHubBasePathName, settingsFilename); - const scriptTypeInit = firstElement(scriptTypeData.types).name; - setScriptType(scriptTypeInit); - setOperationData(scriptTypeInit); - }, []) - - - const handleOnClick = async () => { - console.log(scriptType); - - /* const options: ExecSyncOptionsWithStringEncoding = { - shell: "C:\\Program Files\\Git\\bin\\bash.exe", - encoding: "utf8" - };*/ - - //const executeCmd = "scriptHub.sh scriptType=runners type=update projects=sf-display-service env=local"; - //const path = "cd ~ && cd Documents/Confi/ScriptsHub" - - //execSync(`cd ~ && cd ${scriptHubPathName} && ./scriptHub.sh scriptType=runners type=update projects=sf-display-service env=local`, options); - - /*exec(`${path} && ${executeCmd}`, options, (err: any, stdout: any, stderr: any) => { - if (err) { - console.error(err); - } else { - console.log(`The stdout Buffer from shell: ${stdout.toString()}`); - console.log(`The stderr Buffer from shell: ${stderr.toString()}`); - } - });*/ - }; - - - const updateScriptType = (event: { target: any; }) => { - setScriptType(event.target.value); - setOperationData(event.target.value); - } - - const updateOperation = (event: { target: any; }) => { - setOperation(event.target.value); - - const operationDataType = getElementByType(operationsData.types, event.target.value); - const operationPath = `${scriptTypePathName}${operationDataType.basePath}`; - const settingsData = readFileDataList(operationPath, settingsFilename); - console.log(getElementByType(settingsData.types, event.target.value)); - } - - const setOperationData = (scriptTypeInit: string) => { - const scriptTypeDataType = getElementByType(scriptTypeData.types, scriptTypeInit); - const scriptTypePath = `${scriptHubBasePathName}scripts${scriptTypeDataType.basePath}`; - operationsData = readFileDataList(scriptTypePath, settingsFilename); - scriptTypePathName = scriptTypePath; - - const operationDataType = getElementByType(operationsData.types, firstElement(operationsData.types).type); - const operationPath = `${scriptTypePath}${operationDataType.basePath}`; - const settingsData = readFileDataList(operationPath, settingsFilename); - console.log(getElementByType(settingsData.types, firstElement(operationsData.types).type)); - } - - return ( - <> - { props.argList.map(element => { - - }) - } - - ); -} - -const RenderPanelArgs = (elemCustom: any) => { - const elementRoot = createRoot(elemCustom); - elementRoot.render(()) -}; - -export default RenderPanelArgs; \ No newline at end of file diff --git a/src/app/scripthub/card-component.tsx b/src/app/scripthub/card-component.tsx new file mode 100644 index 0000000..e86d306 --- /dev/null +++ b/src/app/scripthub/card-component.tsx @@ -0,0 +1,201 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { checkForLastSlashInString, firstElement, getElementByType, getFolders, getLastElement, getSettings, isEmpty, isListEmpty, readFileDataList, removeAllElems } from '../utils/Utils'; + +const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; +const emptyListCardData: CardData[] = [emptyCardData]; +const settingsFilename: string = 'settings.json'; +const scriptHubPath = getSettings(settingsFilename).scriptHubPath; + +const CardComponent = () => { + const [cards, setCards] = useState(emptyListCardData); + const [cmdListCount, setCmdListCount] = useState(0); + const isFirstRender = useRef(true); + + useEffect(() => { + const settings = readFileDataList(scriptHubPath, settingsFilename); + const options = settings.types; + const scriptTypeInit = firstElement(options); + setCards([{ id: 0, title: settings.type, selectedOption: scriptTypeInit.type, options: options, filePath: scriptHubPath }]); + }, []) + + useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + const lastElem = getLastElement(cards, cmdListCount); + let newElem: CardData; + if (isListEmpty(lastElem.options)) { + return; + } + + const firstOptionElem = firstElement(lastElem.options); + if (!isListEmpty(firstOptionElem.cmdList)) { + newElem = buildCardOfEnvType(firstOptionElem.cmdList, lastElem.selectedOption); + } else { + newElem = buildCardWithBasePath(lastElem, firstOptionElem); + } + + if (newElem.id === -1) { + return; + } + + setCards(prev => [ + ...prev, + newElem + ]); + }, [cards]); + + const buildCardOfEnvType = (cmdList: any, lastElemSelectedOption: string): CardData => { + //console.log(lastElemSelectedOption); + if (cmdListCount + 1 > cmdList.length) { + return emptyCardData; + } + + setCmdListCount(cmdListCount + 1); + const cmd: { name: any; type: any; } = cmdList[cmdListCount]; + const id = cards.length; + const title = cmd.name; + const selectedOption = cmd.type; + const options: Data[] = getOptionsByType(cmd.type); + const filePath = ""; + + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }; + + const buildCardWithBasePath = (lastElem: CardData, firstOptionElem: any): CardData => { + console.log("lastElem"); + console.log(lastElem); + if (lastElem.selectedOption) { + firstOptionElem = getElementByType(lastElem.options, lastElem.selectedOption); + } + console.log(firstOptionElem); + + const id = cards.length; + const basePath = firstOptionElem.basePath.replaceAll(".", ""); + const basePathFiltered = checkForLastSlashInString(basePath.split('')); + const filePath = `${lastElem.filePath}${basePathFiltered}`; + const settings = readFileDataList(filePath, settingsFilename); + let options = settings.types; + const nextElem = firstElement(options); + + if (isEmpty(nextElem)) { + return emptyCardData; + } + + const title = settings.type; + let selectedOption = nextElem.type; + + if(title==="operation") { + selectedOption = lastElem.selectedOption; + + console.log("******operation*******"); + console.log(settings); + console.log(options); + console.log(selectedOption); + const rawOptions = firstElement(options.filter(type => type.name === selectedOption)).types; + options = []; + rawOptions?.forEach((type: string) => { + options.push({ + type: type, + name: type + }); + }); + console.log(options); + } + + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }; + + const handleSelectChange = (id: number, value: string) => { + cmdListCountRemoval(id); + setCards(removeAllElems(id, cards)); + setCards(prev => + prev.map(card => { + let currentOption = getElementByType(card.options, value); + return card.id === id ? + { + ...card, + selectedOption: getType(currentOption, value) + } : card; + } + ) + ); + }; + + const cmdListCountRemoval = (id: number) => { + const calc = cmdListCount - (cards.length - (id + 1)); + if (calc < 0) { + setCmdListCount(0); + return; + } + + setCmdListCount(calc); + } + + const getType = (currentOption: any, value: string) => { + if (currentOption.type) { + return currentOption.type; + } + + return currentOption.types.filter((type: string) => type === value); + } + + const getOptionsByType = (type: string) => { + switch (type) { + case "projectList": + return listOfAllProjects(); + case "envs": + return listOfAllProjects(); + case "additionalCmd": + return listOfAllProjects(); + default: + return [{ type: "a", name: "b" }]; + } + + } + + const listOfAllProjects = (): Data[] => { + const folderList = getFolders(`${scriptHubPath}/projects`); + const folders: Data[] = []; + folderList?.forEach(element => { + folders.push({ + type: element, + name: element + }); + }); + return folders; + } + + return ( +
+ {cards.filter(card => card.title !== "operations").map(card => ( +
+

{card.title}

+ +
+ ))} +
+ ); +}; + +export default CardComponent; \ No newline at end of file diff --git a/src/app/scripthub/script-hub.tsx b/src/app/scripthub/script-hub.tsx index 5e11f97..bf1229c 100644 --- a/src/app/scripthub/script-hub.tsx +++ b/src/app/scripthub/script-hub.tsx @@ -1,12 +1,13 @@ import React, { useEffect, useState } from "react"; import { createRoot } from "react-dom/client"; import { Dropdown } from "../utils/dropdown/dropdown"; -import { firstElement, getElementByType, readFileDataList } from "../utils/Utils"; +import { firstElement, getElementByType, getSettings, readFileDataList } from "../utils/Utils"; +import CardComponent from "./card-component"; const os = require('os'); const homeDir = os.homedir(); const settingsFilename: string = 'settings.json'; -const scriptHubBasePathName: string = `${homeDir}/Documents/Confi/ScriptsHub/`; +const scriptHubPath = getSettings(settingsFilename).scriptHubPath; let scriptTypePathName = ""; let scriptTypeData: DataList; let operationsData: DataList; @@ -18,34 +19,15 @@ const ScriptHub = (props: {}) => { const [cmdList, setCmdList] = useState([]); useEffect(() => { - scriptTypeData = readFileDataList(scriptHubBasePathName, settingsFilename); + /*scriptTypeData = readFileDataList(scriptHubPath, settingsFilename); const scriptTypeInit = firstElement(scriptTypeData.types).name; setScriptType(scriptTypeInit); - setOperationData(scriptTypeInit); + setOperationData(scriptTypeInit);*/ }, []) const handleOnClick = async () => { console.log(scriptType); - - /* const options: ExecSyncOptionsWithStringEncoding = { - shell: "C:\\Program Files\\Git\\bin\\bash.exe", - encoding: "utf8" - };*/ - - //const executeCmd = "scriptHub.sh scriptType=runners type=update projects=sf-display-service env=local"; - //const path = "cd ~ && cd Documents/Confi/ScriptsHub" - - //execSync(`cd ~ && cd ${scriptHubPathName} && ./scriptHub.sh scriptType=runners type=update projects=sf-display-service env=local`, options); - - /*exec(`${path} && ${executeCmd}`, options, (err: any, stdout: any, stderr: any) => { - if (err) { - console.error(err); - } else { - console.log(`The stdout Buffer from shell: ${stdout.toString()}`); - console.log(`The stderr Buffer from shell: ${stderr.toString()}`); - } - });*/ }; @@ -66,10 +48,10 @@ const ScriptHub = (props: {}) => { const setOperationData = (scriptTypeInit: string) => { const scriptTypeDataType = getElementByType(scriptTypeData.types, scriptTypeInit); - const scriptTypePath = `${scriptHubBasePathName}scripts${scriptTypeDataType.basePath}`; + const scriptTypePath = `${scriptHubPath}/scripts${scriptTypeDataType.basePath}`; operationsData = readFileDataList(scriptTypePath, settingsFilename); scriptTypePathName = scriptTypePath; - + const operationDataType = getElementByType(operationsData.types, firstElement(operationsData.types).type); const operationPath = `${scriptTypePath}${operationDataType.basePath}`; const settingsData = readFileDataList(operationPath, settingsFilename); @@ -87,6 +69,7 @@ const ScriptHub = (props: {}) => { {operationsData !== undefined && } + ); } diff --git a/src/app/settings/settings-form.tsx b/src/app/settings/settings-form.tsx new file mode 100644 index 0000000..179fc0e --- /dev/null +++ b/src/app/settings/settings-form.tsx @@ -0,0 +1,70 @@ +import React, { useEffect, useState } from 'react'; +import { + Box, + Button, + TextField, + Typography, + Container, + Paper, +} from '@mui/material'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; +import { getSettings, saveSettings } from '../utils/Utils'; + +const theme = createTheme({ + palette: { + primary: { + main: '#1976d2', + }, + }, + typography: { + fontFamily: 'Roboto, Arial', + }, +}); + +const SettingsFormImpl = (props: {}) => { + const [formData, setFormData] = useState({ scriptHubPath: '' }); + + useEffect(() => { + setFormData((prevData) => ({ + ...prevData, + ...getSettings("settings.json") + })); + }, []); + + const handleScriptHubPathChange = (event: { target: any; }) => { + setFormData((prevData) => ({ + ...prevData, + scriptHubPath: event.target.value + })); + }; + + const handleSubmit = (e: { preventDefault: () => void; }) => { + e.preventDefault(); + saveSettings(formData, "settings.json"); + }; + + return ( + <> + + + + Settings + + + + + + + + + ); +} + +export const SettingsForm = SettingsFormImpl; diff --git a/src/app/settings/settings.styles.scss b/src/app/settings/settings.styles.scss new file mode 100644 index 0000000..7247356 --- /dev/null +++ b/src/app/settings/settings.styles.scss @@ -0,0 +1,59 @@ +.settings-card { + background: #a74646; + padding: 32px; + border-radius: 12px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.settings-form { + display: flex; + flex-direction: column; + gap: 20px; +} + +.form2 { + max-width: 400px; + margin: 2rem auto; + padding: 1.5rem; + border: 1px solid #ccc; + border-radius: 8px; + background: #f9f9f9; + + &-title { + text-align: center; + margin-bottom: 1rem; + font-size: 1.5rem; + } + + &-group { + margin-bottom: 1rem; + display: flex; + flex-direction: column; + + label { + margin-bottom: 0.5rem; + font-weight: 600; + } + + input { + padding: 0.5rem; + border: 1px solid #aaa; + border-radius: 4px; + font-size: 1rem; + } + } + + &-button { + background-color: #007bff; + color: white; + padding: 0.6rem 1rem; + border: none; + border-radius: 4px; + font-size: 1rem; + cursor: pointer; + + &:hover { + background-color: #0056b3; + } + } +} \ No newline at end of file diff --git a/src/app/settings/settings.tsx b/src/app/settings/settings.tsx index 41012da..8a06998 100644 --- a/src/app/settings/settings.tsx +++ b/src/app/settings/settings.tsx @@ -1,11 +1,12 @@ -import React from "react"; +import React from 'react'; import { createRoot } from "react-dom/client"; +import './settings.styles.scss'; +import { SettingsForm } from './settings-form'; const Settings = (props: {}) => { - console.log("Settings"); return ( <> - + ); } diff --git a/src/app/utils/Utils.ts b/src/app/utils/Utils.ts index b5737c1..a69a998 100644 --- a/src/app/utils/Utils.ts +++ b/src/app/utils/Utils.ts @@ -1,28 +1,71 @@ import fs from 'fs'; import path from "path"; +import os from 'os'; import { ExecSyncOptionsWithStringEncoding } from "child_process"; + +const homeDir = os.homedir(); const options: ExecSyncOptionsWithStringEncoding = { encoding: "utf8" }; -const isListEmpty = (list: any[]) => !list || list.length <= 0; +const openFile = (filePath: string) => fs.readFileSync(filePath.replaceAll("\/", path.sep), options); +const getTypesOrType = (element: any, elementName: string) => { + if (element.type !== undefined) { + return element.type === elementName; + } + + return element.types.includes(elementName); +} + +export const isListEmpty = (list: any[]) => !list || list.length <= 0; +export const getSettings = (fileName: string): SettingsModel => { + const pathName: string = path.resolve(__dirname, fileName); + if (!fs.existsSync(pathName)) { + let settings: SettingsModel = { + scriptHubPath: homeDir + }; + saveSettings(settings!, pathName); + } + + return JSON.parse(fs.readFileSync(pathName, options)); +}; + +export const saveSettings = (formData: SettingsModel, fileName: string) => { + const pathName: string = path.resolve(__dirname, fileName); + fs.writeFileSync(pathName, JSON.stringify(formData), options); +}; export const readFileDataList = (pathName: string, fileName: string): DataList => { - return JSON.parse(openFile(`${pathName}/${fileName}`.replaceAll("\\", "/").replaceAll("//", "/"))); + let settingsPath = `${pathName}/${fileName}`.replaceAll("\\", "/").replaceAll("//", "/"); + + if (!fs.existsSync(settingsPath)) { + return JSON.parse('{ "types": [] }'); + } + return JSON.parse(openFile(settingsPath)); } -const openFile = (filePath: string) => fs.readFileSync(filePath.replaceAll("\/", path.sep), options); -export const isBlank = (stringValue: string) => (!stringValue || /^\s*$/.test(stringValue)); +export const checkForLastSlashInString = (chars: string[]) => { + const lastElem = getLastElement(chars); + if (lastElem === '/' || lastElem === '\\') { + chars.pop(); + } + return chars.join(''); +} + +export const removeAllElems = (startIndex: number, list: CardData[]) => { + return list.filter(card => card.id <= startIndex); +} +export const isBlank = (stringValue: string) => (!stringValue || /^\s*$/.test(stringValue)); +export const isEmpty = (value: string | any[] | null) => value == null || value.length === 0; export const firstElement = (list: any[]) => list.length > 0 ? list[0] : null; export const getFilteredList = (list: any[], filter: any) => list.filter(filter); - -const getTypesOrType = (element: any, elementName: string) => { - if(element.type !== undefined) { - return element.type === elementName; +export const getElementByType = (list: any[], elementName: string) => isListEmpty(list) ? undefined : firstElement(list.filter(element => getTypesOrType(element, elementName))); +export const getLastElement = (list: any[], offset: number = 0) => list[list.length - (1 + offset)]; +export const getFolders = (path: string) => { + if (!fs.existsSync(path)) { + return; } - - return element.types.includes(elementName); -} -export const getElementByType = (list: any[], elementName: string) => isListEmpty(list) ? undefined : firstElement(list.filter(element => getTypesOrType(element, elementName))); \ No newline at end of file + return fs.readdirSync(path).filter(file => fs.statSync(path + '/' + file).isDirectory()); +}; \ No newline at end of file From 8e4d12b5c97ec21a1109194bfb0200dc6c66ca44 Mon Sep 17 00:00:00 2001 From: dariojorge Date: Mon, 23 Jun 2025 23:48:51 +0100 Subject: [PATCH 2/4] Adding the additional-cmd-component Adding the operation-component Adding the script-component Adding the checkbox --- package.json | 2 +- src/app/fragments/checkbox/checkbox.tsx | 26 +++ src/app/model/argument-model.ts | 4 + src/app/model/data-list.ts | 2 + src/app/model/envs-data.ts | 20 +++ .../scripthub/additional-cmd-component.tsx | 92 ++++++++++ src/app/scripthub/card-component.tsx | 56 ++++-- src/app/scripthub/operation-component.tsx | 162 ++++++++++++++++++ src/app/scripthub/script-component.tsx | 135 +++++++++++++++ src/app/scripthub/script-hub.tsx | 119 ++++++++----- src/app/utils/Utils.ts | 15 ++ 11 files changed, 569 insertions(+), 64 deletions(-) create mode 100644 src/app/fragments/checkbox/checkbox.tsx create mode 100644 src/app/model/argument-model.ts create mode 100644 src/app/model/envs-data.ts create mode 100644 src/app/scripthub/additional-cmd-component.tsx create mode 100644 src/app/scripthub/operation-component.tsx create mode 100644 src/app/scripthub/script-component.tsx diff --git a/package.json b/package.json index a0ee3fa..0f6e3ea 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "insomnia-script-hub", "private": true, - "version": "0.0.476", + "version": "0.0.668", "main": "dist/index.js", "insomnia": { "name": "script-hub", diff --git a/src/app/fragments/checkbox/checkbox.tsx b/src/app/fragments/checkbox/checkbox.tsx new file mode 100644 index 0000000..9888633 --- /dev/null +++ b/src/app/fragments/checkbox/checkbox.tsx @@ -0,0 +1,26 @@ +import React, { useState } from 'react'; + +const CheckboxComponent = (props: { title: string; updateData: any; }) => { + const [isChecked, setIsChecked] = useState(false); + + const handleCheckboxChange = (event: { target: { name: string; checked: boolean | ((prevState: boolean) => boolean); }; }) => { + setIsChecked(event.target.checked); + props.updateData({name: event.target.name, value: event.target.checked}); + }; + + return ( +
+ +
+ ); +} + +export default CheckboxComponent; \ No newline at end of file diff --git a/src/app/model/argument-model.ts b/src/app/model/argument-model.ts new file mode 100644 index 0000000..9e2d34f --- /dev/null +++ b/src/app/model/argument-model.ts @@ -0,0 +1,4 @@ +interface ArgumentModel { + title: string; + value: string; +} \ No newline at end of file diff --git a/src/app/model/data-list.ts b/src/app/model/data-list.ts index 701c945..65c8ff2 100644 --- a/src/app/model/data-list.ts +++ b/src/app/model/data-list.ts @@ -6,4 +6,6 @@ interface DataList { interface Data { type: string; name: string; + cmdList?: any[]; + types?: string[]; } \ No newline at end of file diff --git a/src/app/model/envs-data.ts b/src/app/model/envs-data.ts new file mode 100644 index 0000000..ed73b92 --- /dev/null +++ b/src/app/model/envs-data.ts @@ -0,0 +1,20 @@ +interface EnvsData { + envs: Env[]; + additionalCmd: AdditionalCmd[]; +} + +interface Env { + type: string; + envVars: EnvVar[]; +} + +interface EnvVar { + key: string; + value: string; +} + +interface AdditionalCmd { + type: string; + value: string; + cmd: string; +} \ No newline at end of file diff --git a/src/app/scripthub/additional-cmd-component.tsx b/src/app/scripthub/additional-cmd-component.tsx new file mode 100644 index 0000000..9414f6a --- /dev/null +++ b/src/app/scripthub/additional-cmd-component.tsx @@ -0,0 +1,92 @@ +import React, { useEffect, useRef, useState } from 'react'; +import { firstElement, getSettings, isEmpty, isListEmpty, readFileEnvs } from '../utils/Utils'; +import CheckboxComponent from '../fragments/checkbox/checkbox'; + +const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; +const emptyListCardData: CardData[] = [emptyCardData]; +const settingsFilename: string = 'settings.json'; +const scriptHubPath = getSettings(settingsFilename).scriptHubPath; + +const AdditionalCmdComponent = (props: { additionalCmd: CardData; selectedProject: string; updateData: any; }) => { + const [cards, setCards] = useState(emptyListCardData); + const isFirstRender = useRef(true); + + useEffect(() => { + setCards(prev => prev.filter(operation => operation.id !== -1)); + }, []) + + useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + if (cards.length >= 5) { + return; + } + + let newElem: CardData; + if (isListEmpty(props.additionalCmd.options) || cards.filter(card => card.title === "additionalCmd").length === 1) { + return; + } + + const operationOptionElem = firstElement(props.additionalCmd.options); + if (!isListEmpty(operationOptionElem.cmdList)) { + newElem = buildCardOfEnvType(operationOptionElem.cmdList, props.additionalCmd.selectedOption); + } else { + newElem = emptyCardData; + } + + if (newElem.id === -1) { + return; + } + + setCards(prev => [ + ...prev, + newElem + ]); + }, [cards, props.selectedProject]); + + const buildCardOfEnvType = (cmdList: any, lastElemSelectedOption: string): CardData => { + const cmd: { name: any; type: any; } = firstElement(cmdList.filter((cmd: { name: any; type: any; }) => cmd.name === "additionalCmd")); + const id = cards.length; + const title = cmd.name; + const selectedOption = cmd.type; + const options: Data[] = listOfAllAdditionalCmd(); + const filePath = ""; + + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }; + + const handleSelectChange = (value: any) => { + console.log("Additional cmd from checkbox: "); + console.log(value); + }; + + const listOfAllAdditionalCmd = (): Data[] => { + if (isEmpty(props.selectedProject)) { + return []; + } + + const settings = readFileEnvs(`${scriptHubPath}/projects/${props.selectedProject}`); + const envList: Data[] = []; + + settings.additionalCmd?.filter(arg => arg.type === "arg").forEach(env => { + envList.push({ + type: env.value, + name: env.value + }); + }); + return envList; + } + + return ( +
+ {!isListEmpty(cards) && firstElement(cards) !== null && !isListEmpty(firstElement(cards).options) && firstElement(cards).options.map((cmd: { name: string; }) => ( + + ))} +
+ ); +}; + +export default AdditionalCmdComponent; \ No newline at end of file diff --git a/src/app/scripthub/card-component.tsx b/src/app/scripthub/card-component.tsx index e86d306..dc050e3 100644 --- a/src/app/scripthub/card-component.tsx +++ b/src/app/scripthub/card-component.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; -import { checkForLastSlashInString, firstElement, getElementByType, getFolders, getLastElement, getSettings, isEmpty, isListEmpty, readFileDataList, removeAllElems } from '../utils/Utils'; +import { checkForLastSlashInString, firstElement, getElementByType, getFolders, getLastElement, getSettings, isEmpty, isListEmpty, readFileDataList, readFileEnvs, removeAllElems } from '../utils/Utils'; const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; const emptyListCardData: CardData[] = [emptyCardData]; @@ -48,7 +48,6 @@ const CardComponent = () => { }, [cards]); const buildCardOfEnvType = (cmdList: any, lastElemSelectedOption: string): CardData => { - //console.log(lastElemSelectedOption); if (cmdListCount + 1 > cmdList.length) { return emptyCardData; } @@ -65,12 +64,9 @@ const CardComponent = () => { }; const buildCardWithBasePath = (lastElem: CardData, firstOptionElem: any): CardData => { - console.log("lastElem"); - console.log(lastElem); if (lastElem.selectedOption) { firstOptionElem = getElementByType(lastElem.options, lastElem.selectedOption); } - console.log(firstOptionElem); const id = cards.length; const basePath = firstOptionElem.basePath.replaceAll(".", ""); @@ -90,19 +86,17 @@ const CardComponent = () => { if(title==="operation") { selectedOption = lastElem.selectedOption; - console.log("******operation*******"); - console.log(settings); - console.log(options); - console.log(selectedOption); - const rawOptions = firstElement(options.filter(type => type.name === selectedOption)).types; + const rawOptions = firstElement(options.filter(option => option.types?.includes(selectedOption))); + const types = rawOptions.types; + const cmdList = rawOptions.cmdList; options = []; - rawOptions?.forEach((type: string) => { + types?.forEach((type: string) => { options.push({ type: type, - name: type + name: type, + cmdList: cmdList }); }); - console.log(options); } return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; @@ -147,15 +141,19 @@ const CardComponent = () => { case "projectList": return listOfAllProjects(); case "envs": - return listOfAllProjects(); + return listOfAllEnvironments(); case "additionalCmd": - return listOfAllProjects(); + return listOfAllAdditionalCmd(); default: return [{ type: "a", name: "b" }]; } } + const getSelectedProject = () => { + return firstElement(cards.filter(cardData => cardData.title === "projects")).selectedOption; + } + const listOfAllProjects = (): Data[] => { const folderList = getFolders(`${scriptHubPath}/projects`); const folders: Data[] = []; @@ -168,9 +166,35 @@ const CardComponent = () => { return folders; } + const listOfAllEnvironments = (): Data[] => { + const selectedProject = getSelectedProject(); + const settings = readFileEnvs(`${scriptHubPath}/projects/${selectedProject}`); + const envList: Data[] = []; + settings.envs?.forEach(env => { + envList.push({ + type: env.type, + name: env.type + }); + }); + return envList; + } + + const listOfAllAdditionalCmd = (): Data[] => { + const selectedProject = getSelectedProject(); + const settings = readFileEnvs(`${scriptHubPath}/projects/${selectedProject}`); + const envList: Data[] = []; + settings.additionalCmd?.forEach(env => { + envList.push({ + type: env.key, + name: env.key + }); + }); + return envList; + } + return (
- {cards.filter(card => card.title !== "operations").map(card => ( + {cards.filter(card => card.title !== "operation").map(card => (
{ + const isFirstRender = useRef(true); + + useEffect(() => { + props.updateData((prev: any[]) => prev.filter(operation => operation.id !== -1)); + }, []) + + useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + if (isListEmpty(props.operation.options)) { + return; + } + + const operationOptionElem = firstElement(props.operation.options); + if (isListEmpty(operationOptionElem.cmdList)) { + return; + } + + const newElem = buildCardOfEnvType(operationOptionElem.cmdList); + if (newElem.id === -1) { + return; + } + + props.updateData((prev: any) => [ + ...prev, + newElem + ]); + }, [props.operationData]); + + const buildCardOfEnvType = (cmdList: any): CardData => { + const count = isListEmpty(getLastElement(props.operationData)) ? 0 : getLastElement(props.operationData).id + 1; + if(count > cmdList.length) { + return emptyCardData; + } + + const cmd: { name: any; type: any; } = cmdList[count]; + console.log("count: "); + console.log(count); + console.log(cmdList.length); + console.log(cmd); + console.log(cmdList); + console.log(props.operationData); + console.log("******************"); + if (cmd === undefined || cmd.name === "additionalCmd") { + return emptyCardData; + } + const id = props.operationData.length; + const title = cmd.name; + const selectedOption = cmd.type; + const options: Data[] = getOptionsByType(cmd.type); + const filePath = ""; + + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }; + + const handleSelectChange = (id: number, value: string) => { + props.updateData(removeAllElems(id, props.operationData)); + props.updateData((prev: any[]) => + prev.map(card => { + let currentOption = getElementByType(card.options, value); + return card.id === id ? + { + ...card, + selectedOption: getType(currentOption, value) + } : card; + } + ) + ); + }; + + const getType = (currentOption: any, value: string) => { + if (currentOption.type) { + return currentOption.type; + } + + return currentOption.types.filter((type: string) => type === value); + } + + const getOptionsByType = (type: string) => { + switch (type) { + case "projectList": + return listOfAllProjects(); + case "envs": + return listOfAllEnvironments(); + default: + return [{ type: "a", name: "b" }]; + } + + } + + const getSelectedProject = () => { + return firstElement(props.operationData.filter(cardData => cardData.title === "projects")).selectedOption; + } + + const listOfAllProjects = (): Data[] => { + const folderList = getFolders(`${scriptHubPath}/projects`); + const folders: Data[] = []; + folderList?.forEach(element => { + folders.push({ + type: element, + name: element + }); + }); + return folders; + } + + const listOfAllEnvironments = (): Data[] => { + const selectedProject = getSelectedProject(); + const settings = readFileEnvs(`${scriptHubPath}/projects/${selectedProject}`); + const envList: Data[] = []; + settings.envs?.forEach(env => { + envList.push({ + type: env.type, + name: env.type + }); + }); + return envList; + } + + return ( +
+ {props.operationData.map(card => ( +
+

{card.title}

+ +
+ ))} +
+ ); +}; + +export default OperationComponent; \ No newline at end of file diff --git a/src/app/scripthub/script-component.tsx b/src/app/scripthub/script-component.tsx new file mode 100644 index 0000000..f3141eb --- /dev/null +++ b/src/app/scripthub/script-component.tsx @@ -0,0 +1,135 @@ +import React, { useEffect, useRef } from 'react'; +import { checkForLastSlashInString, firstElement, getElementByType, getLastElement, getSettings, isEmpty, isListEmpty, readFileDataList, removeAllElems } from '../utils/Utils'; + +const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; +const emptyListCardData: CardData[] = [emptyCardData]; +const settingsFilename: string = 'settings.json'; +const scriptHubPath = getSettings(settingsFilename).scriptHubPath; + +const ScriptComponent = (props: { scriptData: CardData[]; updateData: any; }) => { + const isFirstRender = useRef(true); + + useEffect(() => { + const settings = readFileDataList(scriptHubPath, settingsFilename); + const options = settings.types; + const scriptTypeInit = firstElement(options); + const initData = [{ id: 0, title: settings.type, selectedOption: scriptTypeInit.type, options: options, filePath: scriptHubPath }]; + props.updateData(initData); + }, []) + + useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + return; + } + + const lastElem = getLastElement(props.scriptData); + if (lastElem.title === "operation") { + return; + } + + const newElem = buildCardWithBasePath(lastElem); + if (newElem.id === -1) { + return; + } + + props.updateData((prev: any) => [ + ...prev, + newElem + ]); + }, [props.scriptData]); + + const buildCardWithBasePath = (lastElem: CardData): CardData => { + if (!lastElem.selectedOption) { + return emptyCardData; + } + + const firstOptionElem = getElementByType(lastElem.options, lastElem.selectedOption); + const id = props.scriptData.length; + const basePath = firstOptionElem.basePath.replaceAll(".", ""); + const basePathFiltered = checkForLastSlashInString(basePath.split('')); + const filePath = `${lastElem.filePath}${basePathFiltered}`; + const settings = readFileDataList(filePath, settingsFilename); + let options = settings.types; + const nextElem = firstElement(options); + + if (isEmpty(nextElem)) { + return emptyCardData; + } + + const title = settings.type; + let selectedOption = nextElem.type; + + if (title === "operation") { + selectedOption = lastElem.selectedOption; + + const rawOptions = firstElement(options.filter(option => option.types?.includes(selectedOption))); + const types = rawOptions.types; + const cmdList = rawOptions.cmdList; + options = []; + types?.forEach((type: string) => { + options.push({ + type: type, + name: type, + cmdList: cmdList + }); + }); + } + + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }; + + const handleSelectChange = (id: number, value: string) => { + props.updateData(removeAllElems(id, props.scriptData)); + props.updateData((prev: { options: any[]; id: number; }[]) => + prev.map((card: { options: any[]; id: number; }) => { + let currentOption = getElementByType(card.options, value); + return card.id === id ? + { + ...card, + selectedOption: getType(currentOption, value) + } : card; + } + ) + ); + }; + + const getType = (currentOption: any, value: string) => { + if (currentOption.type) { + return currentOption.type; + } + + return currentOption.types.filter((type: string) => type === value); + } + + return ( +
+ {props.scriptData.filter(card => card.title !== "operation").map(card => ( +
+

{card.title}

+ +
+ ))} +
+ ); +}; + +export default ScriptComponent; \ No newline at end of file diff --git a/src/app/scripthub/script-hub.tsx b/src/app/scripthub/script-hub.tsx index bf1229c..4569e76 100644 --- a/src/app/scripthub/script-hub.tsx +++ b/src/app/scripthub/script-hub.tsx @@ -1,75 +1,100 @@ import React, { useEffect, useState } from "react"; import { createRoot } from "react-dom/client"; -import { Dropdown } from "../utils/dropdown/dropdown"; -import { firstElement, getElementByType, getSettings, readFileDataList } from "../utils/Utils"; -import CardComponent from "./card-component"; -const os = require('os'); -const homeDir = os.homedir(); +import { firstElement, getLastElement, getSettings, isBlank, isEmpty, isListEmpty } from "../utils/Utils"; +import ScriptComponent from "./script-component"; +import OperationComponent from "./operation-component"; +import AdditionalCmdComponent from "./additional-cmd-component"; const settingsFilename: string = 'settings.json'; const scriptHubPath = getSettings(settingsFilename).scriptHubPath; -let scriptTypePathName = ""; -let scriptTypeData: DataList; -let operationsData: DataList; +const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; +const emptyListCardData: CardData[] = [emptyCardData]; const ScriptHub = (props: {}) => { - const [scriptType, setScriptType] = useState(""); - const [operation, setOperation] = useState(""); - const [cmdList, setCmdList] = useState([]); + const [scriptData, setScriptData] = useState(emptyListCardData); + const [operation, setOperation] = useState(emptyCardData); + const [operationData, setOperationData] = useState(emptyListCardData); + const [additionalCmdData, setAdditionalCmdData] = useState(emptyListCardData); + const [selectedProject, setSelectedProject] = useState(""); - useEffect(() => { - /*scriptTypeData = readFileDataList(scriptHubPath, settingsFilename); - const scriptTypeInit = firstElement(scriptTypeData.types).name; - setScriptType(scriptTypeInit); - setOperationData(scriptTypeInit);*/ - }, []) + const [argumentData, setArgumentData] = useState([]); + useEffect(() => { + //console.log("Argument Data:"); + //console.log(argumentData); + }, [argumentData]); - const handleOnClick = async () => { - console.log(scriptType); - }; + useEffect(() => { + console.log("Script Data:"); + console.log(scriptData); + buildArgumentData(scriptData.filter(script => script.title !== "operation")); + buildOperation(); + }, [scriptData]); - const updateScriptType = (event: { target: any; }) => { - setScriptType(event.target.value); - setOperationData(event.target.value); + const buildOperation = () => { + const opetationResult = firstElement(scriptData.filter(script => script.title === "operation")); + if (opetationResult === null || opetationResult.id === -1) { + return; + } + setOperation(opetationResult); } - const updateOperation = (event: { target: any; }) => { - setOperation(event.target.value); + useEffect(() => { + console.log("Operation Data:"); + console.log(operationData); + buildArgumentData(operationData.filter(card => card.id !== 0)); + buildAdditionalCmdData(); + buildSelectedProject(); + }, [operationData]); + + const buildAdditionalCmdData = () => { + const additionalCmd = operationData.filter(card => card.id !== 0); + setAdditionalCmdData(additionalCmd); + } - const operationDataType = getElementByType(operationsData.types, event.target.value); - const operationPath = `${scriptTypePathName}${operationDataType.basePath}`; - const settingsData = readFileDataList(operationPath, settingsFilename); - console.log(settingsData.types); - console.log(getElementByType(settingsData.types, event.target.value)); + const buildSelectedProject = () => { + const projects = firstElement(operationData.filter(data => data.title === "projects")); + if (projects !== null && !isEmpty(projects.selectedOption)) { + setSelectedProject(projects.selectedOption); + } } - const setOperationData = (scriptTypeInit: string) => { - const scriptTypeDataType = getElementByType(scriptTypeData.types, scriptTypeInit); - const scriptTypePath = `${scriptHubPath}/scripts${scriptTypeDataType.basePath}`; - operationsData = readFileDataList(scriptTypePath, settingsFilename); - scriptTypePathName = scriptTypePath; - const operationDataType = getElementByType(operationsData.types, firstElement(operationsData.types).type); - const operationPath = `${scriptTypePath}${operationDataType.basePath}`; - const settingsData = readFileDataList(operationPath, settingsFilename); - console.log(getElementByType(settingsData.types, firstElement(operationsData.types).type)); + const handleOnClick = async () => { + //console.log(scriptType); + }; + + const buildArgumentData = (cardData: CardData[]) => { + const newData: ArgumentModel[] = cardData.map(data => ({ title: data.title, value: data.selectedOption })); + const mergedUnique = Array.from( + new Map([...argumentData.filter(argument => !isBlank(argument.title)), ...newData].map(item => [item.title, item])).values() + ); + setArgumentData(mergedUnique); } return ( <> - - {scriptTypeData !== undefined && - +
+ +
+
+ +
+ {operation.id !== -1 && +
+ +
} - {operationsData !== undefined && - + {!isListEmpty(additionalCmdData) && firstElement(additionalCmdData).id !== -1 && +
+ +
} - + ); } diff --git a/src/app/utils/Utils.ts b/src/app/utils/Utils.ts index a69a998..75e685e 100644 --- a/src/app/utils/Utils.ts +++ b/src/app/utils/Utils.ts @@ -7,6 +7,11 @@ const homeDir = os.homedir(); const options: ExecSyncOptionsWithStringEncoding = { encoding: "utf8" }; +const ENVS_FILE_NAME = "envs.json"; + +export const log = (message: string) => console.log(message); +export const warning = (message: string) => console.warn(message); +export const error = (message: string) => console.error(message); const openFile = (filePath: string) => fs.readFileSync(filePath.replaceAll("\/", path.sep), options); const getTypesOrType = (element: any, elementName: string) => { @@ -44,6 +49,16 @@ export const readFileDataList = (pathName: string, fileName: string): DataList = return JSON.parse(openFile(settingsPath)); } +export const readFileEnvs = (pathName: string): EnvsData => { + let settingsPath = `${pathName}/${ENVS_FILE_NAME}`.replaceAll("\\", "/").replaceAll("//", "/"); + + if (!fs.existsSync(settingsPath)) { + error(`The file envs.json does not exist. Returning empty json. Path: ${settingsPath}`); + return JSON.parse('{}'); + } + return JSON.parse(openFile(settingsPath)); +} + export const checkForLastSlashInString = (chars: string[]) => { const lastElem = getLastElement(chars); if (lastElem === '/' || lastElem === '\\') { From 306497883ba2911ff7ea9b08b3f01e8d1992abbf Mon Sep 17 00:00:00 2001 From: dariojorge Date: Thu, 26 Jun 2025 01:38:32 +0100 Subject: [PATCH 3/4] Making the additional cmd data working --- package.json | 2 +- .../scripthub/additional-cmd-component.tsx | 19 ++++++++------- src/app/scripthub/script-hub.tsx | 24 +++++++++++++++---- tsconfig.json | 12 +++++----- 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 0f6e3ea..f66d4c6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "insomnia-script-hub", "private": true, - "version": "0.0.668", + "version": "0.0.698", "main": "dist/index.js", "insomnia": { "name": "script-hub", diff --git a/src/app/scripthub/additional-cmd-component.tsx b/src/app/scripthub/additional-cmd-component.tsx index 9414f6a..d3db416 100644 --- a/src/app/scripthub/additional-cmd-component.tsx +++ b/src/app/scripthub/additional-cmd-component.tsx @@ -7,7 +7,7 @@ const emptyListCardData: CardData[] = [emptyCardData]; const settingsFilename: string = 'settings.json'; const scriptHubPath = getSettings(settingsFilename).scriptHubPath; -const AdditionalCmdComponent = (props: { additionalCmd: CardData; selectedProject: string; updateData: any; }) => { +const AdditionalCmdComponent = (props: { operation: CardData; selectedProject: string; updateData: any; }) => { const [cards, setCards] = useState(emptyListCardData); const isFirstRender = useRef(true); @@ -26,13 +26,13 @@ const AdditionalCmdComponent = (props: { additionalCmd: CardData; selectedProjec } let newElem: CardData; - if (isListEmpty(props.additionalCmd.options) || cards.filter(card => card.title === "additionalCmd").length === 1) { + if (isListEmpty(props.operation.options) || cards.filter(card => card.title === "additionalCmd").length === 1) { return; } - const operationOptionElem = firstElement(props.additionalCmd.options); + const operationOptionElem = firstElement(props.operation.options); if (!isListEmpty(operationOptionElem.cmdList)) { - newElem = buildCardOfEnvType(operationOptionElem.cmdList, props.additionalCmd.selectedOption); + newElem = buildCardOfEnvType(operationOptionElem.cmdList); } else { newElem = emptyCardData; } @@ -47,7 +47,7 @@ const AdditionalCmdComponent = (props: { additionalCmd: CardData; selectedProjec ]); }, [cards, props.selectedProject]); - const buildCardOfEnvType = (cmdList: any, lastElemSelectedOption: string): CardData => { + const buildCardOfEnvType = (cmdList: any): CardData => { const cmd: { name: any; type: any; } = firstElement(cmdList.filter((cmd: { name: any; type: any; }) => cmd.name === "additionalCmd")); const id = cards.length; const title = cmd.name; @@ -55,12 +55,15 @@ const AdditionalCmdComponent = (props: { additionalCmd: CardData; selectedProjec const options: Data[] = listOfAllAdditionalCmd(); const filePath = ""; + if(isListEmpty(options)) { + return emptyCardData; + } + return { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; }; - const handleSelectChange = (value: any) => { - console.log("Additional cmd from checkbox: "); - console.log(value); + const handleSelectChange = (data: any) => { + props.updateData({ id: 0, title: data.name, selectedOption: data.value, options: [], filePath: "" }); }; const listOfAllAdditionalCmd = (): Data[] => { diff --git a/src/app/scripthub/script-hub.tsx b/src/app/scripthub/script-hub.tsx index 4569e76..4c0895b 100644 --- a/src/app/scripthub/script-hub.tsx +++ b/src/app/scripthub/script-hub.tsx @@ -16,13 +16,14 @@ const ScriptHub = (props: {}) => { const [operation, setOperation] = useState(emptyCardData); const [operationData, setOperationData] = useState(emptyListCardData); const [additionalCmdData, setAdditionalCmdData] = useState(emptyListCardData); + const [additionalCmd, setAdditionalCmd] = useState(emptyCardData); const [selectedProject, setSelectedProject] = useState(""); const [argumentData, setArgumentData] = useState([]); useEffect(() => { - //console.log("Argument Data:"); - //console.log(argumentData); + console.log("Argument Data:"); + console.log(argumentData); }, [argumentData]); useEffect(() => { @@ -44,7 +45,8 @@ const ScriptHub = (props: {}) => { useEffect(() => { console.log("Operation Data:"); console.log(operationData); - buildArgumentData(operationData.filter(card => card.id !== 0)); + + buildArgumentData(operationData.filter(card => card.id !== -1)); buildAdditionalCmdData(); buildSelectedProject(); }, [operationData]); @@ -61,6 +63,18 @@ const ScriptHub = (props: {}) => { } } + useEffect(() => { + console.log("Additional Cmd Data:"); + console.log(additionalCmd); + + const cardDataList: CardData[] = [{ id: 0, title: additionalCmd.title, selectedOption: additionalCmd.selectedOption, options: [], filePath: '' }]; + buildArgumentData(cardDataList); + /*const newData: ArgumentModel[] = [additionalCmdData].map(data => ({ title: data.name, value: data.value })); + const mergedUnique = Array.from( + new Map([...argumentData.filter(argument => !isBlank(argument.title)), ...newData].map(item => [item.title, item])).values() + ); + setArgumentData(mergedUnique);*/ + }, [additionalCmd]); const handleOnClick = async () => { //console.log(scriptType); @@ -89,9 +103,9 @@ const ScriptHub = (props: {}) => {
} - {!isListEmpty(additionalCmdData) && firstElement(additionalCmdData).id !== -1 && + {!isBlank(selectedProject) &&
- +
} diff --git a/tsconfig.json b/tsconfig.json index 1363817..fc4f8e9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,14 @@ { "compilerOptions": { - "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, - "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "target": "ESNEXT", + "module": "commonjs", "declaration": true, "outDir": "./dist", "rootDir": "./", - "strict": true /* Enable all strict type-checking options. */, - "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, - "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, "downlevelIteration": true, "lib": [ "ESNEXT", From 4b43ecc4ee628af5134fd3ea84deb0335fb1edcf Mon Sep 17 00:00:00 2001 From: dariojorge Date: Tue, 1 Jul 2025 00:49:56 +0100 Subject: [PATCH 4/4] Adding the boolean checkbox --- package.json | 2 +- .../scripthub/additional-cmd-component.tsx | 66 +++++++++++++++++-- src/app/scripthub/operation-component.tsx | 22 ++++--- src/app/scripthub/script-hub.tsx | 45 +++++++++---- 4 files changed, 105 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index f66d4c6..d6d25fc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "insomnia-script-hub", "private": true, - "version": "0.0.698", + "version": "0.0.763", "main": "dist/index.js", "insomnia": { "name": "script-hub", diff --git a/src/app/scripthub/additional-cmd-component.tsx b/src/app/scripthub/additional-cmd-component.tsx index d3db416..dae2250 100644 --- a/src/app/scripthub/additional-cmd-component.tsx +++ b/src/app/scripthub/additional-cmd-component.tsx @@ -15,6 +15,10 @@ const AdditionalCmdComponent = (props: { operation: CardData; selectedProject: s setCards(prev => prev.filter(operation => operation.id !== -1)); }, []) + useEffect(() => { + props.updateData([]); + }, [props.operation]) + useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; @@ -26,36 +30,71 @@ const AdditionalCmdComponent = (props: { operation: CardData; selectedProject: s } let newElem: CardData; - if (isListEmpty(props.operation.options) || cards.filter(card => card.title === "additionalCmd").length === 1) { + if (isListEmpty(props.operation.options) || validateCards()) { return; } const operationOptionElem = firstElement(props.operation.options); + console.log("0--------------->"); + console.log(operationOptionElem.cmdList); if (!isListEmpty(operationOptionElem.cmdList)) { newElem = buildCardOfEnvType(operationOptionElem.cmdList); } else { newElem = emptyCardData; } + console.log("1--------------->"); + console.log(newElem); + newElem.options.push(...buildBooleanlist(operationOptionElem.cmdList)); + /*if (!isListEmpty(operationOptionElem.cmdList) && operationOptionElem.cmdList.filter((cmd: { name: any; type: any; }) => cmd.name === "boolean")) { + const id = cards.length; + const title = "booleanList"; + const selectedOption = "booleanList"; + const options: Data[] = []; + const filePath = ""; + newElem = { id: id, title: title, selectedOption: selectedOption, options: options, filePath: filePath }; + }*/ + + if (newElem.id === -1 && newElem.options.length > 0) { + const id = cards.length; + const title = "booleanList"; + const selectedOption = "booleanList"; + const filePath = ""; + newElem = { id: id, title: title, selectedOption: selectedOption, options: newElem.options, filePath: filePath }; + } + if (newElem.id === -1) { return; } + console.log("2--------------->"); + console.log(newElem); + setCards(prev => [ ...prev, newElem ]); }, [cards, props.selectedProject]); + const validateCards = (): boolean => { + return cards.filter(card => card.title === "additionalCmd").length === 1 || + cards.filter(card => card.title === "booleanList").length === 1; + } + const buildCardOfEnvType = (cmdList: any): CardData => { const cmd: { name: any; type: any; } = firstElement(cmdList.filter((cmd: { name: any; type: any; }) => cmd.name === "additionalCmd")); + + if (cmd === null) { + return emptyCardData; + } + const id = cards.length; const title = cmd.name; const selectedOption = cmd.type; const options: Data[] = listOfAllAdditionalCmd(); const filePath = ""; - if(isListEmpty(options)) { + if (isListEmpty(options)) { return emptyCardData; } @@ -70,10 +109,10 @@ const AdditionalCmdComponent = (props: { operation: CardData; selectedProject: s if (isEmpty(props.selectedProject)) { return []; } - + const settings = readFileEnvs(`${scriptHubPath}/projects/${props.selectedProject}`); const envList: Data[] = []; - + settings.additionalCmd?.filter(arg => arg.type === "arg").forEach(env => { envList.push({ type: env.value, @@ -83,10 +122,27 @@ const AdditionalCmdComponent = (props: { operation: CardData; selectedProject: s return envList; } + const buildBooleanlist = (cmdList: any) => { + const cmdBoolean = cmdList.filter((cmd: { name: any; type: any; }) => cmd.type === "boolean"); + if (isListEmpty(cmdBoolean)) { + return []; + } + + const envList: Data[] = []; + cmdBoolean.forEach((env: { type: any; name: any; }) => { + envList.push({ + type: env.type, + name: env.name + }); + }); + + return envList; + } + return (
{!isListEmpty(cards) && firstElement(cards) !== null && !isListEmpty(firstElement(cards).options) && firstElement(cards).options.map((cmd: { name: string; }) => ( - + ))}
); diff --git a/src/app/scripthub/operation-component.tsx b/src/app/scripthub/operation-component.tsx index de9225b..eb6fe1b 100644 --- a/src/app/scripthub/operation-component.tsx +++ b/src/app/scripthub/operation-component.tsx @@ -13,6 +13,10 @@ const OperationComponent = (props: { operation: CardData; operationData: CardDat props.updateData((prev: any[]) => prev.filter(operation => operation.id !== -1)); }, []) + useEffect(() => { + props.updateData([]); + }, [props.operation]) + useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false; @@ -28,6 +32,9 @@ const OperationComponent = (props: { operation: CardData; operationData: CardDat return; } + console.log("operationOptionElem"); + console.log(operationOptionElem); + const newElem = buildCardOfEnvType(operationOptionElem.cmdList); if (newElem.id === -1) { return; @@ -41,19 +48,12 @@ const OperationComponent = (props: { operation: CardData; operationData: CardDat const buildCardOfEnvType = (cmdList: any): CardData => { const count = isListEmpty(getLastElement(props.operationData)) ? 0 : getLastElement(props.operationData).id + 1; - if(count > cmdList.length) { + if (count > cmdList.length) { return emptyCardData; } const cmd: { name: any; type: any; } = cmdList[count]; - console.log("count: "); - console.log(count); - console.log(cmdList.length); - console.log(cmd); - console.log(cmdList); - console.log(props.operationData); - console.log("******************"); - if (cmd === undefined || cmd.name === "additionalCmd") { + if (cmd === undefined || cmd.type === "additionalCmd" || cmd.type === "boolean") { return emptyCardData; } const id = props.operationData.length; @@ -94,8 +94,10 @@ const OperationComponent = (props: { operation: CardData; operationData: CardDat return listOfAllProjects(); case "envs": return listOfAllEnvironments(); + case "boolean": + return listOfAllEnvironments(); default: - return [{ type: "a", name: "b" }]; + return []; } } diff --git a/src/app/scripthub/script-hub.tsx b/src/app/scripthub/script-hub.tsx index 4c0895b..6efaeeb 100644 --- a/src/app/scripthub/script-hub.tsx +++ b/src/app/scripthub/script-hub.tsx @@ -4,18 +4,24 @@ import { firstElement, getLastElement, getSettings, isBlank, isEmpty, isListEmpt import ScriptComponent from "./script-component"; import OperationComponent from "./operation-component"; import AdditionalCmdComponent from "./additional-cmd-component"; +import fs from 'fs'; +import path from "path"; +import { execSync } from "child_process"; +import { ExecSyncOptionsWithStringEncoding } from "child_process"; +const options: ExecSyncOptionsWithStringEncoding = { + encoding: "utf8", + cwd: "/" +}; const settingsFilename: string = 'settings.json'; const scriptHubPath = getSettings(settingsFilename).scriptHubPath; const emptyCardData: CardData = { id: -1, title: '', selectedOption: '', options: [], filePath: '' }; const emptyListCardData: CardData[] = [emptyCardData]; - const ScriptHub = (props: {}) => { const [scriptData, setScriptData] = useState(emptyListCardData); const [operation, setOperation] = useState(emptyCardData); const [operationData, setOperationData] = useState(emptyListCardData); - const [additionalCmdData, setAdditionalCmdData] = useState(emptyListCardData); const [additionalCmd, setAdditionalCmd] = useState(emptyCardData); const [selectedProject, setSelectedProject] = useState(""); @@ -47,15 +53,9 @@ const ScriptHub = (props: {}) => { console.log(operationData); buildArgumentData(operationData.filter(card => card.id !== -1)); - buildAdditionalCmdData(); buildSelectedProject(); }, [operationData]); - const buildAdditionalCmdData = () => { - const additionalCmd = operationData.filter(card => card.id !== 0); - setAdditionalCmdData(additionalCmd); - } - const buildSelectedProject = () => { const projects = firstElement(operationData.filter(data => data.title === "projects")); if (projects !== null && !isEmpty(projects.selectedOption)) { @@ -69,17 +69,26 @@ const ScriptHub = (props: {}) => { const cardDataList: CardData[] = [{ id: 0, title: additionalCmd.title, selectedOption: additionalCmd.selectedOption, options: [], filePath: '' }]; buildArgumentData(cardDataList); - /*const newData: ArgumentModel[] = [additionalCmdData].map(data => ({ title: data.name, value: data.value })); - const mergedUnique = Array.from( - new Map([...argumentData.filter(argument => !isBlank(argument.title)), ...newData].map(item => [item.title, item])).values() - ); - setArgumentData(mergedUnique);*/ }, [additionalCmd]); const handleOnClick = async () => { - //console.log(scriptType); + const fileName = "scriptHub.sh"; + const pathName = path.resolve(`${scriptHubPath}`).replaceAll("\\", "/").replaceAll("//", "/"); + options.cwd = pathName; + options.shell = getTerminal(); + console.log(options); + console.log(`sh ./${fileName} ${joinAllArguments()}`); + console.log(execSync(`sh ./${fileName} ${joinAllArguments()}`, options)); }; + const joinAllArguments = () => { + let allArgsInfoText = ""; + argumentData.forEach(data => { + allArgsInfoText += `${data.title}=${data.value} `; + }); + return allArgsInfoText; + } + const buildArgumentData = (cardData: CardData[]) => { const newData: ArgumentModel[] = cardData.map(data => ({ title: data.title, value: data.selectedOption })); const mergedUnique = Array.from( @@ -88,6 +97,14 @@ const ScriptHub = (props: {}) => { setArgumentData(mergedUnique); } + const getTerminal = (): string => { + if (process.platform === 'win32') { + return "C:\\Program Files\\Git\\bin\\bash.exe"; + } + + return process.env.SHELL || '/bin/bash';; + } + return ( <>