web: Common: Init commit of new js library for common code of any App in AppServer

This commit is contained in:
Alexey Safronov 2019-11-12 14:55:22 +03:00
parent 05327bbe86
commit 19acdd4a6e
60 changed files with 4124 additions and 4 deletions

1
.gitignore vendored
View File

@ -10,5 +10,6 @@
/build/deploy
*.log
/packages/asc-web-components
/packages/asc-web-common
/products/ASC.People/Data/
Data/

View File

@ -4,6 +4,10 @@
"name": "ASC.Web.Components"
"path": "./web/ASC.Web.Components"
},
{
"name": "ASC.Web.Common"
"path": "./web/ASC.Web.Common"
},
{
"name": "ASC.Web.Client"
"path": "./web/ASC.Web.Client"

View File

@ -10,12 +10,19 @@ echo "ASC.Web.Components"
call yarn install --cwd web/ASC.Web.Components --frozen-lockfile > build\ASC.Web.Components.log
call yarn link --cwd packages/asc-web-components
echo "ASC.Web.Common"
call yarn link "asc-web-components" --cwd web/ASC.Web.Common
call yarn install --cwd web/ASC.Web.Common --frozen-lockfile > build\ASC.Web.Common.log
call yarn link --cwd packages/asc-web-common
echo "ASC.Web.Client"
call yarn link "asc-web-components" --cwd web/ASC.Web.Client
call yarn link "asc-web-common" --cwd web/ASC.Web.Client
call yarn install --cwd web/ASC.Web.Client --frozen-lockfile > build\ASC.Web.Client.log
echo "ASC.Web.People.Client"
call yarn link "asc-web-components" --cwd products/ASC.People/Client
call yarn link "asc-web-common" --cwd products/ASC.People/Client
call yarn install --cwd products/ASC.People/Client --frozen-lockfile > build\ASC.Web.People.Client.log
xcopy build\cra\*.* products\ASC.People\Client\node_modules\ /E /R /Y

View File

@ -4,20 +4,27 @@ call start\stop.bat
PUSHD %~dp0..
del /s /q packages\asc-web-components
del /s /q packages\asc-web-common
echo "ASC.Web.Components"
call yarn install --cwd web/ASC.Web.Components > build\ASC.Web.Components.log
REM xcopy web\ASC.Web.Components\node_modules packages\asc-web-components\node_modules\ /E /R /Y >> build\ASC.Web.Components.log
call yarn install --cwd packages/asc-web-components >> build\ASC.Web.Components.log
call yarn link --cwd packages/asc-web-components
echo "ASC.Web.Common"
call yarn link "asc-web-components" --cwd web/ASC.Web.Common
call yarn install --cwd web/ASC.Web.Common > build\ASC.Web.Common.log
call yarn link --cwd packages/asc-web-common
echo "ASC.Web.Client"
call yarn link "asc-web-components" --cwd web/ASC.Web.Client
call yarn link "asc-web-common" --cwd web/ASC.Web.Client
call yarn install --cwd web/ASC.Web.Client > build\ASC.Web.Client.log
echo "ASC.Web.People.Client"
call yarn link "asc-web-components" --cwd products/ASC.People/Client
call yarn link "asc-web-common" --cwd products/ASC.People/Client
call yarn install --cwd products/ASC.People/Client > build\ASC.Web.People.Client.log
xcopy build\cra\*.* products\ASC.People\Client\node_modules\ /E /R /Y

View File

@ -1,5 +1,5 @@
{
"kafka": {
"BootstrapServers": ""
"BootstrapServers": "localhost:9092"
}
}

View File

@ -5,6 +5,7 @@
"homepage": "/products/people",
"dependencies": {
"asc-web-components": "file:../../../packages/asc-web-components",
"asc-web-common": "file:../../../packages/asc-web-common",
"axios": "^0.19.0",
"bootstrap": "4.3.1",
"connected-react-router": "6.5.2",

View File

@ -1801,8 +1801,15 @@ asap@~2.0.6:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
"asc-web-common@file:../../../packages/asc-web-common":
version "1.0.0"
dependencies:
axios "^0.19.0"
history "4.9.0"
universal-cookie "^4.0.2"
"asc-web-components@file:../../../packages/asc-web-components":
version "1.0.152"
version "1.0.166"
dependencies:
email-addresses "^3.0.3"
moment "^2.24.0"

View File

@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"asc-web-components": "file:../../packages/asc-web-components",
"asc-web-common": "file:../../packages/asc-web-common",
"axios": "^0.19.0",
"bootstrap": "4.3.1",
"connected-react-router": "6.5.2",

View File

@ -1801,8 +1801,15 @@ asap@~2.0.6:
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
"asc-web-common@file:../../packages/asc-web-common":
version "1.0.0"
dependencies:
axios "^0.19.0"
history "4.9.0"
universal-cookie "^4.0.2"
"asc-web-components@file:../../packages/asc-web-components":
version "1.0.152"
version "1.0.166"
dependencies:
email-addresses "^3.0.3"
moment "^2.24.0"

View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@ -0,0 +1 @@
dist/

View File

@ -0,0 +1,13 @@
module.exports = {
parser: 'babel-eslint',
extends: ['eslint:recommended', 'plugin:react/recommended'],
settings: {
react: {
version: 'detect',
},
},
env: {
browser: true,
node: true,
},
};

14
web/ASC.Web.Common/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
**/obj/
**/bin/
/packages/
*.suo
*.user
.vs/
.vscode/
*-lock.json
*.lock
**/node_modules/
**/storybook-static/
/web/ASC.Web.Components/dist
/build/deploy
/coverage

View File

@ -0,0 +1,7 @@
{
"presets": [
"@babel/preset-env",
"react-app"
],
"plugins": [["babel-plugin-styled-components", { "diplayName": true }]]
}

View File

@ -0,0 +1,9 @@
import '@storybook/addons';
import 'storybook-readme/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-storysource/register';
import '@storybook/addon-actions/register';
import '@storybook/addon-options/register';
import '@storybook/addon-links/register';
import '@storybook/addon-viewport/register';
import '@storybook/addon-a11y/register';

View File

@ -0,0 +1,52 @@
import { configure, addDecorator, addParameters } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';
import { addReadme } from 'storybook-readme';
import { withConsole } from '@storybook/addon-console';
import '!style-loader!css-loader!./styles.scss';
//import 'bootstrap/dist/css/bootstrap.css';
//import 'react-toastify/dist/ReactToastify.min.css';
/*
This is a package to make Story panel load and decode all files stories
Also, because of some internal usage, we cannot use the default babel config (for the library)
with this package.
In order to solve that, it's necessary a custom/simple .babelrc inside .storybook/ folder
*/
//import requireContext from 'require-context.macro';
/* Add A11y panel */
addDecorator(withA11y);
/* Enable README for all stories */
addDecorator(addReadme);
/* General options for storybook */
addParameters({
options:
{
name: 'ASC Storybook',
sortStoriesByKind: true,
showAddonPanel: true,
addonPanelInRight: true
},
/* Options for storybook-readme plugin */
readme: {
codeTheme: 'github',
StoryPreview: ({ children }) => children,
},
});
/* automatically import all files ending in *.stories.js inside src folder */
//const req = requireContext('../src', true, /\.stories\.js$/);
//const req = require.context('../src', true, /\.stories\.js$/);
const srcStories = require.context('../src', true, /\.stories\.js$/);
function loadStories() {
//req.keys().forEach(filename => req(filename));
srcStories.keys().forEach(filename => srcStories(filename));
}
addDecorator((storyFn, context) => withConsole()(storyFn)(context));
configure(loadStories, module);

View File

@ -0,0 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
const sectionStyles = {
padding: 16,
};
const Section = props => <div style={sectionStyles}>{props.children}</div>;
Section.propTypes = { children: PropTypes.node.isRequired };
export default Section;

View File

@ -0,0 +1 @@
<script>document.title = "ASC Storybook";</script>

View File

@ -0,0 +1,13 @@
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i' rel='stylesheet' type='text/css'></link>
<style>
html,
body {
margin: 0;
padding: 0;
font-size: 13px;
}
body {
overflow: auto;
}
</style>

View File

@ -0,0 +1,8 @@
/*
Any global style for all stories
It can also be an scss file, however,
you have to go to `webpack.config.js` file
and enable the options in there
*/
@import '../node_modules/bootstrap/dist/css/bootstrap.css';
@import '../node_modules/react-toastify/dist/ReactToastify.min.css';

View File

@ -0,0 +1,102 @@
const path = require('path');
const sourceFolders = [
path.resolve(__dirname),
path.resolve(__dirname, '../src'),
];
module.exports = ({ config }) => {
if (process.env.NODE_ENV === 'production') {
// remove progress plugin
// progress plugin outputs a lot of console logs, which makes
// netlify build realllllllllllllllly slow.
config.plugins = config.plugins.filter(
plugin => plugin.constructor.name !== 'ProgressPlugin'
);
config.devtool = 'none'; // TODO: should we use something differen?
} else {
config.devtool = 'cheap-module-source-map'; // TODO: should we use something differen?
}
config.devtool = 'cheap-module-source-map'; // TODO: should we use something differen?
config.module.rules = [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// add story source
{
test: /\.stories\.js$/,
loaders: [require.resolve('@storybook/source-loader')],
enforce: 'pre',
},
// Process JS with Babel.
{
test: /\.js$/,
include: sourceFolders,
use: [
{
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
compact: false,
presets: [require.resolve('../scripts/get-babel-preset')],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
highlightCode: true,
},
},
],
},
// For svg icons, we want to get them transformed into React components
// when we import them.
{
test: /\.react\.svg$/,
include: sourceFolders,
use: [
{
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
presets: [require.resolve('../scripts/get-babel-preset')],
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
highlightCode: true,
},
},
{
loader: require.resolve('@svgr/webpack'),
options: {
// NOTE: disable this and manually add `removeViewBox: false` in the SVGO plugins list
// See related PR: https://github.com/smooth-code/svgr/pull/137
icon: false,
svgoConfig: {
plugins: [
{ removeViewBox: false },
// Keeps ID's of svgs so they can be targeted with CSS
{ cleanupIDs: false },
],
},
},
},
],
},
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
// Storybook uses a plugin to load and render markdown files.
{
test: /\.md$/,
use: [
{ loader: require.resolve('html-loader') },
{ loader: require.resolve('markdown-loader') },
],
}
];
return config;
};

View File

@ -0,0 +1,11 @@
# asc-web-common
# Common components and solutions to build your product
>
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
## License
AGPL-3.0 © Ascensio System SIA

View File

@ -0,0 +1,21 @@
const presets = [
[
'@babel/preset-env',
{
modules: false,
},
],
'@babel/preset-react',
];
const plugins = ['@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-export-namespace-from', 'babel-plugin-styled-components'];
module.exports = {
presets,
plugins,
env: {
test: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
};

View File

@ -0,0 +1,4 @@
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1374
web/ASC.Web.Common/dist/asc-web-common.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
module.exports = {
setupFiles: [
'<rootDir>/test/setup-tests.js'
],
setupFilesAfterEnv: [
'<rootDir>/scripts/setup-test-framework.js'
],
transform: {
'^.+\\.js$': '<rootDir>/test/transform-babel-jest.js',
},
/* It solves css/less/scss import issues.
You might have similar issues with different file extensions (e.g. md).
Just search for "<file type> jest loader"
*/
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/test/transform-file.js'
},
};

View File

@ -0,0 +1,109 @@
{
"name": "asc-web-common",
"version": "1.0.0",
"description": "Ascensio System SIA common components and solutions library",
"license": "AGPL-3.0",
"main": "dist/asc-web-common.js",
"module": "dist/asc-web-common.esm.js",
"jsnext:main": "dist/asc-web-common.es.js",
"files": [
"dist",
"README.md",
"LICENSE",
"package.json"
],
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"build": "rimraf dist && cross-env NODE_ENV=production rollup -c",
"start": "cross-env NODE_ENV=development rollup -c -w",
"prepare": "yarn run build",
"lint": "eslint .",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"storybook": "start-storybook -p 6006 -s ./public",
"build:storybook": "build-storybook -c .storybook -o storybook-static -s public",
"bump": "yarn version --no-git-tag-version --patch && git add ./package.json && git commit -m \"web: components: bump version\""
},
"peerDependencies": {
"prop-types": "^15.7.2",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-values": "^0.3.3",
"styled-components": "^4.3.2"
},
"devDependencies": {
"@babel/cli": "^7.5.5",
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-export-default-from": "^7.5.2",
"@babel/plugin-proposal-export-namespace-from": "^7.5.2",
"@babel/plugin-transform-runtime": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@emotion/babel-preset-css-prop": "^10.0.17",
"@storybook/addon-a11y": "^5.1.11",
"@storybook/addon-actions": "^5.2.5",
"@storybook/addon-console": "^1.2.1",
"@storybook/addon-knobs": "^5.2.5",
"@storybook/addon-links": "^5.2.5",
"@storybook/addon-options": "^5.2.5",
"@storybook/addon-storysource": "^5.2.5",
"@storybook/addon-viewport": "^5.2.5",
"@storybook/addons": "^5.2.5",
"@storybook/react": "^5.2.5",
"@svgr/rollup": "^4.3.3",
"@svgr/webpack": "^4.3.2",
"@testing-library/react": "^8.0.8",
"@types/jest": "^24.0.17",
"babel-eslint": "^10.0.2",
"babel-jest": "^24.8.0",
"babel-loader": "^8.0.6",
"babel-plugin-inline-react-svg": "^1.1.0",
"babel-plugin-transform-dynamic-import": "^2.1.0",
"babel-plugin-transform-rename-import": "^2.3.0",
"cross-env": "^5.2.0",
"css-loader": "^3.2.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^6.3.0",
"eslint-plugin-react": "^7.14.3",
"jest": "^24.8.0",
"jest-enzyme": "^7.1.0",
"jest-junit": "^8.0.0",
"postcss": "^7.0.17",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-values": "^0.3.3",
"rollup": "^1.21.1",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-cleanup": "^3.1.1",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-copy": "^3.1.0",
"rollup-plugin-generate-package-json": "^3.1.3",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-peer-deps-external": "^2.2.0",
"rollup-plugin-postcss": "^2.0.3",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-url": "^2.2.2",
"storybook-readme": "^5.0.8",
"styled-components": "^4.3.2",
"svg-inline-loader": "^0.8.0",
"prop-types": "^15.7.2"
},
"dependencies": {
"lodash": "4.17.15",
"lodash-es": "4.17.15",
"moment": "^2.24.0",
"universal-cookie": "^4.0.2",
"history": "4.9.0",
"axios": "^0.19.0"
},
"resolutions": {
"js-yaml": "3.13.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>ASC Storybook</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -0,0 +1,34 @@
<svg width="142" height="23" viewBox="0 0 142 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M31 12.0026C31 9.62504 31.6829 7.83068 33.0943 6.66435C34.4602 5.45316 36.0993 4.87 37.966 4.87C39.8326 4.87 41.4262 5.45316 42.792 6.66435C44.1579 7.87554 44.8409 9.62504 44.8409 12.0474C44.8409 14.4249 44.1579 16.2193 42.792 17.3856C41.4262 18.5968 39.7871 19.18 37.966 19.18C36.0993 19.18 34.5057 18.5968 33.0943 17.3856C31.6829 16.1744 31 14.3801 31 12.0026ZM34.0049 12.0026C34.0049 13.6623 34.3236 14.8287 34.9155 15.5913C35.5529 16.3539 36.2358 16.8473 36.9643 17.0268C37.1464 17.0716 37.283 17.1165 37.4651 17.1165C37.6017 17.1165 37.7838 17.1613 37.9204 17.1613C38.1025 17.1613 38.2391 17.1613 38.4212 17.1165C38.6034 17.1165 38.74 17.0716 38.9221 17.0268C39.6505 16.8473 40.3335 16.3539 40.9253 15.5913C41.5172 14.8287 41.8359 13.6175 41.8359 12.0474C41.8359 10.4774 41.5172 9.26617 40.9253 8.50357C40.3335 7.74097 39.6505 7.24752 38.9221 7.06808C38.74 7.02322 38.5578 6.97836 38.4212 6.97836C38.2391 6.97836 38.1025 6.93351 37.9204 6.93351C37.7383 6.93351 37.6017 6.9335 37.4651 6.97836C37.3285 6.97836 37.1464 7.02322 36.9643 7.06808C36.2358 7.24752 35.5529 7.74097 34.9155 8.50357C34.3236 9.22131 34.0049 10.3876 34.0049 12.0026Z" fill="white"/>
<path d="M46.3433 5.00449H50.0767L54.9938 13.8417L55.7223 15.7258H55.7678L55.7223 13.2585V5.00449H58.5906V19.0005H54.8573L49.9401 9.84925L49.2116 8.27919H49.1661L49.2116 10.7464V19.0005H46.3433V5.00449Z" fill="white"/>
<path d="M61.0948 5.00449H63.9631V16.6229H69.6087V19.0005H61.0948V5.00449Z" fill="white"/>
<path d="M67.8331 5.00449H71.1567L74.0705 9.93897L74.5258 10.881H74.6169L75.0722 9.93897L78.0316 5.00449H81.082L75.9372 13.3034V19.0005H73.0689V13.3034L67.8331 5.00449Z" fill="white"/>
<path d="M81.1731 12.0026C81.1731 9.62504 81.856 7.83068 83.2674 6.66435C84.6333 5.45316 86.2723 4.87 88.139 4.87C90.0057 4.87 91.5993 5.45316 92.9651 6.66435C94.331 7.87554 95.0139 9.62504 95.0139 12.0474C95.0139 14.4249 94.331 16.2193 92.9651 17.3856C91.5993 18.5968 89.9602 19.18 88.139 19.18C86.2723 19.18 84.6788 18.5968 83.2674 17.3856C81.9016 16.1744 81.1731 14.3801 81.1731 12.0026ZM84.178 12.0026C84.178 13.6623 84.4967 14.8287 85.0886 15.5913C85.726 16.3539 86.3634 16.8473 87.1374 17.0268C87.3195 17.0716 87.5016 17.1165 87.6382 17.1165C87.7748 17.1165 87.9569 17.1613 88.0935 17.1613C88.2756 17.1613 88.4122 17.1613 88.5943 17.1165C88.7764 17.1165 88.913 17.0716 89.0952 17.0268C89.8236 16.8473 90.5066 16.3539 91.0984 15.5913C91.6903 14.8287 92.009 13.6175 92.009 12.0474C92.009 10.4774 91.6903 9.26617 91.0984 8.50357C90.5066 7.74097 89.8236 7.24752 89.0952 7.06808C88.913 7.02322 88.7309 6.97836 88.5943 6.97836C88.4122 6.97836 88.2756 6.93351 88.0935 6.93351C87.9114 6.93351 87.7748 6.9335 87.6382 6.97836C87.5016 6.97836 87.3195 7.02322 87.1374 7.06808C86.4089 7.24752 85.726 7.74097 85.0886 8.50357C84.4967 9.22131 84.178 10.3876 84.178 12.0026Z" fill="#D7E4EA"/>
<path d="M96.5619 5.00449H104.484V7.38201H99.4303V10.7464H104.256V13.1239H99.4303V19.0005H96.5619V5.00449Z" fill="#D7E4EA"/>
<path d="M106.169 5.00449H114.091V7.38201H109.037V10.7464H113.863V13.1239H109.037V19.0005H106.169V5.00449Z" fill="#D7E4EA"/>
<path d="M115.775 19.0005V5.00449H118.644V19.0005H115.775Z" fill="#D7E4EA"/>
<path d="M131.665 5.3185V7.74088C131.164 7.56144 130.663 7.42687 130.117 7.33715C129.571 7.24743 128.979 7.20257 128.341 7.20257C126.839 7.20257 125.701 7.65116 124.881 8.5932C124.062 9.49038 123.652 10.6567 123.652 12.0473C123.652 13.3931 124.016 14.5146 124.79 15.4118C125.564 16.3089 126.657 16.8024 128.068 16.8024C128.569 16.8024 129.07 16.7575 129.662 16.7127C130.253 16.6229 130.845 16.4884 131.483 16.2192L131.665 18.5967C131.574 18.6416 131.437 18.6865 131.301 18.7313C131.119 18.7762 130.936 18.821 130.709 18.8659C130.345 18.9556 129.889 19.0005 129.343 19.0902C128.797 19.135 128.25 19.1799 127.658 19.1799C127.567 19.1799 127.476 19.1799 127.431 19.1799C127.34 19.1799 127.249 19.1799 127.203 19.1799C125.564 19.0902 124.062 18.4622 122.696 17.3855C121.33 16.2641 120.647 14.5146 120.647 12.1819C120.647 9.89411 121.33 8.09975 122.65 6.8437C123.97 5.58765 125.792 4.95963 128.023 4.95963C128.614 4.95963 129.161 4.95963 129.616 5.00448C130.117 5.04934 130.572 5.13906 131.073 5.22878C131.164 5.27364 131.301 5.27364 131.392 5.3185C131.437 5.27364 131.528 5.3185 131.665 5.3185Z" fill="#D7E4EA"/>
<path d="M133.486 5.00449H142V7.20257H136.4V10.7016H141.454V12.8997H136.4V16.8024H142V19.0005H133.486V5.00449Z" fill="#D7E4EA"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.9389 22.718L0.657327 17.9809C-0.218514 17.5673 -0.218514 16.9282 0.657327 16.5522L4.23685 14.898L10.9009 17.9809C11.7767 18.3944 13.1857 18.3944 14.0234 17.9809L20.6874 14.898L24.267 16.5522C25.1428 16.9658 25.1428 17.6049 24.267 17.9809L13.9853 22.718C13.1857 23.094 11.7767 23.094 10.9389 22.718Z" fill="url(#paint0_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.9389 16.8906L0.657327 12.1535C-0.218514 11.7399 -0.218514 11.1008 0.657327 10.7248L4.16069 9.10815L10.9389 12.2287C11.8148 12.6422 13.2237 12.6422 14.0615 12.2287L20.8398 9.10815L24.3431 10.7248C25.219 11.1384 25.219 11.7775 24.3431 12.1535L14.0615 16.8906C13.1857 17.3042 11.7767 17.3042 10.9389 16.8906Z" fill="url(#paint1_linear)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.9385 11.2131L0.656881 6.47597C-0.21896 6.06241 -0.21896 5.42327 0.656881 5.04731L10.9385 0.31017C11.8143 -0.10339 13.2233 -0.10339 14.0611 0.31017L24.3427 5.04731C25.2185 5.46087 25.2185 6.10001 24.3427 6.47597L14.0611 11.2131C13.1852 11.5891 11.7763 11.5891 10.9385 11.2131Z" fill="url(#paint2_linear)"/>
</g>
<defs>
<linearGradient id="paint0_linear" x1="12.4914" y1="27.2083" x2="12.4914" y2="9.91349" gradientUnits="userSpaceOnUse">
<stop stop-color="#FCC2B1"/>
<stop offset="0.8848" stop-color="#D9420B"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="12.4914" y1="19.7202" x2="12.4914" y2="8.34589" gradientUnits="userSpaceOnUse">
<stop stop-color="#DEEDC9"/>
<stop offset="0.6606" stop-color="#8BBA25"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="12.4909" y1="15.114" x2="12.4909" y2="-0.363895" gradientUnits="userSpaceOnUse">
<stop stop-color="#C2EBFA"/>
<stop offset="1" stop-color="#26A8DE"/>
</linearGradient>
<clipPath id="clip0">
<rect width="142" height="23" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,15 @@
{
"short_name": "ASC Web Components Storybook",
"name": "ASC Storybook",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,124 @@
import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import json from "rollup-plugin-json";
import babel from "rollup-plugin-babel";
import cleanup from "rollup-plugin-cleanup";
import replace from "rollup-plugin-replace";
import postcss from 'rollup-plugin-postcss';
import copy from 'rollup-plugin-copy';
import svgrPlugin from "@svgr/rollup";
import generatePackageJson from 'rollup-plugin-generate-package-json'
import pkg from "./package.json";
const getBabelPreset = require("./scripts/get-babel-preset");
const babelOptions = getBabelPreset();
// This list includes common plugins shared between each output format.
// NOTE: the order of the plugins is important!
const configureRollupPlugins = (options = {}) => [
generatePackageJson({
baseContents: {
name: pkg.name,
version: pkg.version,
description: pkg.description,
license: pkg.license,
main: pkg.main,
module: pkg.module,
peerDependencies: pkg.peerDependencies
},
outputFolder: '../../packages/asc-web-common'
}),
replace({
"process.env.NODE_ENV": JSON.stringify("production")
}),
// To use the nodejs `resolve` algorithm
resolve(),
// See also https://medium.com/@kelin2025/so-you-wanna-use-es6-modules-714f48b3a953
// Transpile sources using our custom babel preset.
babel({
exclude: ["node_modules/**"],
runtimeHelpers: true,
...babelOptions,
plugins: [
...babelOptions.plugins,
...(options.babel && options.babel.plugins ? options.babel.plugins : [])
]
}),
// To convert CJS modules to ES6
commonjs({
include: "node_modules/**"
}),
// To convert JSON files to ES6
json(),
// To convert SVG Icons to ES6
svgrPlugin({
// NOTE: only the files ending with `.react.svg` are supposed to be
// converted to React components
include: ["**/*.react.svg"],
icon: false,
svgoConfig: {
plugins: [
{ removeViewBox: false },
// Keeps ID's of svgs so they can be targeted with CSS
{ cleanupIDs: false }
]
}
}),
postcss({
extensions: ['.css'],
}),
// To remove comments, trim trailing spaces, compact empty lines,
// and normalize line endings
cleanup()
];
const deps = Object.keys(pkg.dependencies || {});
const peerDeps = Object.keys(pkg.peerDependencies || {});
const defaultExternal = ["stream", ...deps.concat(peerDeps)];
// We need to define 2 separate configs (`esm` and `cjs`) so that each can be
// further customized.
const config = [
{
input: "src/index.js",
external: defaultExternal,
output: {
file: pkg.module,
format: "esm",
sourcemap: true
},
plugins: configureRollupPlugins({
babel: {
plugins: [
[
"transform-rename-import",
{
replacements: [{ original: "lodash", replacement: "lodash-es" }]
}
]
]
}
})
},
{
input: "src/index.js",
external: defaultExternal,
output: {
file: pkg.main,
format: "cjs",
sourcemap: true
},
plugins: [
...configureRollupPlugins(),
copy({
targets: [
{ src: 'dist', dest: '../../packages/asc-web-common' },
{ src: 'README.md', dest: '../../packages/asc-web-common' },
],
verbose: true
})]
}
];
export default config;

View File

@ -0,0 +1,134 @@
/* eslint-disable global-require */
module.exports = function getBabelPreset() {
// This is similar to how `env` works in Babel:
// https://babeljs.io/docs/usage/babelrc/#env-option
// We are not using `env` because its ignored in versions > babel-core@6.10.4:
// https://github.com/babel/babel/issues/4539
// https://github.com/facebook/create-react-app/issues/720
// Its also nice that we can enforce `NODE_ENV` being specified.
const env = process.env.BABEL_ENV || process.env.NODE_ENV;
const isEnvDevelopment = env === "development";
const isEnvProduction = env === "production";
const isEnvTest = env === "test";
if (!isEnvDevelopment && !isEnvProduction && !isEnvTest) {
throw new Error(
"The babel preset of requires that you specify `NODE_ENV` or " +
'`BABEL_ENV` environment variables. Valid values are "development", ' +
`"test", and "production". Instead, received: ${JSON.stringify(env)}.`
);
}
return {
presets: [
isEnvTest && [
// ES features necessary for user's Node version
require("@babel/preset-env").default,
{
targets: {
browsers: ["last 1 versions"],
node: "8"
}
}
],
(isEnvProduction || isEnvDevelopment) && [
// Latest stable ECMAScript features
require("@babel/preset-env").default,
{
targets: {
browsers: ["last 1 versions"]
},
corejs: 2,
// `entry` transforms `@babel/polyfill` into individual requires for
// the targeted browsers. This is safer than `usage` which performs
// static code analysis to determine what's required.
// This is probably a fine default to help trim down bundles when
// end-users inevitably import '@babel/polyfill'.
useBuiltIns: "entry",
// Do not transform modules to CJS
modules: false,
include: ["transform-classes"]
}
],
[
require("@babel/preset-react").default,
{
// Adds component stack to warning messages
// Adds __self attribute to JSX which React will use for some warnings
development: isEnvDevelopment || isEnvTest,
// Will use the native built-in instead of trying to polyfill
// behavior for any plugins that require one.
useBuiltIns: true
}
],
[
"@emotion/babel-preset-css-prop",
{
sourceMap: isEnvDevelopment,
autoLabel: !isEnvProduction
}
]
].filter(Boolean),
plugins: [
require("babel-plugin-styled-components").default,
// Experimental macros support. Will be documented after it's had some time
// in the wild.
require("babel-plugin-macros").default,
// https://github.com/emotion-js/emotion/tree/master/packages/babel-plugin-emotion
// export { default } from './foo'
require("@babel/plugin-proposal-export-default-from").default,
// export * from './foo'
require("@babel/plugin-proposal-export-namespace-from").default,
// Necessary to include regardless of the environment because
// in practice some other transforms (such as object-rest-spread)
// don't work without it: https://github.com/babel/babel/issues/7215
require("@babel/plugin-transform-destructuring").default,
// class { handleClick = () => { } }
// Enable loose mode to use assignment instead of defineProperty
// See discussion in https://github.com/facebook/create-react-app/issues/4263
[
require("@babel/plugin-proposal-class-properties").default,
{
loose: true
}
],
// The following two plugins use Object.assign directly, instead of Babel's
// extends helper. Note that this assumes `Object.assign` is available.
// { ...todo, completed: true }
[
require("@babel/plugin-proposal-object-rest-spread").default,
{
useBuiltIns: true
}
],
// Polyfills the runtime needed for async/await and generators
[
require("@babel/plugin-transform-runtime").default,
{
helpers: false,
regenerator: true
}
],
isEnvProduction && [
// Remove PropTypes from production build
require("babel-plugin-transform-react-remove-prop-types").default,
{
mode: "wrap"
}
],
// function* () { yield 42; yield 43; }
!isEnvTest && [
require("@babel/plugin-transform-regenerator").default,
{
// Async functions are converted to generators by @babel/preset-env
async: false
}
],
// Adds syntax support for import()
require("@babel/plugin-syntax-dynamic-import").default,
isEnvTest &&
// Transform dynamic import to require
require("babel-plugin-transform-dynamic-import").default
].filter(Boolean)
};
};

View File

@ -0,0 +1,6 @@
// enzyme setup
import 'jest-enzyme';
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter(), disableLifecycleMethods: true });

View File

@ -0,0 +1,55 @@
export const AUTH_KEY = 'asc_auth_key';
/**
* Enum for employee activation status.
* @readonly
*/
export const EmployeeActivationStatus = Object.freeze({
NotActivated: 0,
Activated: 1,
Pending: 2,
AutoGenerated: 4
});
/**
* Enum for type of confirm link.
* @readonly
*/
export const ConfirmType = Object.freeze({
EmpInvite: 0,
LinkInvite: 1,
PortalSuspend: 2,
PortalContinue: 3,
PortalRemove: 4,
DnsChange: 5,
PortalOwnerChange: 6,
Activation: 7,
EmailChange: 8,
EmailActivation: 9,
PasswordChange: 10,
ProfileRemove: 11,
PhoneActivation: 12,
PhoneAuth: 13,
Auth: 14,
TfaActivation: 15,
TfaAuth: 16
});
/**
* Enum for result of validation confirm link.
* @readonly
*/
export const ValidationResult = Object.freeze({
Ok: 0,
Invalid: 1,
Expired: 2
});
/**
* Enum for employee status.
* @readonly
*/
export const EmployeeStatus = Object.freeze({
Active: 1,
Disabled: 2
});

View File

@ -0,0 +1,3 @@
import { createBrowserHistory } from 'history';
export default createBrowserHistory();

View File

@ -0,0 +1,2 @@
export { default as Api } from './store/services/api';
export { default as Auth } from './store/auth';

View File

@ -0,0 +1,89 @@
import * as api from "../services/api";
//import { fetchGroups, fetchPeople } from "../../../../../products/ASC.People/Client/src/store/people/actions";
import { setAuthorizationToken } from "../services/api/client";
//import { getFilterByLocation } from "../../../../../products/ASC.People/Client/src/helpers/converters";
//import config from "../../../package.json";
export const LOGIN_POST = "LOGIN_POST";
export const SET_CURRENT_USER = "SET_CURRENT_USER";
export const SET_MODULE = "SET_MODULE";
export const SET_MODULES = "SET_MODULES";
export const SET_SETTINGS = "SET_SETTINGS";
export const SET_IS_LOADED = "SET_IS_LOADED";
export const LOGOUT = "LOGOUT";
export function setModule(module) {
return {
type: SET_MODULE,
module
};
}
export function setCurrentUser(user) {
return {
type: SET_CURRENT_USER,
user
};
}
export function setModules(modules) {
return {
type: SET_MODULES,
modules
};
}
export function setSettings(settings) {
return {
type: SET_SETTINGS,
settings
};
}
export function setIsLoaded(isLoaded) {
return {
type: SET_IS_LOADED,
isLoaded
};
}
export function setLogout() {
return {
type: LOGOUT
};
}
export async function getUserInfo(dispatch, additionalAction) {
const { user, modules, settings } = await api.getInitInfo();
let newSettings = settings;
if (user.isAdmin) {
const inviteLinks = await api.getInvitationLinks();
newSettings = Object.assign(newSettings, inviteLinks);
}
dispatch(setCurrentUser(user));
dispatch(setModules(modules));
dispatch(setSettings(newSettings));
additionalAction && additionalAction();
/*await fetchGroups(dispatch);
var re = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm");
const match = window.location.pathname.match(re);
if (match && match.length > 0)
{
const newFilter = getFilterByLocation(window.location);
await fetchPeople(newFilter, dispatch);
}*/
return dispatch(setIsLoaded(true));
}
export function logout() {
return dispatch => {
setAuthorizationToken();
return dispatch(setLogout());
};
}

View File

@ -0,0 +1,5 @@
import * as actions from './actions';
import * as reducers from './reducers';
import * as selectors from './selectors';
export default { actions, reducers, selectors };

View File

@ -0,0 +1,73 @@
import {
SET_CURRENT_USER,
SET_MODULE,
SET_MODULES,
SET_IS_LOADED,
LOGOUT,
SET_SETTINGS
} from "./actions";
import isEmpty from "lodash/isEmpty";
const initialState = {
isAuthenticated: false,
isLoaded: false,
user: {},
modules: [],
settings: {
currentProductId: null,
culture: "en-US",
trustedDomains: [],
trustedDomainsType: 1,
timezone: "UTC",
utcOffset: "00:00:00",
utcHoursOffset: 0,
homepage: "",
datePattern: "M/d/yyyy",
datePatternJQ: "00/00/0000",
dateTimePattern: "dddd, MMMM d, yyyy h:mm:ss tt",
datepicker: {
datePattern: "mm/dd/yy",
dateTimePattern: "DD, mm dd, yy h:mm:ss tt",
timePattern: "h:mm tt"
},
hasShortenService: false
}
};
const authReducer = (state = initialState, action) => {
switch (action.type) {
case SET_CURRENT_USER:
return Object.assign({}, state, {
isAuthenticated: !isEmpty(action.user),
user: action.user
});
case SET_MODULE:
return Object.assign({}, state, {
settings: {
...state.settings,
currentProductId: action.module.id,
homepage: action.module.homepage
}
});
case SET_MODULES:
return Object.assign({}, state, {
modules: action.modules
});
case SET_SETTINGS:
return Object.assign({}, state, {
settings: { ...state.settings, ...action.settings }
});
case SET_IS_LOADED:
return Object.assign({}, state, {
isLoaded: action.isLoaded
});
case LOGOUT:
return Object.assign({}, initialState, {
isLoaded: true
});
default:
return state;
}
};
export default authReducer;

View File

@ -0,0 +1,12 @@
export function isAdmin(user) {
let isPeopleAdmin = user.listAdminModules ? user.listAdminModules.includes('people') : false;
return user.isAdmin || user.isOwner || isPeopleAdmin;
};
export function isMe(user, userName) {
return userName === "@self" || userName === user.userName;
};
export function getCurrentModule(modules, currentModuleId) {
return modules.find(module => module.id === currentModuleId);
}

View File

@ -0,0 +1,104 @@
import axios from "axios";
import Cookies from "universal-cookie";
import history from "../../../history";
import { AUTH_KEY } from "../../../constants";
const PREFIX = "api";
const VERSION = "2.0";
const baseURL = `${window.location.origin}/${PREFIX}/${VERSION}`;
/**
* @description axios instance for ajax requests
*/
const client = axios.create({
baseURL: baseURL,
responseType: 'json',
timeout: 30000, // default is `0` (no timeout)
});
setAuthorizationToken(localStorage.getItem(AUTH_KEY));
/**
* @description if any of the API gets 401 status code, this method
calls getAuthToken method to renew accessToken
* updates the error configuration and retries all failed requests
again
*/
client.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response.status === 401) {
//place your reentry code
history.push("/login/error=unauthorized");
}
if (error.response.status === 502) {
//toastr.error(error.response);
history.push(`/error/${error.response.status}`);
}
return error;
}
);
export function setAuthorizationToken(token) {
const cookies = new Cookies();
if (token) {
client.defaults.headers.common['Authorization'] = token;
localStorage.setItem(AUTH_KEY, token);
const current = new Date();
const nextYear = new Date();
nextYear.setFullYear(current.getFullYear() + 1);
cookies.set(AUTH_KEY, token, {
path: "/",
expires: nextYear
});
} else {
localStorage.clear();
delete client.defaults.headers.common['Authorization'];
cookies.remove(AUTH_KEY, {
path: "/"
});
}
}
const checkResponseError = (res) => {
if (res && res.data && res.data.error) {
console.error(res.data.error);
throw new Error(res.data.error.message);
}
}
/**
* @description wrapper for making ajax requests
* @param {object} object with method,url,data etc.
*/
export const request = function(options) {
const onSuccess = function(response) {
checkResponseError(response);
return response.data.response;
};
const onError = function(error) {
console.error("Request Failed:", error.config);
if (error.response) {
console.error("Status:", error.response.status);
console.error("Data:", error.response.data);
console.error("Headers:", error.response.headers);
} else {
console.error("Error Message:", error.message);
}
return Promise.reject(error.response || error.message);
};
return client(options)
.then(onSuccess)
.catch(onError);
};

View File

@ -0,0 +1,4 @@
import Filter from "./people/filter";
import * as People from './people';
export default { Filter, People };

View File

@ -0,0 +1,142 @@
import { toUrlParams } from "../../../../utils/converter";
const DEFAULT_PAGE = 0;
const DEFAULT_PAGE_COUNT = 25;
const DEFAULT_TOTAL = 0;
const DEFAULT_SORT_BY = "firstname";
const DEFAULT_SORT_ORDER = "ascending";
const DEFAULT_EMPLOYEE_STATUS = null;
const DEFAULT_ACTIVATION_STATUS = null;
const DEFAULT_ROLE = null;
const DEFAULT_SEARCH = null;
const DEFAULT_GROUP = null;
class Filter {
static getDefault(total = DEFAULT_TOTAL) {
return new Filter(DEFAULT_PAGE, DEFAULT_PAGE_COUNT, total);
}
constructor(
page = DEFAULT_PAGE,
pageCount = DEFAULT_PAGE_COUNT,
total = DEFAULT_TOTAL,
sortBy = DEFAULT_SORT_BY,
sortOrder = DEFAULT_SORT_ORDER,
employeeStatus = DEFAULT_EMPLOYEE_STATUS,
activationStatus = DEFAULT_ACTIVATION_STATUS,
role = DEFAULT_ROLE,
search = DEFAULT_SEARCH,
group = DEFAULT_GROUP
) {
this.page = page;
this.pageCount = pageCount;
this.sortBy = sortBy;
this.sortOrder = sortOrder;
this.employeeStatus = employeeStatus;
this.activationStatus = activationStatus;
this.role = role;
this.search = search;
this.total = total;
this.group = group;
}
getStartIndex = () => {
return this.page * this.pageCount;
};
hasNext = () => {
return this.total - this.getStartIndex() > this.pageCount;
};
hasPrev = () => {
return this.page > 0;
};
toDto = () => {
const {
pageCount,
sortBy,
sortOrder,
employeeStatus,
activationStatus,
role,
search,
group
} = this;
let dtoFilter = {
StartIndex: this.getStartIndex(),
Count: pageCount,
sortby: sortBy,
sortorder: sortOrder,
employeestatus: employeeStatus,
activationstatus: activationStatus,
filtervalue: search,
groupId: group
//fields: "id,status,isAdmin,isOwner,isVisitor,activationStatus,userName,email,displayName,avatarSmall,
//listAdminModules,birthday,title,location,isLDAP,isSSO"
};
switch (role) {
case "admin":
dtoFilter.isadministrator = true;
break;
case "user":
dtoFilter.employeeType = 1;
break;
case "guest":
dtoFilter.employeeType = 2;
break;
default:
break;
}
return dtoFilter;
};
toUrlParams = () => {
const dtoFilter = this.toDto();
const str = toUrlParams(dtoFilter, true);
return str;
};
clone(onlySorting) {
return onlySorting
? new Filter(
DEFAULT_PAGE,
DEFAULT_PAGE_COUNT,
DEFAULT_TOTAL,
this.sortBy,
this.sortOrder
)
: new Filter(
this.page,
this.pageCount,
this.total,
this.sortBy,
this.sortOrder,
this.employeeStatus,
this.activationStatus,
this.role,
this.search,
this.group
);
}
equals(filter) {
const equals =
this.employeeStatus === filter.employeeStatus &&
this.activationStatus === filter.activationStatus &&
this.role === filter.role &&
this.group === filter.group &&
this.search === filter.search &&
this.sortBy === filter.sortBy &&
this.sortOrder === filter.sortOrder &&
this.page === filter.page &&
this.pageCount === filter.pageCount;
return equals;
}
}
export default Filter;

