mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ui-library.git
				synced 2025-11-03 20:28:08 +00:00 
			
		
		
		
	init
This commit is contained in:
		
							
								
								
									
										29
									
								
								.babelrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								.babelrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "presets": [
 | 
				
			||||||
 | 
					    [
 | 
				
			||||||
 | 
					      "@babel/preset-env",
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "modules": false
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "@babel/preset-react"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "plugins": [
 | 
				
			||||||
 | 
					    "@babel/plugin-proposal-class-properties",
 | 
				
			||||||
 | 
					    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": true }] // `style: true` for less
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "env": {
 | 
				
			||||||
 | 
					    "production": {
 | 
				
			||||||
 | 
					      "only": ["app"],
 | 
				
			||||||
 | 
					      "plugins": [
 | 
				
			||||||
 | 
					        "lodash",
 | 
				
			||||||
 | 
					        "transform-react-remove-prop-types",
 | 
				
			||||||
 | 
					        "@babel/plugin-transform-react-inline-elements",
 | 
				
			||||||
 | 
					        "@babel/plugin-transform-react-constant-elements"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "test": {
 | 
				
			||||||
 | 
					      "plugins": ["@babel/plugin-transform-modules-commonjs", "dynamic-import-node"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					# http://editorconfig.org
 | 
				
			||||||
 | 
					root = true
 | 
				
			||||||
 | 
					[*]
 | 
				
			||||||
 | 
					charset = utf-8
 | 
				
			||||||
 | 
					end_of_line = lf
 | 
				
			||||||
 | 
					indent_size = 2
 | 
				
			||||||
 | 
					indent_style = space
 | 
				
			||||||
 | 
					insert_final_newline = true
 | 
				
			||||||
 | 
					max_line_length = 100
 | 
				
			||||||
 | 
					trim_trailing_whitespace = true
 | 
				
			||||||
 | 
					[*.md]
 | 
				
			||||||
 | 
					max_line_length = 0
 | 
				
			||||||
 | 
					trim_trailing_whitespace = false
 | 
				
			||||||
 | 
					[{Makefile,**.mk}]
 | 
				
			||||||
 | 
					# Use tabs for indentation (Makefiles require tabs)
 | 
				
			||||||
 | 
					indent_style = tab
 | 
				
			||||||
 | 
					[*.scss]
 | 
				
			||||||
 | 
					indent_size = 2
 | 
				
			||||||
 | 
					indent_style = space
 | 
				
			||||||
							
								
								
									
										40
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.eslintrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "extends": ["airbnb", "prettier", "prettier/react"],
 | 
				
			||||||
 | 
					  "plugins": ["prettier"],
 | 
				
			||||||
 | 
					  "rules": {
 | 
				
			||||||
 | 
					    "react/jsx-filename-extension": [
 | 
				
			||||||
 | 
					      1,
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "extensions": [".js", ".jsx"]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "react/prop-types": 0,
 | 
				
			||||||
 | 
					    "no-underscore-dangle": 0,
 | 
				
			||||||
 | 
					    "import/imports-first": ["error", "absolute-first"],
 | 
				
			||||||
 | 
					    "import/newline-after-import": "error",
 | 
				
			||||||
 | 
					    "import/prefer-default-export": 0,
 | 
				
			||||||
 | 
					    "react/jsx-props-no-spreading": 0,
 | 
				
			||||||
 | 
					    "semi": "error"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "globals": {
 | 
				
			||||||
 | 
					    "window": true,
 | 
				
			||||||
 | 
					    "document": true,
 | 
				
			||||||
 | 
					    "localStorage": true,
 | 
				
			||||||
 | 
					    "FormData": true,
 | 
				
			||||||
 | 
					    "FileReader": true,
 | 
				
			||||||
 | 
					    "Blob": true,
 | 
				
			||||||
 | 
					    "navigator": true,
 | 
				
			||||||
 | 
					    "Headers": true,
 | 
				
			||||||
 | 
					    "Request": true,
 | 
				
			||||||
 | 
					    "fetch": true
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "parser": "babel-eslint",
 | 
				
			||||||
 | 
					  "settings": {
 | 
				
			||||||
 | 
					    "import/resolver": {
 | 
				
			||||||
 | 
					      "node": {
 | 
				
			||||||
 | 
					        "extensions": [".js", ".jsx", ".ts", ".tsx"],
 | 
				
			||||||
 | 
					        "moduleDirectory": ["node_modules", "app"]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dependencies
 | 
				
			||||||
 | 
					/node_modules
 | 
				
			||||||
 | 
					/.pnp
 | 
				
			||||||
 | 
					.pnp.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# testing
 | 
				
			||||||
 | 
					/coverage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# production
 | 
				
			||||||
 | 
					/dist
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# misc
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					.env.local
 | 
				
			||||||
 | 
					.env.development.local
 | 
				
			||||||
 | 
					.env.test.local
 | 
				
			||||||
 | 
					.env.production.local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					npm-debug.log*
 | 
				
			||||||
 | 
					yarn-debug.log*
 | 
				
			||||||
 | 
					yarn-error.log*
 | 
				
			||||||
							
								
								
									
										4
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.prettierrc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "singleQuote": true,
 | 
				
			||||||
 | 
					  "trailingComma": "es5"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										49
									
								
								app/components/GlobalHeader/GlobalHeader.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/components/GlobalHeader/GlobalHeader.module.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					@import 'styles/variables';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.GlobalHeader {
 | 
				
			||||||
 | 
					  height: $header-height;
 | 
				
			||||||
 | 
					  left: $sidebar-width;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  position: fixed;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  right: 0;
 | 
				
			||||||
 | 
					  z-index: 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.collapsed {
 | 
				
			||||||
 | 
					    left: $sidebar-collapsed-width;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  &.mobile {
 | 
				
			||||||
 | 
					    left: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  :global(.ant-row) {
 | 
				
			||||||
 | 
					    margin-bottom: 10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &:last-child {
 | 
				
			||||||
 | 
					      margin-bottom: 0px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.LogoContainer {
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  align-items: center;
 | 
				
			||||||
 | 
					  padding: 0 0 0 24px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  img {
 | 
				
			||||||
 | 
					    border-radius: 5px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.MenuIcon {
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					  font-size: 18px;
 | 
				
			||||||
 | 
					  line-height: 64px;
 | 
				
			||||||
 | 
					  padding: 0 24px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.RightMenu {
 | 
				
			||||||
 | 
					  margin-left: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								app/components/GlobalHeader/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								app/components/GlobalHeader/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					import React, { useState } from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
 | 
					import { Layout, Popover, Row } from 'antd';
 | 
				
			||||||
 | 
					import { MenuUnfoldOutlined, MenuFoldOutlined, SettingOutlined } from '@ant-design/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import styles from './GlobalHeader.module.scss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { Header } = Layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const GlobalHeader = ({ collapsed, onMenuButtonClick, isMobile, logoMobile }) => {
 | 
				
			||||||
 | 
					  const [popoverVisible, setPopoverVisible] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const hidePopover = () => {
 | 
				
			||||||
 | 
					    setPopoverVisible(false);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleVisibleChange = visible => {
 | 
				
			||||||
 | 
					    setPopoverVisible(visible);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const userOptions = (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <Row>
 | 
				
			||||||
 | 
					        <Link onClick={hidePopover} to="/accounts/customers/view">
 | 
				
			||||||
 | 
					          Profile
 | 
				
			||||||
 | 
					        </Link>
 | 
				
			||||||
 | 
					      </Row>
 | 
				
			||||||
 | 
					      <Row>
 | 
				
			||||||
 | 
					        <Link onClick={hidePopover} to="/account">
 | 
				
			||||||
 | 
					          Users
 | 
				
			||||||
 | 
					        </Link>
 | 
				
			||||||
 | 
					      </Row>
 | 
				
			||||||
 | 
					      <Row>
 | 
				
			||||||
 | 
					        <Link onClick={hidePopover} to="/accounts">
 | 
				
			||||||
 | 
					          Advanced
 | 
				
			||||||
 | 
					        </Link>
 | 
				
			||||||
 | 
					      </Row>
 | 
				
			||||||
 | 
					      <Row>
 | 
				
			||||||
 | 
					        <Link onClick={hidePopover} to="/accounts/customersxw">
 | 
				
			||||||
 | 
					          Rules Preference
 | 
				
			||||||
 | 
					        </Link>
 | 
				
			||||||
 | 
					      </Row>
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Header
 | 
				
			||||||
 | 
					      className={`${styles.GlobalHeader} ${collapsed ? styles.collapsed : ''} ${
 | 
				
			||||||
 | 
					        isMobile ? styles.mobile : ''
 | 
				
			||||||
 | 
					      }`}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {isMobile && [
 | 
				
			||||||
 | 
					        <Link className={styles.LogoContainer} to="/" key="mobileLogo">
 | 
				
			||||||
 | 
					          <img src={logoMobile} alt="logo" width="32" />
 | 
				
			||||||
 | 
					        </Link>,
 | 
				
			||||||
 | 
					      ]}
 | 
				
			||||||
 | 
					      {collapsed ? (
 | 
				
			||||||
 | 
					        <MenuUnfoldOutlined className={styles.MenuIcon} onClick={onMenuButtonClick} />
 | 
				
			||||||
 | 
					      ) : (
 | 
				
			||||||
 | 
					        <MenuFoldOutlined className={styles.MenuIcon} onClick={onMenuButtonClick} />
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					      <div className={styles.RightMenu}>
 | 
				
			||||||
 | 
					        <Popover
 | 
				
			||||||
 | 
					          content={userOptions}
 | 
				
			||||||
 | 
					          trigger="click"
 | 
				
			||||||
 | 
					          getPopupContainer={e => e.parentElement}
 | 
				
			||||||
 | 
					          visible={popoverVisible}
 | 
				
			||||||
 | 
					          onVisibleChange={handleVisibleChange}
 | 
				
			||||||
 | 
					          placement="bottomRight"
 | 
				
			||||||
 | 
					          arrowPointAtCenter
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <SettingOutlined className={styles.MenuIcon} />
 | 
				
			||||||
 | 
					        </Popover>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </Header>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GlobalHeader.propTypes = {
 | 
				
			||||||
 | 
					  collapsed: PropTypes.bool.isRequired,
 | 
				
			||||||
 | 
					  onMenuButtonClick: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					  isMobile: PropTypes.bool.isRequired,
 | 
				
			||||||
 | 
					  logoMobile: PropTypes.string.isRequired
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default GlobalHeader;
 | 
				
			||||||
							
								
								
									
										37
									
								
								app/components/SideMenu/Sider.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/components/SideMenu/Sider.module.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					@import 'styles/variables';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Sider {
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  left: 0;
 | 
				
			||||||
 | 
					  position: fixed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.Mobile {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.collapsed {
 | 
				
			||||||
 | 
					    .Logo {
 | 
				
			||||||
 | 
					      width: 32px;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .TopArea {
 | 
				
			||||||
 | 
					    height: $header-height;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .LogoContainer {
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .Logo {
 | 
				
			||||||
 | 
					    width: 200px;
 | 
				
			||||||
 | 
					    border-radius: 5px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .MenuIcon {
 | 
				
			||||||
 | 
					    margin-right: 10px!important;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										271
									
								
								app/components/SideMenu/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								app/components/SideMenu/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,271 @@
 | 
				
			|||||||
 | 
					import React, { useState, useEffect } from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import { Link } from 'react-router-dom';
 | 
				
			||||||
 | 
					import { Layout, Menu, Drawer } from 'antd';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  DashboardOutlined,
 | 
				
			||||||
 | 
					  ProfileOutlined,
 | 
				
			||||||
 | 
					  AreaChartOutlined,
 | 
				
			||||||
 | 
					  MobileOutlined,
 | 
				
			||||||
 | 
					  ApiOutlined,
 | 
				
			||||||
 | 
					  NotificationOutlined,
 | 
				
			||||||
 | 
					  CheckCircleOutlined,
 | 
				
			||||||
 | 
					  SettingOutlined,
 | 
				
			||||||
 | 
					  TeamOutlined,
 | 
				
			||||||
 | 
					  LogoutOutlined,
 | 
				
			||||||
 | 
					} from '@ant-design/icons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import styles from './Sider.module.scss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { Sider } = Layout;
 | 
				
			||||||
 | 
					const { SubMenu, Item } = Menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ACCOUNTS = 'accounts';
 | 
				
			||||||
 | 
					const NETWORK = 'network';
 | 
				
			||||||
 | 
					const CONFIGURATION = 'configuration';
 | 
				
			||||||
 | 
					const INSIGHTS = 'insights';
 | 
				
			||||||
 | 
					const SYSTEM = 'system';
 | 
				
			||||||
 | 
					const HISTORY = 'history';
 | 
				
			||||||
 | 
					const rootSubmenuKeys = [ACCOUNTS, NETWORK, CONFIGURATION, INSIGHTS, SYSTEM, HISTORY];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SideMenu = ({
 | 
				
			||||||
 | 
					  locationState,
 | 
				
			||||||
 | 
					  collapsed,
 | 
				
			||||||
 | 
					  isMobile,
 | 
				
			||||||
 | 
					  logo,
 | 
				
			||||||
 | 
					  logoMobile,
 | 
				
			||||||
 | 
					  onMenuButtonClick,
 | 
				
			||||||
 | 
					  onMenuItemClick,
 | 
				
			||||||
 | 
					  onLogout,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
 | 
					  const [openKeys, setOpenKeys] = useState([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    setOpenKeys([]);
 | 
				
			||||||
 | 
					  }, [collapsed]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const enocMenuItems = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'dashboard',
 | 
				
			||||||
 | 
					      icon: <DashboardOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/',
 | 
				
			||||||
 | 
					      text: 'Dashboard',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'profiles',
 | 
				
			||||||
 | 
					      icon: <ProfileOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/profiles',
 | 
				
			||||||
 | 
					      text: 'Profiles',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'reports',
 | 
				
			||||||
 | 
					      icon: <AreaChartOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/analytics/qoe',
 | 
				
			||||||
 | 
					      text: 'Insights',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'client-devices',
 | 
				
			||||||
 | 
					      icon: <MobileOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/network/client-devices',
 | 
				
			||||||
 | 
					      text: 'Client Devices',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'network-elements',
 | 
				
			||||||
 | 
					      icon: <ApiOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/network/elements',
 | 
				
			||||||
 | 
					      text: 'Network Elements',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'alarms',
 | 
				
			||||||
 | 
					      icon: <NotificationOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/network/alarms',
 | 
				
			||||||
 | 
					      text: 'Alarms',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'recommendations',
 | 
				
			||||||
 | 
					      icon: <CheckCircleOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/recommendations',
 | 
				
			||||||
 | 
					      text: 'Recommendations',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'settings',
 | 
				
			||||||
 | 
					      icon: <SettingOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/settings',
 | 
				
			||||||
 | 
					      text: 'Settings',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: ACCOUNTS,
 | 
				
			||||||
 | 
					      icon: <TeamOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      text: 'Customers',
 | 
				
			||||||
 | 
					      path: '/accounts/customers',
 | 
				
			||||||
 | 
					      onClick: onMenuItemClick,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const commonMenuItems = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      key: 'logout',
 | 
				
			||||||
 | 
					      icon: <LogoutOutlined className={styles.MenuIcon} />,
 | 
				
			||||||
 | 
					      path: '/signout',
 | 
				
			||||||
 | 
					      text: 'Sign Out',
 | 
				
			||||||
 | 
					      onClick: onLogout,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onOpenChange = keys => {
 | 
				
			||||||
 | 
					    const latestOpenKey = keys.find(key => !openKeys.includes(key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
 | 
				
			||||||
 | 
					      setOpenKeys(keys);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const getMenu = (config = { items: [] }, defaultSelectedKeys = []) => {
 | 
				
			||||||
 | 
					    const items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let keys = [];
 | 
				
			||||||
 | 
					    let selectedKeys = [...defaultSelectedKeys];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    config.items.forEach(item => {
 | 
				
			||||||
 | 
					      if (item && item.key) {
 | 
				
			||||||
 | 
					        if (item.children) {
 | 
				
			||||||
 | 
					          const subMenu = getMenu({ items: item.children, parent: item });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (subMenu.selectedKeys && subMenu.selectedKeys.length) {
 | 
				
			||||||
 | 
					            selectedKeys = [...selectedKeys, ...subMenu.selectedKeys];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          if (subMenu.openKeys && subMenu.openKeys.length) {
 | 
				
			||||||
 | 
					            keys = [...keys, ...subMenu.openKeys];
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          items.push(
 | 
				
			||||||
 | 
					            <SubMenu
 | 
				
			||||||
 | 
					              key={item.key}
 | 
				
			||||||
 | 
					              title={
 | 
				
			||||||
 | 
					                <span>
 | 
				
			||||||
 | 
					                  {item.icon}
 | 
				
			||||||
 | 
					                  <span>{item.text}</span>
 | 
				
			||||||
 | 
					                </span>
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            >
 | 
				
			||||||
 | 
					              {subMenu.items}
 | 
				
			||||||
 | 
					            </SubMenu>
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          const ItemComponent = item.Component || Item;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          let LinkComponent = ({ ...restP }) => (
 | 
				
			||||||
 | 
					            <Link
 | 
				
			||||||
 | 
					              // preserveParams={this.getPreservedParams(item.path, locationState)}
 | 
				
			||||||
 | 
					              {...restP}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (item.LinkComponent) {
 | 
				
			||||||
 | 
					            LinkComponent = item.LinkComponent;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const path = locationState.pathname;
 | 
				
			||||||
 | 
					          const pathAndHash = `${path}${locationState.hash}`; // for hash routing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (path.startsWith(item.path) || pathAndHash.startsWith(item.path)) {
 | 
				
			||||||
 | 
					            if (config.parent) {
 | 
				
			||||||
 | 
					              keys.push(config.parent.key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            selectedKeys.push(item.key.toString());
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          items.push(
 | 
				
			||||||
 | 
					            <ItemComponent key={item.key} className="ant-menu-item">
 | 
				
			||||||
 | 
					              <LinkComponent onClick={item.onClick} to={item.path}>
 | 
				
			||||||
 | 
					                {item.icon}
 | 
				
			||||||
 | 
					                <span>{item.text}</span>
 | 
				
			||||||
 | 
					              </LinkComponent>
 | 
				
			||||||
 | 
					            </ItemComponent>
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      items,
 | 
				
			||||||
 | 
					      selectedKeys,
 | 
				
			||||||
 | 
					      keys,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const menuConfig = {
 | 
				
			||||||
 | 
					    items: [...enocMenuItems, ...commonMenuItems],
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const menu = getMenu(menuConfig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const sider = (
 | 
				
			||||||
 | 
					    <Sider
 | 
				
			||||||
 | 
					      collapsed={isMobile ? false : collapsed}
 | 
				
			||||||
 | 
					      width="234px"
 | 
				
			||||||
 | 
					      collapsedWidth="80px"
 | 
				
			||||||
 | 
					      breakpoint="lg"
 | 
				
			||||||
 | 
					      className={`${styles.Sider} ${collapsed ? styles.collapsed : ''}  ${
 | 
				
			||||||
 | 
					        isMobile ? styles.Mobile : ''
 | 
				
			||||||
 | 
					      }`}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <div className={styles.TopArea}>
 | 
				
			||||||
 | 
					        <Link className={styles.LogoContainer} to="/">
 | 
				
			||||||
 | 
					          <img className={styles.Logo} alt="ConnectUs" src={collapsed ? logoMobile : logo} />
 | 
				
			||||||
 | 
					        </Link>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <Menu
 | 
				
			||||||
 | 
					        className="sidemenu"
 | 
				
			||||||
 | 
					        selectedKeys={menu.selectedKeys}
 | 
				
			||||||
 | 
					        defaultOpenKeys={menu.openKeys}
 | 
				
			||||||
 | 
					        onOpenChange={onOpenChange}
 | 
				
			||||||
 | 
					        mode="inline"
 | 
				
			||||||
 | 
					        theme="dark"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {menu.items}
 | 
				
			||||||
 | 
					      </Menu>
 | 
				
			||||||
 | 
					    </Sider>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (isMobile) {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <Drawer
 | 
				
			||||||
 | 
					        zIndex={9999}
 | 
				
			||||||
 | 
					        placement="left"
 | 
				
			||||||
 | 
					        closable={false}
 | 
				
			||||||
 | 
					        visible={!collapsed}
 | 
				
			||||||
 | 
					        onClose={onMenuButtonClick}
 | 
				
			||||||
 | 
					        bodyStyle={{ padding: 0 }}
 | 
				
			||||||
 | 
					        width={256}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        {sider}
 | 
				
			||||||
 | 
					      </Drawer>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return sider;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SideMenu.propTypes = {
 | 
				
			||||||
 | 
					  locationState: PropTypes.instanceOf(Object).isRequired,
 | 
				
			||||||
 | 
					  collapsed: PropTypes.bool.isRequired,
 | 
				
			||||||
 | 
					  isMobile: PropTypes.bool.isRequired,
 | 
				
			||||||
 | 
					  logo: PropTypes.string.isRequired,
 | 
				
			||||||
 | 
					  logoMobile: PropTypes.string.isRequired,
 | 
				
			||||||
 | 
					  onMenuButtonClick: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					  onMenuItemClick: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					  onLogout: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default SideMenu;
 | 
				
			||||||
							
								
								
									
										5
									
								
								app/containers/Dashboard/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app/containers/Dashboard/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Dashboard = () => <h1>Dashboard</h1>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Dashboard;
 | 
				
			||||||
							
								
								
									
										22
									
								
								app/containers/MasterLayout/MasterLayout.module.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/containers/MasterLayout/MasterLayout.module.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					@import 'styles/variables';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.MainLayout {
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  margin-left: $sidebar-width;
 | 
				
			||||||
 | 
					  overflow: auto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.collapsed {
 | 
				
			||||||
 | 
					    margin-left: $sidebar-collapsed-width;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  &.mobile {
 | 
				
			||||||
 | 
					    margin-left: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Content {
 | 
				
			||||||
 | 
					  margin-top: $header-height;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Footer {
 | 
				
			||||||
 | 
					  text-align: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										103
									
								
								app/containers/MasterLayout/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								app/containers/MasterLayout/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					import React, { useState, useEffect } from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
 | 
					import { Layout } from 'antd';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import GlobalHeader from 'components/GlobalHeader';
 | 
				
			||||||
 | 
					import SideMenu from 'components/SideMenu';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import styles from './MasterLayout.module.scss';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { Content, Footer } = Layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const MasterLayout = ({ children, logo, logoMobile, locationState, onLogout }) => {
 | 
				
			||||||
 | 
					  const [isCollapsed, setIsCollapsed] = useState(false);
 | 
				
			||||||
 | 
					  const [isMobile, setIsMobile] = useState(false);
 | 
				
			||||||
 | 
					  const [screenSize, setScreenSize] = useState('lg');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const currentYear = new Date().getFullYear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleResize = () => {
 | 
				
			||||||
 | 
					    const width = window.innerWidth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (width < 768 && screenSize !== 'sm') {
 | 
				
			||||||
 | 
					      setIsCollapsed(true);
 | 
				
			||||||
 | 
					      setIsMobile(true);
 | 
				
			||||||
 | 
					      setScreenSize('sm');
 | 
				
			||||||
 | 
					    } else if (width >= 768 && width < 992 && screenSize !== 'md') {
 | 
				
			||||||
 | 
					      setIsCollapsed(true);
 | 
				
			||||||
 | 
					      setIsMobile(false);
 | 
				
			||||||
 | 
					      setScreenSize('md');
 | 
				
			||||||
 | 
					    } else if (width >= 992 && screenSize !== 'lg') {
 | 
				
			||||||
 | 
					      setIsCollapsed(false);
 | 
				
			||||||
 | 
					      setIsMobile(false);
 | 
				
			||||||
 | 
					      setScreenSize('lg');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleMenuToggle = () => {
 | 
				
			||||||
 | 
					    setIsCollapsed(!isCollapsed);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleMenuItemClick = () => {
 | 
				
			||||||
 | 
					    if (isMobile === true) {
 | 
				
			||||||
 | 
					      setIsCollapsed(true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleLogout = () => {
 | 
				
			||||||
 | 
					    onLogout();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    handleResize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    window.addEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					    return () => window.removeEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    window.addEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					    return () => window.removeEventListener('resize', handleResize);
 | 
				
			||||||
 | 
					  }, [screenSize]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Layout>
 | 
				
			||||||
 | 
					      <SideMenu
 | 
				
			||||||
 | 
					        locationState={locationState}
 | 
				
			||||||
 | 
					        collapsed={isCollapsed}
 | 
				
			||||||
 | 
					        isMobile={isMobile}
 | 
				
			||||||
 | 
					        logo={logo}
 | 
				
			||||||
 | 
					        logoMobile={logoMobile}
 | 
				
			||||||
 | 
					        onMenuButtonClick={handleMenuToggle}
 | 
				
			||||||
 | 
					        onMenuItemClick={handleMenuItemClick}
 | 
				
			||||||
 | 
					        onLogout={handleLogout}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					      <Layout
 | 
				
			||||||
 | 
					        className={`${styles.MainLayout} ${isCollapsed ? styles.collapsed : ''} ${
 | 
				
			||||||
 | 
					          isMobile ? styles.mobile : ''
 | 
				
			||||||
 | 
					        }`}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <GlobalHeader
 | 
				
			||||||
 | 
					          collapsed={isCollapsed}
 | 
				
			||||||
 | 
					          isMobile={isMobile}
 | 
				
			||||||
 | 
					          logoMobile={logoMobile}
 | 
				
			||||||
 | 
					          onMenuButtonClick={handleMenuToggle}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					        <Content className={styles.Content}>{children}</Content>
 | 
				
			||||||
 | 
					        <Footer className={styles.Footer}>
 | 
				
			||||||
 | 
					          Copyright © {currentYear} ConnectUs Inc. All Rights Reserved.
 | 
				
			||||||
 | 
					        </Footer>
 | 
				
			||||||
 | 
					      </Layout>
 | 
				
			||||||
 | 
					    </Layout>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MasterLayout.propTypes = {
 | 
				
			||||||
 | 
					  children: PropTypes.node.isRequired,
 | 
				
			||||||
 | 
					  logo: PropTypes.string.isRequired,
 | 
				
			||||||
 | 
					  logoMobile: PropTypes.string.isRequired,
 | 
				
			||||||
 | 
					  onLogout: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					  locationState: PropTypes.instanceOf(Object).isRequired,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default MasterLayout;
 | 
				
			||||||
							
								
								
									
										3
									
								
								app/styles/index.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/styles/index.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					body {
 | 
				
			||||||
 | 
					  font-family: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								app/styles/variables.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								app/styles/variables.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					$sidebar-width: 234px;
 | 
				
			||||||
 | 
					$sidebar-collapsed-width: 80px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$header-height: 64px;
 | 
				
			||||||
							
								
								
									
										31
									
								
								jest.config.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								jest.config.js
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  collectCoverageFrom: [
 | 
				
			||||||
 | 
					    'app/**/*.{js,jsx}',
 | 
				
			||||||
 | 
					    '!app/**/*.test.{js,jsx}',
 | 
				
			||||||
 | 
					    '!app/*/RbGenerated*/*.{js,jsx}',
 | 
				
			||||||
 | 
					    '!app/app.js',
 | 
				
			||||||
 | 
					    '!app/global-styles.js',
 | 
				
			||||||
 | 
					    '!app/*/*/Loadable.{js,jsx}',
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  coverageThreshold: {
 | 
				
			||||||
 | 
					    global: {
 | 
				
			||||||
 | 
					      statements: 98,
 | 
				
			||||||
 | 
					      branches: 91,
 | 
				
			||||||
 | 
					      functions: 98,
 | 
				
			||||||
 | 
					      lines: 98,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  moduleDirectories: ['node_modules', 'app'],
 | 
				
			||||||
 | 
					  moduleNameMapper: {
 | 
				
			||||||
 | 
					    '.*\\.(css|less|styl|scss|sass)$': '<rootDir>/internals/mocks/cssModule.js',
 | 
				
			||||||
 | 
					    '.*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
 | 
				
			||||||
 | 
					      '<rootDir>/internals/mocks/image.js',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  setupFilesAfterEnv: [
 | 
				
			||||||
 | 
					    '<rootDir>/internals/testing/test-bundler.js',
 | 
				
			||||||
 | 
					    'react-testing-library/cleanup-after-each',
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  setupFiles: ['raf/polyfill'],
 | 
				
			||||||
 | 
					  testRegex: 'tests/.*\\.test\\.js$',
 | 
				
			||||||
 | 
					  snapshotSerializers: [],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										11
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								jsconfig.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "compilerOptions": {
 | 
				
			||||||
 | 
					    "target": "ES6",
 | 
				
			||||||
 | 
					    "module": "commonjs",
 | 
				
			||||||
 | 
					    "allowSyntheticDefaultImports": true,
 | 
				
			||||||
 | 
					    "baseUrl": "./",
 | 
				
			||||||
 | 
					    "paths": {
 | 
				
			||||||
 | 
					      "~/*": ["./app/*"]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13625
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13625
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										80
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "cu-ui",
 | 
				
			||||||
 | 
					  "version": "0.1.0",
 | 
				
			||||||
 | 
					  "author": "ConnectUs",
 | 
				
			||||||
 | 
					  "description": "",
 | 
				
			||||||
 | 
					  "engines": {
 | 
				
			||||||
 | 
					    "npm": ">=5",
 | 
				
			||||||
 | 
					    "node": ">=8"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "scripts": {
 | 
				
			||||||
 | 
					    "format": "prettier --write \"app/**/*.js\"",
 | 
				
			||||||
 | 
					    "eslint-fix": "eslint --fix \"app/**/*.js\"",
 | 
				
			||||||
 | 
					    "build": "webpack --mode production"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "license": "MIT",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "@ant-design/icons": "^4.0.2",
 | 
				
			||||||
 | 
					    "antd": "^4.0.2",
 | 
				
			||||||
 | 
					    "clean-webpack-plugin": "^3.0.0",
 | 
				
			||||||
 | 
					    "connected-react-router": "^6.7.0",
 | 
				
			||||||
 | 
					    "history": "^4.10.1",
 | 
				
			||||||
 | 
					    "prop-types": "^15.7.2",
 | 
				
			||||||
 | 
					    "react": "^16.13.0",
 | 
				
			||||||
 | 
					    "react-dom": "^16.13.0",
 | 
				
			||||||
 | 
					    "react-router-dom": "^5.1.2"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "@babel/core": "^7.8.7",
 | 
				
			||||||
 | 
					    "@babel/plugin-proposal-class-properties": "^7.8.3",
 | 
				
			||||||
 | 
					    "@babel/preset-env": "^7.8.7",
 | 
				
			||||||
 | 
					    "@babel/preset-react": "^7.8.3",
 | 
				
			||||||
 | 
					    "babel-core": "^6.26.3",
 | 
				
			||||||
 | 
					    "babel-eslint": "^10.1.0",
 | 
				
			||||||
 | 
					    "babel-loader": "^8.0.6",
 | 
				
			||||||
 | 
					    "babel-plugin-root-import": "^6.4.1",
 | 
				
			||||||
 | 
					    "babel-polyfill": "^6.26.0",
 | 
				
			||||||
 | 
					    "css-loader": "^3.4.2",
 | 
				
			||||||
 | 
					    "eslint": "^6.8.0",
 | 
				
			||||||
 | 
					    "eslint-config-airbnb": "^18.0.1",
 | 
				
			||||||
 | 
					    "eslint-config-prettier": "^6.10.0",
 | 
				
			||||||
 | 
					    "eslint-config-react": "^1.1.7",
 | 
				
			||||||
 | 
					    "eslint-loader": "^3.0.3",
 | 
				
			||||||
 | 
					    "eslint-plugin-import": "^2.20.1",
 | 
				
			||||||
 | 
					    "eslint-plugin-jsx-a11y": "^6.2.3",
 | 
				
			||||||
 | 
					    "eslint-plugin-prettier": "^3.1.2",
 | 
				
			||||||
 | 
					    "eslint-plugin-react": "^7.19.0",
 | 
				
			||||||
 | 
					    "eslint-plugin-react-hooks": "^2.5.0",
 | 
				
			||||||
 | 
					    "husky": "^4.2.3",
 | 
				
			||||||
 | 
					    "less": "^3.11.1",
 | 
				
			||||||
 | 
					    "less-loader": "^5.0.0",
 | 
				
			||||||
 | 
					    "lint-staged": "^10.0.8",
 | 
				
			||||||
 | 
					    "node-sass": "^4.13.1",
 | 
				
			||||||
 | 
					    "prettier": "^1.19.1",
 | 
				
			||||||
 | 
					    "pretty-quick": "^2.0.1",
 | 
				
			||||||
 | 
					    "sass-loader": "^8.0.2",
 | 
				
			||||||
 | 
					    "style-loader": "^1.1.3",
 | 
				
			||||||
 | 
					    "uglifyjs-webpack-plugin": "^2.2.0",
 | 
				
			||||||
 | 
					    "webpack": "^4.42.0",
 | 
				
			||||||
 | 
					    "webpack-cli": "^3.3.11",
 | 
				
			||||||
 | 
					    "webpack-dev-server": "^3.10.3"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "precommit": "NODE_ENV=production lint-staged",
 | 
				
			||||||
 | 
					  "browserslist": [
 | 
				
			||||||
 | 
					    "last 2 versions",
 | 
				
			||||||
 | 
					    "> 1%",
 | 
				
			||||||
 | 
					    "IE 10"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "lint-staged": {
 | 
				
			||||||
 | 
					    "*.{js,jsx}": [
 | 
				
			||||||
 | 
					      "pretty-quick --staged",
 | 
				
			||||||
 | 
					      "eslint app/ --fix",
 | 
				
			||||||
 | 
					      "git add"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "husky": {
 | 
				
			||||||
 | 
					    "hooks": {
 | 
				
			||||||
 | 
					      "pre-commit": "lint-staged"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										80
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								webpack.config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					const path = require('path');
 | 
				
			||||||
 | 
					const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
 | 
				
			||||||
 | 
					const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					  mode: process.env.NODE_ENV,
 | 
				
			||||||
 | 
					  entry: ['babel-polyfill', './app/index.js'],
 | 
				
			||||||
 | 
					  output: {
 | 
				
			||||||
 | 
					    path: path.join(__dirname, 'dist'),
 | 
				
			||||||
 | 
					    publicPath: '/',
 | 
				
			||||||
 | 
					    filename: 'bundle.js',
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  devtool: 'inline-source-map',
 | 
				
			||||||
 | 
					  devServer: {
 | 
				
			||||||
 | 
					    port: 3000,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  module: {
 | 
				
			||||||
 | 
					    rules: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        test: /\.(js|jsx)$/,
 | 
				
			||||||
 | 
					        exclude: /node_modules/,
 | 
				
			||||||
 | 
					        use: ['babel-loader', 'eslint-loader'],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        // Preprocess 3rd party .css files located in node_modules
 | 
				
			||||||
 | 
					        test: /\.css$/,
 | 
				
			||||||
 | 
					        include: /node_modules/,
 | 
				
			||||||
 | 
					        use: ['style-loader', 'css-loader'],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        test: /\.less$/,
 | 
				
			||||||
 | 
					        use: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'style-loader',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'css-loader',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'less-loader',
 | 
				
			||||||
 | 
					            options: {
 | 
				
			||||||
 | 
					              javascriptEnabled: true,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        test: /\.(css|scss)$/,
 | 
				
			||||||
 | 
					        exclude: /node_modules/,
 | 
				
			||||||
 | 
					        use: [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'style-loader',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'css-loader',
 | 
				
			||||||
 | 
					            options: {
 | 
				
			||||||
 | 
					              modules: {
 | 
				
			||||||
 | 
					                localIdentName: '[name]__[local]___[hash:base64:5]',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              sourceMap: true,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            loader: 'sass-loader',
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  optimization: {
 | 
				
			||||||
 | 
					    minimizer: [new UglifyJsPlugin()],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  resolve: {
 | 
				
			||||||
 | 
					    modules: ['node_modules', path.resolve(`${__dirname}/app`)],
 | 
				
			||||||
 | 
					    alias: {
 | 
				
			||||||
 | 
					      app: path.resolve(`${__dirname}/app`),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  plugins: [new CleanWebpackPlugin()],
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Reference in New Issue
	
	Block a user