feat(frontend): upgrade frontend dependencies DTD-11 (#6244)

* upgrade webpack, eslint, storybook and other dependencies
pull/5002/head
Richard Wei 3 years ago committed by GitHub
parent 730fdb160d
commit 187b66f5cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,6 +9,7 @@ globals:
extends:
- 'eslint:recommended'
- 'plugin:storybook/recommended'
- prettier
plugins:
@ -60,6 +61,7 @@ overrides:
- 'plugin:@typescript-eslint/recommended'
- 'plugin:@typescript-eslint/eslint-recommended'
- 'plugin:promise/recommended'
- 'plugin:storybook/recommended'
- prettier # should be last
settings:
react:
@ -83,6 +85,8 @@ overrides:
'@typescript-eslint/no-unused-vars': 'error'
'@typescript-eslint/no-explicit-any': 'error'
'jsx-a11y/label-has-associated-control': ['error', { 'assert': 'either' }]
'react/function-component-definition': ['error', { 'namedComponents': 'function-declaration' }]
'react/jsx-no-bind': off
- files:
- app/**/*.test.*
extends:

@ -28,4 +28,7 @@ module.exports = {
];
return config;
},
core: {
builder: 'webpack5',
},
};

@ -353,11 +353,9 @@ angular.module('portainer.docker').controller('ServiceController', [
const registryChanged = $scope.initialRegistryID != newRegistryID;
if ($scope.WebhookExists && registryChanged) {
WebhookService.updateServiceWebhook($scope.webhookID, newRegistryID)
.then(function success() {})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update webhook');
});
WebhookService.updateServiceWebhook($scope.webhookID, newRegistryID).catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update webhook');
});
}
};

@ -18,12 +18,12 @@
<![endif]-->
<!-- Fav and touch icons -->
<link rel="apple-touch-icon" sizes="180x180" href="${require('./assets/ico/apple-touch-icon.png')}" />
<link rel="icon" type="image/png" sizes="32x32" href="${require('./assets/ico/favicon-32x32.png')}" />
<link rel="icon" type="image/png" sizes="16x16" href="${require('./assets/ico/favicon-16x16.png')}" />
<link rel="mask-icon" href="${require('./assets/ico/safari-pinned-tab.svg')}" color="#5bbad5" />
<link rel="shortcut icon" href="${require('./assets/ico/favicon.ico')}" />
<meta name="msapplication-config" content="${require('./assets/ico/browserconfig.xml')}" />
<link rel="apple-touch-icon" sizes="180x180" href="<%=require('./assets/ico/apple-touch-icon.png')%>" />
<link rel="icon" type="image/png" sizes="32x32" href="<%=require('./assets/ico/favicon-32x32.png')%>" />
<link rel="icon" type="image/png" sizes="16x16" href="<%=require('./assets/ico/favicon-16x16.png')%>" />
<link rel="mask-icon" href="<%=require('./assets/ico/safari-pinned-tab.svg')%>" color="#5bbad5" />
<link rel="shortcut icon" href="<%=require('./assets/ico/favicon.ico')%>" />
<meta name="msapplication-config" content="<%=require('./assets/ico/browserconfig.xml')%>" />
<meta name="theme-color" content="#ffffff" />
</head>
@ -47,7 +47,7 @@
<!-- loading box logo -->
<div class="row">
<img ng-if="logo" ng-src="{{ logo }}" class="simple-box-logo" />
<img ng-if="!logo" src="${require('./assets/images/logo_alt.svg')}" class="simple-box-logo" alt="Portainer" />
<img ng-if="!logo" src="<%=require('./assets/images/logo_alt.svg')%>" class="simple-box-logo" alt="Portainer" />
</div>
<!-- !loading box logo -->
<!-- panel -->

@ -1,5 +1,4 @@
import './assets/css';
import '@babel/polyfill';
import angular from 'angular';
import { UI_ROUTER_REACT_HYBRID } from '@uirouter/react-hybrid';

@ -14,7 +14,9 @@ const meta: Meta = {
export default meta;
export function Example() {
export { Example, LimitedFeature };
function Example() {
const [value, setValue] = useState(3);
const options: BoxSelectorOption<number>[] = [
{
@ -45,7 +47,7 @@ export function Example() {
);
}
export function LimitedFeature() {
function LimitedFeature() {
initFeatureService(Edition.CE);
const [value, setValue] = useState(3);
const options: BoxSelectorOption<number>[] = [

@ -12,7 +12,9 @@ const meta: Meta = {
export default meta;
export function Example() {
export { Example };
function Example() {
return (
<UIRouter plugins={[pushStateLocationPlugin]}>
<Breadcrumbs>

@ -1,4 +1,5 @@
import { Meta, Story } from '@storybook/react';
import { useMemo } from 'react';
import { Link } from '@/portainer/components/Link';
import { UserContext } from '@/portainer/hooks/useUser';
@ -19,10 +20,13 @@ interface StoryProps {
}
function Template({ title }: StoryProps) {
const state = useMemo(
() => ({ user: new UserViewModel({ Username: 'test' }) }),
[]
);
return (
<UserContext.Provider
value={{ user: new UserViewModel({ Username: 'test' }) }}
>
<UserContext.Provider value={state}>
<Header>
<HeaderTitle title={title} />
<HeaderContent>

@ -9,12 +9,13 @@ const meta: Meta = {
};
export default meta;
export { Example };
interface Props {
text: string;
}
export function Example({ text }: Props) {
function Example({ text }: Props) {
return (
<UIRouter plugins={[pushStateLocationPlugin]}>
<ReactExample text={text} />

@ -8,7 +8,9 @@ export default {
title: 'Components/ButtonSelector',
} as Meta;
export function TwoOptionsSelector() {
export { TwoOptionsSelector };
function TwoOptionsSelector() {
const options: Option<string>[] = [
{ value: 'sAMAccountName', label: 'username' },
{ value: 'userPrincipalName', label: 'user@domainname' },

@ -14,7 +14,9 @@ interface TextFieldProps {
tooltip?: string;
}
export function TextField({ label, tooltip = '' }: TextFieldProps) {
export { TextField, SelectField };
function TextField({ label, tooltip = '' }: TextFieldProps) {
const [value, setValue] = useState('');
const inputId = 'input';
return (
@ -29,7 +31,7 @@ TextField.args = {
tooltip: '',
};
export function SelectField({ label, tooltip = '' }: TextFieldProps) {
function SelectField({ label, tooltip = '' }: TextFieldProps) {
const options = [
{ value: 1, label: 'one' },
{ value: 2, label: 'two' },

@ -8,7 +8,9 @@ export default {
title: 'Components/Form/InputGroup',
} as Meta;
export function BasicExample() {
export { BasicExample, Addons, Sizing };
function BasicExample() {
const [value1, setValue1] = useState('');
const [valueNumber, setValueNumber] = useState(0);
@ -58,7 +60,7 @@ export function BasicExample() {
);
}
export function Addons() {
function Addons() {
const [value1, setValue1] = useState('');
const [value2, setValue2] = useState('');
return (
@ -85,7 +87,7 @@ export function Addons() {
);
}
export function Sizing() {
function Sizing() {
const [value, setValue] = useState('');
return (
<div className="space-y-8">

@ -12,7 +12,9 @@ const meta: Meta = {
export default meta;
export function Defaults() {
export { Defaults, ListWithInputAndSelect };
function Defaults() {
const [values, setValues] = useState<DefaultType[]>([{ value: '' }]);
return (
@ -35,7 +37,7 @@ interface ListWithInputAndSelectArgs {
movable: boolean;
tooltip: string;
}
export function ListWithInputAndSelect({
function ListWithInputAndSelect({
label,
movable,
tooltip,

@ -28,13 +28,9 @@ const meta: Meta<WidgetProps> = {
export default meta;
export function Default({
loading,
bodyText,
footerText,
icon,
title,
}: WidgetProps) {
export { Default, WidgetWithCustomImage, WidgetWithTaskBar };
function Default({ loading, bodyText, footerText, icon, title }: WidgetProps) {
return (
<Widget>
<WidgetTitle title={title} icon={icon} />
@ -44,7 +40,7 @@ export function Default({
);
}
export function WidgetWithCustomImage({
function WidgetWithCustomImage({
loading,
bodyText,
footerText,
@ -73,7 +69,7 @@ WidgetWithCustomImage.args = {
icon: 'https://via.placeholder.com/150',
};
export function WidgetWithTaskBar({
function WidgetWithTaskBar({
loading,
bodyText,
footerText,

@ -6,6 +6,7 @@ import {
useContext,
useEffect,
useState,
useMemo,
} from 'react';
import { getUser } from '@/portainer/services/api/userService';
@ -15,7 +16,7 @@ import { UserViewModel } from '../models/user';
import { useLocalStorage } from './useLocalStorage';
interface State {
user?: UserViewModel;
user?: UserViewModel | null;
}
const state: State = {};
@ -70,10 +71,13 @@ interface AuthorizedProps {
children: ReactNode;
}
export function Authorized({ authorizations, children }: AuthorizedProps) {
export function Authorized({
authorizations,
children,
}: AuthorizedProps): ReactNode {
const isAllowed = useAuthorizations(authorizations);
return isAllowed ? <>{children}</> : null;
return isAllowed ? children : null;
}
interface UserProviderProps {
@ -94,16 +98,20 @@ export function UserProvider({ children }: UserProviderProps) {
}
}, [jwt]);
const providerState = useMemo(() => ({ user }), [user]);
if (jwt === '') {
return null;
}
if (user === null) {
if (providerState.user === null) {
return null;
}
return (
<UserContext.Provider value={{ user }}>{children}</UserContext.Provider>
<UserContext.Provider value={providerState}>
{children}
</UserContext.Provider>
);
async function loadUser(id: number) {

@ -64,25 +64,24 @@
},
"dependencies": {
"@aws-crypto/sha256-js": "^2.0.0",
"@babel/polyfill": "^7.2.5",
"@fortawesome/fontawesome-free": "^5.11.2",
"@fortawesome/fontawesome-free": "^5.15.4",
"@nxmix/tokenize-ansi": "^3.0.0",
"@uirouter/angularjs": "1.0.11",
"@uirouter/react": "^1.0.7",
"@uirouter/react-hybrid": "^1.0.4",
"angular": "1.8.0",
"angular": "1.8.2",
"angular-clipboard": "^1.6.2",
"angular-file-saver": "^1.1.3",
"angular-json-tree": "1.0.1",
"angular-json-tree": "1.1.0",
"angular-jwt": "~0.1.8",
"angular-loading-bar": "~0.9.0",
"angular-local-storage": "~0.5.2",
"angular-messages": "1.8.0",
"angular-mocks": "1.8.0",
"angular-messages": "1.8.2",
"angular-mocks": "1.8.2",
"angular-moment-picker": "^0.10.2",
"angular-multiselect": "github:portainer/angular-multi-select#semver:~v4.0.1",
"angular-resource": "1.8.0",
"angular-sanitize": "1.8.0",
"angular-resource": "1.8.2",
"angular-sanitize": "1.8.2",
"angular-ui-bootstrap": "~2.5.0",
"angular-utils-pagination": "~0.11.1",
"angularjs-scroll-glue": "^2.2.0",
@ -90,30 +89,30 @@
"angulartics": "^1.6.0",
"axios": "^0.24.0",
"babel-plugin-angularjs-annotate": "^0.10.0",
"bootbox": "^5.4.0",
"bootbox": "^5.5.2",
"bootstrap": "^3.4.0",
"chardet": "^1.3.0",
"buffer": "^6.0.3",
"chardet": "^1.4.0",
"chart.js": "~2.7.0",
"clsx": "^1.1.1",
"codemirror": "~5.30.0",
"core-js": "^3.16.3",
"fast-json-patch": "^3.0.0-1",
"codemirror": "~5.64.0",
"core-js": "^3.19.3",
"fast-json-patch": "^3.1.0",
"filesize": "~3.3.0",
"filesize-parser": "^1.5.0",
"jquery": "^3.5.1",
"js-base64": "^3.6.0",
"jquery": "^3.6.0",
"js-base64": "^3.7.2",
"js-yaml": "^3.14.0",
"jwt-decode": "^3.1.2",
"lodash-es": "^4.17.21",
"moment": "^2.21.0",
"moment": "^2.29.1",
"ng-file-upload": "~12.2.13",
"parse-duration": "^1.0.0",
"rc-slider": "^9.7.4",
"parse-duration": "^1.0.2",
"rc-slider": "^9.7.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-tooltip": "^4.2.21",
"sanitize-html": "^2.5.3",
"source-map-loader": "^1.1.2",
"spinkit": "^2.0.1",
"splitargs": "github:deviantony/splitargs#semver:~0.2.0",
"strip-ansi": "^6.0.0",
@ -122,61 +121,63 @@
"uuid": "^3.3.2",
"x256": "^0.0.2",
"xterm": "^3.8.0",
"yaml": "^1.10.0"
"yaml": "^1.10.2"
},
"devDependencies": {
"@apidevtools/swagger-cli": "^4.0.4",
"@babel/core": "^7.1.2",
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@babel/core": "^7.16.0",
"@babel/preset-env": "^7.16.4",
"@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@simbathesailor/use-what-changed": "^2.0.0",
"@storybook/addon-actions": "^6.3.11",
"@storybook/addon-essentials": "^6.3.11",
"@storybook/addon-links": "^6.3.11",
"@storybook/addon-actions": "^6.4.9",
"@storybook/addon-essentials": "^6.4.9",
"@storybook/addon-links": "^6.4.9",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/react": "^6.3.11",
"@testing-library/jest-dom": "^5.14.1",
"@storybook/builder-webpack5": "^6.4.9",
"@storybook/manager-webpack5": "^6.4.9",
"@storybook/react": "^6.4.9",
"@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.2",
"@types/angular": "^1.8.3",
"@types/bootbox": "^5.2.2",
"@types/jest": "^27.0.2",
"@types/jquery": "^3.5.6",
"@types/jest": "^27.0.3",
"@types/jquery": "^3.5.10",
"@types/lodash-es": "^4.17.5",
"@types/react": "^17.0.27",
"@types/react-dom": "^17.0.9",
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"@types/sanitize-html": "^2.5.0",
"@types/toastr": "^2.1.39",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
"auto-ngtemplate-loader": "^2.0.1",
"autoprefixer": "^7.1.1",
"babel-jest": "^27.1.0",
"babel-loader": "^8.0.4",
"babel-jest": "^27.4.2",
"babel-loader": "^8.2.3",
"babel-plugin-lodash": "^3.3.4",
"clean-terminal-webpack-plugin": "^1.1.0",
"clean-webpack-plugin": "^0.1.19",
"clean-terminal-webpack-plugin": "^3.0.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "5",
"cssnano": "^4.1.10",
"cypress": "^5.2.0",
"cypress": "8.7",
"cypress-wait-until": "^1.7.1",
"dotenv-webpack": "^7.0.3",
"eslint": "^7.29.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-typescript": "^14.0.1",
"eslint": "^8.4.1",
"eslint-config-airbnb": "^19.0.2",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-jest": "^24.4.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-webpack-plugin": "^2.5.4",
"file-loader": "^1.1.11",
"grunt": "^1.1.0",
"grunt-cli": "^1.3.2",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jest": "^25.3.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-promise": "^5.2.0",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-storybook": "^0.5.3",
"eslint-webpack-plugin": "^3.1.1",
"grunt": "^1.4.1",
"grunt-cli": "^1.4.3",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-env": "^0.4.4",
@ -185,36 +186,35 @@
"grunt-replace": "^1.0.1",
"grunt-shell-spawn": "^0.4.0",
"grunt-usemin": "^3.1.1",
"grunt-webpack": "^3.1.3",
"grunt-webpack": "^5.0.0",
"gruntify-eslint": "^3.1.0",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"html-webpack-plugin": "^5.5.0",
"husky": ">=4",
"image-webpack-loader": "^4.5.0",
"jest": "^27.1.0",
"jest": "^27.4.3",
"lint-staged": ">=10",
"load-grunt-tasks": "^3.5.2",
"lodash-webpack-plugin": "^0.11.5",
"lodash-webpack-plugin": "^0.11.6",
"mini-css-extract-plugin": "1",
"ngtemplate-loader": "^2.0.1",
"ngtemplate-loader": "^2.1.0",
"plop": "^2.6.0",
"postcss": "7",
"postcss-loader": "4",
"prettier": "^2.0.2",
"prettier": "^2.5.1",
"react-query": "^3.34.3",
"react-test-renderer": "^17.0.2",
"speed-measure-webpack-plugin": "^1.2.3",
"source-map-loader": "^3.0.0",
"speed-measure-webpack-plugin": "^1.5.0",
"storybook-css-modules-preset": "^1.1.1",
"style-loader": "2",
"swagger2openapi": "^7.0.8",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"typescript": "^4.4.3",
"url-loader": "^1.1.1",
"webpack": "^4.26.0",
"webpack-build-notifier": "^0.1.30",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.1.4"
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.5.2",
"webpack": "^5.65.0",
"webpack-build-notifier": "^2.3.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.6.0",
"webpack-merge": "^5.8.0"
},
"resolutions": {
"jquery": "^3.5.1",
@ -232,4 +232,4 @@
"pre-commit": "lint-staged"
}
}
}
}

@ -4,7 +4,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const CleanTerminalPlugin = require('clean-terminal-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
@ -18,13 +18,14 @@ module.exports = {
main: './app',
},
output: {
filename: '[name].[hash].js',
filename: '[name].[contenthash].js',
path: path.resolve(projectRoot, 'dist/public'),
},
module: {
rules: [
{
test: /\.js$/,
type: 'javascript/auto',
enforce: 'pre',
use: [
{
@ -59,7 +60,7 @@ module.exports = {
{
test: /.xml$/,
use: 'file-loader',
type: 'asset/resource',
},
{
test: /\.css$/,
@ -82,14 +83,18 @@ module.exports = {
],
},
devServer: {
contentBase: path.join(__dirname, '.tmp'),
static: {
directory: path.join(__dirname, 'public'),
},
compress: true,
port: 8999,
proxy: {
'/api': 'http://localhost:9000',
},
open: true,
writeToDisk: true,
devMiddleware: {
writeToDisk: true,
},
},
plugins: [
new Dotenv(),
@ -118,11 +123,11 @@ module.exports = {
jsyaml: 'js-yaml',
}),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
filename: '[name].[contenthash].css',
chunkFilename: '[name].[id].css',
}),
new CleanWebpackPlugin(['dist/public']),
new IgnorePlugin(/^\.\/locale$/, /moment$/),
new CleanWebpackPlugin(),
new IgnorePlugin({ resourceRegExp: /^.\/locale$/, contextRegExp: /moment$/ }),
// new BundleAnalyzerPlugin()
new LodashModuleReplacementPlugin({
shorthands: true,
@ -131,7 +136,10 @@ module.exports = {
}),
],
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /node_modules/,

@ -1,19 +1,14 @@
const webpackMerge = require('webpack-merge');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
module.exports = webpackMerge(commonConfig, {
module.exports = merge(commonConfig, {
mode: 'development',
devtool: 'eval-source-map',
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|svg|ico|png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
// options: { limit: 25000 }
},
],
type: 'asset/resource',
},
],
},

@ -1,29 +1,18 @@
const webpackMerge = require('webpack-merge');
const { merge } = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
module.exports = webpackMerge(commonConfig, {
module.exports = merge(commonConfig, {
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
test: /\.(woff|woff2|eot|ttf|ico)$/,
use: [
{
loader: 'url-loader',
options: { limit: 25000 },
},
],
type: 'asset/inline',
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {},
},
],
type: 'asset/resource',
},
],
},

@ -1,6 +1,6 @@
const webpackMerge = require('webpack-merge');
const { merge } = require('webpack-merge');
const productionConfig = require('./webpack.production');
module.exports = webpackMerge(productionConfig, {
module.exports = merge(productionConfig, {
optimization: { nodeEnv: 'testing' },
});

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save