View File

@ -0,0 +1,16 @@
import { request } from "../client";
//import axios from "axios";
import Filter from "./filter";
export function getUserList(filter = Filter.getDefault()) {
const params =
filter && filter instanceof Filter
? `/filter.json?${filter.toUrlParams()}`
: "";
return request({
method: "get",
url: `/people${params}`
});
}

View File

@ -0,0 +1,14 @@
export const toUrlParams = (obj, skipNull) => {
let str = "";
for (var key in obj) {
if (skipNull && !obj[key]) continue;
if (str !== "") {
str += "&";
}
str += key + "=" + encodeURIComponent(obj[key]);
}
return str;
};

View File

@ -0,0 +1,17 @@
const path = require('path');
module.exports = function replaceImport(originalPath, callingFileName) {
// This replacement rewrites imports of ui-kit to an import using a relative
// path pointing at the root folder.
// This allows to import from the bundled ui-kit using
// import { PrimaryButton } from 'ui-kit'
// instead of
// import { PrimaryButton } from '../../..'
if (originalPath === 'ui-kit' && callingFileName.endsWith('.bundlespec.js')) {
const fromPath = path.dirname(callingFileName);
const toPath = process.cwd();
const relativePath = path.relative(fromPath, toPath);
return relativePath;
}
return originalPath;
};

