mirror of https://github.com/lidarr/Lidarr
New: Webpack 5, UI Package Updates
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
This commit is contained in:
parent
3722099b02
commit
6c9808fe56
|
@ -20,7 +20,7 @@ Setup guides, FAQ, the more information we have on the [wiki](https://wiki.serva
|
|||
1. Fork Lidarr
|
||||
2. Clone the repository into your development machine. [*info*](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github)
|
||||
3. Install the required Node Packages `yarn install`
|
||||
4. Start gulp to monitor your dev environment for any changes that need post processing using `yarn start` command.
|
||||
4. Start webpack to monitor your dev environment for any changes that need post processing using `yarn start` command.
|
||||
5. Build the project in Visual Studio, Setting startup project to `Lidarr.Console` and framework to `netcoreapp31`
|
||||
6. Debug the project in Visual Studio
|
||||
7. Open http://localhost:8686
|
||||
|
|
10
build.sh
10
build.sh
|
@ -77,11 +77,11 @@ YarnInstall()
|
|||
ProgressEnd 'yarn install'
|
||||
}
|
||||
|
||||
RunGulp()
|
||||
RunWebpack()
|
||||
{
|
||||
ProgressStart 'Running gulp'
|
||||
yarn run build --production
|
||||
ProgressEnd 'Running gulp'
|
||||
ProgressStart 'Running webpack'
|
||||
yarn run build --env production
|
||||
ProgressEnd 'Running webpack'
|
||||
}
|
||||
|
||||
PackageFiles()
|
||||
|
@ -326,7 +326,7 @@ fi
|
|||
if [ "$FRONTEND" = "YES" ];
|
||||
then
|
||||
YarnInstall
|
||||
RunGulp
|
||||
RunWebpack
|
||||
fi
|
||||
|
||||
if [ "$LINT" = "YES" ];
|
||||
|
|
|
@ -6,8 +6,10 @@ const dirs = fs
|
|||
.map((dirent) => dirent.name)
|
||||
.join('|');
|
||||
|
||||
const frontendFolder = __dirname;
|
||||
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
parser: '@babel/eslint-parser',
|
||||
|
||||
env: {
|
||||
browser: true,
|
||||
|
@ -25,6 +27,9 @@ module.exports = {
|
|||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
sourceType: 'module',
|
||||
babelOptions: {
|
||||
configFile: `${frontendFolder}/babel.config.js`,
|
||||
},
|
||||
ecmaFeatures: {
|
||||
modules: true,
|
||||
impliedStrict: true
|
||||
|
@ -271,7 +276,7 @@ module.exports = {
|
|||
|
||||
// ImportSort
|
||||
|
||||
'simple-import-sort/sort': 'error',
|
||||
'simple-import-sort/imports': 'error',
|
||||
'import/newline-after-import': 'error',
|
||||
|
||||
// React
|
||||
|
@ -309,7 +314,7 @@ module.exports = {
|
|||
{
|
||||
files: ['*.js'],
|
||||
rules: {
|
||||
'simple-import-sort/sort': [
|
||||
'simple-import-sort/imports': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
|
|
|
@ -0,0 +1,270 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const FileManagerPlugin = require('filemanager-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const LiveReloadPlugin = require('webpack-livereload-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
module.exports = (env) => {
|
||||
const uiFolder = 'UI';
|
||||
const frontendFolder = path.join(__dirname, '..');
|
||||
const srcFolder = path.join(frontendFolder, 'src');
|
||||
const isProduction = !!env.production;
|
||||
const isProfiling = isProduction && !!env.profile;
|
||||
const inlineWebWorkers = 'no-fallback';
|
||||
|
||||
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
|
||||
|
||||
console.log('Source Folder:', srcFolder);
|
||||
console.log('Output Folder:', distFolder);
|
||||
console.log('isProduction:', isProduction);
|
||||
console.log('isProfiling:', isProfiling);
|
||||
|
||||
const config = {
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||
|
||||
stats: {
|
||||
children: false
|
||||
},
|
||||
|
||||
watchOptions: {
|
||||
ignored: /node_modules/
|
||||
},
|
||||
|
||||
entry: {
|
||||
index: 'index.js'
|
||||
},
|
||||
|
||||
resolve: {
|
||||
modules: [
|
||||
srcFolder,
|
||||
path.join(srcFolder, 'Shims'),
|
||||
'node_modules'
|
||||
],
|
||||
alias: {
|
||||
jquery: 'jquery/src/jquery'
|
||||
},
|
||||
fallback: {
|
||||
buffer: false,
|
||||
http: false,
|
||||
https: false,
|
||||
url: false,
|
||||
util: false,
|
||||
net: false
|
||||
}
|
||||
},
|
||||
|
||||
output: {
|
||||
path: distFolder,
|
||||
publicPath: '/',
|
||||
filename: '[name].js',
|
||||
sourceMapFilename: '[file].map'
|
||||
},
|
||||
|
||||
optimization: {
|
||||
moduleIds: 'deterministic',
|
||||
chunkIds: 'named',
|
||||
splitChunks: {
|
||||
chunks: 'initial',
|
||||
name: 'vendors'
|
||||
}
|
||||
},
|
||||
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
__DEV__: !isProduction,
|
||||
'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development')
|
||||
}),
|
||||
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'Content/styles.css'
|
||||
}),
|
||||
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'frontend/src/index.ejs',
|
||||
filename: 'index.html',
|
||||
publicPath: '/'
|
||||
}),
|
||||
|
||||
new FileManagerPlugin({
|
||||
events: {
|
||||
onEnd: {
|
||||
copy: [
|
||||
// HTML
|
||||
{
|
||||
source: 'frontend/src/*.html',
|
||||
destination: distFolder
|
||||
},
|
||||
|
||||
// Fonts
|
||||
{
|
||||
source: 'frontend/src/Content/Fonts/*.*',
|
||||
destination: path.join(distFolder, 'Content/Fonts')
|
||||
},
|
||||
|
||||
// Icon Images
|
||||
{
|
||||
source: 'frontend/src/Content/Images/Icons/*.*',
|
||||
destination: path.join(distFolder, 'Content/Images/Icons')
|
||||
},
|
||||
|
||||
// Images
|
||||
{
|
||||
source: 'frontend/src/Content/Images/*.*',
|
||||
destination: path.join(distFolder, 'Content/Images')
|
||||
},
|
||||
|
||||
// Robots
|
||||
{
|
||||
source: 'frontend/src/Content/robots.txt',
|
||||
destination: path.join(distFolder, 'Content/robots.txt')
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
new LiveReloadPlugin()
|
||||
],
|
||||
|
||||
resolveLoader: {
|
||||
modules: [
|
||||
'node_modules',
|
||||
'frontend/build/webpack/'
|
||||
]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
filename: '[name].js',
|
||||
inline: inlineWebWorkers
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js?$/,
|
||||
exclude: /(node_modules|JsLibraries)/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
configFile: `${frontendFolder}/babel.config.js`,
|
||||
envName: isProduction ? 'production' : 'development',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
modules: false,
|
||||
loose: true,
|
||||
debug: false,
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// CSS Modules
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: /(node_modules|globals.css)/,
|
||||
use: [
|
||||
{ loader: MiniCssExtractPlugin.loader },
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
modules: {
|
||||
localIdentName: '[name]/[local]/[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
config: 'frontend/postcss.config.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Global styles
|
||||
{
|
||||
test: /\.css$/,
|
||||
include: /(node_modules|globals.css)/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Fonts
|
||||
{
|
||||
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10240,
|
||||
mimetype: 'application/font-woff',
|
||||
emitFile: false,
|
||||
name: 'Content/Fonts/[name].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.(ttf|eot|eot?#iefix|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
emitFile: false,
|
||||
name: 'Content/Fonts/[name].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
if (isProfiling) {
|
||||
config.resolve.alias['react-dom$'] = 'react-dom/profiling';
|
||||
config.resolve.alias['scheduler/tracing'] = 'scheduler/tracing-profiling';
|
||||
|
||||
config.optimization.minimizer = [
|
||||
new TerserPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
sourceMap: true, // Must be set to true if using source-maps in production
|
||||
terserOptions: {
|
||||
mangle: false,
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
return config;
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
const gulp = require('gulp');
|
||||
|
||||
require('./clean');
|
||||
require('./copy');
|
||||
require('./webpack');
|
||||
|
||||
gulp.task('build',
|
||||
gulp.series('clean',
|
||||
gulp.parallel(
|
||||
'webpack',
|
||||
'copyHtml',
|
||||
'copyFonts',
|
||||
'copyImages',
|
||||
'copyRobots'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
const gulp = require('gulp');
|
||||
const del = require('del');
|
||||
|
||||
const paths = require('./helpers/paths');
|
||||
|
||||
gulp.task('clean', () => {
|
||||
return del([paths.dest.root]);
|
||||
});
|
|
@ -1,42 +0,0 @@
|
|||
const path = require('path');
|
||||
const gulp = require('gulp');
|
||||
const print = require('gulp-print').default;
|
||||
const cache = require('gulp-cached');
|
||||
const livereload = require('gulp-livereload');
|
||||
const paths = require('./helpers/paths.js');
|
||||
|
||||
gulp.task('copyHtml', () => {
|
||||
return gulp.src(paths.src.html, { base: paths.src.root })
|
||||
.pipe(cache('copyHtml'))
|
||||
.pipe(print())
|
||||
.pipe(gulp.dest(paths.dest.root))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('copyFonts', () => {
|
||||
return gulp.src(
|
||||
path.join(paths.src.fonts, '**', '*.*'), { base: paths.src.root }
|
||||
)
|
||||
.pipe(cache('copyFonts'))
|
||||
.pipe(print())
|
||||
.pipe(gulp.dest(paths.dest.root))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('copyImages', () => {
|
||||
return gulp.src(
|
||||
path.join(paths.src.images, '**', '*.*'), { base: paths.src.root }
|
||||
)
|
||||
.pipe(cache('copyImages'))
|
||||
.pipe(print())
|
||||
.pipe(gulp.dest(paths.dest.root))
|
||||
.pipe(livereload());
|
||||
});
|
||||
|
||||
gulp.task('copyRobots', () => {
|
||||
return gulp.src(paths.src.robots, { base: paths.src.root })
|
||||
.pipe(cache('copyRobots'))
|
||||
.pipe(print())
|
||||
.pipe(gulp.dest(paths.dest.root))
|
||||
.pipe(livereload());
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
require('./build.js');
|
||||
require('./clean.js');
|
||||
require('./copy.js');
|
||||
require('./watch.js');
|
||||
require('./webpack.js');
|
|
@ -1,6 +0,0 @@
|
|||
const colors = require('ansi-colors');
|
||||
|
||||
module.exports = function errorHandler(error) {
|
||||
console.log(colors.red(`Error (${error.plugin}): ${error.message}`));
|
||||
this.emit('end');
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
const root = './frontend/src';
|
||||
|
||||
const paths = {
|
||||
src: {
|
||||
root,
|
||||
html: `${root}/*.html`,
|
||||
scripts: `${root}/**/*.js`,
|
||||
content: `${root}/Content/`,
|
||||
fonts: `${root}/Content/Fonts/`,
|
||||
images: `${root}/Content/Images/`,
|
||||
robots: `${root}/Content/robots.txt`,
|
||||
exclude: {
|
||||
libs: `!${root}/JsLibraries/**`
|
||||
}
|
||||
},
|
||||
dest: {
|
||||
root: './_output/UI/',
|
||||
content: './_output/UI/Content/',
|
||||
fonts: './_output/UI/Content/Fonts/',
|
||||
images: './_output/UI/Content/Images/'
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = paths;
|
|
@ -1,19 +0,0 @@
|
|||
const gulp = require('gulp');
|
||||
const livereload = require('gulp-livereload');
|
||||
const gulpWatch = require('gulp-watch');
|
||||
const paths = require('./helpers/paths.js');
|
||||
|
||||
require('./copy.js');
|
||||
require('./webpack.js');
|
||||
|
||||
function watch() {
|
||||
livereload.listen({ start: true });
|
||||
|
||||
gulp.task('webpackWatch')();
|
||||
gulpWatch(paths.src.html, gulp.series('copyHtml'));
|
||||
gulpWatch(`${paths.src.fonts}**/*.*`, gulp.series('copyFonts'));
|
||||
gulpWatch(`${paths.src.images}**/*.*`, gulp.series('copyImages'));
|
||||
gulpWatch(paths.src.robots, gulp.series('copyRobots'));
|
||||
}
|
||||
|
||||
gulp.task('watch', gulp.series('build', watch));
|
|
@ -1,271 +0,0 @@
|
|||
const gulp = require('gulp');
|
||||
const webpackStream = require('webpack-stream');
|
||||
const livereload = require('gulp-livereload');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const errorHandler = require('./helpers/errorHandler');
|
||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const HtmlWebpackPluginHtmlTags = require('html-webpack-plugin/lib/html-tags');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const uiFolder = 'UI';
|
||||
const frontendFolder = path.join(__dirname, '..');
|
||||
const srcFolder = path.join(frontendFolder, 'src');
|
||||
const isProduction = process.argv.indexOf('--production') > -1;
|
||||
const isProfiling = isProduction && process.argv.indexOf('--profile') > -1;
|
||||
const inlineWebWorkers = 'no-fallback';
|
||||
|
||||
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
|
||||
|
||||
console.log('Source Folder:', srcFolder);
|
||||
console.log('Output Folder:', distFolder);
|
||||
console.log('isProduction:', isProduction);
|
||||
console.log('isProfiling:', isProfiling);
|
||||
|
||||
const cssVarsFiles = [
|
||||
'../src/Styles/Variables/colors',
|
||||
'../src/Styles/Variables/dimensions',
|
||||
'../src/Styles/Variables/fonts',
|
||||
'../src/Styles/Variables/animations',
|
||||
'../src/Styles/Variables/zIndexes'
|
||||
].map(require.resolve);
|
||||
|
||||
// Override the way HtmlWebpackPlugin injects the scripts
|
||||
// TODO: Find a better way to get these paths without
|
||||
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, assets, assetTags) {
|
||||
const head = assetTags.headTags.map((v) => {
|
||||
const href = v.attributes.href
|
||||
.replace('\\', '/')
|
||||
.replace('%5C', '/');
|
||||
|
||||
v.attributes = { rel: 'stylesheet', type: 'text/css', href: `/${href}` };
|
||||
return HtmlWebpackPluginHtmlTags.htmlTagObjectToString(v, this.options.xhtml);
|
||||
});
|
||||
const body = assetTags.bodyTags.map((v) => {
|
||||
v.attributes = { src: `/${v.attributes.src}` };
|
||||
return HtmlWebpackPluginHtmlTags.htmlTagObjectToString(v, this.options.xhtml);
|
||||
});
|
||||
|
||||
return html
|
||||
.replace('<!-- webpack bundles head -->', head.join('\r\n '))
|
||||
.replace('<!-- webpack bundles body -->', body.join('\r\n '));
|
||||
};
|
||||
|
||||
const plugins = [
|
||||
new OptimizeCssAssetsPlugin({}),
|
||||
|
||||
new webpack.DefinePlugin({
|
||||
__DEV__: !isProduction,
|
||||
'process.env.NODE_ENV': isProduction ? JSON.stringify('production') : JSON.stringify('development')
|
||||
}),
|
||||
|
||||
new MiniCssExtractPlugin({
|
||||
filename: path.join('Content', 'styles.css')
|
||||
}),
|
||||
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'frontend/src/index.html',
|
||||
filename: 'index.html'
|
||||
})
|
||||
];
|
||||
|
||||
const config = {
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
devtool: '#source-map',
|
||||
|
||||
stats: {
|
||||
children: false
|
||||
},
|
||||
|
||||
watchOptions: {
|
||||
ignored: /node_modules/
|
||||
},
|
||||
|
||||
entry: {
|
||||
index: 'index.js'
|
||||
},
|
||||
|
||||
resolve: {
|
||||
modules: [
|
||||
srcFolder,
|
||||
path.join(srcFolder, 'Shims'),
|
||||
'node_modules'
|
||||
],
|
||||
alias: {
|
||||
jquery: 'jquery/src/jquery'
|
||||
}
|
||||
},
|
||||
|
||||
output: {
|
||||
path: distFolder,
|
||||
filename: '[name].js',
|
||||
sourceMapFilename: '[file].map'
|
||||
},
|
||||
|
||||
optimization: {
|
||||
chunkIds: 'named',
|
||||
splitChunks: {
|
||||
chunks: 'initial'
|
||||
}
|
||||
},
|
||||
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
|
||||
plugins,
|
||||
|
||||
resolveLoader: {
|
||||
modules: [
|
||||
'node_modules',
|
||||
'frontend/gulp/webpack/'
|
||||
]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.worker\.js$/,
|
||||
use: {
|
||||
loader: 'worker-loader',
|
||||
options: {
|
||||
filename: '[name].js',
|
||||
inline: inlineWebWorkers
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js?$/,
|
||||
exclude: /(node_modules|JsLibraries)/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
configFile: `${frontendFolder}/babel.config.js`,
|
||||
envName: isProduction ? 'production' : 'development',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
modules: false,
|
||||
loose: true,
|
||||
debug: false,
|
||||
useBuiltIns: 'entry',
|
||||
corejs: 3
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// CSS Modules
|
||||
{
|
||||
test: /\.css$/,
|
||||
exclude: /(node_modules|globals.css)/,
|
||||
use: [
|
||||
{ loader: MiniCssExtractPlugin.loader },
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
modules: {
|
||||
localIdentName: '[name]/[local]/[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
ident: 'postcss',
|
||||
config: {
|
||||
ctx: {
|
||||
cssVarsFiles
|
||||
},
|
||||
path: 'frontend/postcss.config.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Global styles
|
||||
{
|
||||
test: /\.css$/,
|
||||
include: /(node_modules|globals.css)/,
|
||||
use: [
|
||||
'style-loader',
|
||||
{
|
||||
loader: 'css-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// Fonts
|
||||
{
|
||||
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10240,
|
||||
mimetype: 'application/font-woff',
|
||||
emitFile: false,
|
||||
name: 'Content/Fonts/[name].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.(ttf|eot|eot?#iefix|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
emitFile: false,
|
||||
name: 'Content/Fonts/[name].[ext]'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
if (isProfiling) {
|
||||
config.resolve.alias['react-dom$'] = 'react-dom/profiling';
|
||||
config.resolve.alias['scheduler/tracing'] = 'scheduler/tracing-profiling';
|
||||
|
||||
config.optimization.minimizer = [
|
||||
new TerserPlugin({
|
||||
cache: true,
|
||||
parallel: true,
|
||||
sourceMap: true, // Must be set to true if using source-maps in production
|
||||
terserOptions: {
|
||||
mangle: false,
|
||||
keep_classnames: true,
|
||||
keep_fnames: true
|
||||
}
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
gulp.task('webpack', () => {
|
||||
return webpackStream(config)
|
||||
.pipe(gulp.dest('_output/UI'));
|
||||
});
|
||||
|
||||
gulp.task('webpackWatch', () => {
|
||||
config.watch = true;
|
||||
|
||||
return webpackStream(config, webpack)
|
||||
.on('error', errorHandler)
|
||||
.pipe(gulp.dest('_output/UI'))
|
||||
.on('error', errorHandler)
|
||||
.pipe(livereload())
|
||||
.on('error', errorHandler);
|
||||
});
|
|
@ -1,23 +1,32 @@
|
|||
const reload = require('require-nocache')(module);
|
||||
|
||||
module.exports = (ctx, configPath, options) => {
|
||||
const config = {
|
||||
plugins: {
|
||||
'postcss-mixins': {
|
||||
mixinsDir: [
|
||||
'frontend/src/Styles/Mixins'
|
||||
]
|
||||
},
|
||||
'postcss-simple-vars': {
|
||||
const cssVarsFiles = [
|
||||
'./src/Styles/Variables/colors',
|
||||
'./src/Styles/Variables/dimensions',
|
||||
'./src/Styles/Variables/fonts',
|
||||
'./src/Styles/Variables/animations',
|
||||
'./src/Styles/Variables/zIndexes'
|
||||
].map(require.resolve);
|
||||
|
||||
const mixinsFiles = [
|
||||
'frontend/src/Styles/Mixins/cover.css',
|
||||
'frontend/src/Styles/Mixins/linkOverlay.css',
|
||||
'frontend/src/Styles/Mixins/scroller.css',
|
||||
'frontend/src/Styles/Mixins/truncate.css'
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
['postcss-mixins', {
|
||||
mixinsFiles
|
||||
}],
|
||||
['postcss-simple-vars', {
|
||||
variables: () =>
|
||||
ctx.options.cssVarsFiles.reduce((acc, vars) => {
|
||||
cssVarsFiles.reduce((acc, vars) => {
|
||||
return Object.assign(acc, reload(vars));
|
||||
}, {})
|
||||
},
|
||||
'postcss-color-function': {},
|
||||
'postcss-nested': {}
|
||||
}
|
||||
};
|
||||
|
||||
return config;
|
||||
}],
|
||||
'postcss-color-function',
|
||||
'postcss-nested'
|
||||
]
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ function createTagListSelector() {
|
|||
(selectedFilterBuilderProp.type === filterBuilderTypes.NUMBER ||
|
||||
selectedFilterBuilderProp.type === filterBuilderTypes.STRING) &&
|
||||
filterType !== filterTypes.EQUAL &&
|
||||
filterType !== filterBuilderTypes.NOT_EQUAL ||
|
||||
filterType !== filterTypes.NOT_EQUAL ||
|
||||
!selectedFilterBuilderProp.optionsSelector
|
||||
) {
|
||||
return [];
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import _ from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { DndProvider } from 'react-dnd-multi-backend';
|
||||
import HTML5toTouch from 'react-dnd-multi-backend/dist/esm/HTML5toTouch';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
|
@ -127,7 +127,7 @@ class TableOptionsModal extends Component {
|
|||
const isDraggingDown = isDragging && dropIndex > dragIndex;
|
||||
|
||||
return (
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<DndProvider options={HTML5toTouch}>
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onModalClose={onModalClose}
|
||||
|
|
|
@ -98,7 +98,7 @@ class MetadataProfile extends Component {
|
|||
return (
|
||||
<Label
|
||||
key={item.albumType.id}
|
||||
kind={kinds.default}
|
||||
kind={kinds.DEFAULT}
|
||||
title={null}
|
||||
>
|
||||
{item.albumType.name}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
import { DndProvider } from 'react-dnd-multi-backend';
|
||||
import HTML5toTouch from 'react-dnd-multi-backend/dist/esm/HTML5toTouch';
|
||||
import PageContent from 'Components/Page/PageContent';
|
||||
import PageContentBody from 'Components/Page/PageContentBody';
|
||||
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
|
||||
|
@ -25,7 +25,7 @@ class Profiles extends Component {
|
|||
/>
|
||||
|
||||
<PageContentBody>
|
||||
<DndProvider backend={HTML5Backend}>
|
||||
<DndProvider options={HTML5toTouch}>
|
||||
<QualityProfilesConnector />
|
||||
<MetadataProfilesConnector />
|
||||
<DelayProfilesConnector />
|
||||
|
|
|
@ -103,7 +103,7 @@ class QualityProfile extends Component {
|
|||
return (
|
||||
<Label
|
||||
key={item.quality.id}
|
||||
kind={isCutoff ? kinds.INFO : kinds.default}
|
||||
kind={isCutoff ? kinds.INFO : kinds.DEFAULT}
|
||||
title={isCutoff ? 'Upgrade until this quality is met or exceeded' : null}
|
||||
>
|
||||
{item.quality.name}
|
||||
|
@ -119,7 +119,7 @@ class QualityProfile extends Component {
|
|||
className={styles.tooltipLabel}
|
||||
anchor={
|
||||
<Label
|
||||
kind={isCutoff ? kinds.INFO : kinds.default}
|
||||
kind={isCutoff ? kinds.INFO : kinds.DEFAULT}
|
||||
title={isCutoff ? 'Cutoff' : null}
|
||||
>
|
||||
{item.name}
|
||||
|
@ -132,7 +132,7 @@ class QualityProfile extends Component {
|
|||
return (
|
||||
<Label
|
||||
key={groupItem.quality.id}
|
||||
kind={isCutoff ? kinds.INFO : kinds.default}
|
||||
kind={isCutoff ? kinds.INFO : kinds.DEFAULT}
|
||||
title={isCutoff ? 'Cutoff' : null}
|
||||
>
|
||||
{groupItem.quality.name}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
@define-mixin scrollbarTrack {
|
||||
&&::-webkit-scrollbar-track {
|
||||
&::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ function getStatusIconProps(status, message) {
|
|||
case 'failed':
|
||||
return {
|
||||
name: icons.FATAL,
|
||||
kind: kinds.ERROR,
|
||||
kind: kinds.DANGER,
|
||||
title: `${title}: ${message}`
|
||||
};
|
||||
|
||||
|
|
229
package.json
229
package.json
|
@ -3,10 +3,11 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Lidarr",
|
||||
"scripts": {
|
||||
"build": "gulp build",
|
||||
"start": "gulp watch",
|
||||
"watch": "gulp watch",
|
||||
"clean": "git clean -fXd",
|
||||
"build": "webpack --config ./frontend/build/webpack.config.js",
|
||||
"prebuild": "yarn clean",
|
||||
"clean": "rimraf ./_output/UI && rimraf \"**/*.js.map\"",
|
||||
"start": "webpack --watch --config ./frontend/build/webpack.config.js",
|
||||
"watch": "webpack --watch --config ./frontend/build/webpack.config.js",
|
||||
"lint": "esprint check",
|
||||
"lint-fix": "esprint check --fix",
|
||||
"stylelint-linux": "stylelint $(find frontend -name '*.css') --config frontend/.stylelintrc",
|
||||
|
@ -19,121 +20,119 @@
|
|||
"author": "Team Lidarr",
|
||||
"license": "GPL-3.0",
|
||||
"readmeFilename": "readme.md",
|
||||
"dependencies": {
|
||||
"@babel/core": "7.11.6",
|
||||
"@babel/plugin-proposal-class-properties": "7.10.4",
|
||||
"@babel/plugin-proposal-decorators": "7.10.5",
|
||||
"@babel/plugin-proposal-export-default-from": "7.10.4",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.10.4",
|
||||
"@babel/plugin-proposal-function-sent": "7.10.4",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.10.4",
|
||||
"@babel/plugin-proposal-numeric-separator": "7.10.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.11.0",
|
||||
"@babel/plugin-proposal-throw-expressions": "7.10.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@babel/preset-env": "7.11.5",
|
||||
"@babel/preset-react": "7.10.4",
|
||||
"@fortawesome/fontawesome-free": "5.15.0",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.31",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.0",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.0",
|
||||
"@fortawesome/react-fontawesome": "0.1.11",
|
||||
"@microsoft/signalr": "3.1.13",
|
||||
"@sentry/browser": "5.24.2",
|
||||
"@sentry/integrations": "5.24.2",
|
||||
"ansi-colors": "4.1.1",
|
||||
"autoprefixer": "9.7.5",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-inline-classnames": "2.0.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
||||
"classnames": "2.2.6",
|
||||
"clipboard": "2.0.6",
|
||||
"connected-react-router": "6.8.0",
|
||||
"core-js": "3.6.5",
|
||||
"css-loader": "3.4.2",
|
||||
"del": "6.0.0",
|
||||
"element-class": "0.2.2",
|
||||
"eslint": "7.10.0",
|
||||
"eslint-plugin-filenames": "1.3.2",
|
||||
"eslint-plugin-import": "2.22.0",
|
||||
"eslint-plugin-react": "7.21.3",
|
||||
"eslint-plugin-simple-import-sort": "5.0.3",
|
||||
"esprint": "0.7.0",
|
||||
"file-loader": "6.1.0",
|
||||
"filesize": "6.1.0",
|
||||
"fuse.js": "6.4.1",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-cached": "1.1.1",
|
||||
"gulp-concat": "2.6.1",
|
||||
"gulp-livereload": "4.0.2",
|
||||
"gulp-postcss": "8.0.0",
|
||||
"gulp-print": "5.0.2",
|
||||
"gulp-sourcemaps": "2.6.5",
|
||||
"gulp-watch": "5.0.1",
|
||||
"gulp-wrap": "0.15.0",
|
||||
"history": "4.10.1",
|
||||
"html-webpack-plugin": "4.5.0",
|
||||
"jdu": "1.0.0",
|
||||
"jquery": "3.5.1",
|
||||
"loader-utils": "^2.0.0",
|
||||
"lodash": "4.17.20",
|
||||
"mini-css-extract-plugin": "0.9.0",
|
||||
"mobile-detect": "1.4.4",
|
||||
"moment": "2.29.0",
|
||||
"mousetrap": "1.6.5",
|
||||
"normalize.css": "8.0.1",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.3",
|
||||
"postcss-color-function": "4.1.0",
|
||||
"postcss-loader": "3.0.0",
|
||||
"postcss-mixins": "6.2.3",
|
||||
"postcss-nested": "4.2.1",
|
||||
"postcss-simple-vars": "5.0.2",
|
||||
"postcss-url": "8.0.0",
|
||||
"prop-types": "15.7.2",
|
||||
"qs": "6.9.4",
|
||||
"react": "16.13.1",
|
||||
"react-addons-shallow-compare": "15.6.2",
|
||||
"react-async-script": "1.2.0",
|
||||
"react-autosuggest": "10.0.2",
|
||||
"react-custom-scrollbars": "4.2.1",
|
||||
"react-dnd": "11.1.3",
|
||||
"react-dnd-html5-backend": "11.1.3",
|
||||
"react-document-title": "2.0.3",
|
||||
"react-dom": "16.13.1",
|
||||
"react-focus-lock": "2.4.1",
|
||||
"react-google-recaptcha": "2.1.0",
|
||||
"react-lazyload": "3.0.0",
|
||||
"react-measure": "1.4.7",
|
||||
"react-popper": "1.3.7",
|
||||
"react-redux": "7.2.1",
|
||||
"react-router": "5.2.0",
|
||||
"react-router-dom": "5.2.0",
|
||||
"react-slider": "1.0.11",
|
||||
"react-text-truncate": "0.16.0",
|
||||
"react-virtualized": "9.21.1",
|
||||
"redux": "4.0.5",
|
||||
"redux-actions": "2.6.5",
|
||||
"redux-batched-actions": "0.5.0",
|
||||
"redux-localstorage": "0.4.1",
|
||||
"redux-thunk": "2.3.0",
|
||||
"require-nocache": "1.0.0",
|
||||
"reselect": "4.0.0",
|
||||
"run-sequence": "2.2.1",
|
||||
"streamqueue": "1.1.2",
|
||||
"style-loader": "1.2.1",
|
||||
"stylelint": "13.7.2",
|
||||
"stylelint-order": "4.1.0",
|
||||
"url-loader": "4.1.0",
|
||||
"webpack": "4.44.2",
|
||||
"webpack-stream": "6.1.0",
|
||||
"worker-loader": "3.0.3"
|
||||
},
|
||||
"main": "index.js",
|
||||
"browserslist": [
|
||||
">0.25%",
|
||||
"not ie 11",
|
||||
"not op_mini all",
|
||||
"not chrome < 60"
|
||||
]
|
||||
],
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "5.15.3",
|
||||
"@fortawesome/fontawesome-svg-core": "1.2.35",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.3",
|
||||
"@fortawesome/free-solid-svg-icons": "5.15.3",
|
||||
"@fortawesome/react-fontawesome": "0.1.14",
|
||||
"@microsoft/signalr": "5.0.7",
|
||||
"@sentry/browser": "6.3.6",
|
||||
"@sentry/integrations": "6.3.6",
|
||||
"ansi-colors": "4.1.1",
|
||||
"classnames": "2.3.1",
|
||||
"clipboard": "2.0.8",
|
||||
"connected-react-router": "6.9.1",
|
||||
"element-class": "0.2.2",
|
||||
"filemanager-webpack-plugin": "5.0.0",
|
||||
"filesize": "6.3.0",
|
||||
"fuse.js": "6.4.6",
|
||||
"history": "4.10.1",
|
||||
"jdu": "1.0.0",
|
||||
"jquery": "3.6.0",
|
||||
"lodash": "4.17.21",
|
||||
"mobile-detect": "1.4.5",
|
||||
"moment": "2.29.1",
|
||||
"mousetrap": "1.6.5",
|
||||
"normalize.css": "8.0.1",
|
||||
"prop-types": "15.7.2",
|
||||
"qs": "6.10.1",
|
||||
"react": "17.0.2",
|
||||
"react-addons-shallow-compare": "15.6.3",
|
||||
"react-async-script": "1.2.0",
|
||||
"react-autosuggest": "10.1.0",
|
||||
"react-custom-scrollbars": "4.2.1",
|
||||
"react-dnd": "14.0.2",
|
||||
"react-dnd-html5-backend": "14.0.0",
|
||||
"react-dnd-multi-backend": "6.0.2",
|
||||
"react-dnd-touch-backend": "14.0.0",
|
||||
"react-document-title": "2.0.3",
|
||||
"react-dom": "17.0.2",
|
||||
"react-focus-lock": "2.5.0",
|
||||
"react-google-recaptcha": "2.1.0",
|
||||
"react-lazyload": "3.2.0",
|
||||
"react-measure": "1.4.7",
|
||||
"react-popper": "1.3.7",
|
||||
"react-redux": "7.2.4",
|
||||
"react-router": "5.2.0",
|
||||
"react-router-dom": "5.2.0",
|
||||
"react-slider": "1.1.4",
|
||||
"react-tabs": "3.2.2",
|
||||
"react-text-truncate": "0.16.0",
|
||||
"react-virtualized": "9.21.1",
|
||||
"redux": "4.1.0",
|
||||
"redux-actions": "2.6.5",
|
||||
"redux-batched-actions": "0.5.0",
|
||||
"redux-localstorage": "0.4.1",
|
||||
"redux-thunk": "2.3.0",
|
||||
"reselect": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.14.0",
|
||||
"@babel/eslint-parser": "7.13.14",
|
||||
"@babel/plugin-proposal-class-properties": "7.13.0",
|
||||
"@babel/plugin-proposal-decorators": "7.13.15",
|
||||
"@babel/plugin-proposal-export-default-from": "7.12.13",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.12.13",
|
||||
"@babel/plugin-proposal-function-sent": "7.12.13",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.13.8",
|
||||
"@babel/plugin-proposal-numeric-separator": "7.12.13",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.13.12",
|
||||
"@babel/plugin-proposal-throw-expressions": "7.12.13",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@babel/preset-env": "7.14.1",
|
||||
"@babel/preset-react": "7.13.13",
|
||||
"autoprefixer": "10.2.5",
|
||||
"babel-loader": "8.2.2",
|
||||
"babel-plugin-inline-classnames": "2.0.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
|
||||
"core-js": "3.12.1",
|
||||
"css-loader": "5.2.4",
|
||||
"eslint": "7.26.0",
|
||||
"eslint-plugin-filenames": "1.3.2",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"eslint-plugin-react": "7.23.2",
|
||||
"eslint-plugin-simple-import-sort": "7.0.0",
|
||||
"esprint": "2.0.0",
|
||||
"file-loader": "6.2.0",
|
||||
"html-webpack-plugin": "5.3.1",
|
||||
"loader-utils": "^2.0.0",
|
||||
"mini-css-extract-plugin": "1.6.0",
|
||||
"postcss": "8.2.15",
|
||||
"postcss-color-function": "4.1.0",
|
||||
"postcss-loader": "5.2.0",
|
||||
"postcss-mixins": "7.0.3",
|
||||
"postcss-nested": "5.0.5",
|
||||
"postcss-simple-vars": "6.0.3",
|
||||
"postcss-url": "10.1.3",
|
||||
"require-nocache": "1.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
"run-sequence": "2.2.1",
|
||||
"streamqueue": "1.1.2",
|
||||
"style-loader": "2.0.0",
|
||||
"stylelint": "13.13.1",
|
||||
"stylelint-order": "4.1.0",
|
||||
"url-loader": "4.1.1",
|
||||
"webpack": "5.37.0",
|
||||
"webpack-cli": "4.7.0",
|
||||
"webpack-livereload-plugin": "3.0.1",
|
||||
"worker-loader": "3.0.8"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue