feat(TEAMMSBMOB-16123): запуск приложения в режиме prod
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
.npmrc
|
||||
jest.config.ts
|
||||
commitlint.config.js
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
prettier.config.js
|
||||
.stylelintrc.js
|
||||
.lintstagedrc.js
|
||||
@@ -5,3 +5,4 @@ build
|
||||
lerna-debug.log
|
||||
.idea
|
||||
.vscode
|
||||
/msb-*
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
registry=https://nexus-npm.gboteam.ru/
|
||||
//nexus.gboteam.ru/repository/:_auth=""
|
||||
//nexus.gboteam.ru/repository/:_auth=${NPM_AUTH_TOKEN}
|
||||
@@ -0,0 +1,9 @@
|
||||
FROM nginx:1.27.4-alpine
|
||||
|
||||
COPY msb-host /opt/site/msb-host
|
||||
COPY msb-main-page /opt/site/msb-main-page
|
||||
COPY msb-deposits /opt/site/msb-deposits
|
||||
COPY msb-payments /opt/site/msb-payments
|
||||
COPY msb-statements-and-inquiries /opt/site/msb-statements-and-inquiries
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
@@ -47,81 +47,34 @@
|
||||
1. Настройка микрофронтового модуля
|
||||
Создать `webpack.config.ts` с параметрами конфигурации:
|
||||
|
||||
```ts
|
||||
/** webpack.config.ts */
|
||||
import type { IWebpackAppConfig } from '@msb/mf-builder';
|
||||
import { normalizePackageName } from '@msb/mf-builder';
|
||||
import packageJson from './package.json';
|
||||
|
||||
const config: WebpackAppConfig = {
|
||||
paths: { entryPath: '/', publicPath: '/', outputPath: '/', srcPath: '/', publicUrl: '/' },
|
||||
devServerOptions: { port: 3001, open: true },
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': path.resolve(__dirname, 'src/exposes/App.tsx'),
|
||||
},
|
||||
shared: {
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/composites': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/composites'],
|
||||
},
|
||||
'@fractal-ui/form': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/form'],
|
||||
},
|
||||
'@fractal-ui/layout': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/layout'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'@fractal-ui/table': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/table'],
|
||||
},
|
||||
'@fractal-ui/visualization': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/visualization'],
|
||||
},
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
'styled-components': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-components'],
|
||||
},
|
||||
},
|
||||
```ts
|
||||
/** webpack.config.ts */
|
||||
import type { IWebpackAppConfig } from '@msb/mf-builder';
|
||||
import { normalizePackageName } from '@msb/mf-builder';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
const packageName = normalizePackageName(packageJson.name);
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../msb-main-page'),
|
||||
publicUrl: '/msb-main-page/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3002,
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': {
|
||||
import: path.resolve(__dirname, 'src/exposes/App.tsx'),
|
||||
name: `${packageName}_remote`,
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
```
|
||||
1. Для того, чтобы поднять приложение интернет-банка в режиме 'production', необходимо запустить команду npm run start:prod. В последующих итерациях нужно будет перед запуском скрипта удалить ранее созданный докер контейнер и образ.
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
nginx-msb:
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: Dockerfile
|
||||
container_name: nginx-msb
|
||||
ports:
|
||||
- 3001:80
|
||||
networks:
|
||||
- network-local
|
||||
networks:
|
||||
network-local:
|
||||
driver: bridge
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"automatedSystemCode": "MSB",
|
||||
"projectCodeDevOps": "MSB",
|
||||
"name": "msb-platform-monorepo",
|
||||
"title": "Интернет-банк МСБ",
|
||||
"type": "application",
|
||||
"valueStreamMaintainer": "ДБО (Цифровые каналы МСБ)",
|
||||
"valueStreamContributors": null,
|
||||
"jiraDevProject": "TEAMMSBMOB",
|
||||
"jiraDevComponent": "msb-platform-monorepo",
|
||||
"confluenceUrl": "https://confluence.int.gazprombank.ru",
|
||||
"emailItLeader": "sergey.barykin@gazprombank.ru",
|
||||
"emailTechDevLeader": "egor.onufriychuk@gazprombank.ru",
|
||||
"emailDevOps": "nikita.pa.filatov@gazprombank.ru",
|
||||
"emailEnterpriseArchitect": null,
|
||||
"emailOperations": "eco_ops@gazprombank.ru",
|
||||
"emailSolutionArchitect": null,
|
||||
"description": "Монорепозиторий интернет-банка МСБ"
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
worker_processes auto;
|
||||
|
||||
events {
|
||||
worker_connections 8000;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
root /opt/site;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
root /opt/site/msb-host;
|
||||
try_files $uri $uri/ /index.html =404;
|
||||
}
|
||||
location /msb-host/ {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
location /msb-main-page/ {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
location /msb-deposits/ {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
location /msb-payments/ {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
location /msb-statements-and-inquiries/ {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+1596
-24216
File diff suppressed because it is too large
Load Diff
+13
-8
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"name": "msb-platform-monorepo",
|
||||
"version": "1.0.0-beta.2",
|
||||
"files": ["msb-host", "msb-main-page", "msb-deposits", "msb-payments", "msb-statements-and-inquiries"],
|
||||
"workspaces": ["packages/*", "services/*"],
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"services/*"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "lerna run start --stream",
|
||||
"start:statements": "lerna run start --scope=msb-host --scope=msb-statements-and-inquiries --stream",
|
||||
@@ -14,6 +13,7 @@
|
||||
"start:service": "lerna run start --scope=msb-host --stream",
|
||||
"build": "lerna run build --scope=msb-* --stream",
|
||||
"build:packages": "lerna run build --scope=@msb/* --stream",
|
||||
"start:prod": "npm run build && docker-compose up",
|
||||
"lint": "lerna run lint --scope=msb-* --stream",
|
||||
"lint-fix": "lerna run lint-fix --scope=msb-* --stream",
|
||||
"check-types": "lerna run check-types --scope=msb-* --stream",
|
||||
@@ -22,9 +22,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.3.0",
|
||||
"@commitlint/config-conventional": "^8.3.4",
|
||||
"@eco/eslint-config": "^21.10.0",
|
||||
"@eco/eslint-plugin": "^21.7.0",
|
||||
"@commitlint/config-conventional": "8.3.4",
|
||||
"@eco/eslint-config": "22.0.0",
|
||||
"@eco/eslint-plugin": "21.7.0",
|
||||
"@eco/lint-staged-config": "21.10.0",
|
||||
"@eco/prettier-config": "21.10.0",
|
||||
"@eco/stylelint-config": "^22.0.0",
|
||||
@@ -42,6 +42,11 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react-dom": "17.0.2",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@ type IRemoteRouteConfig = RemoteRouteConfigBase | RemoteRouteConfigVisibleOnMobi
|
||||
interface IRemoteSettings {
|
||||
modules: IRemoteRouteConfig[];
|
||||
settings: {
|
||||
rateManagementHost: string;
|
||||
apiPath: string;
|
||||
authProviderHost: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ export * from './endpoints';
|
||||
export * from './network';
|
||||
export * from './mocks';
|
||||
export * from './treasury-deals-client';
|
||||
export * from '@tanstack/react-query';
|
||||
export * from '@tanstack/react-query';
|
||||
|
||||
@@ -89,9 +89,7 @@ const SETTINGS_MOCK = {
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
rateManagementHost: 'foo',
|
||||
apiPath: 'bar',
|
||||
authProviderHost: 'baz',
|
||||
apiPath: '',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { fetchDepositManagementFundsHandlers } from '../treasury-deals-client';
|
||||
import { settingsHandlers } from './fetchAppSettings';
|
||||
import { clientOrganizationsHandlers } from './fetchClientOrganizations';
|
||||
import { fetchDepositDocumentNewForEditHandlers } from './fetchDepositDocumentNewForEdit';
|
||||
import { fetchDepositGeneralAgreementsHandlers } from './fetchDepositGeneralAgreements';
|
||||
import { financialAccountsHandlers } from './fetchFinancialAccounts';
|
||||
import { fetchProductsHandlers } from './fetchProducts';
|
||||
import { fetchUserAuthoritiesHandlers } from './fetchUserAuthorities';
|
||||
import { fetchUserInfoUnionHandlerHandlers } from './fetchUserInfoUnion';
|
||||
import { statementsHandlers } from './statements';
|
||||
import { fetchDepositGeneralAgreementsHandlers } from './fetchDepositGeneralAgreements';
|
||||
import { fetchDepositManagementFundsHandlers } from '../treasury-deals-client';
|
||||
|
||||
const handlers = [
|
||||
...settingsHandlers,
|
||||
@@ -19,7 +19,7 @@ const handlers = [
|
||||
...fetchDepositDocumentNewForEditHandlers,
|
||||
...statementsHandlers,
|
||||
...fetchDepositGeneralAgreementsHandlers,
|
||||
...fetchDepositManagementFundsHandlers
|
||||
...fetchDepositManagementFundsHandlers,
|
||||
];
|
||||
|
||||
export { handlers };
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"@tanstack/react-query": "4.36.1",
|
||||
"axios": "1.7.9",
|
||||
"use-sync-external-store": "^1.2.0",
|
||||
"@tanstack/query-core": "4.36.1"
|
||||
"@tanstack/query-core": "4.36.1",
|
||||
"msw": "1.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"msw": "1.3.5"
|
||||
|
||||
@@ -5,3 +5,4 @@ export * from './cookies';
|
||||
export * from './dateTime';
|
||||
export * from './useRedirect';
|
||||
export * from './useElementHeight';
|
||||
export * from './useRefetchData';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
const REFETCH_DELAY = 10_000;
|
||||
|
||||
export { REFETCH_DELAY };
|
||||
@@ -0,0 +1 @@
|
||||
export * from './useRefetchData';
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { REFETCH_DELAY } from './constants';
|
||||
|
||||
/**
|
||||
* Хук, для управления состоянием повторного запроса данных.
|
||||
* @param refetch Функция повторного запроса данных.
|
||||
* @returns Состояние блокировки кнопки повторного запроса данных.
|
||||
*/
|
||||
function useRefetchData(refetch: () => void) {
|
||||
const [disabledRefetchButton, setDisabled] = useState(false);
|
||||
const [isAbleToRefetchData, setIsAbleToRefetchData] = useState(true);
|
||||
|
||||
const refetchData = () => {
|
||||
refetch();
|
||||
setIsAbleToRefetchData(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isAbleToRefetchData) {
|
||||
return;
|
||||
}
|
||||
|
||||
setDisabled(true);
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setDisabled(false);
|
||||
setIsAbleToRefetchData(true);
|
||||
}, REFETCH_DELAY);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [isAbleToRefetchData]);
|
||||
|
||||
return { disabledRefetchButton, refetchData };
|
||||
}
|
||||
|
||||
export { useRefetchData };
|
||||
@@ -3,12 +3,23 @@
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.ts",
|
||||
"files": [
|
||||
"assets",
|
||||
"constants",
|
||||
"lib"
|
||||
],
|
||||
"files": ["assets", "constants", "lib"],
|
||||
"dependencies": {
|
||||
"@msb/http": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"styled-system": "5.1.5",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"react-router-dom": "5.2.0",
|
||||
"react-animate-height": "2.0.23"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class WebpackConfigBuilder {
|
||||
}) || [];
|
||||
const otherPlugins = this.appConfig.plugins;
|
||||
if (Array.isArray(otherPlugins) && Array.isArray(this.config.plugins)) {
|
||||
this.config.plugins.concat(otherPlugins);
|
||||
this.config.plugins = this.config.plugins.concat(otherPlugins);
|
||||
}
|
||||
}
|
||||
merge(newConfig) {
|
||||
|
||||
@@ -15,9 +15,53 @@ const setModuleFederationPlugin = ({ moduleName, moduleFederationOptions, }) =>
|
||||
singleton: true,
|
||||
eager: true,
|
||||
},
|
||||
'styled-components': {
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/composites': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-animate-height': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-dnd': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-dnd-html5-backend': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
},
|
||||
} }, moduleFederationOptions));
|
||||
exports.setModuleFederationPlugin = setModuleFederationPlugin;
|
||||
|
||||
@@ -8,18 +8,44 @@ const terser_webpack_plugin_1 = __importDefault(require("terser-webpack-plugin")
|
||||
/**
|
||||
* Установка правил оптимизации сборки.
|
||||
*/
|
||||
const setOptimizationRules = (options) => (Object.assign({ minimize: true, minimizer: [new terser_webpack_plugin_1.default()], splitChunks: {
|
||||
chunks: 'all',
|
||||
maxInitialRequests: Number.POSITIVE_INFINITY,
|
||||
minSize: 0,
|
||||
const setOptimizationRules = (options) => (Object.assign({ minimize: true, minimizer: [new terser_webpack_plugin_1.default()], runtimeChunk: false, splitChunks: {
|
||||
minSize: 17000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30000,
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name(module) {
|
||||
var _a;
|
||||
const packageName = (_a = module.context.match(/[/\\]node_modules[/\\](.*?)([/\\]|$)/)) !== null && _a !== void 0 ? _a : 'package';
|
||||
return `npm.${packageName[1].replace('@', '')}`;
|
||||
name: (module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
return name === null || name === void 0 ? void 0 : name.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
return name === null || name === void 0 ? void 0 : name.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
} }, options));
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
"description": "CLI для сборки модулей с помощью Webpack 5",
|
||||
"main": "lib/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"bin",
|
||||
"lib",
|
||||
"types"
|
||||
],
|
||||
"files": ["bin", "lib", "types"],
|
||||
"bin": {
|
||||
"build-app": "bin/build-app.js"
|
||||
},
|
||||
|
||||
@@ -118,7 +118,7 @@ export class WebpackConfigBuilder {
|
||||
const otherPlugins = this.appConfig.plugins;
|
||||
|
||||
if (Array.isArray(otherPlugins) && Array.isArray(this.config.plugins)) {
|
||||
this.config.plugins.concat(otherPlugins);
|
||||
this.config.plugins = this.config.plugins.concat(otherPlugins);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,53 @@ export const setModuleFederationPlugin = ({
|
||||
singleton: true,
|
||||
eager: true,
|
||||
},
|
||||
'styled-components': {
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/composites': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-animate-height': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-dnd': {
|
||||
singleton: true,
|
||||
},
|
||||
'react-dnd-html5-backend': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
},
|
||||
},
|
||||
...moduleFederationOptions,
|
||||
|
||||
@@ -1,24 +1,58 @@
|
||||
import TerserPlugin from 'terser-webpack-plugin';
|
||||
import type { Configuration } from 'webpack';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
|
||||
/**
|
||||
* Установка правил оптимизации сборки.
|
||||
*/
|
||||
export const setOptimizationRules = (options?: Configuration['optimization']): Configuration['optimization'] => ({
|
||||
minimize: true,
|
||||
minimizer: [new TerserPlugin()],
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
maxInitialRequests: Number.POSITIVE_INFINITY,
|
||||
minSize: 0,
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendor: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name(module: { context: string }) {
|
||||
const packageName = module.context.match(/[/\\]node_modules[/\\](.*?)([/\\]|$)/) ?? 'package';
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return `npm.${packageName[1].replace('@', '')}`;
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"setModuleFederationPlugin.d.ts","sourceRoot":"","sources":["../../../src/config/webpack/setModuleFederationPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,yBAAyB,6CAGnC,KAAK,cAAc,EAAE,yBAAyB,GAAG,YAAY,CAAC,qCAmB7D,CAAC"}
|
||||
{"version":3,"file":"setModuleFederationPlugin.d.ts","sourceRoot":"","sources":["../../../src/config/webpack/setModuleFederationPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC;;GAEG;AACH,eAAO,MAAM,yBAAyB,6CAGnC,KAAK,cAAc,EAAE,yBAAyB,GAAG,YAAY,CAAC,qCA+D7D,CAAC"}
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"setOptimizationRules.d.ts","sourceRoot":"","sources":["../../../src/config/webpack/setOptimizationRules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,oBAAoB,aAAc,aAAa,CAAC,cAAc,CAAC,KAAG,aAAa,CAAC,cAAc,CAmBzG,CAAC"}
|
||||
{"version":3,"file":"setOptimizationRules.d.ts","sourceRoot":"","sources":["../../../src/config/webpack/setOptimizationRules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7C;;GAEG;AACH,eAAO,MAAM,oBAAoB,aAAc,aAAa,CAAC,cAAc,CAAC,KAAG,aAAa,CAAC,cAAc,CAgDzG,CAAC"}
|
||||
@@ -23,11 +23,13 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.8.1",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/core": "^30.2.0",
|
||||
"@fractal-ui/extended": "^30.2.0",
|
||||
"@fractal-ui/library": "^30.2.0",
|
||||
"@fractal-ui/overlays": "^30.2.0",
|
||||
"@fractal-ui/styling": "^30.1.0",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/form": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"@msb/mf-utils": "^1.0.0",
|
||||
"@msb/http": "^1.0.0",
|
||||
"@msb/shared": "^1.0.0",
|
||||
@@ -66,9 +68,5 @@
|
||||
"lint-staged": "^12.3.4",
|
||||
"react-test-renderer": "17.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
]
|
||||
"browserslist": [">0.2%", "not dead", "not op_mini all"]
|
||||
}
|
||||
|
||||
@@ -3,68 +3,17 @@ import { normalizePackageName } from '@msb/mf-builder';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
|
||||
const packageName = normalizePackageName(packageJson.name);
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../build/msb-deposits'),
|
||||
publicUrl: 'auto',
|
||||
outputPath: path.resolve(__dirname, '../../msb-deposits'),
|
||||
publicUrl: '/msb-deposits/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3007,
|
||||
},
|
||||
optimizationOptions: {
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': {
|
||||
@@ -72,66 +21,6 @@ const config: IWebpackAppConfig = {
|
||||
name: `${packageName}_remote`,
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/http'],
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/shared'],
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-system'],
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@styled-system/css'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/react'],
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/styled'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -23,17 +23,12 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.8.1",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/composites": "30.6.0",
|
||||
"@fractal-ui/core": "30.6.0",
|
||||
"@fractal-ui/extended": "30.6.0",
|
||||
"@fractal-ui/form": "30.6.0",
|
||||
"@fractal-ui/layout": "30.6.0",
|
||||
"@fractal-ui/library": "30.6.0",
|
||||
"@fractal-ui/overlays": "30.6.0",
|
||||
"@fractal-ui/styling": "30.6.0",
|
||||
"@fractal-ui/svg-generator": "30.3.1",
|
||||
"@fractal-ui/table": "30.6.0",
|
||||
"@fractal-ui/visualization": "30.6.0",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"@msb/http": "^1.0.0",
|
||||
"@msb/mf-utils": "^1.0.0",
|
||||
"@msb/shared": "1.0.0",
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"id": 1,
|
||||
"remoteEntryUrl": "/msb-main-page/remoteEntry.js",
|
||||
"remoteName": "msb-main-page",
|
||||
"moduleName": "App",
|
||||
"path": "/",
|
||||
"title": "Главная",
|
||||
"showOnMobile": true,
|
||||
"shortTitle": "Главная",
|
||||
"exact": true
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"remoteEntryUrl": "/msb-transaction-history/remoteEntry.js",
|
||||
"remoteName": "msb-transaction-history",
|
||||
"moduleName": "App",
|
||||
"path": "/transaction-history",
|
||||
"title": "История операций",
|
||||
"showOnMobile": true,
|
||||
"shortTitle": "История",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"remoteEntryUrl": "/msb-payments/remoteEntry.js",
|
||||
"remoteName": "msb-payments",
|
||||
"moduleName": "App",
|
||||
"path": "/payments",
|
||||
"title": "Платежи",
|
||||
"showOnMobile": true,
|
||||
"shortTitle": "Платежи",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"remoteEntryUrl": "/msb-statements-and-inquiries/remoteEntry.js",
|
||||
"remoteName": "msb-statements-and-inquiries",
|
||||
"moduleName": "App",
|
||||
"path": "/statements-and-inquiries",
|
||||
"title": "Выписки и\u00A0справки",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"remoteEntryUrl": "/msb-accounts/remoteEntry.js",
|
||||
"remoteName": "msb-accounts",
|
||||
"moduleName": "App",
|
||||
"path": "/accounts",
|
||||
"title": "Счета",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"remoteEntryUrl": "/msb-deposits/remoteEntry.js",
|
||||
"remoteName": "msb-deposits",
|
||||
"moduleName": "App",
|
||||
"path": "/deposits",
|
||||
"title": "Депозиты и\u00A0МНО",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"remoteEntryUrl": "/msb-fea/remoteEntry.js",
|
||||
"remoteName": "msb-fea",
|
||||
"moduleName": "App",
|
||||
"path": "/fea",
|
||||
"title": "ВЭД",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"remoteEntryUrl": "/msb-credit-account/remoteEntry.js",
|
||||
"remoteName": "msb-credit-account",
|
||||
"moduleName": "App",
|
||||
"path": "/credit-account",
|
||||
"title": "Кредитный кабинет",
|
||||
"exact": false
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"remoteEntryUrl": "/msb-acquiring/remoteEntry.js",
|
||||
"remoteName": "msb-acquiring",
|
||||
"moduleName": "App",
|
||||
"path": "/acquiring",
|
||||
"title": "Эквайринг",
|
||||
"exact": false
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"apiPath": "/api"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<title>ГАЗПРОМБАНК | МСБ</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
const MOCK_SERVER_API_PATH_KEY = 'mock_server_api_path';
|
||||
|
||||
export { MOCK_SERVER_API_PATH_KEY };
|
||||
@@ -1,8 +0,0 @@
|
||||
import type { IRemoteSettings } from '@msb/http';
|
||||
|
||||
export interface ReturnType {
|
||||
modules: IRemoteSettings['modules'] | undefined;
|
||||
error: Error | null | undefined;
|
||||
isLoading: boolean;
|
||||
handleClick(): void;
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useQuery, type IRemoteSettings } from '@msb/http';
|
||||
import type { ReturnType } from './types';
|
||||
import { useLayoutEffect } from 'react';
|
||||
import { network, useQuery, type IRemoteSettings } from '@msb/http';
|
||||
import { MOCK_SERVER_API_PATH_KEY } from './constants';
|
||||
import { fetchAppSettings, QUERY_KEYS_SETTINGS } from '@/shared/api/fetchAppSettings';
|
||||
|
||||
export const useAppSettings = (): ReturnType => {
|
||||
export const useAppSettings = () => {
|
||||
const { data, error, isLoading, refetch } = useQuery<IRemoteSettings, Error | undefined>({
|
||||
queryKey: [QUERY_KEYS_SETTINGS],
|
||||
queryFn: fetchAppSettings,
|
||||
@@ -10,14 +11,27 @@ export const useAppSettings = (): ReturnType => {
|
||||
cacheTime: Number.POSITIVE_INFINITY,
|
||||
});
|
||||
|
||||
const handleClick = (): void => {
|
||||
refetch();
|
||||
};
|
||||
useLayoutEffect(() => {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { apiPath } = data.settings;
|
||||
|
||||
const mockServerApiPath = localStorage.getItem(MOCK_SERVER_API_PATH_KEY);
|
||||
|
||||
// для перенаправления запросов на моковый сервер для тестирования
|
||||
if (mockServerApiPath) {
|
||||
network.client.defaults.baseURL = mockServerApiPath;
|
||||
} else if (apiPath) {
|
||||
network.client.defaults.baseURL = apiPath;
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return {
|
||||
modules: data?.modules,
|
||||
error,
|
||||
isLoading,
|
||||
handleClick,
|
||||
refetch,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,10 +6,10 @@ import LayoutEmptyState from './LayoutEmptyState';
|
||||
import { StyledThemeProvider } from '@/app/providers';
|
||||
|
||||
const Layout: FC = () => {
|
||||
const { modules, isLoading: isSettingsLoading, error: settingsError, handleClick } = useAppSettings();
|
||||
const { modules, isLoading: isSettingsLoading, error: settingsError, refetch } = useAppSettings();
|
||||
|
||||
if (settingsError || isSettingsLoading)
|
||||
return <LayoutEmptyState handleClick={handleClick} isLoading={isSettingsLoading} settingsError={settingsError} />;
|
||||
return <LayoutEmptyState handleClick={refetch} isLoading={isSettingsLoading} settingsError={settingsError} />;
|
||||
|
||||
return (
|
||||
<StyledThemeProvider>
|
||||
|
||||
@@ -2,6 +2,5 @@ const ACCOUNTS_NOT_FOUND = 'Счета недоступны';
|
||||
const NOT_FOUND = 'Информация не загрузилась';
|
||||
const NOT_FOUND_BUTTON_TEXT = 'Попробовать ещё раз';
|
||||
const ORGANIZATIONS = 'Организации';
|
||||
const ALL_ORGANIZATIONS = 'Все организации';
|
||||
|
||||
export { ACCOUNTS_NOT_FOUND, NOT_FOUND, NOT_FOUND_BUTTON_TEXT, ORGANIZATIONS, ALL_ORGANIZATIONS };
|
||||
export { ACCOUNTS_NOT_FOUND, NOT_FOUND, NOT_FOUND_BUTTON_TEXT, ORGANIZATIONS };
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { useRef, useState, type ReactElement } from 'react';
|
||||
import { DropdownBase, DropdownItem } from '@fractal-ui/composites';
|
||||
import { useOnOutsideClick } from '@fractal-ui/core';
|
||||
import { BriefcaseIcon, DownIcon } from '@fractal-ui/library';
|
||||
import { PopupContainer } from '@fractal-ui/overlays';
|
||||
import { Text } from '@fractal-ui/styling';
|
||||
import type { OrganizationDto } from '@msb/http';
|
||||
import { ACCOUNTS, pluralize, useRefetchData } from '@msb/shared';
|
||||
import { ACCOUNTS_NOT_FOUND, ORGANIZATIONS } from '../constants';
|
||||
import { EmptyState } from './EmptyState';
|
||||
import * as S from './Organizations.styles';
|
||||
|
||||
interface Props {
|
||||
organizations: OrganizationDto[];
|
||||
isLoading: boolean;
|
||||
refetch(): void;
|
||||
error: Error | null | undefined;
|
||||
}
|
||||
|
||||
const DesktopOrganizations = ({ organizations, error, isLoading, refetch }: Props): ReactElement => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const containerRef = useRef(null);
|
||||
const dropdownRef = useRef(null);
|
||||
|
||||
const { disabledRefetchButton, refetchData } = useRefetchData(refetch);
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
useOnOutsideClick({
|
||||
elements: [dropdownRef, containerRef],
|
||||
handler: toggleOpen,
|
||||
isActive: isOpen,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<S.Organizations ref={containerRef} $isExpaned={isOpen} onClick={toggleOpen}>
|
||||
<S.Amount>
|
||||
{organizations.length > 1 ? (
|
||||
<Text.P4>{organizations.length}</Text.P4>
|
||||
) : (
|
||||
<div>
|
||||
<BriefcaseIcon />
|
||||
</div>
|
||||
)}
|
||||
</S.Amount>
|
||||
<Text.P2 minWidth={132} overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap" width="100%">
|
||||
{organizations.length === 1 ? organizations[0].shortName : ORGANIZATIONS}
|
||||
</Text.P2>
|
||||
{(isLoading || Boolean(error) || organizations.length > 1) && (
|
||||
<S.ToggleIconBox $isExpanded={isOpen}>
|
||||
<DownIcon />
|
||||
</S.ToggleIconBox>
|
||||
)}
|
||||
</S.Organizations>
|
||||
<PopupContainer anchorEl={containerRef} isOpen={isOpen} offsetX={0} offsetY={4}>
|
||||
<div ref={dropdownRef}>
|
||||
<DropdownBase width={328}>
|
||||
{organizations.length > 0 ? (
|
||||
organizations.map(item => (
|
||||
<DropdownItem
|
||||
key={item.id}
|
||||
description={
|
||||
item.accounts && item.accounts.length > 0
|
||||
? `${item.accounts.length} ${pluralize(item.accounts.length, ACCOUNTS)}`
|
||||
: ACCOUNTS_NOT_FOUND
|
||||
}
|
||||
size="M"
|
||||
>
|
||||
{item.shortName}
|
||||
</DropdownItem>
|
||||
))
|
||||
) : (
|
||||
<EmptyState disabled={disabledRefetchButton} isLoading={isLoading} refetch={refetchData} />
|
||||
)}
|
||||
</DropdownBase>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { DesktopOrganizations };
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { FC } from 'react';
|
||||
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
|
||||
import { type FC } from 'react';
|
||||
import { Button } from '@fractal-ui/core';
|
||||
import { LoopArrowIcon } from '@fractal-ui/library';
|
||||
import { Text } from '@fractal-ui/styling';
|
||||
@@ -8,11 +9,12 @@ import { Loader } from '@/shared/ui/components';
|
||||
|
||||
interface Props {
|
||||
isLoading: boolean;
|
||||
disabled: boolean;
|
||||
buttonWidth?: string;
|
||||
refetch(): void;
|
||||
}
|
||||
|
||||
const EmptyState: FC<Props> = ({ isLoading, buttonWidth, refetch }) => (
|
||||
const EmptyState: FC<Props> = ({ disabled, isLoading, buttonWidth, refetch }) => (
|
||||
<S.EmptyStateContentBox>
|
||||
{isLoading ? (
|
||||
<Loader dataName="loader" />
|
||||
@@ -21,6 +23,7 @@ const EmptyState: FC<Props> = ({ isLoading, buttonWidth, refetch }) => (
|
||||
<Text.P1>{NOT_FOUND}</Text.P1>
|
||||
<Button
|
||||
dataAction="reload"
|
||||
disabled={disabled}
|
||||
icon={LoopArrowIcon}
|
||||
shape="default"
|
||||
variant="blue"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, type ReactElement } from 'react';
|
||||
import { Drawer } from '@fractal-ui/overlays';
|
||||
import { ACCOUNTS, pluralize } from '@msb/shared';
|
||||
import { ACCOUNTS, pluralize, useRefetchData } from '@msb/shared';
|
||||
import { ACCOUNTS_NOT_FOUND, ORGANIZATIONS } from '../constants';
|
||||
import { EmptyState } from './EmptyState';
|
||||
import * as S from './Organizations.styles';
|
||||
@@ -10,6 +10,8 @@ const MobileOrganizations = (): ReactElement => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { organizations, isLoading, refetch } = useClientOrganizations();
|
||||
|
||||
const { disabledRefetchButton, refetchData } = useRefetchData(refetch);
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
@@ -32,7 +34,7 @@ const MobileOrganizations = (): ReactElement => {
|
||||
</MobileOrganizationItem>
|
||||
))
|
||||
) : (
|
||||
<EmptyState buttonWidth="100%" isLoading={isLoading} refetch={refetch} />
|
||||
<EmptyState buttonWidth="100%" disabled={disabledRefetchButton} isLoading={isLoading} refetch={refetchData} />
|
||||
)}
|
||||
</Drawer>
|
||||
</>
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { BriefcaseIcon } from '@fractal-ui/library';
|
||||
|
||||
const Organizations = styled.div(() => ({
|
||||
const Organizations = styled.div<{ $isExpaned: boolean }>(({ theme, $isExpaned }) => ({
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: '216px',
|
||||
maxWidth: '216px',
|
||||
gap: '8px',
|
||||
padding: '0 8px',
|
||||
padding: '8px 14px 8px 8px',
|
||||
borderRadius: '16px',
|
||||
cursor: 'pointer',
|
||||
border: `1px solid ${theme.colors.control.bg}`,
|
||||
...($isExpaned && { '&&&': { borderColor: theme.colors.control.borderFocus } }),
|
||||
'&:hover': {
|
||||
borderColor: theme.colors.control.border,
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledBriefcaseIcon = styled(BriefcaseIcon)({
|
||||
@@ -16,15 +22,13 @@ const StyledBriefcaseIcon = styled(BriefcaseIcon)({
|
||||
});
|
||||
|
||||
const ToggleIconBox = styled.div<{ $isExpanded: boolean }>(({ $isExpanded, theme }) => ({
|
||||
position: 'absolute',
|
||||
right: '14px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
transform: $isExpanded ? 'rotateX(180deg)' : 'rotateX(0deg)',
|
||||
svg: {
|
||||
width: '17px',
|
||||
height: '17px',
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
color: theme.colors.text.primary,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,99 +1,17 @@
|
||||
import { useRef, useState, type ReactElement } from 'react';
|
||||
import { DropdownBase, DropdownItem } from '@fractal-ui/composites';
|
||||
import { useOnOutsideClick } from '@fractal-ui/core';
|
||||
import { BriefcaseIcon, DownIcon } from '@fractal-ui/library';
|
||||
import { Drawer, PopupContainer } from '@fractal-ui/overlays';
|
||||
import { Text } from '@fractal-ui/styling';
|
||||
import { ACCOUNTS, MEDIA, pluralize, useMediaQuery } from '@msb/shared';
|
||||
import { ACCOUNTS_NOT_FOUND, ALL_ORGANIZATIONS, ORGANIZATIONS } from '../constants';
|
||||
import { EmptyState } from './EmptyState';
|
||||
import * as S from './Organizations.styles';
|
||||
import { TabletOrganizationItem, useClientOrganizations } from '@/entities/Organization';
|
||||
import { type ReactElement } from 'react';
|
||||
import { MEDIA, useMediaQuery } from '@msb/shared';
|
||||
import { DesktopOrganizations } from './DesktopOrganizations';
|
||||
import { TabletOrganizations } from './TabletOrganizations';
|
||||
import { useClientOrganizations } from '@/entities/Organization';
|
||||
|
||||
const Organizations = (): ReactElement => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const containerRef = useRef(null);
|
||||
const dropdownRef = useRef(null);
|
||||
const isDesktop = useMediaQuery(MEDIA.desktop);
|
||||
const { organizations, isLoading, refetch } = useClientOrganizations();
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
useOnOutsideClick({
|
||||
elements: [dropdownRef, containerRef],
|
||||
handler: toggleOpen,
|
||||
isActive: isOpen,
|
||||
});
|
||||
const { organizations, isLoading, error, refetch } = useClientOrganizations();
|
||||
|
||||
return isDesktop ? (
|
||||
<>
|
||||
<S.Organizations ref={containerRef} onClick={toggleOpen}>
|
||||
<S.Amount>
|
||||
{organizations.length > 1 ? (
|
||||
<Text.P4>{organizations.length}</Text.P4>
|
||||
) : (
|
||||
<div>
|
||||
<BriefcaseIcon />
|
||||
</div>
|
||||
)}
|
||||
</S.Amount>
|
||||
<Text.P2 overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap">
|
||||
{organizations.length === 1 ? organizations[0].shortName : ALL_ORGANIZATIONS}
|
||||
</Text.P2>
|
||||
<S.ToggleIconBox $isExpanded={isOpen}>
|
||||
<DownIcon />
|
||||
</S.ToggleIconBox>
|
||||
</S.Organizations>
|
||||
<PopupContainer anchorEl={containerRef} isOpen={isOpen} offsetX={-8} offsetY={12}>
|
||||
<div ref={dropdownRef}>
|
||||
<DropdownBase width={328}>
|
||||
{organizations.length > 0 ? (
|
||||
organizations.map(item => (
|
||||
<DropdownItem
|
||||
key={item.id}
|
||||
description={
|
||||
item.accounts && item.accounts.length > 0
|
||||
? `${item.accounts.length} ${pluralize(item.accounts.length, ACCOUNTS)}`
|
||||
: ACCOUNTS_NOT_FOUND
|
||||
}
|
||||
size="M"
|
||||
>
|
||||
{item.shortName}
|
||||
</DropdownItem>
|
||||
))
|
||||
) : (
|
||||
<EmptyState isLoading={isLoading} refetch={refetch} />
|
||||
)}
|
||||
</DropdownBase>
|
||||
</div>
|
||||
</PopupContainer>
|
||||
</>
|
||||
<DesktopOrganizations error={error} isLoading={isLoading} organizations={organizations} refetch={refetch} />
|
||||
) : (
|
||||
<>
|
||||
<S.StyledBriefcaseIcon onClick={toggleOpen} />
|
||||
<Drawer preventCloseOnOutside header={ORGANIZATIONS} isOpen={isOpen} onClose={toggleOpen}>
|
||||
<S.DrawerContentBox>
|
||||
{organizations.length > 0 ? (
|
||||
organizations.map(item => (
|
||||
<TabletOrganizationItem
|
||||
key={item.id}
|
||||
description={
|
||||
item.accounts && item.accounts.length > 0
|
||||
? `${item.accounts.length} ${pluralize(item.accounts.length, ACCOUNTS)}`
|
||||
: ACCOUNTS_NOT_FOUND
|
||||
}
|
||||
>
|
||||
{item.shortName}
|
||||
</TabletOrganizationItem>
|
||||
))
|
||||
) : (
|
||||
<EmptyState buttonWidth="100%" isLoading={isLoading} refetch={refetch} />
|
||||
)}
|
||||
</S.DrawerContentBox>
|
||||
</Drawer>
|
||||
</>
|
||||
<TabletOrganizations error={error} isLoading={isLoading} organizations={organizations} refetch={refetch} />
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import { useState, type ReactElement } from 'react';
|
||||
import { Drawer } from '@fractal-ui/overlays';
|
||||
import type { OrganizationDto } from '@msb/http';
|
||||
import { ACCOUNTS, pluralize, useRefetchData } from '@msb/shared';
|
||||
import { ACCOUNTS_NOT_FOUND, ORGANIZATIONS } from '../constants';
|
||||
import { EmptyState } from './EmptyState';
|
||||
import * as S from './Organizations.styles';
|
||||
import { TabletOrganizationItem } from '@/entities/Organization';
|
||||
|
||||
interface Props {
|
||||
organizations: OrganizationDto[];
|
||||
isLoading: boolean;
|
||||
refetch(): void;
|
||||
error: Error | null | undefined;
|
||||
}
|
||||
|
||||
const TabletOrganizations = ({ organizations, isLoading, refetch }: Props): ReactElement => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const { disabledRefetchButton, refetchData } = useRefetchData(refetch);
|
||||
|
||||
const toggleOpen = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<S.StyledBriefcaseIcon onClick={toggleOpen} />
|
||||
<Drawer preventCloseOnOutside header={ORGANIZATIONS} isOpen={isOpen} onClose={toggleOpen}>
|
||||
<S.DrawerContentBox>
|
||||
{organizations.length > 0 ? (
|
||||
organizations.map(item => (
|
||||
<TabletOrganizationItem
|
||||
key={item.id}
|
||||
description={
|
||||
item.accounts && item.accounts.length > 0
|
||||
? `${item.accounts.length} ${pluralize(item.accounts.length, ACCOUNTS)}`
|
||||
: ACCOUNTS_NOT_FOUND
|
||||
}
|
||||
>
|
||||
{item.shortName}
|
||||
</TabletOrganizationItem>
|
||||
))
|
||||
) : (
|
||||
<EmptyState buttonWidth="100%" disabled={disabledRefetchButton} isLoading={isLoading} refetch={refetchData} />
|
||||
)}
|
||||
</S.DrawerContentBox>
|
||||
</Drawer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { TabletOrganizations };
|
||||
@@ -15,17 +15,17 @@ const MobileMenu: FC<Props> = ({ modules = [] }) => (
|
||||
{modules
|
||||
.filter((item): item is RemoteRouteConfigVisibleOnMobile => 'showOnMobile' in item && item.showOnMobile)
|
||||
.map(item => (
|
||||
<MobileMenuItem
|
||||
key={item.title}
|
||||
exact={item.exact}
|
||||
href={item.path}
|
||||
icon={SIDEBAR_ICONS[item.path as PATHS]}
|
||||
title={item.shortTitle}
|
||||
/>
|
||||
<S.StyledNavLink key={item.title} exact={item.exact} to={item.path}>
|
||||
<MobileMenuItem icon={SIDEBAR_ICONS[item.path as PATHS]}>{item.shortTitle}</MobileMenuItem>
|
||||
</S.StyledNavLink>
|
||||
))}
|
||||
<S.Divider />
|
||||
<MobileMenuItem exact href={PATHS.CONTACT} icon={SIDEBAR_ICONS[PATHS.CONTACT]} title={LOCALIZATION.CONTACT_MOBILE} />
|
||||
<MobileMenuItem exact href={PATHS.SERVICES} icon={SIDEBAR_ICONS[PATHS.SERVICES]} title={LOCALIZATION.SERVICES} />
|
||||
<S.StyledNavLink exact to={PATHS.CONTACT}>
|
||||
<MobileMenuItem icon={SIDEBAR_ICONS[PATHS.CONTACT]}>{LOCALIZATION.CONTACT_MOBILE}</MobileMenuItem>
|
||||
</S.StyledNavLink>
|
||||
<S.StyledNavLink exact to={PATHS.SERVICES}>
|
||||
<MobileMenuItem icon={SIDEBAR_ICONS[PATHS.SERVICES]}>{LOCALIZATION.SERVICES}</MobileMenuItem>
|
||||
</S.StyledNavLink>
|
||||
</S.List>
|
||||
) : null}
|
||||
</S.Navigation>
|
||||
|
||||
@@ -1,7 +1,81 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import styled from '@emotion/styled';
|
||||
import { MEDIA } from '@msb/shared';
|
||||
import { StyledNavLink, Box } from './SidebarItem/SidebarItem.styles';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { Box } from './SidebarItem/SidebarItem.styles';
|
||||
|
||||
const NewServices = styled.div(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '12px 16px 12px 12px',
|
||||
marginTop: '16px',
|
||||
position: 'relative',
|
||||
borderRadius: '16px',
|
||||
backgroundColor: theme.colors.bg.primary,
|
||||
cursor: 'pointer',
|
||||
'&&&': {
|
||||
[`${Box}`]: {
|
||||
padding: 0,
|
||||
color: theme.colors.text.accentBrand,
|
||||
gap: '16px',
|
||||
svg: {
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
},
|
||||
[`@media ${MEDIA.tablet}`]: { padding: '8px 0', left: 0, width: '100%', justifyContent: 'center' },
|
||||
}));
|
||||
|
||||
const StyledNavLink = styled(NavLink)(({ theme }) => ({
|
||||
display: 'block',
|
||||
textDecoration: 'none',
|
||||
'&.active': {
|
||||
[`${Box}`]: {
|
||||
fontWeight: 700,
|
||||
svg: {
|
||||
color: theme.colors.text.primary,
|
||||
},
|
||||
},
|
||||
[`${NewServices}`]: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
svg: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
},
|
||||
[`@media ${MEDIA.desktop}`]: {
|
||||
'&:hover': {
|
||||
[`${NewServices}`]: {
|
||||
backgroundColor: theme.colors.control.secondary.white.bgHover,
|
||||
},
|
||||
'&&&': {
|
||||
[`${Box}`]: {
|
||||
backgroundColor: theme.colors.control.secondary.white.bgHover,
|
||||
color: theme.colors.control.secondary.white.typoHover,
|
||||
svg: {
|
||||
color: theme.colors.control.secondary.white.typoHover,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`@media ${MEDIA.mobile}`]: {
|
||||
'&&&': {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
'&.active': {
|
||||
[`${Box}`]: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
svg: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const Navigation = styled.nav(({ theme }) => ({
|
||||
gridArea: 'sd',
|
||||
@@ -39,29 +113,6 @@ const Tag = styled.div(({ theme }) => ({
|
||||
[`@media ${MEDIA.tablet}`]: { display: 'none' },
|
||||
}));
|
||||
|
||||
const NewItem = styled.div(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '12px 16px 12px 12px',
|
||||
marginTop: '16px',
|
||||
position: 'relative',
|
||||
width: '224px',
|
||||
left: '-5px',
|
||||
borderRadius: '16px',
|
||||
backgroundColor: theme.colors.bg.primary,
|
||||
[`${Box}`]: {
|
||||
padding: 0,
|
||||
},
|
||||
[`${StyledNavLink}`]: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
svg: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
[`@media ${MEDIA.tablet}`]: { padding: '8px 0', left: 0, width: '100%', justifyContent: 'center' },
|
||||
}));
|
||||
|
||||
const Divider = styled.div(({ theme }) => ({
|
||||
height: '1px',
|
||||
marginTop: '12px',
|
||||
@@ -71,4 +122,4 @@ const Divider = styled.div(({ theme }) => ({
|
||||
[`@media ${MEDIA.mobile}`]: { display: 'none' },
|
||||
}));
|
||||
|
||||
export { Navigation, NewItem, List, Divider, Tag };
|
||||
export { Navigation, NewServices, List, Divider, Tag, StyledNavLink };
|
||||
|
||||
@@ -16,27 +16,26 @@ const Sidebar: FC<Props> = ({ modules = [] }) => {
|
||||
{modules?.length > 0 ? (
|
||||
<S.List>
|
||||
{modules.map(item => (
|
||||
<SidebarItem
|
||||
key={item.title}
|
||||
exact={item.exact}
|
||||
href={item.path}
|
||||
icon={SIDEBAR_ICONS[item.path as PATHS]}
|
||||
isDesktop={isDesktop}
|
||||
title={item.title}
|
||||
/>
|
||||
<S.StyledNavLink key={item.title} exact={item.exact} to={item.path}>
|
||||
<SidebarItem icon={SIDEBAR_ICONS[item.path as PATHS]} isDesktop={isDesktop}>
|
||||
{item.title}
|
||||
</SidebarItem>
|
||||
</S.StyledNavLink>
|
||||
))}
|
||||
<S.Divider />
|
||||
<SidebarItem exact href={PATHS.CONTACT} icon={SIDEBAR_ICONS[PATHS.CONTACT]} isDesktop={isDesktop} title={LOCALIZATION.CONTACT} />
|
||||
<S.NewItem>
|
||||
<SidebarItem
|
||||
exact
|
||||
href={PATHS.SERVICES}
|
||||
icon={SIDEBAR_ICONS[PATHS.SERVICES]}
|
||||
isDesktop={isDesktop}
|
||||
title={LOCALIZATION.SERVICES}
|
||||
/>
|
||||
<S.Tag>New</S.Tag>
|
||||
</S.NewItem>
|
||||
<S.StyledNavLink exact to={PATHS.CONTACT}>
|
||||
<SidebarItem icon={SIDEBAR_ICONS[PATHS.CONTACT]} isDesktop={isDesktop}>
|
||||
{LOCALIZATION.CONTACT}
|
||||
</SidebarItem>
|
||||
</S.StyledNavLink>
|
||||
<S.StyledNavLink exact to={PATHS.SERVICES}>
|
||||
<S.NewServices>
|
||||
<SidebarItem icon={SIDEBAR_ICONS[PATHS.SERVICES]} isDesktop={isDesktop}>
|
||||
{LOCALIZATION.SERVICES}
|
||||
</SidebarItem>
|
||||
<S.Tag>New</S.Tag>
|
||||
</S.NewServices>
|
||||
</S.StyledNavLink>
|
||||
</S.List>
|
||||
) : null}
|
||||
</S.Navigation>
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import type { ReactElement } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { Text } from '@fractal-ui/styling';
|
||||
import * as S from './SidebarItem.styles';
|
||||
import type { Props } from './types';
|
||||
|
||||
const MobileMenuItem = ({ icon, href, exact, title }: Props): ReactElement => (
|
||||
<S.StyledNavLink exact={exact} to={href}>
|
||||
<S.Box>
|
||||
{icon}
|
||||
<Text.P4>{title}</Text.P4>
|
||||
</S.Box>
|
||||
</S.StyledNavLink>
|
||||
interface Props {
|
||||
icon: React.ReactNode;
|
||||
}
|
||||
|
||||
const MobileMenuItem: FC<Props> = ({ icon, children }) => (
|
||||
<S.Box>
|
||||
{icon}
|
||||
<Text.P4>{children}</Text.P4>
|
||||
</S.Box>
|
||||
);
|
||||
|
||||
export { MobileMenuItem };
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { MEDIA } from '@msb/shared';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
const IconBox = styled.div({
|
||||
display: 'flex',
|
||||
@@ -11,8 +10,10 @@ const Box = styled.div(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '12px',
|
||||
height: '40px',
|
||||
padding: '0 6px',
|
||||
height: '48px',
|
||||
borderRadius: '8px',
|
||||
padding: '0 8px',
|
||||
color: theme.colors.text.primary,
|
||||
svg: {
|
||||
width: '20px',
|
||||
height: '20px',
|
||||
@@ -20,6 +21,7 @@ const Box = styled.div(({ theme }) => ({
|
||||
color: theme.colors.text.secondary,
|
||||
},
|
||||
[`@media ${MEDIA.mobile}`]: {
|
||||
width: '72px',
|
||||
svg: {
|
||||
width: '22px',
|
||||
height: '22px',
|
||||
@@ -40,29 +42,4 @@ const Box = styled.div(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledNavLink = styled(NavLink)(({ theme }) => ({
|
||||
display: 'block',
|
||||
color: theme.colors.text.primary,
|
||||
textDecoration: 'none',
|
||||
'&.active': { fontWeight: 700 },
|
||||
'&:hover': { fontWeight: 700 },
|
||||
[`@media ${MEDIA.mobile}`]: {
|
||||
'&&&': {
|
||||
fontWeight: 'normal',
|
||||
},
|
||||
'&.active': {
|
||||
color: theme.colors.text.accentBrand,
|
||||
svg: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
'&:hover': {
|
||||
color: theme.colors.text.accentBrand,
|
||||
svg: {
|
||||
color: theme.colors.text.accentBrand,
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export { Box, IconBox, StyledNavLink };
|
||||
export { Box, IconBox };
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import type { ReactElement } from 'react';
|
||||
import type { FC } from 'react';
|
||||
import { Text, ExtraText } from '@fractal-ui/styling';
|
||||
import * as S from './SidebarItem.styles';
|
||||
import type { Props } from './types';
|
||||
|
||||
const SidebarItem = ({ icon, href, exact, title, isDesktop }: Props): ReactElement => (
|
||||
<S.StyledNavLink exact={exact} to={href}>
|
||||
<S.Box>
|
||||
{icon}
|
||||
{isDesktop ? <Text.P3>{title}</Text.P3> : <ExtraText.Description>{title}</ExtraText.Description>}
|
||||
</S.Box>
|
||||
</S.StyledNavLink>
|
||||
interface Props {
|
||||
icon: React.ReactNode;
|
||||
isDesktop?: boolean;
|
||||
}
|
||||
|
||||
const SidebarItem: FC<Props> = ({ icon, isDesktop, children }) => (
|
||||
<S.Box>
|
||||
{icon}
|
||||
{isDesktop ? <Text.P3>{children}</Text.P3> : <ExtraText.Description>{children}</ExtraText.Description>}
|
||||
</S.Box>
|
||||
);
|
||||
|
||||
export { SidebarItem };
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
interface Props {
|
||||
href: string;
|
||||
icon: React.ReactNode;
|
||||
title: string;
|
||||
isDesktop?: boolean;
|
||||
exact: boolean;
|
||||
}
|
||||
|
||||
export type { Props };
|
||||
@@ -1,138 +1,36 @@
|
||||
import type { IWebpackAppConfig } from '@msb/mf-builder';
|
||||
import CopyPlugin from 'copy-webpack-plugin';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
const outputPath = path.resolve(__dirname, '../../msb-host');
|
||||
const publicPath = path.resolve(__dirname, 'public');
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../build/msb-host'),
|
||||
outputPath,
|
||||
publicUrl: '/msb-host/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3001,
|
||||
},
|
||||
optimizationOptions: {
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -5,
|
||||
reuseExistingChunk: true,
|
||||
plugins: [
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
context: publicPath,
|
||||
from: '**/*.json',
|
||||
to: outputPath,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
{
|
||||
context: publicPath,
|
||||
from: '**/*.png',
|
||||
to: outputPath,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
chunks: 'all',
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name.replace('@', '').replace('/', '_'),
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
chunks: 'all',
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/http'],
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/shared'],
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-system'],
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@styled-system/css'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/react'],
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/styled'],
|
||||
},
|
||||
'react-animate-height': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-animate-height'],
|
||||
},
|
||||
'react-dnd': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-dnd'],
|
||||
},
|
||||
'react-dnd-html5-backend': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-dnd-html5-backend'],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.8.1",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/core": "^30.2.0",
|
||||
"@fractal-ui/extended": "^30.2.0",
|
||||
"@fractal-ui/library": "^30.2.0",
|
||||
"@fractal-ui/overlays": "^30.2.0",
|
||||
"@fractal-ui/styling": "^30.1.0",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"@msb/mf-utils": "^1.0.0",
|
||||
"@msb/shared": "1.0.0",
|
||||
"@msb/http": "1.0.0",
|
||||
@@ -68,9 +69,5 @@
|
||||
"lint-staged": "^12.3.4",
|
||||
"react-test-renderer": "17.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
]
|
||||
"browserslist": [">0.2%", "not dead", "not op_mini all"]
|
||||
}
|
||||
|
||||
@@ -3,68 +3,17 @@ import { normalizePackageName } from '@msb/mf-builder';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
|
||||
const packageName = normalizePackageName(packageJson.name);
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../build/msb-main-page'),
|
||||
publicUrl: 'auto',
|
||||
outputPath: path.resolve(__dirname, '../../msb-main-page'),
|
||||
publicUrl: '/msb-main-page/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3002,
|
||||
},
|
||||
optimizationOptions: {
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': {
|
||||
@@ -72,66 +21,6 @@ const config: IWebpackAppConfig = {
|
||||
name: `${packageName}_remote`,
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/http'],
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/shared'],
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-system'],
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@styled-system/css'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/react'],
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/styled'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.8.1",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/core": "^30.2.0",
|
||||
"@fractal-ui/extended": "^30.2.0",
|
||||
"@fractal-ui/library": "^30.2.0",
|
||||
"@fractal-ui/overlays": "^30.2.0",
|
||||
"@fractal-ui/styling": "^30.1.0",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"@msb/mf-utils": "^1.0.0",
|
||||
"@msb/http": "^1.0.0",
|
||||
"@msb/shared": "^1.0.0",
|
||||
@@ -66,9 +67,5 @@
|
||||
"lint-staged": "^12.3.4",
|
||||
"react-test-renderer": "17.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
]
|
||||
"browserslist": [">0.2%", "not dead", "not op_mini all"]
|
||||
}
|
||||
|
||||
@@ -3,68 +3,17 @@ import { normalizePackageName } from '@msb/mf-builder';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
|
||||
const packageName = normalizePackageName(packageJson.name);
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../build/msb-payments'),
|
||||
publicUrl: 'auto',
|
||||
outputPath: path.resolve(__dirname, '../../msb-payments'),
|
||||
publicUrl: '/msb-payments/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3004,
|
||||
},
|
||||
optimizationOptions: {
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': {
|
||||
@@ -72,66 +21,6 @@ const config: IWebpackAppConfig = {
|
||||
name: `${packageName}_remote`,
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/http'],
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/shared'],
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-system'],
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@styled-system/css'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/react'],
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/styled'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -23,11 +23,13 @@
|
||||
"dependencies": {
|
||||
"@emotion/react": "11.8.1",
|
||||
"@emotion/styled": "11.8.1",
|
||||
"@fractal-ui/core": "^30.2.0",
|
||||
"@fractal-ui/extended": "^30.2.0",
|
||||
"@fractal-ui/library": "^30.2.0",
|
||||
"@fractal-ui/overlays": "^30.2.0",
|
||||
"@fractal-ui/styling": "^30.1.0",
|
||||
"@fractal-ui/core": "30.2.0",
|
||||
"@fractal-ui/extended": "30.2.0",
|
||||
"@fractal-ui/composites": "30.2.0",
|
||||
"@fractal-ui/library": "30.2.0",
|
||||
"@fractal-ui/overlays": "30.2.0",
|
||||
"@fractal-ui/table": "30.2.0",
|
||||
"@fractal-ui/styling": "30.1.0",
|
||||
"@msb/mf-utils": "^1.0.0",
|
||||
"@msb/http": "^1.0.0",
|
||||
"@msb/shared": "^1.0.0",
|
||||
@@ -68,9 +70,5 @@
|
||||
"lint-staged": "^12.3.4",
|
||||
"react-test-renderer": "17.0.2"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
]
|
||||
"browserslist": [">0.2%", "not dead", "not op_mini all"]
|
||||
}
|
||||
|
||||
@@ -3,68 +3,17 @@ import { normalizePackageName } from '@msb/mf-builder';
|
||||
import path from 'node:path';
|
||||
import packageJson from './package.json';
|
||||
|
||||
interface Module {
|
||||
context: string;
|
||||
resourceResolveData: { descriptionFileData: Record<string, string> };
|
||||
}
|
||||
|
||||
const packageName = normalizePackageName(packageJson.name);
|
||||
|
||||
const config: IWebpackAppConfig = {
|
||||
moduleName: packageJson.name,
|
||||
paths: {
|
||||
outputPath: path.resolve(__dirname, '../../build/msb-statements-and-inquiries'),
|
||||
publicUrl: 'auto',
|
||||
outputPath: path.resolve(__dirname, '../../msb-statements-and-inquiries'),
|
||||
publicUrl: '/msb-statements-and-inquiries/',
|
||||
},
|
||||
devServerOptions: {
|
||||
port: 3005,
|
||||
},
|
||||
optimizationOptions: {
|
||||
runtimeChunk: false,
|
||||
splitChunks: {
|
||||
minSize: 17_000,
|
||||
minRemainingSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 30,
|
||||
automaticNameDelimiter: '_',
|
||||
maxInitialRequests: 30,
|
||||
enforceSizeThreshold: 30_000,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[/\\]node_modules[/\\]/,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
minSize: 0,
|
||||
priority: -10,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
default: {
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
},
|
||||
fractalPackages: {
|
||||
test: /[/\\]node_modules[/\\](@fractal-ui)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => {
|
||||
const { name } = module.resourceResolveData.descriptionFileData;
|
||||
|
||||
return name?.replace('@', '').replace('/', '_');
|
||||
},
|
||||
priority: 10,
|
||||
},
|
||||
reactPackages: {
|
||||
test: /[/\\]node_modules[/\\](react|react-dom|react-router-dom|react-animate-height|react-dnd|react-dnd-html5-backend)\//,
|
||||
reuseExistingChunk: true,
|
||||
name: (module: Module) => module.resourceResolveData.descriptionFileData.name,
|
||||
priority: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
moduleFederationOptions: {
|
||||
exposes: {
|
||||
'./App': {
|
||||
@@ -72,70 +21,6 @@ const config: IWebpackAppConfig = {
|
||||
name: `${packageName}_remote`,
|
||||
},
|
||||
},
|
||||
shared: {
|
||||
react: {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies.react,
|
||||
},
|
||||
'react-dom': {
|
||||
singleton: true,
|
||||
eager: true,
|
||||
requiredVersion: packageJson.dependencies['react-dom'],
|
||||
},
|
||||
'react-router-dom': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['react-router-dom'],
|
||||
},
|
||||
'@msb/http': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/http'],
|
||||
},
|
||||
'@msb/shared': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@msb/shared'],
|
||||
},
|
||||
'@fractal-ui/styling': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/styling'],
|
||||
},
|
||||
'@fractal-ui/core': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/core'],
|
||||
},
|
||||
'@fractal-ui/extended': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/extended'],
|
||||
},
|
||||
'@fractal-ui/overlays': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/overlays'],
|
||||
},
|
||||
'styled-system': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-system'],
|
||||
},
|
||||
'@styled-system/css': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@styled-system/css'],
|
||||
},
|
||||
'@fractal-ui/library': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@fractal-ui/library'],
|
||||
},
|
||||
'@emotion/react': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/react'],
|
||||
},
|
||||
'@emotion/styled': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['@emotion/styled'],
|
||||
},
|
||||
'styled-components': {
|
||||
singleton: true,
|
||||
requiredVersion: packageJson.dependencies['styled-components'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user