feat: first alpha release

This commit is contained in:
2023-06-25 16:31:16 +02:00
parent 4a8b7a248f
commit 9262d5a729
7 changed files with 293 additions and 99 deletions

View File

@@ -1,5 +1,5 @@
{
"tabWidth": 4,
"tabWidth": 2,
"useTabs": true,
"singleQuote": true
}

View File

@@ -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
View File

@@ -0,0 +1,16 @@
.:-=-:.
.:=+++++++++=-.
:-=+++++++++++++++++=-:
=++++++++++++++++++++=:.
=+++++++++++++++=-:
=++++++++++++-. ###### ######## ######## ## ## ###### ## ## ####
=++++++++++++*+=:. ## ## ## ## ## ### ## ## ## ## ## ##
=++++++++++++******=-. ## ## ## ## #### ## ## ## ## ##
:=+++++++++++**********+- ###### ###### ######## ## ## ## ## #### ## ## ##
.:-+++++++********###* ## ## ## ## ## #### ## ## ## ## ##
:-=++***########* ## ## ## ## ## ## ### ## ## ## ## ##
.-*###########* ###### ######## ## ## ## ## ###### ####### ####
:=+###############*
.-=*###################*
.:=*#################*=-.
:=+#########+=:

View File

@@ -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);
@@ -57,3 +115,22 @@ app.on('activate', () => {
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'))

View File

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

View File

@@ -33,3 +33,13 @@
gap: 20px;
margin-bottom: 20px;
}
.bottomRight {
position: absolute;
right: 0;
bottom: 0;
width: 100%;
text-align: right;
margin-bottom: 40px;
margin-right: 40px;
}

View File

@@ -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==