diff --git a/.gitignore b/.gitignore
index bec7510..d012435 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
/node_modules
-/server/.inpx-web
+/server/.inpx-web*
+/server/inpx-web-filter.json
/dist
+dev*.sh
\ No newline at end of file
diff --git a/build/prepkg.js b/build/prepkg.js
new file mode 100644
index 0000000..5e4ba08
--- /dev/null
+++ b/build/prepkg.js
@@ -0,0 +1,43 @@
+const fs = require('fs-extra');
+const path = require('path');
+const { execSync } = require('child_process');
+
+const platform = process.argv[2];
+
+const distDir = path.resolve(__dirname, '../dist');
+const tmpDir = `${distDir}/tmp`;
+const publicDir = `${tmpDir}/public`;
+const outDir = `${distDir}/${platform}`;
+
+async function build() {
+ if (platform != 'linux' && platform != 'win')
+ throw new Error(`Unknown platform: ${platform}`);
+
+ await fs.emptyDir(outDir);
+
+ // перемещаем public на место
+ if (await fs.pathExists(publicDir)) {
+
+ const zipFile = `${tmpDir}/public.zip`;
+ const jsonFile = `${distDir}/public.json`;//distDir !!!
+
+ await fs.remove(zipFile);
+ execSync(`zip -r ${zipFile} .`, {cwd: publicDir, stdio: 'inherit'});
+
+ const data = (await fs.readFile(zipFile)).toString('base64');
+ await fs.writeFile(jsonFile, JSON.stringify({data}));
+ } else {
+ throw new Error(`publicDir: ${publicDir} does not exist`);
+ }
+}
+
+async function main() {
+ try {
+ await build();
+ } catch(e) {
+ console.error(e);
+ process.exit(1);
+ }
+}
+
+main();
diff --git a/build/webpack.base.config.js b/build/webpack.base.config.js
new file mode 100644
index 0000000..16bb957
--- /dev/null
+++ b/build/webpack.base.config.js
@@ -0,0 +1,69 @@
+const path = require('path');
+const DefinePlugin = require('webpack').DefinePlugin;
+const { VueLoaderPlugin } = require('vue-loader');
+
+const clientDir = path.resolve(__dirname, '../client');
+
+module.exports = {
+ resolve: {
+ alias: {
+ ws: false,
+ }
+ },
+ entry: [`${clientDir}/main.js`],
+ output: {
+ publicPath: '/app/',
+ clean: true
+ },
+
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ },
+ {
+ test: /\.js$/,
+ loader: 'babel-loader',
+ exclude: /node_modules/,
+ options: {
+ presets: [['@babel/preset-env', { targets: { esmodules: true } }]],
+ plugins: [
+ ['@babel/plugin-proposal-decorators', { legacy: true }]
+ ]
+ }
+ },
+ {
+ test: /\.(gif|png)$/,
+ type: 'asset/inline',
+ },
+ {
+ test: /\.jpg$/,
+ type: 'asset/resource',
+ generator: {
+ filename: 'images/[name]-[hash:6][ext]'
+ },
+ },
+
+ {
+ test: /\.(ttf|eot|woff|woff2)$/,
+ type: 'asset/resource',
+ generator: {
+ filename: 'fonts/[name]-[hash:6][ext]'
+ },
+ },
+ ]
+ },
+
+ plugins: [
+ new DefinePlugin({
+ __VUE_OPTIONS_API__: true,
+ __VUE_PROD_DEVTOOLS__: false,
+ __QUASAR_SSR__: false,
+ __QUASAR_SSR_SERVER__: false,
+ __QUASAR_SSR_CLIENT__: false,
+ __QUASAR_VERSION__: false,
+ }),
+ new VueLoaderPlugin(),
+ ]
+};
diff --git a/build/webpack.dev.config.js b/build/webpack.dev.config.js
new file mode 100644
index 0000000..5c64251
--- /dev/null
+++ b/build/webpack.dev.config.js
@@ -0,0 +1,45 @@
+const path = require('path');
+const webpack = require('webpack');
+const pckg = require('../package.json');
+
+const { merge } = require('webpack-merge');
+const baseWpConfig = require('./webpack.base.config');
+
+baseWpConfig.entry.unshift('webpack-hot-middleware/client');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+
+const publicDir = path.resolve(__dirname, `../server/.${pckg.name}/public`);
+const clientDir = path.resolve(__dirname, '../client');
+
+module.exports = merge(baseWpConfig, {
+ mode: 'development',
+ devtool: 'inline-source-map',
+ output: {
+ path: `${publicDir}/app`,
+ filename: 'bundle.js',
+ clean: true
+ },
+
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ 'vue-style-loader',
+ 'css-loader'
+ ]
+ },
+ ]
+ },
+
+ plugins: [
+ new webpack.HotModuleReplacementPlugin(),
+ new webpack.NoEmitOnErrorsPlugin(),
+ new HtmlWebpackPlugin({
+ template: `${clientDir}/index.html.template`,
+ filename: `${publicDir}/index.html`
+ }),
+ new CopyWebpackPlugin({patterns: [{context: `${clientDir}/assets`, from: `${clientDir}/assets/*`, to: `${publicDir}/`}]})
+ ]
+});
diff --git a/build/webpack.prod.config.js b/build/webpack.prod.config.js
new file mode 100644
index 0000000..03adc5e
--- /dev/null
+++ b/build/webpack.prod.config.js
@@ -0,0 +1,61 @@
+const fs = require('fs-extra');
+const path = require('path');
+//const webpack = require('webpack');
+
+const { merge } = require('webpack-merge');
+const baseWpConfig = require('./webpack.base.config');
+const TerserPlugin = require('terser-webpack-plugin');
+const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+
+const publicDir = path.resolve(__dirname, '../dist/tmp/public');
+const clientDir = path.resolve(__dirname, '../client');
+
+fs.emptyDirSync(publicDir);
+
+module.exports = merge(baseWpConfig, {
+ mode: 'production',
+ output: {
+ path: `${publicDir}/app`,
+ filename: 'bundle.[contenthash].js',
+ clean: true
+ },
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ 'css-loader'
+ ]
+ }
+ ]
+ },
+ optimization: {
+ minimizer: [
+ new TerserPlugin({
+ parallel: true,
+ terserOptions: {
+ format: {
+ comments: false,
+ },
+ },
+ }),
+ new CssMinimizerWebpackPlugin()
+ ]
+ },
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: "[name].[contenthash].css"
+ }),
+ new HtmlWebpackPlugin({
+ template: `${clientDir}/index.html.template`,
+ filename: `${publicDir}/index.html`
+ }),
+ new CopyWebpackPlugin({patterns:
+ [{context: `${clientDir}/assets`, from: `${clientDir}/assets/*`, to: `${publicDir}/` }]
+ }),
+ ]
+});
diff --git a/client/assets/favicon.ico b/client/assets/favicon.ico
new file mode 100644
index 0000000..68d7f56
Binary files /dev/null and b/client/assets/favicon.ico differ
diff --git a/client/assets/robots.txt b/client/assets/robots.txt
new file mode 100644
index 0000000..4d6e74a
--- /dev/null
+++ b/client/assets/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /#
diff --git a/client/components/Api/Api.vue b/client/components/Api/Api.vue
new file mode 100644
index 0000000..b0b7df0
--- /dev/null
+++ b/client/components/Api/Api.vue
@@ -0,0 +1,270 @@
+
+
+