View File

@ -0,0 +1,76 @@
import fs from 'fs';
import path from 'path';
import colors from 'colors/safe';
const shouldSilenceWarnings = (...messages) =>
[/Warning: componentWillReceiveProps has been renamed/].some(msgRegex =>
messages.some(msg => msgRegex.test(msg))
);
global.window.app = {
mcApiUrl: 'http://localhost:8080',
};
// setup file
const logOrThrow = (log, method, messages) => {
const warning = `console.${method} calls not allowed in tests`;
if (process.env.CI) {
if (shouldSilenceWarnings(messages)) {
return;
}
log(warning, '\n', ...messages);
throw new Error(warning);
} else {
log(colors.bgYellow.black(' WARN '), warning, '\n', ...messages);
}
};
// eslint-disable-next-line no-console
const logMessage = console.log;
global.console.log = (...messages) => {
logOrThrow(logMessage, 'log', messages);
};
// eslint-disable-next-line no-console
const logInfo = console.info;
global.console.info = (...messages) => {
logOrThrow(logInfo, 'info', messages);
};
// eslint-disable-next-line no-console
const logWarning = console.warn;
global.console.warn = (...messages) => {
logOrThrow(logWarning, 'warn', messages);
};
// eslint-disable-next-line no-console
const logError = console.error;
global.console.error = (...messages) => {
logOrThrow(logError, 'error', messages);
};
// Avoid unhandled promise rejections from going unnoticed
// https://github.com/facebook/jest/issues/3251#issuecomment-299183885
// In Node v7 unhandled promise rejections will terminate the process
if (!process.env.LISTENING_TO_UNHANDLED_REJECTION) {
process.on('unhandledRejection', reason => {
logMessage('UNHANDLED REJECTION', reason);
// We create a file in case there is an unhandled rejection
// We later check for the existence of this file to fail CI
if (process.env.CI && !process.env.HAS_CREATED_UNHANDLED_REJECTION_FILE) {
const rootPath = process.cwd();
fs.writeFileSync(
path.join(
rootPath,
'./fail-tests-because-there-was-an-unhandled-rejection.lock'
),
''
);
process.env.HAS_CREATED_UNHANDLED_REJECTION_FILE = true;
}
});
// Avoid memory leak by adding too many listeners
process.env.LISTENING_TO_UNHANDLED_REJECTION = true;
}

View File

@ -0,0 +1,15 @@
const babelPresetJest = require('babel-preset-jest');
const getBabelPreset = require('../scripts/get-babel-preset');
const babelOptions = getBabelPreset();
const jestBabelConfig = {
...babelOptions,
plugins: [
...babelOptions.plugins,
...babelPresetJest().plugins/*,
['module-rewrite', { replaceFunc: './test/replace-module-paths.js' }],*/
],
};
module.exports = require('babel-jest').createTransformer(jestBabelConfig);

View File

@ -0,0 +1 @@
module.exports = 'test-file-stub';