commit c6928eb137dd15da8f3a67e9a8d0977808818456 Author: sebseb7 Date: Thu Sep 5 04:00:27 2024 +0200 genesis diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c8efffe --- /dev/null +++ b/.eslintrc @@ -0,0 +1,38 @@ +{ + "parser": "@babel/eslint-parser", + "env": { + "browser": true, + "commonjs": true, + "es6": true, + "node": false + }, + "rules": { + "react/prop-types": "off", + "no-restricted-imports": [ + "error", + { + "patterns": ["@mui/*/*/*", "!@mui/material/test-utils/*"] + } + ] + }, + "parserOptions": { + "requireConfigFile": false, + "babelOptions": { + "presets": ["@babel/preset-react"] + } + }, + "plugins": [ + "react", + "@studysync/eslint-plugin-material-ui" + ], + "extends": [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:react/jsx-runtime" + ], + "settings": { + "react": { + "version": "detect" + } + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f06235c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/package.json b/package.json new file mode 100644 index 0000000..9913eca --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "search", + "version": "1.0.0", + "description": "", + "main": "search.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@babel/eslint-parser": "^7.25.1", + "@emotion/react": "^11.13.3", + "@emotion/styled": "^11.13.0", + "@fontsource/source-sans-pro": "^5.0.8", + "@mui/icons-material": "^6.0.2", + "@mui/material": "^6.0.2", + "@mui/styled-engine": "^6.0.2", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", + "@studysync/eslint-plugin-material-ui": "^1.2.1", + "async": "^3.2.6", + "babel-loader": "^9.1.3", + "compression": "^1.7.4", + "css-loader": "^7.1.2", + "eslint-plugin-react": "^7.35.2", + "eslint-webpack-plugin": "^4.2.0", + "express": "^4.19.2", + "html-webpack-plugin": "^5.6.0", + "mssql": "^11.0.1", + "mysql": "^2.18.1", + "react": "^18.3.1", + "socket.io": "^4.7.5", + "socket.io-client": "^4.7.5", + "style-loader": "^4.0.0", + "webpack-dev-middleware": "^7.4.2", + "webpack-hot-middleware": "^2.26.1" + } +} diff --git a/search.js b/search.js new file mode 100644 index 0000000..3dcfc01 --- /dev/null +++ b/search.js @@ -0,0 +1,236 @@ +const webpack = require("webpack"); +const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const ESLintPlugin = require("eslint-webpack-plugin"); +const fs = require("fs"); +const isDev = false; + +const compiler = webpack({ + mode: isDev ? "development" : "production", + entry: ["./src/index.js", ...(isDev ? ["webpack-hot-middleware/client?reload=true&overlay=true"] : [])], + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: [ + { + loader: require.resolve("babel-loader"), + options: { + plugins: [isDev && require.resolve("react-refresh/babel")].filter(Boolean), + presets: [["@babel/preset-react", { runtime: "automatic" }]] + } + } + ] + }, + { + test: /\.css$/, + 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: [ + new HtmlWebpackPlugin({ + templateContent: "\n" + '' + }), + //new BundleAnalyzerPlugin({analyzerHost:'0.0.0.0'}), + ...(isDev ? [new ReactRefreshWebpackPlugin(), new webpack.HotModuleReplacementPlugin(), new ESLintPlugin()] : []) + ], + resolve: { + extensions: ["*", ".js"], + fallback: { crypto: false } + }, + performance: { + maxEntrypointSize: 2024000, + maxAssetSize: 2024000 + }, + devtool: isDev ? "source-map" : false, + optimization: { + moduleIds: "deterministic", + splitChunks: { + chunks: "all", + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: "vendors", + chunks: "all" + } + } + } + }, + output: { + filename: "[name].[contenthash].js", + chunkFilename: "[name].[contenthash].js", + clean: true, + asyncChunks: true + } +}); + +const express = require("express"); +const app = express(); +const http = require("http"); +const server = http.createServer(app); +const compression = require("compression"); +const { Server } = require("socket.io"); +const async = require("async"); + +var onlyOnce = true; + +async function run() { + + const io = new Server(server); + const interval = setInterval(async () => { + const sockets = await io.fetchSockets(); + + async.forEachOf( + sockets, + async function (socket, key, callback) { + if (socket.data && socket.data.auth) { + callback(); + } else { + callback(); + } + }, + async function (err) {} + ); + }, 1000 * 10); + + let globalHash; + + var connListener = io.on("connection", (socket) => { + if (socket.handshake.headers.authorization) { + const authheader = socket.handshake.headers.authorization; + const auth = new Buffer.from(authheader.split(" ")[1], "base64").toString().split(":"); + console.log(auth); + } + socket.on("getHash", () => { + if (globalHash) socket.emit("hash", globalHash); + }); + runapp(socket); + }); + + if (isDev) { + app.use( + require("webpack-dev-middleware")(compiler, { + headers: (req, res, context) => { + if (req.url == "/") { + res.setHeader("Cache-Control", "max-age=0"); + } + } + }) + ); + app.use(require("webpack-hot-middleware")(compiler)); + + compiler.hooks.done.tap("MyPlugin", (params) => { + globalHash = params.toJson().hash; + if (onlyOnce) io.emit("hash", globalHash); + onlyOnce = false; + }); + + } else { + compiler.run((err, stats) => { + if (err || stats.hasErrors()) { + console.log(err); + } + globalHash = "prod" + stats.hash; + io.emit("hash", globalHash); + console.log("prod" + stats.hash); + console.log(stats.toString({ colors: true })); + }); + + app.use(function (req, res, next) { + if (req.path == "/") { + express.static("dist")(req, res, next); + } else { + express.static("dist", { maxAge: 60 * 60 * 24 * 100 * 1000 })(req, res, next); + } + }); + app.use(compression()); + } + + + + let printerOnline = false; + + + server.listen(1111, "0.0.0.0", () => {}); +} + +run(); + +var mysql = require('mysql'); +var connection = mysql.createConnection({ + host : 'localhost', + user : 'jtlshop', + password : 'jtlshop', + database : 'jtldb' +}); +connection.connect(); + +function permute(nums) { + let result = []; + if (nums.length === 0) return []; + if (nums.length === 1) return [nums]; + for (let i = 0; i < nums.length; i++) { + const currentNum = nums[i]; + const remainingNums = nums.slice(0, i).concat(nums.slice(i + 1)); + const remainingNumsPermuted = permute(remainingNums); + for (let j = 0; j < remainingNumsPermuted.length; j++) { + const permutedArray = [currentNum].concat(remainingNumsPermuted[j]); + result.push(permutedArray); + } + } + return result; +} + +function runapp(socket){ + + socket.on("search", (text, callback) => { + + try{ + + if(text.length > 2){ + + let queries = []; + let qstr = ''; + + for(const per of permute(text.toString().trim().replace(/ {2,}/g, " ").split(' '))){ + queries.push('%'+(per.join('%'))+'%'); + qstr+= ' OR cName LIKE ? '; + } + + connection.query('SELECT tartikel.kArtikel,cArtNr,cName,cSeo FROM tartikel LEFT OUTER JOIN tartikelpict ON (tartikelpict.kArtikel = tartikel.kArtikel) WHERE 1=2 '+qstr+' limit 15',queries, function (error, results) { + if (callback) callback(error,results); + }); + + + }else{ + callback(true); + } + } + catch(e){ + callback(e); + console.log('exception',e); + } + finally{ + }; + }); + +} diff --git a/src/Content.js b/src/Content.js new file mode 100644 index 0000000..ae3133e --- /dev/null +++ b/src/Content.js @@ -0,0 +1,90 @@ +import { + Paper, + TextField, + Stack, + Popper, + Avatar, + Typography, + Card, + InputAdornment +} from "@mui/material"; + +import SearchIcon from "@mui/icons-material/Search"; + +import React from "react"; + +export default class Content extends React.Component { + constructor(props) { + super(props); + + this.state = { + searchtext:'', + result:[], + anchorEl:null + }; + } + + + handleSearch = (searchtext) => { + if(searchtext.trim().length > 2){ + this.props.socket.emit('search',searchtext,(err,res)=>{ + if(!err){ + this.setState({ result:res }); + console.log(res); + } + else{ + console.log('Err',err); + this.setState({ result:[] }); + } + }); + } + else{ + this.setState({ result:[] }); + } + } + + render() { + return ( +
+ + + + + + ) + }} + value={this.state.searchtext} + inputRef={(input) => {input && input.focus()}} + onChange={(e) => { + this.setState({ anchorEl:e.target,searchtext: e.target.value }); + this.handleSearch(e.target.value); + }} + autoComplete="off" + fullWidth + /> + + 0} + anchorEl={this.state.anchorEl} + placement={'bottom-start'} + > + + + {this.state.result.map((line,i)=>( + { window.location = 'https://t.growheads.de/'+line.cSeo }}> + + {line.cName} + + ))} + + + + +
+ ); + } +} diff --git a/src/Wrapper.js b/src/Wrapper.js new file mode 100644 index 0000000..a2b2f51 --- /dev/null +++ b/src/Wrapper.js @@ -0,0 +1,62 @@ +const io = require("socket.io-client"); +import React, { lazy, Suspense } from "react"; + +const Content = lazy(() => import("./Content")); + +var globalHash; + +export default class Wrapper extends React.Component { + constructor(props) { + super(props); + + const socket = io("", { transports: ["websocket"] }); + + this.socket = socket; + + this.state = { + socket: socket + }; + + this.setState.bind(this); + + socket.io.on("reconnect", () => { + console.log('reconnect'); + socket.emit('getHash'); + }); + + socket.on("disconnect", (reason) => { + console.log('disconnect'); + if (reason == "io server disconnect") { + setTimeout(() => { + console.log('reconnect attempt'); + socket.connect(); + }, 1000); + } + }); + socket.on("connect", () => { + console.log('connect'); + socket.emit('getHash'); + }); + + socket.on("hash", (hash) => { + console.log('hash',hash); + if (globalHash) { + if (globalHash !== hash) { + setTimeout(function () { + window.location.reload(); + }, 1500); + } + } + globalHash = hash; + }); + } + componentDidMount() {} + + render() { + return ( + }> + + + ); + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..fbf1d30 --- /dev/null +++ b/src/index.js @@ -0,0 +1,53 @@ +import * as ReactDOM from "react-dom/client"; +import "@fontsource/source-sans-pro/300.css"; +import "@fontsource/source-sans-pro/400.css"; +import "@fontsource/source-sans-pro/600.css"; +import "@fontsource/source-sans-pro/700.css"; +import CssBaseline from "@mui/material/CssBaseline"; +import { ThemeProvider, createTheme } from "@mui/material/styles"; + +import Wrapper from "./Wrapper"; + +import "./styles.css"; + +function App() { + return ; +} + +const theme = createTheme({ + palette: { + background: { + default: "#c0d0d0;" + } + }, + typography: { + fontFamily: "Source Sans Pro,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif", + fontWeightBold: 700, + fontWeightMedium: 600, + fontWeightRegular: 400, + fontWeightLight: 300 + }, + components: { + MuiTableCell: { + styleOverrides: { + head: { + fontWeight: 700 + } + } + }, + MuiInputBase: { + styleOverrides: { + input: {} + } + } + } +}); + +var appDiv = document.createElement("div"); +document.body.appendChild(appDiv); +ReactDOM.createRoot(appDiv).render( + + + + +); diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..f0f92a5 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,4 @@ +body { + overflow-y: scroll; + padding: 20px; +}