This commit is contained in:
sebseb7
2024-09-23 09:12:52 +02:00
parent 41ebffe71c
commit cc8b5d2765
4 changed files with 128 additions and 94 deletions

View File

@@ -27,30 +27,12 @@ const compiler = webpack({
test: /\.css$/, test: /\.css$/,
use: ["style-loader", "css-loader"] use: ["style-loader", "css-loader"]
} }
/* {
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}*/
/*{
test: /\.(woff|woff2)$/i,
use: ['base64-inline-loader'],
type: 'javascript/auto'
}*/
] ]
}, },
plugins: [ plugins: [
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
templateContent: "<!DOCTYPE html>\n<html><head>" + '<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="data:;base64,iVBORw0KGgo="></head><body style="background-color: rgb(192,208,208)"></body></html>' templateContent: "<!DOCTYPE html>\n<html><head>" + '<meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" href="data:;base64,iVBORw0KGgo="></head><body style="background-color: #c5cbe3"><div id="react_insert"></div></body></html>'
}), }),
//new BundleAnalyzerPlugin({analyzerHost:'0.0.0.0'}),
...(isDev ? [new ReactRefreshWebpackPlugin(), new webpack.HotModuleReplacementPlugin(), new ESLintPlugin()] : []) ...(isDev ? [new ReactRefreshWebpackPlugin(), new webpack.HotModuleReplacementPlugin(), new ESLintPlugin()] : [])
], ],
resolve: { resolve: {
@@ -65,21 +47,21 @@ const compiler = webpack({
optimization: { optimization: {
moduleIds: "deterministic", moduleIds: "deterministic",
splitChunks: { splitChunks: {
chunks: "all", //chunks: "all",
cacheGroups: { /*cacheGroups: {
commons: { commons: {
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
name: "vendors", name: "vendors",
chunks: "all" chunks: "all"
} }
} }*/
} }
}, },
output: { output: {
filename: "[name].[contenthash].js", filename: "searchPopper.js",//"[name].[contenthash].js",
chunkFilename: "[name].[contenthash].js", chunkFilename: "searchPopper.js",//"[name].[contenthash].js",
clean: true, clean: true,
asyncChunks: true asyncChunks: false
} }
}); });
@@ -205,25 +187,46 @@ function runapp(socket){
socket.on("search", (text, offset, callback) => { socket.on("search", (text, offset, callback) => {
try{ try{
text = text.toString().trim().replace(/(\D)-/g, "$1 ").replace(/ {2,}/g, " ");
if(text.length > 2){ let queries = [];
let qstr = '';
let queries = []; for(const per of permute(text.split(' '))){
let qstr = ''; for(let i=0;i<per.length;i++) if (!isNaN(parseInt(per[i], 10))) {
per[i] = ' '+per[i];
for(const per of permute(text.toString().trim().replace(/ {2,}/g, " ").split(' '))){
queries.push('%'+(per.join('%'))+'%');
qstr+= ' OR cName LIKE ? ';
} }
queries.push(offset*10); queries.push('%'+(per.join('%'))+'%');
qstr+= ' OR cName LIKE ? ';
}
qstr = qstr.substring(3);
connection.query('SELECT tartikel.kArtikel,cArtNr,cName,cSeo FROM tartikel LEFT OUTER JOIN tartikelpict ON (tartikelpict.kArtikel = tartikel.kArtikel) WHERE 1=2 '+qstr+' ORDER BY cName limit 11 OFFSET ?',queries, function (error, results) { queries.push(offset*10);
if((text.length < 200)&&(text.length > 2)&&(queries.length < 129)){
connection.query(`
SELECT
tartikel.kArtikel,
cArtNr,
cName,
cSeo,
fLieferantenlagerbestand > 0 as bLieferantenlagerbestand,
fLagerbestand > 0 as bLagerbestand,
fStandardpreisNetto,
fMwSt
FROM tartikel
LEFT OUTER JOIN tartikelpict ON (tartikelpict.kArtikel = tartikel.kArtikel AND nNr = 1)
WHERE nIstVater = 0 and ( `+qstr+` ) ORDER BY cName limit 11 OFFSET ?`,
queries, function (error, results)
{
if (callback) callback(error,results); if (callback) callback(error,results);
}); });
}else{ }else{
callback(true); callback({length:text.length,permutations:queries.length});
} }
} }
catch(e){ catch(e){

View File

@@ -5,9 +5,7 @@ import {
Popper, Popper,
Avatar, Avatar,
Typography, Typography,
Card,
InputAdornment, InputAdornment,
IconButton,
Grid Grid
} from "@mui/material"; } from "@mui/material";
@@ -50,6 +48,7 @@ export default class Content extends React.Component {
offset:0, offset:0,
anchorEl:null anchorEl:null
}; };
this.interval = null;
} }
navigateNext = () => { navigateNext = () => {
@@ -65,60 +64,66 @@ export default class Content extends React.Component {
render() { render() {
return ( return (
<div style={{ width:'100%'}}> <>
<Stack spacing={2}> <TextField
<Card style={{ width:'100%',margin:'20px auto'}} sx={{ maxWidth: 'sm' }}> spellCheck={false}
<TextField InputProps={{
spellCheck={false} endAdornment: (
InputProps={{ <InputAdornment position="end">
endAdornment: ( <SearchIcon/>
<InputAdornment position="end"> </InputAdornment>
<SearchIcon/> )
</InputAdornment> }}
) value={this.state.searchtext}
}} inputRef={(input) => {input && input.focus()}}
value={this.state.searchtext} onChange={(e) => {
inputRef={(input) => {input && input.focus()}} this.setState({ offset:0,anchorEl:e.target,searchtext: e.target.value });
onChange={(e) => { const setState = this.setState.bind(this);
this.setState({ offset:0,anchorEl:e.target,searchtext: e.target.value }); searchDebounced(e.target.value,this.props.socket,setState,0);
const setState = this.setState.bind(this); }}
searchDebounced(e.target.value,this.props.socket,setState,0); autoComplete="off"
}} onBlur={()=>{if(this.state.result.length > 0) this.setState({result:[]})}}
autoComplete="off" onKeyDown={(e)=>{ if (e.key === 'Enter') window.location = window.location.protocol + "//" + window.location.host + '/' + encodeURIComponent(this.state.searchtext); }}
fullWidth fullWidth
/> />
</Card> <Popper
<Popper open={this.state.result.length > 0}
open={this.state.result.length > 0} anchorEl={this.state.anchorEl}
anchorEl={this.state.anchorEl} placement={'bottom-start'}
placement={'bottom-start'} style={{ zIndex:1024,width:'100%'}} sx={{ maxWidth: 'sm' }}
style={{ width:'100%'}} sx={{ maxWidth: 'sm' }} onMouseDown={e => e.preventDefault()}
> >
<Paper style={{ width:'100%',margin:0, padding: 20}} sx={{ maxWidth: 'sm' }}> <Paper style={{ width:'100%',margin:0,marginTop:'5px', padding: 20}} elevation={20} sx={{ maxWidth: 'sm' }}>
<Stack spacing={1}> <Stack spacing={1}>
{this.state.result.slice(0, 10).map((line,i)=>( { (((this.state.offset!=0)||(this.state.result[10])) &&
<Stack key={i} direction="row" spacing={2} style={{cursor: 'pointer',userSelect:'none'}} sx={{alignItems: "center"}} onClick={() => { window.location = 'https://t.growheads.de/'+line.cSeo }}>
<Avatar src={'https://t.growheads.de/media/image/product/'+(line.kArtikel)+'/xs/'+(line.cSeo)+'.jpg'} sx={{ width: 40, height: 40 }} variant="square"/>
<Typography>{line.cName}</Typography>
</Stack>
))}
<Grid container> <Grid container>
<Grid item xs={6}> <Grid item xs={6}>
{ (this.state.offset!=0 && { (this.state.offset!=0 &&
<IconButton onClick={this.navigateBefore}><NavigateBeforeIcon/></IconButton> <NavigateBeforeIcon style={{cursor: 'pointer'}} onClick={this.navigateBefore}/>
)} )}
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
{ (this.state.result[10] && { (this.state.result[10] &&
<Grid container justifyContent="flex-end"><IconButton onClick={this.navigateNext}><NavigateNextIcon/></IconButton></Grid> <Grid container justifyContent="flex-end"><NavigateNextIcon style={{cursor: 'pointer'}} onClick={this.navigateNext}/></Grid>
)} )}
</Grid> </Grid>
</Grid> </Grid>
</Stack> )}
</Paper> {this.state.result.slice(0, 10).map((line,i)=>(
</Popper> <Stack key={i} direction="row" spacing={2} style={{cursor: 'pointer',userSelect:'none'}} sx={{alignItems: "center"}} onClick={() => { window.location = window.location.protocol + "//" + window.location.host + '/' + line.cSeo }}>
</Stack> <Avatar src={'/media/image/product/'+(line.kArtikel)+'/xs/'+(line.cSeo)+'.jpg'} imgProps={{style:{width:40,height:40,objectFit: 'contain'}}} variant="square"/>
</div> <Typography style={{width:'100%',display:'flex',flexDirection:'row'}}>
<span style={{flexGrow:1,display:'block',overflow:'hidden'}}>{line.cName}</span>
<span style={{display:'block',paddingLeft:'1em'}}>{
(line.bLieferantenlagerbestand||line.bLagerbestand)?(new Intl.NumberFormat("de-DE", {style: "currency",currency: "EUR"}).format(line.fStandardpreisNetto * (100 + line.fMwSt) / 100)):''
}</span>
</Typography>
</Stack>
))}
</Stack>
</Paper>
</Popper>
</>
); );
} }
} }

View File

@@ -15,11 +15,11 @@ function App() {
} }
const theme = createTheme({ const theme = createTheme({
palette: { /* palette: {
background: { background: {
default: "#c0d0d0;" default: "#c5cbe3;"
} }
}, },*/
typography: { typography: {
fontFamily: "Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif", fontFamily: "Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif",
fontWeightBold: 700, fontWeightBold: 700,
@@ -43,11 +43,37 @@ const theme = createTheme({
} }
}); });
var appDiv = document.createElement("div"); function waitForElm(selector) {
document.body.appendChild(appDiv); return new Promise(resolve => {
ReactDOM.createRoot(appDiv).render( if (document.querySelector(selector)) {
<ThemeProvider theme={theme}> return resolve(document.querySelector(selector));
<CssBaseline /> }
<App />
</ThemeProvider> const observer = new MutationObserver(() => {
); if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
});
}
waitForElm('#react_insert').then((elm) => {
console.log('Element is ready');
const root = ReactDOM.createRoot(elm);
root.render(
//var appDiv = document.createElement("div");
//document.body.appendChild(appDiv);
//ReactDOM.createRoot(appDiv).render(
<ThemeProvider theme={theme}>
<CssBaseline />
<App />
</ThemeProvider>
);
});

View File

@@ -1,4 +1,4 @@
body { body {
overflow-y: scroll; overflow-y: scroll;
padding: 20px; padding: 0px;
} }