mirror of
https://github.com/sern-handler/gui
synced 2026-06-05 17:06:52 +00:00
feat: first alpha release
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"tabWidth": 2,
|
||||
"useTabs": true,
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -13,8 +13,10 @@
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@mui/icons-material": "^5.11.16",
|
||||
"@mui/lab": "^5.0.0-alpha.134",
|
||||
"@mui/material": "^5.13.4",
|
||||
"axios": "^1.4.0",
|
||||
"colorette": "^2.0.20",
|
||||
"electron": "^25.1.0",
|
||||
"electron-is-dev": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
|
||||
16
public/ascii.txt
Normal file
16
public/ascii.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
.:-=-:.
|
||||
.:=+++++++++=-.
|
||||
:-=+++++++++++++++++=-:
|
||||
=++++++++++++++++++++=:.
|
||||
=+++++++++++++++=-:
|
||||
=++++++++++++-. ###### ######## ######## ## ## ###### ## ## ####
|
||||
=++++++++++++*+=:. ## ## ## ## ## ### ## ## ## ## ## ##
|
||||
=++++++++++++******=-. ## ## ## ## #### ## ## ## ## ##
|
||||
:=+++++++++++**********+- ###### ###### ######## ## ## ## ## #### ## ## ##
|
||||
.:-+++++++********###* ## ## ## ## ## #### ## ## ## ## ##
|
||||
:-=++***########* ## ## ## ## ## ## ### ## ## ## ## ##
|
||||
.-*###########* ###### ######## ## ## ## ## ###### ####### ####
|
||||
:=+###############*
|
||||
.-=*###################*
|
||||
.:=*#################*=-.
|
||||
:=+#########+=:
|
||||
@@ -1,6 +1,9 @@
|
||||
const path = require('path');
|
||||
const { app, BrowserWindow, dialog, ipcMain } = require('electron');
|
||||
const isDev = require('electron-is-dev');
|
||||
const fs = require('fs');
|
||||
const colorette = require('colorette')
|
||||
const { spawn } = require('node:child_process')
|
||||
|
||||
function createWindow() {
|
||||
const mainWindow = new BrowserWindow({
|
||||
@@ -41,7 +44,62 @@ function createWindow() {
|
||||
console.error(error);
|
||||
event.reply('folderData', []);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.on('submitForm', async (event, data) => {
|
||||
// Process the submitted data here
|
||||
console.log(`${colorette.green('✓')} Received sern init submit form data:`)
|
||||
console.log(data);
|
||||
console.log(`${colorette.cyan('🛈')} Current OS: ${currentOS}`)
|
||||
|
||||
let packageManagerCommand
|
||||
switch (data.chosenPackageManager) {
|
||||
case 'npm':
|
||||
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=npm`
|
||||
break;
|
||||
case 'yarn':
|
||||
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=yarn`
|
||||
break;
|
||||
case 'pnpm':
|
||||
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}" --install=pnpm`
|
||||
break;
|
||||
default:
|
||||
packageManagerCommand = `npm create @sern/bot@latest -- --template=${data.chosenTemplate} --name="${data.projectName}"`
|
||||
break;
|
||||
}
|
||||
let commandToRun
|
||||
switch (currentOS) {
|
||||
case 'linux':
|
||||
commandToRun = `cd ${data.selectedPath};${packageManagerCommand}`
|
||||
break;
|
||||
case 'windows':
|
||||
commandToRun = `cd /D ${data.selectedPath};${packageManagerCommand}`
|
||||
break;
|
||||
case 'macOS':
|
||||
commandToRun = `cd ${data.selectedPath};${packageManagerCommand}`
|
||||
break;
|
||||
default:
|
||||
// defaulting for linux (most probable command syntax)
|
||||
commandToRun = `cd ${data.selectedPath};${packageManagerCommand}`
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(`${colorette.cyan('🛈')} About to execute command: ${commandToRun}`)
|
||||
const cmd = spawn(commandToRun, { shell: true })
|
||||
|
||||
cmd.stdout.on('data', (data) => {
|
||||
console.log(`${colorette.cyan('🛈')} Command stdout: ${data}`);
|
||||
});
|
||||
|
||||
cmd.stderr.on('data', (data) => {
|
||||
console.error(`${colorette.red('×')} Command stderr: ${data}`);
|
||||
});
|
||||
|
||||
cmd.on('close', (code) => {
|
||||
console.log(`${colorette.cyan('🛈')} Command exited with status code ${code}. Now notifying frontend...`);
|
||||
event.reply('submitForm')
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow);
|
||||
@@ -56,4 +114,23 @@ app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let currentOS
|
||||
switch (process.platform) {
|
||||
case 'linux':
|
||||
currentOS = 'linux'
|
||||
break;
|
||||
case 'win32':
|
||||
currentOS = 'windows'
|
||||
break;
|
||||
case 'darwin':
|
||||
currentOS = 'macOS'
|
||||
break;
|
||||
default:
|
||||
// defaulting for linux (most probable command syntax)
|
||||
currentOS = 'linux'
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(fs.readFileSync(__dirname + '/ascii.txt', 'utf-8'))
|
||||
251
src/InitModal.js
251
src/InitModal.js
@@ -11,9 +11,9 @@ import TextField from '@mui/material/TextField';
|
||||
import Checkbox from '@mui/material/Checkbox';
|
||||
import FormGroup from '@mui/material/FormGroup';
|
||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||
import CardActions from '@mui/material/CardActions';
|
||||
import Alert from '@mui/material/Alert';
|
||||
import './modalStyles.css';
|
||||
const { ipcRenderer } = window.require('electron')
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const style = {
|
||||
@@ -71,6 +71,11 @@ export default function InitModal() {
|
||||
ipcRenderer.send('openFolder');
|
||||
};
|
||||
|
||||
const [projectName, setProjectName] = React.useState('');
|
||||
const handleProjectNameChange = (event) => {
|
||||
setProjectName(event.target.value);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
ipcRenderer.on('folderData', handleFolderData);
|
||||
|
||||
@@ -84,99 +89,155 @@ export default function InitModal() {
|
||||
setSelectedPath(selectedPath);
|
||||
};
|
||||
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
|
||||
const isFormValid = () => {
|
||||
return projectName !== '' && selectedPath !== '';
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!isFormValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
projectName,
|
||||
chosenTemplate,
|
||||
installPackages,
|
||||
chosenPackageManager,
|
||||
selectedPath,
|
||||
};
|
||||
|
||||
setLoading(true);
|
||||
|
||||
ipcRenderer.send('submitForm', data);
|
||||
|
||||
ipcRenderer.on('submitForm', () => {
|
||||
setLoading(false);
|
||||
handleClose();
|
||||
ipcRenderer.removeAllListeners('submitForm'); // Remove the listener to avoid memory leaks
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button onClick={handleOpen}>Open modal</Button>
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box className="boxStyle" sx={{ bgcolor: 'background.paper' }}>
|
||||
<Typography
|
||||
id="modal-modal-title"
|
||||
variant="h1"
|
||||
component="h1"
|
||||
>
|
||||
~$ sern init
|
||||
</Typography>
|
||||
<div className="formRow">
|
||||
<TextField
|
||||
id="modal-form-projectName"
|
||||
label="Project name"
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
/>
|
||||
<FormControl fullWidth className="chooseTemplateForm">
|
||||
<InputLabel id="modal-form-templateLabel">
|
||||
Select template
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="modal-form-templateSelect"
|
||||
id="modal-form-templateSelect"
|
||||
value={chosenTemplate}
|
||||
label="Select template"
|
||||
onChange={handleTemplateChange}
|
||||
fullWidth
|
||||
>
|
||||
{templates.map((template) => (
|
||||
<MenuItem
|
||||
key={template.value}
|
||||
value={template.value}
|
||||
>
|
||||
{template.title}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={installPackages}
|
||||
onChange={handlePackagesChange}
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
label="Install packages while you're at it"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormControl className="choosePkgManagerForm" fullWidth>
|
||||
<InputLabel id="modal-form-packageManagerLabel">
|
||||
Select package manager
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="modal-form-packageManagerLabel"
|
||||
id="modal-form-packageManagerSelect"
|
||||
value={chosenPackageManager}
|
||||
label="Select package manager"
|
||||
onChange={handlePackageManagerChange}
|
||||
disabled={!installPackages}
|
||||
>
|
||||
<MenuItem value="npm">npm</MenuItem>
|
||||
<MenuItem value="yarn">yarn</MenuItem>
|
||||
<MenuItem value="pnpm">pnpm</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<Button
|
||||
variant="contained"
|
||||
component="label"
|
||||
onClick={handleChooseDirButton}
|
||||
sx={{ display: 'block', margin: '0 auto', marginTop: '20px' }}
|
||||
>
|
||||
Select directory
|
||||
</Button>
|
||||
{/* <Typography variant="body1" component="div">
|
||||
Selected directory: {selectedPath}
|
||||
</Typography> */}
|
||||
</div>
|
||||
</Box>
|
||||
</Modal>
|
||||
</div>
|
||||
<div>
|
||||
<Button onClick={handleOpen}>Open modal</Button>
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
aria-labelledby="modal-modal-title"
|
||||
aria-describedby="modal-modal-description"
|
||||
>
|
||||
<Box className="boxStyle" sx={{ bgcolor: 'background.paper' }}>
|
||||
<Typography id="modal-modal-title" variant="h1" component="h1">
|
||||
~$ sern init
|
||||
</Typography>
|
||||
<div className="formRow">
|
||||
<TextField
|
||||
id="modal-form-projectName"
|
||||
label="Project name"
|
||||
variant="outlined"
|
||||
onChange={handleProjectNameChange}
|
||||
required
|
||||
fullWidth
|
||||
/>
|
||||
<FormControl fullWidth className="chooseTemplateForm">
|
||||
<InputLabel id="modal-form-templateLabel">
|
||||
Select template
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="modal-form-templateSelect"
|
||||
id="modal-form-templateSelect"
|
||||
value={chosenTemplate}
|
||||
label="Select template"
|
||||
onChange={handleTemplateChange}
|
||||
fullWidth
|
||||
>
|
||||
{templates.map((template) => (
|
||||
<MenuItem key={template.value} value={template.value}>
|
||||
{template.title}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={installPackages}
|
||||
onChange={handlePackagesChange}
|
||||
/>
|
||||
}
|
||||
fullWidth
|
||||
label="Install packages while you're at it"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormControl className="choosePkgManagerForm" fullWidth>
|
||||
<InputLabel id="modal-form-packageManagerLabel">
|
||||
Select package manager
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="modal-form-packageManagerLabel"
|
||||
id="modal-form-packageManagerSelect"
|
||||
value={chosenPackageManager}
|
||||
label="Select package manager"
|
||||
onChange={handlePackageManagerChange}
|
||||
disabled={!installPackages}
|
||||
required={installPackages}
|
||||
>
|
||||
<MenuItem value="npm">npm</MenuItem>
|
||||
<MenuItem value="yarn">yarn</MenuItem>
|
||||
<MenuItem value="pnpm">pnpm</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
onClick={handleChooseDirButton}
|
||||
sx={{ display: 'block', margin: '0 auto', marginTop: '5px' }}
|
||||
>
|
||||
Select directory
|
||||
</Button>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<Typography
|
||||
variant="body1"
|
||||
component="div"
|
||||
sx={{ display: 'block', margin: '0 auto', marginTop: '5px' }}
|
||||
>
|
||||
{selectedPath ? `Selected directory: ${selectedPath}` : ''}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="formRow">
|
||||
<Typography
|
||||
variant="body1"
|
||||
component="div"
|
||||
sx={{
|
||||
display: 'block',
|
||||
margin: '0 auto',
|
||||
marginTop: '5px',
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
Do not close the modal while it's loading.
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="bottomRight">
|
||||
<Button
|
||||
variant="contained"
|
||||
component="label"
|
||||
onClick={handleSubmit}
|
||||
disabled={loading || !isFormValid()}
|
||||
>
|
||||
{loading ? 'Go!' : 'Go!'}
|
||||
</Button>
|
||||
</div>
|
||||
</Box>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,4 +32,14 @@
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.bottomRight {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
margin-bottom: 40px;
|
||||
margin-right: 40px;
|
||||
}
|
||||
30
yarn.lock
30
yarn.lock
@@ -1851,6 +1851,20 @@
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
|
||||
"@mui/lab@^5.0.0-alpha.134":
|
||||
version "5.0.0-alpha.134"
|
||||
resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.134.tgz#e48c108fce91fbb89446dcf86ca35e7e761bc078"
|
||||
integrity sha512-GhvuM2dNOi6hzjbeGEocWVozgyyeUn7RBmZhLFtniROauxmPCZMcTsEU+GAxmpyYppqHuI8flP6tGKgMuEAK/g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
"@mui/base" "5.0.0-beta.4"
|
||||
"@mui/system" "^5.13.5"
|
||||
"@mui/types" "^7.2.4"
|
||||
"@mui/utils" "^5.13.1"
|
||||
clsx "^1.2.1"
|
||||
prop-types "^15.8.1"
|
||||
react-is "^18.2.0"
|
||||
|
||||
"@mui/material@^5.13.4":
|
||||
version "5.13.4"
|
||||
resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.13.4.tgz#1fed8249c980ed37f9767f9dba8aa3a589495ff3"
|
||||
@@ -1902,6 +1916,20 @@
|
||||
csstype "^3.1.2"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@mui/system@^5.13.5":
|
||||
version "5.13.5"
|
||||
resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.13.5.tgz#9f67ea0c4f6974713f90b7b94c999fd3f40f8de3"
|
||||
integrity sha512-n0gzUxoZ2ZHZgnExkh2Htvo9uW2oakofgPRQrDoa/GQOWyRD0NH9MDszBwOb6AAoXZb+OV5TE7I4LeZ/dzgHYA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
"@mui/private-theming" "^5.13.1"
|
||||
"@mui/styled-engine" "^5.13.2"
|
||||
"@mui/types" "^7.2.4"
|
||||
"@mui/utils" "^5.13.1"
|
||||
clsx "^1.2.1"
|
||||
csstype "^3.1.2"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@mui/types@^7.2.4":
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328"
|
||||
@@ -3604,7 +3632,7 @@ colord@^2.9.1:
|
||||
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
|
||||
integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==
|
||||
|
||||
colorette@^2.0.10:
|
||||
colorette@^2.0.10, colorette@^2.0.20:
|
||||
version "2.0.20"
|
||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
|
||||
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
|
||||
|
||||
Reference in New Issue
Block a user